Skip to content
Open
14 changes: 14 additions & 0 deletions .changeset/regional-dates-show-day-of-week.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
"@tailor-platform/app-shell": minor
---

Add `dateFormat` and `showDayOfWeek` to `DateField`, `DatePicker`, and `DateRangePicker`, plus an app-wide default on `AppShell` via `dateInputDateFormat`.

- `dateFormat="regional"` lays the segments out in the locale's written business form wherever that form keeps the month numeric — `2025年12月19日` for ja / zh, `2025년 12월 19일` for ko. Locales whose written form spells the month as a word (en, de, fr, …) stay numeric, so a single app-wide setting is safe for multi-locale apps. The default remains `"numeric"`, so existing screens are unchanged. The default is planned to become `"regional"` in a future major release; set `"numeric"` explicitly to keep the numeric layout across that upgrade.
- `showDayOfWeek` appends the locale's short day of the week (`2025年12月19日(金)`, `Fri, 12/19/2025`). It is read-only, derived from the entered date, holds the previous day of the week while a date segment is mid-entry (so typing `25` never flashes the 2nd's), and is announced to screen readers with each date segment's value.

```tsx
<AppShell dateInputDateFormat="regional" modules={modules} />

<DatePicker aria-label="Closing date" showDayOfWeek />
```
16 changes: 8 additions & 8 deletions docs-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,10 @@
"claims": [],
"symbols": ["AppShell", "AppShellProps"],
"hashes": {
"typeSurface": "51313066e142afc2",
"outline": "05d3544ec249692f",
"typeSurface": "eb9f3d56e647a63e",
"outline": "bc57fd4f036b1ab3",
"snapshot": null,
"outputMd": "081e4c7bb61db191",
"outputMd": "aa2cbe86153db2a0",
"examples": null
}
},
Expand Down Expand Up @@ -470,10 +470,10 @@
"DateRangePickerProps"
],
"hashes": {
"typeSurface": "6b07d4169fa991df",
"outline": "caab56e5766bdb72",
"typeSurface": "97f771503044256f",
"outline": "d1009e13680a1f70",
"snapshot": null,
"outputMd": "f39002ad79625dc4",
"outputMd": "4ef526c25046a94e",
"examples": null
}
},
Expand Down Expand Up @@ -1664,7 +1664,7 @@
"packages/core/skills/app-shell-patterns/references/components/activity-card.md": "4f386e49380fb0b0",
"packages/core/skills/app-shell-patterns/references/components/ai-chat.md": "824d1aa36bb7f194",
"packages/core/skills/app-shell-patterns/references/components/alert.md": "db2c4388ca783a75",
"packages/core/skills/app-shell-patterns/references/components/app-shell.md": "081e4c7bb61db191",
"packages/core/skills/app-shell-patterns/references/components/app-shell.md": "aa2cbe86153db2a0",
"packages/core/skills/app-shell-patterns/references/components/appearance-switcher.md": "b55f1d538651d467",
"packages/core/skills/app-shell-patterns/references/components/attachment.md": "35bebce540d6ac28",
"packages/core/skills/app-shell-patterns/references/components/autocomplete.md": "bd6ae01bf39d1ad6",
Expand All @@ -1677,7 +1677,7 @@
"packages/core/skills/app-shell-patterns/references/components/command-palette.md": "7e5bc675a593791a",
"packages/core/skills/app-shell-patterns/references/components/csv-importer.md": "53d3c795ca21b9dc",
"packages/core/skills/app-shell-patterns/references/components/data-table.md": "97ae28f7a98c5d97",
"packages/core/skills/app-shell-patterns/references/components/date-picker.md": "f39002ad79625dc4",
"packages/core/skills/app-shell-patterns/references/components/date-picker.md": "4ef526c25046a94e",
"packages/core/skills/app-shell-patterns/references/components/default-header.md": "375e55f4b12fa2be",
"packages/core/skills/app-shell-patterns/references/components/default-sidebar.md": "3422388a0cc78571",
"packages/core/skills/app-shell-patterns/references/components/description-card.md": "a347fd1f4ccd433e",
Expand Down
14 changes: 14 additions & 0 deletions docs-src/components/app-shell.docs.outline.md
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,20 @@ Supported locales: `en`, `ja`
</AppShell>
```

### dateInputDateFormat

- **Type:** `"numeric" | "regional"` (optional)
- **Default:** `"numeric"` (planned to become `"regional"` — see below)
- **Description:** Default segment layout for `DateField`, `DatePicker`, and `DateRangePicker`. `"numeric"` uses the locale's numeric form (`2025/12/19`). `"regional"` uses the locale's written business form where it keeps the month numeric (`2025年12月19日` for ja / zh, `2025년 12월 19일` for ko) and stays numeric for every other locale. Each component's own `dateFormat` prop overrides it.

```tsx
<AppShell dateInputDateFormat="regional" modules={modules}>
{/* ... */}
</AppShell>
```

> **Planned default change:** the default is planned to become `"regional"` in a future major release. Apps that want to keep the numeric layout should set `"numeric"` explicitly now; apps already on `"regional"` won't be affected.

Access the configured timezone in components using [`useTimeZone`](../api/use-time-zone.md).

### errorBoundary
Expand Down
70 changes: 47 additions & 23 deletions docs-src/components/date-picker.docs.outline.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,28 @@ Locale and timezone come from AppShell automatically. Override per field with `l
<DatePicker aria-label="Date" locale="ja-JP" />
```

### Date format

By default the segments follow the locale's **numeric** form (`2025/12/19` for ja-JP, `12/19/2025` for en-US). `dateFormat="regional"` switches to the locale's written business form wherever that form keeps the month numeric — `2025年12月19日` for ja / zh, `2025년 12월 19일` for ko. Locales whose written form spells the month as a word (en, de, fr, …) stay numeric, so one setting is safe for a multi-locale app.

Set it once for the whole app with `AppShell`'s `dateInputDateFormat`, or per field with `dateFormat` (the prop wins):

```tsx
<AppShell dateInputDateFormat="regional" modules={modules} />

<DatePicker aria-label="Date" dateFormat="numeric" />
```

> **Planned default change:** the default is planned to become `"regional"` in a future major release. Apps that want to keep the numeric layout should set `"numeric"` explicitly now; apps already on `"regional"` won't be affected.

### Day of the week

`showDayOfWeek` adds the locale's short day of the week where the locale places it — `2025年12月19日(金)` for ja-JP, `Fri, 12/19/2025` for en-US. It is read-only and derived from the entered date: it shows a placeholder until the date is complete, and while a date segment is mid-entry it keeps the previous day of the week (muted), so typing `25` into the day never flashes the 2nd's. Screen readers hear the full day name with each date segment's value.

```tsx
<DatePicker aria-label="Closing date" showDayOfWeek />
```

## Keyboard

- **Segments:** `↑`/`↓` increment/decrement, digits type-to-fill (auto-advance), `←`/`→` move between segments, `Backspace` clears, `/` commits the current segment and advances.
Expand All @@ -193,28 +215,30 @@ Locale and timezone come from AppShell automatically. Override per field with `l

### DateFieldProps

| Prop | Type | Description |
| -------------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------ |
| `value` / `defaultValue` | `DateValue \| null` | Controlled / uncontrolled value |
| `onChange` | `(v: DateValue \| null) => void` | Fires when the value changes |
| `onBlur` | `() => void` | Fires when focus leaves the whole segmented control |
| `minValue` / `maxValue` | `DateValue` | Inclusive date range bounds |
| `isDateUnavailable` | `(date: DateValue) => boolean` | Marks specific dates unavailable |
| `isDisabled` | `boolean` | Disables interaction and form submission |
| `isReadOnly` | `boolean` | Allows focus/navigation without editing |
| `isRequired` | `boolean` | Marks the control required |
| `isInvalid` | `boolean` | Adds invalid styling / `aria-invalid` to the segmented UI |
| `placeholderValue` | `DateValue` | Seeds unset segments |
| `granularity` | `"day" \| "hour" \| "minute" \| "second"` | Smallest editable unit; time granularities add time segments |
| `hourCycle` | `12 \| 24` | Force 12- or 24-hour time; defaults to the locale |
| `autoFocus` | `boolean` | Focus the first segment on mount |
| `locale` | `string` | BCP-47 locale override |
| `name` | `string` | Emits a form value through the proxy input |
| `id` | `string` | Proxy input id (use with external `<label htmlFor>`). |
| `firstDayOfWeek` | `"sun" \| "mon" \| "tue" \| "wed" \| "thu" \| "fri" \| "sat"` | Override the locale week start used by `w` / `k` shortcuts |
| `aria-label` / `aria-labelledby` | `string` | Accessible name |
| `aria-describedby` | `string` | IDs of description / error elements |
| `className` | `string` | Root element class |
| Prop | Type | Description |
| -------------------------------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| `value` / `defaultValue` | `DateValue \| null` | Controlled / uncontrolled value |
| `onChange` | `(v: DateValue \| null) => void` | Fires when the value changes |
| `onBlur` | `() => void` | Fires when focus leaves the whole segmented control |
| `minValue` / `maxValue` | `DateValue` | Inclusive date range bounds |
| `isDateUnavailable` | `(date: DateValue) => boolean` | Marks specific dates unavailable |
| `isDisabled` | `boolean` | Disables interaction and form submission |
| `isReadOnly` | `boolean` | Allows focus/navigation without editing |
| `isRequired` | `boolean` | Marks the control required |
| `isInvalid` | `boolean` | Adds invalid styling / `aria-invalid` to the segmented UI |
| `placeholderValue` | `DateValue` | Seeds unset segments |
| `granularity` | `"day" \| "hour" \| "minute" \| "second"` | Smallest editable unit; time granularities add time segments |
| `hourCycle` | `12 \| 24` | Force 12- or 24-hour time; defaults to the locale |
| `autoFocus` | `boolean` | Focus the first segment on mount |
| `locale` | `string` | BCP-47 locale override |
| `dateFormat` | `"numeric" \| "regional"` | Segment layout; defaults to the `AppShell` `dateInputDateFormat` (`"numeric"`; planned to become `"regional"`) |
| `showDayOfWeek` | `boolean` | Show the locale's short day of the week next to the date |
| `name` | `string` | Emits a form value through the proxy input |
| `id` | `string` | Proxy input id (use with external `<label htmlFor>`). |
| `firstDayOfWeek` | `"sun" \| "mon" \| "tue" \| "wed" \| "thu" \| "fri" \| "sat"` | Override the locale week start used by `w` / `k` shortcuts |
| `aria-label` / `aria-labelledby` | `string` | Accessible name |
| `aria-describedby` | `string` | IDs of description / error elements |
| `className` | `string` | Root element class |

### DatePickerProps

Expand All @@ -231,7 +255,7 @@ See the calendar docs in-code: controlled/uncontrolled value, min/max, unavailab

### DateRangePickerProps

The `DatePickerProps` surface (labeling, `isInvalid`, `min/maxValue`, `isDateUnavailable`, `granularity`, `hourCycle`, `firstDayOfWeek`, `timeZone`, `locale`, `autoFocus`, `isDisabled/ReadOnly/Required`), with the range-specific differences:
The `DatePickerProps` surface (labeling, `isInvalid`, `min/maxValue`, `isDateUnavailable`, `granularity`, `hourCycle`, `firstDayOfWeek`, `timeZone`, `locale`, `dateFormat`, `showDayOfWeek`, `autoFocus`, `isDisabled/ReadOnly/Required`), with the range-specific differences:

| Prop | Type | Description |
| ------------------------ | -------------------------------- | ------------------------------------------------------------------------------- |
Expand Down
14 changes: 14 additions & 0 deletions docs/components/app-shell.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading