Inspector Date

Settings row for a date, a time, or both: the row reads the value the way anyone would write it down and opens a real month calendar, while a time on its own keeps the platform's own field inline, since a time has no month to show.

Installation

Adds the component and everything it depends on to your project.

npx shadcn add https://ui.beste.co/component/r-base/inspector-date

New here? Read the installation guide.

Usage

The import and the props worth knowing about, in one place.

import { InspectorDate } from "@/components/beste/component/inspector-date";

// Uncontrolled. The value is the format the platform uses, which is also what a
// form submits and what new Date() parses.
<InspectorDate label="Publish on" defaultValue="2026-08-01" />

// Controlled
<InspectorDate label="Publish on" value={date} onValueChange={setDate} />

// A time, or both at once
<InspectorDate label="Opens at" mode="time" value={time} onValueChange={setTime} />
<InspectorDate label="Starts" mode="datetime" value={start} onValueChange={setStart} />

<InspectorDate
  label="Deadline"
  icon={CalendarClockIcon}  // optional leading icon; the mode brings its own
  tone="outline"            // "muted" (default) | "outline" | "ghost"
  size="sm"                 // "sm" | "default" | "lg"
  mode="datetime"
  min="2026-01-01T00:00"    // in the same format as the value
  max="2026-12-31T23:59"
  step={900}                // granularity in seconds
  name="deadline"           // takes part in a form
  required
  value={deadline}
  onValueChange={setDeadline}
/>

// The row's reading is deterministic on purpose, so the server and the browser
// agree on it. Bring your own locale where it can only run in one place:
<InspectorDate
  label="Publish on"
  value={date}
  onValueChange={setDate}
  formatValue={(iso) => new Date(iso).toLocaleDateString("tr-TR", { dateStyle: "long" })}
/>

// A clear button inside the panel, and a week that starts on Monday
<InspectorDate label="Publish on" clearable weekStartsOn={1} value={date} onValueChange={setDate} />

// The value is what a form submits, what `new Date()` parses, and what comes back
// out, and the calendar never turns it into anything else. Parsing is deliberately not
// `new Date("2026-08-01")`: a bare date string is read as UTC midnight, which is the
// evening before anywhere west of Greenwich.

Playground

Turn the props on the right; the snippet under them is what you would write to get what you see.

Usage
import { InspectorDate } from "@/components/beste/component/inspector-date";

<InspectorDate
  label="Publish on"
  className="w-72"
  defaultValue="2026-08-01"
  clearable
/>

Props

Read from the component's own type, so this cannot drift from what it accepts.

PropTypeDefaultDescription
label*stringLabel rendered on the left, inside the row.
iconLucideIconOptional leading icon shown before the label. Defaults to the mode's own.
valuestringControlled value, in the format the platform uses: `2026-07-25` for a date, `14:30` for a time, `2026-07-25T14:30` for both. That is also what a form submits and what `new Date()` parses, so nothing has to be converted twice.
defaultValuestringInitial value in uncontrolled mode.
onValueChange(value: string) => voidFires whenever a day is picked, a time typed, or the value cleared.
onOpenChange(open: boolean) => voidFires when the calendar opens or closes.
mode"date" | "time" | "datetime""date"What is being picked.
minstringEarliest allowed value, in the same format.
maxstringLatest allowed value, in the same format.
stepnumberGranularity in seconds, for the time half.
formatValue(value: string) => stringHow the value reads on the row. Use it to bring your own locale, which is the one thing this cannot do for you without guessing where it is running.
emptyLabelstringWhat the row reads while there is no value.
clearablebooleanOffer a button that clears the value.
weekStartsOn0 | 1 | 2 | 3 | 4 | 5 | 6Which day starts the week: 0 is Sunday, 1 is Monday.
disabledbooleanBlock interaction and dim the row.
readOnlybooleanShow the value but refuse edits.
tone"muted" | "outline" | "ghost""muted"Surface treatment: filled (default), hairline outline, or bare until hover.
size"sm" | "default" | "lg""default"Row height preset.
namestringName of the field, so the row can take part in a form.
idstringId of the field. One is generated when it is left out.
classNamestring
aria-labelstringAccessible name. Falls back to `label`.

More Inspector components

View all Inspector

Inspector Aspect

Settings row for a ratio: the row prints it and draws it, and opens an editor with the ratios worth a name plus both sides always editable. It is kept as two numbers rather than as their quotient, since 16:9 is what a reader recognises.

Inspector Input

Settings row with a label on the left and a plain text field on the right, sharing the family's pill: the whole row is the label, so pressing anywhere puts the caret in the field.

Inspector Range

Settings row for a span rather than a value: two thumbs on the row itself, the band between them filling it, and both ends of the pair read out on the right. Ticks, tones and thumb states follow inspector-slider exactly, appearing on hover.

Inspector Border

Settings row for a border: the row draws one exactly as described beside a summary of it, and opens an editor with the sides as icon toggles and the width, style and colour under them, each one a row of the family.

px

Inspector Dimensions

Width and height on one row, with the lock between them: while it is closed, editing one scales the other by the ratio the pair had when the lock closed. Both fields are as wide as the largest number they can hold, so typing never shifts the row.

Dark Mode

Inspector Segmented

Settings row whose choices sit side by side on the right, with a marker that slides between them: the readable alternative to a switch when the two states deserve names, and the compact one to a select at three or four options.