Inkbox

Component

Date Picker

The select trigger with a calendar glyph that opens the calendar in a white panel, for one date or a range, with optional presets.

npx -y github:anwarlemu/inkbox-brand-cli#release add date-picker
Preview
Range
Presets
States

Usage

Use DatePicker for one date (a key's expiry, when to send) and DateRangePicker for a period (the delivery log's range). Pass value and onValueChange, a placeholder, and presets for common choices (Today, Last 7 days). Pass calendar props such as disabled days through calendar. Give it a name to submit the date as YYYY-MM-DD with a form.

Avoid

  • A text field people must type a date into
  • A range picker for a single date
  • More than six presets
  • Closing a range before both ends are picked

Exports: DatePicker, DateRangePicker, formatDate, formatRange, DatePickerProps, DateRangePickerProps. This component is a client component.

Dependencies: calendar, popover, @phosphor-icons/react.

Example

examples/date-picker.tsx
"use client";​import * as React from "react";​import type { DateRange } from "@/components/ui/calendar";import { DatePicker, DateRangePicker } from "@/components/ui/date-picker";import { Label } from "@/components/ui/label";​// A fixed today, so the examples read the same on every visit.const TODAY = new Date(2026, 7, 8);const days = (n: number) => new Date(TODAY.getFullYear(), TODAY.getMonth(), TODAY.getDate() + n);​export function Preview() {  const [date, setDate] = React.useState<Date | undefined>();  return (    <div className="grid w-full max-w-72 gap-1">      <Label htmlFor="expires">Key expires</Label>      <DatePicker id="expires" value={date} onValueChange={setDate} placeholder="Never" calendar={{ today: TODAY, disabled: { before: TODAY } }} />    </div>  );}​export function Range() {  const [range, setRange] = React.useState<DateRange | undefined>({ from: days(-6), to: TODAY });  return (    <div className="grid w-full max-w-80 gap-1">      <Label htmlFor="log-range">Delivery log</Label>      <DateRangePicker id="log-range" value={range} onValueChange={setRange} calendar={{ today: TODAY, disabled: { after: TODAY } }} />    </div>  );}​export function Presets() {  const [send, setSend] = React.useState<Date | undefined>(days(1));  const [range, setRange] = React.useState<DateRange | undefined>();  return (    <div className="grid w-full max-w-80 gap-4">      <div className="grid gap-1">        <Label htmlFor="send-at">Send the summary on</Label>        <DatePicker          id="send-at"          value={send}          onValueChange={setSend}          calendar={{ today: TODAY, disabled: { before: TODAY } }}          presets={[            { label: "Today", value: TODAY },            { label: "Tomorrow", value: days(1) },            { label: "In a week", value: days(7) },            { label: "In a month", value: days(30) },          ]}        />      </div>      <div className="grid gap-1">        <Label htmlFor="usage-range">Usage</Label>        <DateRangePicker          id="usage-range"          value={range}          onValueChange={setRange}          placeholder="All time"          calendar={{ today: TODAY, disabled: { after: TODAY } }}          presets={[            { label: "Last 7 days", value: { from: days(-6), to: TODAY } },            { label: "Last 30 days", value: { from: days(-29), to: TODAY } },            { label: "Last 90 days", value: { from: days(-89), to: TODAY } },          ]}        />      </div>    </div>  );}​export function States() {  return (    <div className="grid w-full max-w-72 gap-3">      <DatePicker aria-label="Disabled date" defaultValue={TODAY} disabled />      <div className="grid gap-1">        <DatePicker aria-label="Start date" aria-invalid calendar={{ today: TODAY }} />        <p className="text-caption leading-body text-danger">Choose a start date.</p>      </div>    </div>  );}

Source

components/ui/date-picker.tsx
"use client";​import * as React from "react";import { CalendarBlankIcon, CaretDownIcon } from "@phosphor-icons/react/ssr";​import { Calendar, type CalendarProps, type DateRange } from "@/components/ui/calendar";import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";import { cn } from "@/lib/utils";​// A date field (extrapolated from the Inkbox console, Figma 427:2715: the select trigger "Any State" and its menu// panel). The trigger is the select's white 40px key with 8px corners and the Shadow/S ring: a 24px calendar glyph in// the softer purple, the date in 14px ink (the placeholder in the light purple) and the bold caret at the right. The// calendar opens under it in the popover's white panel, growing from the trigger. Presets sit in a column of 36px rows// at the panel's left, the chosen one on the lilac. A single date closes the panel when picked; a range closes once both// ends are set. Opening puts focus on the chosen day (or today), so the arrow keys work at once.const TRIGGER =  "flex h-10 w-full min-w-0 cursor-pointer items-center gap-2.5 rounded-control bg-surface pr-3 pl-3 font-sans text-body leading-tight whitespace-nowrap text-fg shadow-s outline-none transition-[box-shadow] duration-150 ease-out focus-visible:shadow-[var(--ds-shadow-s),var(--ds-shadow-focus)] disabled:cursor-not-allowed disabled:bg-subtle disabled:text-fg-muted aria-invalid:shadow-[0_0_0_1px_var(--ds-color-status-danger)] data-[empty=true]:text-fg-subtle motion-reduce:transition-none";​type Preset<T> = { label: string; value: T };​function formatDate(date: Date, locale?: string, options: Intl.DateTimeFormatOptions = { month: "short", day: "numeric", year: "numeric" }) {  return new Intl.DateTimeFormat(locale, options).format(date);}​function formatRange(range: DateRange | undefined, locale?: string) {  if (!range?.from) return undefined;  if (!range.to) return `${formatDate(range.from, locale)} -`;  const sameYear = range.from.getFullYear() === range.to.getFullYear();  return `${formatDate(range.from, locale, sameYear ? { month: "short", day: "numeric" } : undefined)} - ${formatDate(range.to, locale)}`;}​function DatePickerTrigger({ empty, label, className, children, ...props }: React.ComponentProps<"button"> & { empty: boolean; label?: string }) {  return (    <PopoverTrigger asChild>      <button type="button" data-slot="date-picker-trigger" data-empty={empty} aria-label={label} className={cn(TRIGGER, className)} {...props}>        <CalendarBlankIcon aria-hidden weight="fill" className="size-6 shrink-0 text-icon-secondary" />        <span className="min-w-0 flex-1 truncate text-left">{children}</span>        <CaretDownIcon aria-hidden weight="bold" className="size-4 shrink-0 text-fg" />      </button>    </PopoverTrigger>  );}​function Presets<T>({ presets, isActive, onPick }: { presets: Preset<T>[]; isActive: (p: Preset<T>) => boolean; onPick: (value: T) => void }) {  return (    <div data-slot="date-picker-presets" role="group" aria-label="Presets" className="flex gap-1 overflow-x-auto border-line-subtle p-1 max-sm:border-b sm:w-40 sm:flex-col sm:border-r">      {presets.map((p) => (        <button          key={p.label}          type="button"          aria-pressed={isActive(p)}          onClick={() => onPick(p.value)}          className="flex h-9 shrink-0 items-center rounded-control px-2.5 text-left font-sans text-body leading-tight whitespace-nowrap text-fg outline-none transition-colors duration-150 ease-out hover:bg-subtle focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-focus-ring aria-pressed:bg-subtle aria-pressed:font-medium motion-reduce:transition-none"        >          {p.label}        </button>      ))}    </div>  );}​const sameDay = (a?: Date, b?: Date) => !!a && !!b && a.toDateString() === b.toDateString();​type CalendarPassThrough = Omit<CalendarProps, "mode" | "selected" | "onSelect" | "required" | "min" | "max">;​type DatePickerProps = {  value?: Date;  defaultValue?: Date;  onValueChange?: (date: Date | undefined) => void;  placeholder?: string;  disabled?: boolean;  /** Shortcuts beside the calendar (Today, In a week). */  presets?: Preset<Date>[];  /** Props for the calendar inside (disabled days, the first day of the week, today). */  calendar?: CalendarPassThrough;  locale?: string;  id?: string;  name?: string;  className?: string;  "aria-invalid"?: boolean;  "aria-label"?: string;};​function DatePicker({ value: valueProp, defaultValue, onValueChange, placeholder = "Pick a date", disabled, presets, calendar, locale, id, name, className, ...aria }: DatePickerProps) {  const [open, setOpen] = React.useState(false);  const [inner, setInner] = React.useState(defaultValue);  const value = valueProp !== undefined ? valueProp : inner;  const set = (d: Date | undefined) => {    if (valueProp === undefined) setInner(d);    onValueChange?.(d);  };  return (    <Popover open={open} onOpenChange={setOpen}>      <DatePickerTrigger id={id} empty={!value} disabled={disabled} className={className} aria-invalid={aria["aria-invalid"]} label={aria["aria-label"]}>        {value ? formatDate(value, locale) : placeholder}      </DatePickerTrigger>      {name && <input type="hidden" name={name} value={value ? value.toISOString().slice(0, 10) : ""} />}      <PopoverContent data-slot="date-picker-content" align="start" onOpenAutoFocus={(e) => e.preventDefault()} className="w-auto gap-0 overflow-hidden p-0">        <div className="flex flex-col sm:flex-row">          {presets && (            <Presets              presets={presets}              isActive={(p) => sameDay(p.value, value)}              onPick={(d) => {                set(d);                setOpen(false);              }}            />          )}          <Calendar            {...calendar}            mode="single"            selected={value}            defaultMonth={value ?? calendar?.defaultMonth}            locale={locale}            autoFocus            onSelect={(d) => {              set(d);              if (d) setOpen(false);            }}          />        </div>      </PopoverContent>    </Popover>  );}​type DateRangePickerProps = Omit<DatePickerProps, "value" | "defaultValue" | "onValueChange" | "presets"> & {  value?: DateRange;  defaultValue?: DateRange;  onValueChange?: (range: DateRange | undefined) => void;  presets?: Preset<DateRange>[];  /** How many months show side by side (two by default; one on a phone). */  numberOfMonths?: number;};​function DateRangePicker({ value: valueProp, defaultValue, onValueChange, placeholder = "Pick a date range", disabled, presets, calendar, locale, numberOfMonths = 2, id, name, className, ...aria }: DateRangePickerProps) {  const [open, setOpen] = React.useState(false);  const [inner, setInner] = React.useState(defaultValue);  const value = valueProp !== undefined ? valueProp : inner;  const set = (r: DateRange | undefined) => {    if (valueProp === undefined) setInner(r);    onValueChange?.(r);  };  const [narrow, setNarrow] = React.useState(false);  React.useEffect(() => {    const query = window.matchMedia("(max-width: 39.99rem)");    const update = () => setNarrow(query.matches);    update();    query.addEventListener("change", update);    return () => query.removeEventListener("change", update);  }, []);  const label = formatRange(value, locale);  return (    <Popover open={open} onOpenChange={setOpen}>      <DatePickerTrigger id={id} empty={!label} disabled={disabled} className={className} aria-invalid={aria["aria-invalid"]} label={aria["aria-label"]}>        {label ?? placeholder}      </DatePickerTrigger>      {name && (        <>          <input type="hidden" name={`${name}From`} value={value?.from ? value.from.toISOString().slice(0, 10) : ""} />          <input type="hidden" name={`${name}To`} value={value?.to ? value.to.toISOString().slice(0, 10) : ""} />        </>      )}      <PopoverContent data-slot="date-range-picker-content" align="start" onOpenAutoFocus={(e) => e.preventDefault()} className="w-auto max-w-[calc(100vw-2rem)] gap-0 overflow-hidden p-0">        <div className="flex flex-col sm:flex-row">          {presets && (            <Presets              presets={presets}              isActive={(p) => sameDay(p.value.from, value?.from) && sameDay(p.value.to, value?.to)}              onPick={(r) => {                set(r);                setOpen(false);              }}            />          )}          <Calendar            {...calendar}            mode="range"            selected={value}            defaultMonth={value?.from ?? calendar?.defaultMonth}            numberOfMonths={narrow ? 1 : numberOfMonths}            locale={locale}            autoFocus            onSelect={(r) => {              set(r);              if (r?.from && r.to) setOpen(false);            }}          />        </div>      </PopoverContent>    </Popover>  );}​export { DatePicker, DateRangePicker, formatDate, formatRange };export type { DatePickerProps, DateRangePickerProps };

Reference: Extrapolated from the Inkbox console (Figma 427:2715): the select trigger (Any State) and the menu panel, with the calendar.