add top-level dropdown menu to workspace nav

This commit is contained in:
Brent Schroeter 2025-10-22 00:43:53 -07:00
parent cc285aaaaa
commit 15e1057a8d
8 changed files with 141 additions and 16 deletions

View file

@ -4,6 +4,7 @@
<title>{% block title %}Interim{% endblock %}</title>
{% include "meta_tags.html" %}
<link rel="stylesheet" href="{{ settings.root_path }}/css_dist/main.css">
<script type="module" src="{{ settings.root_path }}/js_dist/basic-dropdown.webc.mjs"></script>
{%- block head_extras %}{% endblock -%}
</head>
<body>

View file

@ -1,5 +1,30 @@
<nav class="workspace-nav">
<section>
<div class="workspace-nav__heading">
<h1>
{% if workspace.name.is_empty() %}
Untitled Workspace
{% else %}
{{ workspace.name }}
{% endif %}
</h1>
<basic-dropdown button-class="button--secondary button--small" button-aria-label="Workspace Menu">
<span slot="button-contents">...</span>
<menu slot="popover" class="basic-dropdown__menu">
<li>
<button
popovertarget="sql-conn-dialog"
popovertargetaction="toggle"
type="button"
>
PostgreSQL connection
</button>
</li>
</menu>
</basic-dropdown>
<dialog class="dialog" id="sql-conn-dialog" popover="auto">
</dialog>
</div>
<section class="workspace-nav__section">
<div class="workspace-nav__heading">
<h2>Tables</h2>
<form
@ -19,7 +44,7 @@
class="workspace-nav__menu-item"
expanded="
{%- if let Some(NavLocation::Rel(rel_oid, _)) = current -%}
{%- if rel_oid.to_owned() == rel.oid -%}
{%- if rel_oid == &rel.oid -%}
true
{%- endif -%}
{%- endif -%}
@ -69,8 +94,7 @@
/r/{{ rel.oid.0 -}}
/p/{{ portal.id.simple() -}}
"
class="workspace-nav__menu-link
"
class="workspace-nav__menu-link"
>
{{ portal.name }}
</a>
@ -97,6 +121,5 @@
{% endfor -%}
</menu>
</section>
<script type="module" src="{{ navigator.get_root_path() }}/js_dist/collapsible-menu.webc.mjs"></script>
</nav>

39
sass/_basic-dropdown.scss Normal file
View file

@ -0,0 +1,39 @@
@use 'globals';
.basic-dropdown {
&__button {
anchor-name: --anchor-button;
}
&__popover {
&:popover-open {
@include globals.popover;
left: anchor(left);
padding: 0;
position: absolute;
position-anchor: --anchor-button;
top: anchor(bottom);
}
}
&__menu {
list-style-type: none;
margin: 0;
padding: 8px 0;
& > li {
padding: 0;
&:hover {
background: #0001;
}
& > button {
@include globals.reset-button;
padding: 8px 16px;
}
}
}
}

View file

@ -111,7 +111,7 @@ $hover-lightness-scale-factor: -5%;
}
@mixin button-small {
padding: 0.25rem 0.5rem;
padding: 4px 8px;
font-size: 0.9rem;
}
@ -139,7 +139,8 @@ $hover-lightness-scale-factor: -5%;
inset: unset;
border: $popover-border;
margin: 0;
margin-top: 0.25rem;
margin-top: 4px;
padding: 0;
position: relative;
display: block;
background: #fff;

View file

@ -1,5 +1,6 @@
@use 'sass:color';
@use 'basic-dropdown';
@use 'globals';
@use 'modern-normalize';
@use 'forms';
@ -64,6 +65,10 @@ button, input[type="submit"] {
&--clear {
@include globals.button-clear;
}
&--small {
@include globals.button-small;
}
}
.page-grid {

View file

@ -223,7 +223,7 @@ $table-border-color: #ccc;
width: max-content;
&:not(:has(button)) {
padding: 6px 8px;
padding: 6px 12px;
}
&--red {
@ -265,7 +265,7 @@ $table-border-color: #ccc;
@include globals.button-clear;
color: inherit;
padding: 8px;
padding: 6px 12px;
}
}

View file

@ -6,6 +6,13 @@ $background-current-item: #0001;
& h1, h2, h3, h4, h5, h6 {
margin: 0;
font-weight: 600;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
& h1 {
font-size: 1.5rem;
}
& h2 {
@ -20,10 +27,15 @@ $background-current-item: #0001;
font-size: 1rem;
}
&__section {
margin-top: 16px;
}
&__menu {
list-style-type: none;
padding: 0;
margin-bottom: 0;
margin: 0;
margin-top: 16px;
}
&__heading {
@ -31,8 +43,7 @@ $background-current-item: #0001;
display: flex;
font-size: inherit;
justify-content: space-between;
margin: 0;
padding: 0.5rem;
margin: 8px;
}
&__aux-button {
@ -43,8 +54,9 @@ $background-current-item: #0001;
}
&__menu-item {
padding-top: 0.5rem;
padding-left: 0.5rem;
display: block;
margin-left: 8px;
padding: 0;
}
&__menu-leaf {
@ -52,7 +64,7 @@ $background-current-item: #0001;
align-items: center;
display: flex;
justify-content: space-between;
padding: 0 0.5rem;
padding: 0 8px;
&--current, &:hover {
background: $background-current-item;
@ -62,7 +74,7 @@ $background-current-item: #0001;
&__menu-link {
color: globals.$link-color;
flex: 1;
padding: 0.75rem 0;
padding: 12px 0;
text-decoration: none;
}
}

View file

@ -0,0 +1,44 @@
<svelte:options
customElement={{
props: {
button_aria_label: { attribute: "button-aria-label" },
button_class: { attribute: "button-class" },
},
tag: "basic-dropdown",
}}
/>
<script lang="ts">
type Props = {
button_aria_label?: string;
button_class?: string;
};
let { button_aria_label, button_class = "button--secondary" }: Props =
$props();
let popover_element: HTMLElement | undefined = $state();
</script>
<button
aria-label={button_aria_label}
class={["basic-dropdown__button", button_class]}
id="dropdown-button"
onclick={() => {
popover_element.showPopover();
}}
type="button"
>
<slot name="button-contents"></slot>
</button>
<div
aria-labelledby="dropdown-button"
bind:this={popover_element}
class="basic-dropdown__popover"
popover="auto"
>
<slot name="popover"></slot>
</div>
<style lang="scss">
@use "../../sass/main";
</style>