improve dropdown

This commit is contained in:
Chris Kruining 2025-01-07 08:13:09 +01:00
parent f73ad56c0e
commit b1aad32beb
No known key found for this signature in database
GPG key ID: EB894A3560CCCAD2
2 changed files with 20 additions and 12 deletions

View file

@ -1,6 +1,5 @@
.box { .box {
display: contents; display: contents;
inline-size: max-content;
&:has(> :popover-open) > .button { &:has(> :popover-open) > .button {
background-color: var(--surface-500); background-color: var(--surface-500);
@ -15,7 +14,9 @@
grid-template-columns: inherit; grid-template-columns: inherit;
place-items: center start; place-items: center start;
inline-size: max-content; /* Make sure the height of the button does not collapse when it is empty */
block-size: 1em;
box-sizing: content-box;
padding: var(--padding-m); padding: var(--padding-m);
background-color: transparent; background-color: transparent;
@ -44,13 +45,14 @@
.dialog { .dialog {
display: none; display: none;
position: relative;
grid-template-columns: inherit; grid-template-columns: inherit;
inset-inline-start: anchor(start); inset-inline-start: anchor(start);
inset-block-start: anchor(end); inset-block-start: anchor(end);
position-try-fallbacks: flip-inline; position-try-fallbacks: flip-block, flip-inline;
inline-size: anchor-size(self-inline); /* inline-size: anchor-size(self-inline); */
background-color: var(--surface-500); background-color: var(--surface-500);
padding: var(--padding-m); padding: var(--padding-m);
border: none; border: none;

View file

@ -1,12 +1,12 @@
import { createMemo, createSignal, For, JSX, Setter, createEffect, Show } from "solid-js"; import { createMemo, createSignal, For, JSX, Setter, createEffect, Show } from "solid-js";
import css from './index.module.css';
import { FaSolidAngleDown } from "solid-icons/fa"; import { FaSolidAngleDown } from "solid-icons/fa";
import css from './index.module.css';
interface DropdownProps<T, K extends string> { interface DropdownProps<T, K extends string> {
id: string; id: string;
class?: string; class?: string;
value: K; value?: K;
setValue?: Setter<K>; setValue?: Setter<K | undefined>;
values: Record<K, T>; values: Record<K, T>;
open?: boolean; open?: boolean;
showCaret?: boolean; showCaret?: boolean;
@ -16,7 +16,7 @@ interface DropdownProps<T, K extends string> {
export function Dropdown<T, K extends string>(props: DropdownProps<T, K>) { export function Dropdown<T, K extends string>(props: DropdownProps<T, K>) {
const [dialog, setDialog] = createSignal<HTMLDialogElement>(); const [dialog, setDialog] = createSignal<HTMLDialogElement>();
const [value, setValue] = createSignal<K>(props.value); const [key, setKey] = createSignal<K | undefined>(props.value);
const [open, setOpen] = createSignal<boolean>(props.open ?? false); const [open, setOpen] = createSignal<boolean>(props.open ?? false);
const [query, setQuery] = createSignal<string>(''); const [query, setQuery] = createSignal<string>('');
@ -35,7 +35,7 @@ export function Dropdown<T, K extends string>(props: DropdownProps<T, K>) {
const showCaret = createMemo(() => props.showCaret ?? true); const showCaret = createMemo(() => props.showCaret ?? true);
createEffect(() => { createEffect(() => {
props.setValue?.(() => value()); props.setValue?.(() => key());
}); });
createEffect(() => { createEffect(() => {
@ -44,7 +44,13 @@ export function Dropdown<T, K extends string>(props: DropdownProps<T, K>) {
return <section class={`${css.box} ${props.class}`}> return <section class={`${css.box} ${props.class}`}>
<button id={`${props.id}_button`} popoverTarget={`${props.id}_dialog`} class={css.button}> <button id={`${props.id}_button`} popoverTarget={`${props.id}_dialog`} class={css.button}>
{props.children(value(), props.values[value()])} <Show when={key()}>{
key => {
const value = createMemo(() => props.values[key()]);
return <>{props.children(key(), value())}</>;
}
}</Show>
<Show when={showCaret()}> <Show when={showCaret()}>
<FaSolidAngleDown class={css.caret} /> <FaSolidAngleDown class={css.caret} />
@ -61,10 +67,10 @@ export function Dropdown<T, K extends string>(props: DropdownProps<T, K>) {
<main> <main>
<For each={values()}>{ <For each={values()}>{
([k, v]) => { ([k, v]) => {
const selected = createMemo(() => value() === k); const selected = createMemo(() => key() === k);
return <span class={`${css.option} ${selected() ? css.selected : ''}`} onpointerdown={() => { return <span class={`${css.option} ${selected() ? css.selected : ''}`} onpointerdown={() => {
setValue(() => k); setKey(() => k);
dialog()?.hidePopover(); dialog()?.hidePopover();
}}>{props.children(k, v)}</span>; }}>{props.children(k, v)}</span>;
} }