# DatePicker

> A field that opens a floating month grid, with full keyboard navigation (arrow keys across days, Page Up/Down across months, Shift for years), min/max and per-day disabling, and a fully localized accessible name on every day cell.

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

## Import

```svelte
<script lang="ts">
  import { DatePicker } 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 { DatePicker } from 'fancy-ui-react';` (same prop names; `class` becomes `className`, snippets become `ReactNode`).

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value` | `Date \| null` | `null` | The selected date; bindable. Always a local-midnight Date — see the README's time-zone note. |
| `onValueChange` | `(value: Date \| null) => void` | — | Called with the new value whenever a day is picked. |
| `min` | `Date` | — | Earliest selectable day (inclusive), compared at day granularity. |
| `max` | `Date` | — | Latest selectable day (inclusive), compared at day granularity. |
| `weekStartsOn` | `0 \| 1` | `1` | 0 for Sunday, 1 for Monday. |
| `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 value as YYYY-MM-DD. |
| `label` | `string` | — | Accessible name — for a control with no visible Label next to it. |
| `placeholder` | `string` | `"Pick a date"` | Shown in the trigger while no day is selected. |
| `locale` | `string` | — | BCP 47 locale for month, weekday, day and trigger-label formatting. |
| `isDateDisabled` | `(date: Date) => boolean` | — | Rejects individual days beyond min/max — e.g. weekends, holidays. |
| `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 day and close on a dismissal, once the user has enabled sound |

## Examples

### Basic Usage

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

	let selected = $state<Date | null>(null);
</script>

<DatePicker sound bind:value={selected} label="Date" />
```

### With Bounds

Restricted to a 30-day window starting today.

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

	let selected = $state<Date | null>(null);

	const today = new Date();
	const min = new Date(today.getFullYear(), today.getMonth(), today.getDate());
	const max = new Date(today.getFullYear(), today.getMonth() + 1, today.getDate());
</script>

<DatePicker
	sound
	bind:value={selected}
	{min}
	{max}
	label="Appointment date"
	placeholder="Within the next 30 days"
/>
```

### Disabled Dates

Weekends rejected via isDateDisabled.

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

	let selected = $state<Date | null>(null);

	function isWeekend(date: Date): boolean {
		const day = date.getDay();
		return day === 0 || day === 6;
	}
</script>

<DatePicker
	sound
	bind:value={selected}
	isDateDisabled={isWeekend}
	label="Delivery date"
	placeholder="Weekdays only"
/>
```

### With FormField

Wrapped in FormField — required and the error message driven by context.

```svelte
<script lang="ts">
	// FormField renders its own internal Label from the `label` prop below and
	// derives invalid state from whether `error` is set — it supplies
	// controlId, aria-describedby and aria-invalid to DatePicker through
	// context, so DatePicker itself needs no id or invalid prop here.
	import { FormField } from "fancy-ui-svelte";
	import { DatePicker } from "fancy-ui-svelte";

	let deadline = $state<Date | null>(null);
</script>

<FormField
	label="Deadline"
	required
	error={deadline ? undefined : "Pick a deadline before continuing."}
	class="w-full max-w-sm"
>
	<DatePicker sound bind:value={deadline} />
</FormField>
```
