The footer affordances (Clear / Cancel / Close) lived inline in each
demo as picker-actions.svelte. Promoted to canonical Eidos surface so
the API is consistent and the contract is auditable.
morfo:
- date-picker + date-range-picker: added Footer (archetype 'footer'),
Clear/Cancel/Close (archetype 'trigger', kind 'public', optional).
Each part declares aria-label via idlangref and data-action="…".
- types.ts: added 'footer' to ARCHETYPE_VOCABULARY array + the
MorfoArchetype union (the type had it, the runtime list did not).
- lang catalogs: added clear / cancel / close idlangref entries to
date-picker.ts and date-range-picker.ts.
eidos:
- Created date-picker-footer/clear/cancel/close.svelte and the range
mirrors. Each part:
- Pulls the provider from context via DatePickerProvider.require()
(analogous DateRangePickerProvider.require() for the range).
- Renders nothing when the corresponding *Button opt is false; the
Close part stays visible whenever mode === 'modal' (modal pickers
need a way out — outside-click and Escape are blocked).
- Emits data-{component}-{part} + data-action so the recipe selector
matches the morfo declaration.
- aria-label resolves via uix.langs.ts('#?components.X.{action}|…').
- onclick calls provider.clear() / cancel() / commit() then forwards
any consumer-supplied onclick.
- index.ts barrels: registered Footer/Clear/Cancel + replaced
Close (was popover-close.svelte) with the new picker-aware Close.
Soma popover-close still drives the old aria; date-picker's Close
adds the modal-conditional visibility + commit semantics.
- *.css: folded the inline picker-actions styles into the recipes —
data-{name}-footer flex row + data-{name}-{clear,cancel,close}
buttons (clear/cancel margin-inline-end: auto so close sits flush
right). prefers-reduced-motion already covered.
soma:
- date-picker exports.ts: surfaces DatePickerProvider + DatePickerMode
+ datePickerAttrs so the Eidos parts can consume them (mirrors what
date-range-picker already exposed). No new behavior — just plumbing.
demo:
- date-picker + date-range-picker demos: replaced
<PickerActions /> with <DatePicker.Footer>
<DatePicker.Clear /><DatePicker.Cancel /><DatePicker.Close />
</DatePicker.Footer>. The two picker-actions.svelte files are
deleted.
Verification: 0 type errors, morfo:check PASS (Footer parts not
required in DOM; conditional visibility honored), component:audit
67/67 PASS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
active-uix
parent
9bd9db408d
commit
394aeaa476
@ -0,0 +1,40 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DatePickerProvider } from '$soma/components/date-picker';
|
||||||
|
import { getActiveUix } from '$active-uix';
|
||||||
|
import type { Snippet } from 'svelte';
|
||||||
|
import type { HTMLButtonAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
|
// Cancel action — reverts to the value snapshot taken on open and
|
||||||
|
// closes the popover. Hidden when `cancelButton` is false on the root.
|
||||||
|
interface CancelProps extends HTMLButtonAttributes {
|
||||||
|
children?: Snippet;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { children, onclick, ...rest }: CancelProps = $props();
|
||||||
|
|
||||||
|
const uix = getActiveUix();
|
||||||
|
const provider = DatePickerProvider.require();
|
||||||
|
const visible = $derived(provider.opts.cancelButton.current);
|
||||||
|
|
||||||
|
function handleClick(event: MouseEvent & { currentTarget: EventTarget & HTMLButtonElement }) {
|
||||||
|
provider.cancel();
|
||||||
|
if (typeof onclick === 'function') onclick.call(event.currentTarget, event);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if visible}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
data-date-picker-cancel
|
||||||
|
data-action="cancel"
|
||||||
|
aria-label={uix.langs.ts('#?components.date-picker.cancel|Cancel')}
|
||||||
|
onclick={handleClick}
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
|
{#if children}
|
||||||
|
{@render children()}
|
||||||
|
{:else}
|
||||||
|
{uix.langs.ts('#?components.date-picker.cancel|Cancel')}
|
||||||
|
{/if}
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DatePickerProvider } from '$soma/components/date-picker';
|
||||||
|
import { getActiveUix } from '$active-uix';
|
||||||
|
import type { Snippet } from 'svelte';
|
||||||
|
import type { HTMLButtonAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
|
// Clear action — resets the picker's value (undefined) and keeps the
|
||||||
|
// popover open. Hidden when `clearButton` is false on the root.
|
||||||
|
interface ClearProps extends HTMLButtonAttributes {
|
||||||
|
children?: Snippet;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { children, onclick, ...rest }: ClearProps = $props();
|
||||||
|
|
||||||
|
const uix = getActiveUix();
|
||||||
|
const provider = DatePickerProvider.require();
|
||||||
|
const visible = $derived(provider.opts.clearButton.current);
|
||||||
|
|
||||||
|
function handleClick(event: MouseEvent & { currentTarget: EventTarget & HTMLButtonElement }) {
|
||||||
|
provider.clear();
|
||||||
|
if (typeof onclick === 'function') onclick.call(event.currentTarget, event);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if visible}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
data-date-picker-clear
|
||||||
|
data-action="clear"
|
||||||
|
aria-label={uix.langs.ts('#?components.date-picker.clear|Clear date')}
|
||||||
|
onclick={handleClick}
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
|
{#if children}
|
||||||
|
{@render children()}
|
||||||
|
{:else}
|
||||||
|
{uix.langs.ts('#?components.date-picker.clear|Clear date')}
|
||||||
|
{/if}
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DatePickerProvider } from '$soma/components/date-picker';
|
||||||
|
import { getActiveUix } from '$active-uix';
|
||||||
|
import type { Snippet } from 'svelte';
|
||||||
|
import type { HTMLButtonAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
|
// Close / Save action — commits the current value and closes the
|
||||||
|
// popover. Visible when `closeButton` is true OR `mode='modal'`
|
||||||
|
// (modal pickers always need a way out — outside-click and Escape
|
||||||
|
// are intentionally blocked).
|
||||||
|
interface CloseProps extends HTMLButtonAttributes {
|
||||||
|
children?: Snippet;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { children, onclick, ...rest }: CloseProps = $props();
|
||||||
|
|
||||||
|
const uix = getActiveUix();
|
||||||
|
const provider = DatePickerProvider.require();
|
||||||
|
const visible = $derived(
|
||||||
|
provider.opts.closeButton.current || provider.opts.mode.current === 'modal'
|
||||||
|
);
|
||||||
|
|
||||||
|
function handleClick(event: MouseEvent & { currentTarget: EventTarget & HTMLButtonElement }) {
|
||||||
|
provider.commit();
|
||||||
|
if (typeof onclick === 'function') onclick.call(event.currentTarget, event);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if visible}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
data-date-picker-close
|
||||||
|
data-action="close"
|
||||||
|
aria-label={uix.langs.ts('#?components.date-picker.close|Close')}
|
||||||
|
onclick={handleClick}
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
|
{#if children}
|
||||||
|
{@render children()}
|
||||||
|
{:else}
|
||||||
|
{uix.langs.ts('#?components.date-picker.close|Close')}
|
||||||
|
{/if}
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DatePickerProvider } from '$soma/components/date-picker';
|
||||||
|
import type { Snippet } from 'svelte';
|
||||||
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
|
// Footer container for the picker calendar. Renders only when the
|
||||||
|
// consumer enabled at least one button (clearButton/cancelButton/
|
||||||
|
// closeButton on the root) — `mode='modal'` forces Close on.
|
||||||
|
interface FooterProps extends HTMLAttributes<HTMLDivElement> {
|
||||||
|
children?: Snippet;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { children, ...rest }: FooterProps = $props();
|
||||||
|
|
||||||
|
const provider = DatePickerProvider.require();
|
||||||
|
const mode = $derived(provider.opts.mode.current);
|
||||||
|
const showClear = $derived(provider.opts.clearButton.current);
|
||||||
|
const showCancel = $derived(provider.opts.cancelButton.current);
|
||||||
|
const showClose = $derived(provider.opts.closeButton.current || mode === 'modal');
|
||||||
|
const visible = $derived(showClear || showCancel || showClose);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if visible}
|
||||||
|
<div data-date-picker-footer data-mode={mode} {...rest}>
|
||||||
|
{@render children?.()}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DateRangePickerProvider } from '$soma/components/date-range-picker';
|
||||||
|
import { getActiveUix } from '$active-uix';
|
||||||
|
import type { Snippet } from 'svelte';
|
||||||
|
import type { HTMLButtonAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
|
interface CancelProps extends HTMLButtonAttributes {
|
||||||
|
children?: Snippet;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { children, onclick, ...rest }: CancelProps = $props();
|
||||||
|
|
||||||
|
const uix = getActiveUix();
|
||||||
|
const provider = DateRangePickerProvider.require();
|
||||||
|
const visible = $derived(provider.opts.cancelButton.current);
|
||||||
|
|
||||||
|
function handleClick(event: MouseEvent & { currentTarget: EventTarget & HTMLButtonElement }) {
|
||||||
|
provider.cancel();
|
||||||
|
if (typeof onclick === 'function') onclick.call(event.currentTarget, event);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if visible}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
data-date-range-picker-cancel
|
||||||
|
data-action="cancel"
|
||||||
|
aria-label={uix.langs.ts('#?components.date-range-picker.cancel|Cancel')}
|
||||||
|
onclick={handleClick}
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
|
{#if children}
|
||||||
|
{@render children()}
|
||||||
|
{:else}
|
||||||
|
{uix.langs.ts('#?components.date-range-picker.cancel|Cancel')}
|
||||||
|
{/if}
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DateRangePickerProvider } from '$soma/components/date-range-picker';
|
||||||
|
import { getActiveUix } from '$active-uix';
|
||||||
|
import type { Snippet } from 'svelte';
|
||||||
|
import type { HTMLButtonAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
|
interface ClearProps extends HTMLButtonAttributes {
|
||||||
|
children?: Snippet;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { children, onclick, ...rest }: ClearProps = $props();
|
||||||
|
|
||||||
|
const uix = getActiveUix();
|
||||||
|
const provider = DateRangePickerProvider.require();
|
||||||
|
const visible = $derived(provider.opts.clearButton.current);
|
||||||
|
|
||||||
|
function handleClick(event: MouseEvent & { currentTarget: EventTarget & HTMLButtonElement }) {
|
||||||
|
provider.clear();
|
||||||
|
if (typeof onclick === 'function') onclick.call(event.currentTarget, event);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if visible}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
data-date-range-picker-clear
|
||||||
|
data-action="clear"
|
||||||
|
aria-label={uix.langs.ts('#?components.date-range-picker.clear|Clear range')}
|
||||||
|
onclick={handleClick}
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
|
{#if children}
|
||||||
|
{@render children()}
|
||||||
|
{:else}
|
||||||
|
{uix.langs.ts('#?components.date-range-picker.clear|Clear range')}
|
||||||
|
{/if}
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DateRangePickerProvider } from '$soma/components/date-range-picker';
|
||||||
|
import { getActiveUix } from '$active-uix';
|
||||||
|
import type { Snippet } from 'svelte';
|
||||||
|
import type { HTMLButtonAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
|
interface CloseProps extends HTMLButtonAttributes {
|
||||||
|
children?: Snippet;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { children, onclick, ...rest }: CloseProps = $props();
|
||||||
|
|
||||||
|
const uix = getActiveUix();
|
||||||
|
const provider = DateRangePickerProvider.require();
|
||||||
|
const visible = $derived(
|
||||||
|
provider.opts.closeButton.current || provider.opts.mode.current === 'modal'
|
||||||
|
);
|
||||||
|
|
||||||
|
function handleClick(event: MouseEvent & { currentTarget: EventTarget & HTMLButtonElement }) {
|
||||||
|
provider.commit();
|
||||||
|
if (typeof onclick === 'function') onclick.call(event.currentTarget, event);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if visible}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
data-date-range-picker-close
|
||||||
|
data-action="close"
|
||||||
|
aria-label={uix.langs.ts('#?components.date-range-picker.close|Close')}
|
||||||
|
onclick={handleClick}
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
|
{#if children}
|
||||||
|
{@render children()}
|
||||||
|
{:else}
|
||||||
|
{uix.langs.ts('#?components.date-range-picker.close|Close')}
|
||||||
|
{/if}
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { DateRangePickerProvider } from '$soma/components/date-range-picker';
|
||||||
|
import type { Snippet } from 'svelte';
|
||||||
|
import type { HTMLAttributes } from 'svelte/elements';
|
||||||
|
|
||||||
|
interface FooterProps extends HTMLAttributes<HTMLDivElement> {
|
||||||
|
children?: Snippet;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { children, ...rest }: FooterProps = $props();
|
||||||
|
|
||||||
|
const provider = DateRangePickerProvider.require();
|
||||||
|
const mode = $derived(provider.opts.mode.current);
|
||||||
|
const showClear = $derived(provider.opts.clearButton.current);
|
||||||
|
const showCancel = $derived(provider.opts.cancelButton.current);
|
||||||
|
const showClose = $derived(provider.opts.closeButton.current || mode === 'modal');
|
||||||
|
const visible = $derived(showClear || showCancel || showClose);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if visible}
|
||||||
|
<div data-date-range-picker-footer data-mode={mode} {...rest}>
|
||||||
|
{@render children?.()}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
@ -1,111 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import { DatePickerProvider } from '$soma/components/date-picker';
|
|
||||||
|
|
||||||
// Footer for the DatePicker calendar. Lives inside the provider tree
|
|
||||||
// (rendered from the Calendar snippet) so it can pull options + helpers
|
|
||||||
// straight from context.
|
|
||||||
//
|
|
||||||
// Buttons are configured via props on the picker:
|
|
||||||
// - `clearButton` — Clear (reset value, keep open)
|
|
||||||
// - `cancelButton` — Cancel (revert to value-at-open, close)
|
|
||||||
// - `closeButton` — Close / Save (commit current value, close)
|
|
||||||
//
|
|
||||||
// In `mode='modal'` Close is forced on so the user always has a way out:
|
|
||||||
// modal popovers ignore outside-click and Escape.
|
|
||||||
//
|
|
||||||
// If no buttons are enabled (and the picker is not modal), this footer
|
|
||||||
// renders nothing.
|
|
||||||
const provider = DatePickerProvider.require();
|
|
||||||
const mode = $derived(provider.opts.mode.current);
|
|
||||||
const showClear = $derived(provider.opts.clearButton.current);
|
|
||||||
const showCancel = $derived(provider.opts.cancelButton.current);
|
|
||||||
const showClose = $derived(provider.opts.closeButton.current || mode === 'modal');
|
|
||||||
const visible = $derived(showClear || showCancel || showClose);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{#if visible}
|
|
||||||
<div class="picker-footer" data-date-picker-footer data-mode={mode}>
|
|
||||||
{#if showClear}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="picker-footer-button"
|
|
||||||
data-tone="ghost"
|
|
||||||
onclick={() => provider.clear()}
|
|
||||||
>
|
|
||||||
Clear
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
<div class="picker-footer-spacer"></div>
|
|
||||||
{#if showCancel}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="picker-footer-button"
|
|
||||||
data-tone="ghost"
|
|
||||||
onclick={() => provider.cancel()}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
{#if showClose}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="picker-footer-button"
|
|
||||||
data-tone="solid"
|
|
||||||
onclick={() => provider.commit()}
|
|
||||||
>
|
|
||||||
Close
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.picker-footer {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: var(--uix-space-2, 0.5rem);
|
|
||||||
padding-block-start: var(--uix-space-3, 0.75rem);
|
|
||||||
margin-block-start: var(--uix-space-3, 0.75rem);
|
|
||||||
border-block-start: 1px solid var(--color-border-subtle);
|
|
||||||
}
|
|
||||||
|
|
||||||
.picker-footer-spacer {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.picker-footer-button {
|
|
||||||
inline-size: max-content;
|
|
||||||
min-block-size: var(--control-height-sm);
|
|
||||||
padding-inline: var(--uix-space-3, 0.75rem);
|
|
||||||
border-radius: var(--radius-md);
|
|
||||||
border: var(--border-width) solid transparent;
|
|
||||||
background: transparent;
|
|
||||||
color: var(--color-content-primary);
|
|
||||||
font: inherit;
|
|
||||||
font-size: var(--uix-text-sm);
|
|
||||||
cursor: pointer;
|
|
||||||
transition:
|
|
||||||
background var(--duration-fast) var(--ease-default),
|
|
||||||
border-color var(--duration-fast) var(--ease-default),
|
|
||||||
color var(--duration-fast) var(--ease-default);
|
|
||||||
}
|
|
||||||
|
|
||||||
.picker-footer-button[data-tone='ghost']:hover {
|
|
||||||
background: var(--color-surface-overlay);
|
|
||||||
}
|
|
||||||
|
|
||||||
.picker-footer-button[data-tone='solid'] {
|
|
||||||
border-color: var(--color-primary-border);
|
|
||||||
background: var(--color-primary-solid);
|
|
||||||
color: var(--color-content-on-solid);
|
|
||||||
}
|
|
||||||
|
|
||||||
.picker-footer-button[data-tone='solid']:hover {
|
|
||||||
background: var(--color-primary-solid-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
.picker-footer-button:focus-visible {
|
|
||||||
outline: var(--focus-ring-width) solid var(--color-primary-border);
|
|
||||||
outline-offset: var(--focus-ring-offset);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,111 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import { DateRangePickerProvider } from '$soma/components/date-range-picker';
|
|
||||||
|
|
||||||
// Footer for the DateRangePicker calendar. Lives inside the provider tree
|
|
||||||
// (rendered from the Calendar snippet) so it can pull options + helpers
|
|
||||||
// straight from context.
|
|
||||||
//
|
|
||||||
// Buttons are configured via props on the picker:
|
|
||||||
// - `clearButton` — Clear (reset value, keep open)
|
|
||||||
// - `cancelButton` — Cancel (revert to value-at-open, close)
|
|
||||||
// - `closeButton` — Close / Save (commit current value, close)
|
|
||||||
//
|
|
||||||
// In `mode='modal'` Close is forced on so the user always has a way out:
|
|
||||||
// modal popovers ignore outside-click and Escape.
|
|
||||||
//
|
|
||||||
// If no buttons are enabled (and the picker is not modal), this footer
|
|
||||||
// renders nothing.
|
|
||||||
const provider = DateRangePickerProvider.require();
|
|
||||||
const mode = $derived(provider.opts.mode.current);
|
|
||||||
const showClear = $derived(provider.opts.clearButton.current);
|
|
||||||
const showCancel = $derived(provider.opts.cancelButton.current);
|
|
||||||
const showClose = $derived(provider.opts.closeButton.current || mode === 'modal');
|
|
||||||
const visible = $derived(showClear || showCancel || showClose);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{#if visible}
|
|
||||||
<div class="picker-footer" data-date-range-picker-footer data-mode={mode}>
|
|
||||||
{#if showClear}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="picker-footer-button"
|
|
||||||
data-tone="ghost"
|
|
||||||
onclick={() => provider.clear()}
|
|
||||||
>
|
|
||||||
Clear
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
<div class="picker-footer-spacer"></div>
|
|
||||||
{#if showCancel}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="picker-footer-button"
|
|
||||||
data-tone="ghost"
|
|
||||||
onclick={() => provider.cancel()}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
{#if showClose}
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="picker-footer-button"
|
|
||||||
data-tone="solid"
|
|
||||||
onclick={() => provider.commit()}
|
|
||||||
>
|
|
||||||
Close
|
|
||||||
</button>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.picker-footer {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: var(--uix-space-2, 0.5rem);
|
|
||||||
padding-block-start: var(--uix-space-3, 0.75rem);
|
|
||||||
margin-block-start: var(--uix-space-3, 0.75rem);
|
|
||||||
border-block-start: 1px solid var(--color-border-subtle);
|
|
||||||
}
|
|
||||||
|
|
||||||
.picker-footer-spacer {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.picker-footer-button {
|
|
||||||
inline-size: max-content;
|
|
||||||
min-block-size: var(--control-height-sm);
|
|
||||||
padding-inline: var(--uix-space-3, 0.75rem);
|
|
||||||
border-radius: var(--radius-md);
|
|
||||||
border: var(--border-width) solid transparent;
|
|
||||||
background: transparent;
|
|
||||||
color: var(--color-content-primary);
|
|
||||||
font: inherit;
|
|
||||||
font-size: var(--uix-text-sm);
|
|
||||||
cursor: pointer;
|
|
||||||
transition:
|
|
||||||
background var(--duration-fast) var(--ease-default),
|
|
||||||
border-color var(--duration-fast) var(--ease-default),
|
|
||||||
color var(--duration-fast) var(--ease-default);
|
|
||||||
}
|
|
||||||
|
|
||||||
.picker-footer-button[data-tone='ghost']:hover {
|
|
||||||
background: var(--color-surface-overlay);
|
|
||||||
}
|
|
||||||
|
|
||||||
.picker-footer-button[data-tone='solid'] {
|
|
||||||
border-color: var(--color-primary-border);
|
|
||||||
background: var(--color-primary-solid);
|
|
||||||
color: var(--color-content-on-solid);
|
|
||||||
}
|
|
||||||
|
|
||||||
.picker-footer-button[data-tone='solid']:hover {
|
|
||||||
background: var(--color-primary-solid-hover);
|
|
||||||
}
|
|
||||||
|
|
||||||
.picker-footer-button:focus-visible {
|
|
||||||
outline: var(--focus-ring-width) solid var(--color-primary-border);
|
|
||||||
outline-offset: var(--focus-ring-offset);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
Loading…
Reference in new issue