action select: add frameless, support custom button content

This commit is contained in:
Elijah Duffy
2025-07-11 14:06:46 -07:00
parent 56c5b90629
commit c99b1a2899
2 changed files with 41 additions and 15 deletions

View File

@@ -1,6 +1,5 @@
<script lang="ts" module>
export type ActionSelectOption = {
/** value is a convenience field, it has no internal use */
value?: string;
icon?: IconDef | Snippet<[opt: ActionSelectOption]>;
label: string | Snippet<[opt: ActionSelectOption]>;
@@ -19,6 +18,7 @@
import type { IconDef } from './util';
interface Props {
name?: string;
label?: string;
placeholder?: string;
value?: ActionSelectOption;
@@ -27,10 +27,13 @@
sameWidth?: boolean;
options: ActionSelectOption[];
class?: ClassValue | null | undefined;
frameless?: boolean;
onchange?: (value: ActionSelectOption | undefined) => void;
children?: Snippet;
}
let {
name,
label,
placeholder = 'Choose an action',
value = $bindable(undefined),
@@ -39,7 +42,9 @@
sameWidth = true,
options,
class: classValue,
onchange
frameless = false,
onchange,
children
}: Props = $props();
const select = new Select<ActionSelectOption>({
@@ -84,12 +89,22 @@
<Label {...select.label}>{label}</Label>
{/if}
{#if name}
<input type="hidden" {name} value={value?.value} />
{/if}
<Button
bind:ref={buttonElement}
class={['flex w-full items-center rounded-xl!']}
class={[
'flex w-full items-center rounded-xl!',
frameless && 'hover:bg-sui-text-100/50 bg-transparent',
frameless && select.open && 'bg-sui-text-100/50!'
]}
{...select.trigger}
{...!tabbable && { tabindex: -1 }}
>
{#if children}{@render children()}
{:else}
{#if stateless || !select.value}
{placeholder}
{:else}
@@ -102,6 +117,7 @@
size="1.1em"
class={[select.open && '-scale-y-100', 'ml-auto transition-transform']}
/>
{/if}
</Button>
<div
@@ -127,7 +143,7 @@
{@render optionIcon(option)}
{@render optionLabel(option)}
{#if !stateless && select.isSelected(option)}
{#if !stateless && select.value?.label === option.label}
<Check size="1.1em" weight="bold" class={['ml-auto']} />
{/if}
</div>

View File

@@ -22,6 +22,7 @@
import {
ArrowUUpLeft,
ArrowUUpRight,
DotsThreeOutlineVertical,
Plus,
TextB,
TextItalic,
@@ -76,7 +77,7 @@
</div>
<div class="component">
<p class="title">Button Select</p>
<p class="title">Action Select</p>
<div class="flex gap-2">
<ActionSelect
@@ -104,6 +105,15 @@
}
]}
/>
<ActionSelect
class="mt-7"
options={[{ label: 'Option 1' }, { label: 'Option 2' }, { label: 'Option 3' }]}
sameWidth={false}
frameless={true}
stateless={true}
>
<DotsThreeOutlineVertical class="text-sui-text" size="1.2em" />
</ActionSelect>
</div>
</div>