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> <title>{% block title %}Interim{% endblock %}</title>
{% include "meta_tags.html" %} {% include "meta_tags.html" %}
<link rel="stylesheet" href="{{ settings.root_path }}/css_dist/main.css"> <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 -%} {%- block head_extras %}{% endblock -%}
</head> </head>
<body> <body>

View file

@ -1,5 +1,30 @@
<nav class="workspace-nav"> <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"> <div class="workspace-nav__heading">
<h2>Tables</h2> <h2>Tables</h2>
<form <form
@ -19,7 +44,7 @@
class="workspace-nav__menu-item" class="workspace-nav__menu-item"
expanded=" expanded="
{%- if let Some(NavLocation::Rel(rel_oid, _)) = current -%} {%- if let Some(NavLocation::Rel(rel_oid, _)) = current -%}
{%- if rel_oid.to_owned() == rel.oid -%} {%- if rel_oid == &rel.oid -%}
true true
{%- endif -%} {%- endif -%}
{%- endif -%} {%- endif -%}
@ -69,8 +94,7 @@
/r/{{ rel.oid.0 -}} /r/{{ rel.oid.0 -}}
/p/{{ portal.id.simple() -}} /p/{{ portal.id.simple() -}}
" "
class="workspace-nav__menu-link class="workspace-nav__menu-link"
"
> >
{{ portal.name }} {{ portal.name }}
</a> </a>
@ -97,6 +121,5 @@
{% endfor -%} {% endfor -%}
</menu> </menu>
</section> </section>
<script type="module" src="{{ navigator.get_root_path() }}/js_dist/collapsible-menu.webc.mjs"></script>
</nav> </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 { @mixin button-small {
padding: 0.25rem 0.5rem; padding: 4px 8px;
font-size: 0.9rem; font-size: 0.9rem;
} }
@ -139,7 +139,8 @@ $hover-lightness-scale-factor: -5%;
inset: unset; inset: unset;
border: $popover-border; border: $popover-border;
margin: 0; margin: 0;
margin-top: 0.25rem; margin-top: 4px;
padding: 0;
position: relative; position: relative;
display: block; display: block;
background: #fff; background: #fff;

View file

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

View file

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

View file

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