# TimePicker

> A field that opens a floating listbox of time slots generated at a configurable step, fully keyboard-navigable, with the highlighted slot always scrolled into view.

- Package: `fancy-ui-svelte` (Svelte 5 + Tailwind CSS v4)
- Category: Forms
- Tags: time-picker, listbox, combobox, form, time, accessibility
- Docs: https://fancy-ui.rama.app/docs/components/time-picker
- Source: https://github.com/RamaHerbin/fancy-ui/tree/main/src/lib/fancy-ui/time-picker

## Import

```svelte
<script lang="ts">
  import { TimePicker } from 'fancy-ui-svelte';
</script>
```

Setup (once per project): `npm install fancy-ui-svelte`, then add `@import "fancy-ui-svelte/tailwind.css";` after `@import "tailwindcss";` in your main CSS file. Full guide: https://fancy-ui.rama.app/llms.txt

React: `import { TimePicker } from 'fancy-ui-react';` (same prop names; `class` becomes `className`, snippets become `ReactNode`).

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value` | `string \| null` | `null` | The selected time, "HH:mm" 24-hour; bindable. hour12 changes display only. |
| `onValueChange` | `(value: string \| null) => void` | — | Called with the new value whenever a slot is picked. |
| `step` | `number` | `30` | Minutes between generated slots. |
| `min` | `string` | — | Earliest selectable slot ("HH:mm", inclusive). |
| `max` | `string` | — | Latest selectable slot ("HH:mm", inclusive). |
| `hour12` | `boolean` | `false` | Display only — 12-hour clock with AM/PM. The value stays HH:mm either way. |
| `disabled` | `boolean` | `false` | Blocks opening the panel; excludes the control from form submission. |
| `required` | `boolean` | `false` | Marks the field required for the surrounding form. |
| `invalid` | `boolean` | `false` | Drives the error border and aria-invalid. |
| `id` | `string` | — | Element id. |
| `name` | `string` | — | Native name. When set, a hidden input carries the HH:mm value. |
| `label` | `string` | — | Accessible name — for a control with no visible Label next to it. |
| `placeholder` | `string` | `"Select a time"` | Shown in the trigger while no time is selected. |
| `locale` | `string` | — | BCP 47 locale for slot and trigger-label formatting. |
| `class` | `string` | — | Additional CSS classes, merged onto the trigger button. |
| `ref` | `HTMLButtonElement \| null` | `null` | Bindable reference to the trigger button. |
| `sound` | `boolean` | `false` | Plays open on opening, select on a picked slot and close on a dismissal, once the user has enabled sound |

## Examples

### Basic Usage

```svelte
<script lang="ts">
	import { TimePicker } from "fancy-ui-svelte";

	let time = $state<string | null>(null);
</script>

<TimePicker sound bind:value={time} label="Time" />
```

### Custom Step

15-minute slots instead of the default 30.

```svelte
<script lang="ts">
	import { TimePicker } from "fancy-ui-svelte";

	let time = $state<string | null>(null);
</script>

<TimePicker
	sound
	bind:value={time}
	step={15}
	label="Appointment slot"
	placeholder="15-minute slots"
/>
```

### With Bounds

Restricted to business hours, 09:00 to 17:00.

```svelte
<script lang="ts">
	import { TimePicker } from "fancy-ui-svelte";

	let time = $state<string | null>(null);
</script>

<TimePicker
	sound
	bind:value={time}
	min="09:00"
	max="17:00"
	label="Meeting time"
	placeholder="Business hours only"
/>
```
