Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -1681,7 +1681,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 @@ -1694,7 +1694,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": "3e8474e4d1437c91",
"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