{
  "name": "TimeField",
  "source": "src/components/TimeField.tsx",
  "propsType": "TimeFieldProps",
  "description": "TimeField — a time of day, typed into segments.\n\nDatePicker's text half, for times: hour, minute and, where the locale uses\none, AM/PM — each a spinbutton that takes digits or arrow keys. The order,\nthe separator and the 12 or 24-hour clock come from the reader's locale, so\n\"2:30 PM\" and \"14:30\" are the same field and the same value.\n\nWHY NOT A TEXT INPUT OR `<input type=\"time\">`\n\nFree text means guessing whether \"2:30\" is afternoon. The native control\ncannot be styled to match the other fields, and Safari's has no picker at\nall. Segments cannot hold a time that does not exist, and every browser\ndraws them the same.\n\nNo dropdown of times. A list of 96 quarter-hours is slower to scan than two\ndigits are to type, and it makes 09:07 impossible. Where only a few times\nare allowed, that is a Select, not a TimeField.",
  "import": "import { TimeField } from 'ionbase-ui';",
  "status": "stable",
  "since": "0.80.0",
  "summary": "A time of day typed into hour, minute and AM/PM segments in the reader's own format, taking and returning a 24-hour HH:MM string.",
  "useWhen": [
    "the user sets a time of day — a schedule, a reminder, the start of a window",
    "any minute is allowed, so a list of choices would be long or would leave times out",
    "beside a DatePicker only when the time is a separate, optional choice — a due date with an optional reminder time"
  ],
  "useInstead": [
    {
      "when": "the value is a date and a time — one moment, such as when a run starts",
      "use": "DateTimePicker",
      "why": "one field holds both and checks a bound such as \"not before now\" against the date and the time together; a TimeField beside a DatePicker leaves that rule to the caller"
    },
    {
      "when": "only a handful of times are allowed — delivery slots, office hours",
      "use": "Select",
      "why": "picking from four slots is a choice from a list, and a field that accepts any minute invites times the product will refuse"
    },
    {
      "when": "the value is a duration — 30 minutes, 2 hours",
      "use": "NumberInput",
      "why": "a duration is an amount, not a time of day; 02:00 as a length reads as two in the morning"
    },
    {
      "when": "the value is a calendar date",
      "use": "DatePicker"
    }
  ],
  "variants": {
    "size": {
      "sm": {
        "use": "dense forms, table filters"
      },
      "md": {
        "use": "the default"
      },
      "lg": {
        "use": "prominent single-field forms"
      }
    },
    "granularity": {
      "hour": {
        "use": "on-the-hour schedules — the minute segment is not shown"
      },
      "minute": {
        "use": "the default — almost every time of day a person sets"
      },
      "second": {
        "use": "logs and precise triggers; the value becomes HH:MM:SS"
      }
    }
  },
  "a11y": {
    "guarantees": [
      "each segment is a spinbutton that announces its own name, value and bounds — 'hour, 2, minimum 1, maximum 12' — and takes digits or arrow keys",
      "each editable segment is its own tab stop, like DatePicker and the native time input; the separator is not",
      "the 12 or 24-hour clock, the separator and the AM/PM wording come from the reader's locale, so '2:30 PM' and '14:30' are the same field and the same value",
      "the segments sit in one labelled group, so the name is announced once on entry",
      "a time that does not exist cannot be typed",
      "a time outside `minValue`/`maxValue` turns the field invalid and names the bound in the reader's own format, without `isInvalid` — the value is kept, not silently clamped"
    ],
    "requires": [
      "`label`, or `aria-label` when no visible label is rendered",
      "a `description` saying which timezone the time is in, whenever the reader could be in a different one from the thing being scheduled"
    ],
    "notes": [
      "`value` is a wall-clock time with no date and no zone. Keep the timezone as its own field or setting; a time pinned to a `Date` drifts an hour at every daylight-saving change.",
      "The clock icon is decorative. There is no dropdown of times: two digits are faster to type than 96 quarter-hours are to scan, and a list makes 09:07 impossible."
    ]
  },
  "antiPatterns": [
    {
      "dont": "passing a Date, a timestamp or a locale-formatted string such as \"2:30 PM\" as `value`",
      "why": "the value is 24-hour HH:MM. A malformed value throws with the prop name rather than rendering an empty field"
    },
    {
      "dont": "forcing `hourCycle={12}` for everyone",
      "why": "a reader whose locale uses 24 hours has to translate every value, which is the misreading the segments exist to prevent. Leave it to the locale"
    },
    {
      "dont": "a schedule time with no timezone anywhere on the form",
      "why": "\"09:00\" is nine o'clock somewhere; if the reader and the workspace are in different zones, they will each assume their own"
    },
    {
      "dont": "using `minValue` and `maxValue` for a window that crosses midnight",
      "why": "22:00 to 02:00 has a minimum later than its maximum, so every time is refused; validate the window yourself and set `isInvalid`"
    }
  ],
  "stylesheet": "src/styles/time-field.css",
  "tokens": [],
  "props": {
    "label": {
      "type": "React.ReactNode",
      "required": false,
      "origin": "own",
      "description": "Field label. Required for a usable control — see `a11y.requires`."
    },
    "aria-label": {
      "type": "string | undefined",
      "required": false,
      "origin": "own",
      "description": "Names the field when there is no visible `label`."
    },
    "description": {
      "type": "React.ReactNode",
      "required": false,
      "origin": "own",
      "description": "Helper text below the field — \"In the workspace's timezone\"."
    },
    "errorMessage": {
      "type": "React.ReactNode",
      "required": false,
      "origin": "own",
      "description": "Replaces the helper text while the field is invalid — `isInvalid`, or its own bounds check."
    },
    "isInvalid": {
      "type": "boolean | undefined",
      "required": false,
      "origin": "own"
    },
    "isDisabled": {
      "type": "boolean | undefined",
      "required": false,
      "origin": "own"
    },
    "isReadOnly": {
      "type": "boolean | undefined",
      "required": false,
      "origin": "own"
    },
    "isRequired": {
      "type": "boolean | undefined",
      "required": false,
      "origin": "own"
    },
    "size": {
      "type": "TimeFieldSize | undefined",
      "required": false,
      "origin": "own",
      "description": "Matches Input's `Size` variant: Small, Medium, Large.",
      "values": [
        "sm",
        "md",
        "lg"
      ]
    },
    "value": {
      "type": "string | null | undefined",
      "required": false,
      "origin": "own",
      "description": "The time as `HH:MM` (or `HH:MM:SS`), 24-hour, whatever the reader sees.\n`null` means no time is chosen. A wall-clock reading — no date, no\ntimezone. A malformed value throws rather than rendering an empty field."
    },
    "defaultValue": {
      "type": "string | undefined",
      "required": false,
      "origin": "own",
      "description": "The initial time, for an uncontrolled field."
    },
    "onChange": {
      "type": "((value: IsoTime | null) => void) | undefined",
      "required": false,
      "origin": "own",
      "description": "Fires with `HH:MM` (`HH:MM:SS` at second granularity), or `null` when cleared."
    },
    "minValue": {
      "type": "string | undefined",
      "required": false,
      "origin": "own",
      "description": "Earliest allowed time, `HH:MM`. Later is not wrapped past midnight."
    },
    "maxValue": {
      "type": "string | undefined",
      "required": false,
      "origin": "own",
      "description": "Latest allowed time, `HH:MM`."
    },
    "granularity": {
      "type": "TimeFieldGranularity | undefined",
      "required": false,
      "origin": "own",
      "description": "Defaults to `minute`. `second` adds a seconds segment and value.",
      "values": [
        "minute",
        "second",
        "hour"
      ]
    },
    "hourCycle": {
      "type": "12 | 24 | undefined",
      "required": false,
      "origin": "own",
      "description": "12 or 24-hour display. Leave it out: the reader's locale already knows,\nand forcing 12-hour on a 24-hour reader is the misreading this field\nexists to prevent. The value is 24-hour either way."
    },
    "name": {
      "type": "string | undefined",
      "required": false,
      "origin": "own",
      "description": "Posts the value under this name, for an uncontrolled form."
    },
    "className": {
      "type": "string | undefined",
      "required": false,
      "origin": "own"
    },
    "wrapperClassName": {
      "type": "string | undefined",
      "required": false,
      "origin": "own"
    },
    "id": {
      "type": "string | undefined",
      "required": false,
      "origin": "own"
    }
  },
  "propCounts": {
    "own": 20,
    "aria": 0,
    "dom": 0,
    "other": 0
  }
}
