action select: add frameless, support custom button content
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
<script lang="ts" module>
|
<script lang="ts" module>
|
||||||
export type ActionSelectOption = {
|
export type ActionSelectOption = {
|
||||||
/** value is a convenience field, it has no internal use */
|
|
||||||
value?: string;
|
value?: string;
|
||||||
icon?: IconDef | Snippet<[opt: ActionSelectOption]>;
|
icon?: IconDef | Snippet<[opt: ActionSelectOption]>;
|
||||||
label: string | Snippet<[opt: ActionSelectOption]>;
|
label: string | Snippet<[opt: ActionSelectOption]>;
|
||||||
@@ -19,6 +18,7 @@
|
|||||||
import type { IconDef } from './util';
|
import type { IconDef } from './util';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
name?: string;
|
||||||
label?: string;
|
label?: string;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
value?: ActionSelectOption;
|
value?: ActionSelectOption;
|
||||||
@@ -27,10 +27,13 @@
|
|||||||
sameWidth?: boolean;
|
sameWidth?: boolean;
|
||||||
options: ActionSelectOption[];
|
options: ActionSelectOption[];
|
||||||
class?: ClassValue | null | undefined;
|
class?: ClassValue | null | undefined;
|
||||||
|
frameless?: boolean;
|
||||||
onchange?: (value: ActionSelectOption | undefined) => void;
|
onchange?: (value: ActionSelectOption | undefined) => void;
|
||||||
|
children?: Snippet;
|
||||||
}
|
}
|
||||||
|
|
||||||
let {
|
let {
|
||||||
|
name,
|
||||||
label,
|
label,
|
||||||
placeholder = 'Choose an action',
|
placeholder = 'Choose an action',
|
||||||
value = $bindable(undefined),
|
value = $bindable(undefined),
|
||||||
@@ -39,7 +42,9 @@
|
|||||||
sameWidth = true,
|
sameWidth = true,
|
||||||
options,
|
options,
|
||||||
class: classValue,
|
class: classValue,
|
||||||
onchange
|
frameless = false,
|
||||||
|
onchange,
|
||||||
|
children
|
||||||
}: Props = $props();
|
}: Props = $props();
|
||||||
|
|
||||||
const select = new Select<ActionSelectOption>({
|
const select = new Select<ActionSelectOption>({
|
||||||
@@ -84,24 +89,35 @@
|
|||||||
<Label {...select.label}>{label}</Label>
|
<Label {...select.label}>{label}</Label>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
{#if name}
|
||||||
|
<input type="hidden" {name} value={value?.value} />
|
||||||
|
{/if}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
bind:ref={buttonElement}
|
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}
|
{...select.trigger}
|
||||||
{...!tabbable && { tabindex: -1 }}
|
{...!tabbable && { tabindex: -1 }}
|
||||||
>
|
>
|
||||||
{#if stateless || !select.value}
|
{#if children}{@render children()}
|
||||||
{placeholder}
|
|
||||||
{:else}
|
{:else}
|
||||||
{@render optionIcon(select.value)}
|
{#if stateless || !select.value}
|
||||||
{@render optionLabel(select.value)}
|
{placeholder}
|
||||||
{/if}
|
{:else}
|
||||||
|
{@render optionIcon(select.value)}
|
||||||
|
{@render optionLabel(select.value)}
|
||||||
|
{/if}
|
||||||
|
|
||||||
<CaretDown
|
<CaretDown
|
||||||
weight="bold"
|
weight="bold"
|
||||||
size="1.1em"
|
size="1.1em"
|
||||||
class={[select.open && '-scale-y-100', 'ml-auto transition-transform']}
|
class={[select.open && '-scale-y-100', 'ml-auto transition-transform']}
|
||||||
/>
|
/>
|
||||||
|
{/if}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
@@ -127,7 +143,7 @@
|
|||||||
{@render optionIcon(option)}
|
{@render optionIcon(option)}
|
||||||
{@render optionLabel(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']} />
|
<Check size="1.1em" weight="bold" class={['ml-auto']} />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
import {
|
import {
|
||||||
ArrowUUpLeft,
|
ArrowUUpLeft,
|
||||||
ArrowUUpRight,
|
ArrowUUpRight,
|
||||||
|
DotsThreeOutlineVertical,
|
||||||
Plus,
|
Plus,
|
||||||
TextB,
|
TextB,
|
||||||
TextItalic,
|
TextItalic,
|
||||||
@@ -76,7 +77,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="component">
|
<div class="component">
|
||||||
<p class="title">Button Select</p>
|
<p class="title">Action Select</p>
|
||||||
|
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<ActionSelect
|
<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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user