fix: select dropdown transition

This commit is contained in:
2025-03-18 17:05:21 -04:00
parent 2abd44990f
commit 21cd91156c
2 changed files with 47 additions and 35 deletions

View File

@ -42,7 +42,7 @@
<div <div
class="bg-mantle border-surface-0 hover:border-surface-2 flex items-center rounded border pl-2 text-sm drop-shadow-md transition-all" class="bg-mantle border-surface-0 hover:border-surface-2 flex items-center rounded border pl-2 text-sm drop-shadow-md transition-all"
> >
<div class="grow flex items-center justify-center"> <div class="flex grow items-center justify-center">
{#each ['start', 'end'] as const as type} {#each ['start', 'end'] as const as type}
<DateRangePicker.Input {type}> <DateRangePicker.Input {type}>
{#snippet children({ segments })} {#snippet children({ segments })}
@ -72,7 +72,7 @@
{/each} {/each}
</div> </div>
<DateRangePicker.Trigger <DateRangePicker.Trigger
class="text-overlay-2 hover:bg-surface-0 grow flex justify-center items-center focus:outline-sky ml-1 cursor-pointer p-2 transition-all focus:outline focus:outline-offset-1" class="text-overlay-2 hover:bg-surface-0 focus:outline-sky ml-1 flex grow cursor-pointer items-center justify-center p-2 transition-all focus:outline focus:outline-offset-1"
> >
<Calendar size="20" /> <Calendar size="20" />
</DateRangePicker.Trigger> </DateRangePicker.Trigger>

View File

@ -2,19 +2,20 @@
import { cn } from '$lib/utils'; import { cn } from '$lib/utils';
import { Check, ChevronsDown, ChevronsUp, ChevronsUpDown, X } from '@lucide/svelte'; import { Check, ChevronsDown, ChevronsUp, ChevronsUpDown, X } from '@lucide/svelte';
import { Select } from 'bits-ui'; import { Select } from 'bits-ui';
import { fade } from 'svelte/transition';
let { let {
value = $bindable('10'), value = $bindable('10'),
placeholder = 'Select an item', placeholder = 'Select an item',
items = [], items = [],
defaultValue = '', defaultValue = '',
className, className,
onchange onchange
}: { }: {
value?: string; value?: string;
placeholder?: string; placeholder?: string;
items: { value: string; label: string; disabled?: boolean }[]; items: { value: string; label: string; disabled?: boolean }[];
defaultValue?: string; defaultValue?: string;
className?: string; className?: string;
onchange?: (e: string) => void; onchange?: (e: string) => void;
} = $props(); } = $props();
@ -30,42 +31,53 @@
> >
<Select.Root type="single" {items} bind:value onValueChange={onchange}> <Select.Root type="single" {items} bind:value onValueChange={onchange}>
<Select.Trigger <Select.Trigger
class="focus:outline-sky data-placeholder:text-overlay-0 gap-2 inline-flex grow cursor-pointer select-none items-center justify-between rounded-l py-2 pl-2 text-sm transition-colors focus:outline focus:outline-offset-1" class="focus:outline-sky data-placeholder:text-overlay-0 inline-flex grow cursor-pointer select-none items-center justify-between gap-2 rounded-l py-2 pl-2 text-sm transition-colors focus:outline focus:outline-offset-1"
aria-label={placeholder} aria-label={placeholder}
> >
{selectedLabel} {selectedLabel}
<ChevronsUpDown class="text-overlay-0" size="20" /> <ChevronsUpDown class="text-overlay-0" size="20" />
</Select.Trigger> </Select.Trigger>
<Select.Portal> <Select.Portal>
<Select.Content <Select.Content forceMount>
class="focus-override border-surface-0 bg-mantle shadow-popover data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 outline-hidden z-50 select-none rounded border p-1" {#snippet child({ wrapperProps, props, open })}
sideOffset={10} {#if open}
> <div {...wrapperProps}>
<Select.ScrollUpButton class="flex w-full items-center justify-center"> <div
<ChevronsUp size="20" /> {...props}
</Select.ScrollUpButton> class="border-surface-0 bg-mantle shadow-popover outline-hidden z-50 mt-1 select-none rounded border p-1"
<Select.Viewport class="p-1"> transition:fade={{
{#each items as item, i (i + item.value)} duration: 100
<Select.Item }}
class="data-disabled:cursor-not-allowed data-highlighted:bg-surface-0 outline-hidden data-disabled:opacity-50 flex h-10 w-full cursor-pointer select-none items-center gap-4 rounded px-5 py-3 text-sm capitalize" >
value={item.value} <Select.ScrollUpButton class="flex w-full items-center justify-center">
label={item.label} <ChevronsUp size="20" />
disabled={item.disabled} </Select.ScrollUpButton>
> <Select.Viewport class="p-1">
{#snippet children({ selected })} {#each items as item, i (i + item.value)}
{item.label} <Select.Item
{#if selected} class="data-disabled:cursor-not-allowed data-highlighted:bg-surface-0 outline-hidden data-disabled:opacity-50 flex h-10 w-full cursor-pointer select-none items-center gap-4 rounded px-5 py-3 text-sm capitalize"
<div class="ml-auto"> value={item.value}
<Check size="20" /> label={item.label}
</div> disabled={item.disabled}
{/if} >
{/snippet} {#snippet children({ selected })}
</Select.Item> {item.label}
{/each} {#if selected}
</Select.Viewport> <div class="ml-auto">
<Select.ScrollDownButton class="flex w-full items-center justify-center"> <Check size="20" />
<ChevronsDown size="20" /> </div>
</Select.ScrollDownButton> {/if}
{/snippet}
</Select.Item>
{/each}
</Select.Viewport>
<Select.ScrollDownButton class="flex w-full items-center justify-center">
<ChevronsDown size="20" />
</Select.ScrollDownButton>
</div>
</div>
{/if}
{/snippet}
</Select.Content> </Select.Content>
</Select.Portal> </Select.Portal>
</Select.Root> </Select.Root>
@ -74,7 +86,7 @@
type="button" type="button"
onclick={() => { onclick={() => {
value = defaultValue; value = defaultValue;
onchange?.(value); onchange?.(value);
}} }}
> >
<X size="20" /> <X size="20" />