{
  "name": "Calendar",
  "source": "src/components/Calendar.tsx",
  "propsType": "CalendarProps",
  "description": "Calendar — one month in the page, for a day chosen by looking at the month.\n\nDATEPICKER FIRST\n\nA date someone knows — a birthday, an invoice date — is typed faster than\nit is found, and a field takes one row where this takes a month. This is\nfor a day that is chosen by where it falls: a day to resume on, a delivery\nday, and for a place where a popover would be a second layer — a Modal, a\nSidePanel.\n\nNAMED WITH THE MONTH\n\n`label` is the calendar's name, joined by react-aria to the visible month —\n\"Resume on October 2026\" — so moving to another month says where you are.\nEvery day's name is its full date, in the reader's language; today and the\nselected day are said as such.",
  "import": "import { Calendar } from 'ionbase-ui';",
  "status": "stable",
  "summary": "One month in the page for a day chosen by where it falls — a day to resume on, a delivery day — taking and returning a YYYY-MM-DD string.",
  "useWhen": [
    "the day is chosen by looking at the month — which weekday, how far off — not recalled and typed",
    "the calendar would otherwise be a second layer: inside a Modal or a SidePanel, where a DatePicker's popover opens over a dialog",
    "the page has room for a month, and the day is the main question on it"
  ],
  "useInstead": [
    {
      "when": "a date the person knows — a birthday, an invoice date — or a form with other fields",
      "use": "DatePicker",
      "why": "typing a known date is faster than finding it, and a field takes one row where this takes a month"
    },
    {
      "when": "a start and an end",
      "use": "DateRangePicker",
      "why": "this holds one day; a range needs the band between its ends and a check that the end is not before the start"
    },
    {
      "when": "a moment, with a time of day",
      "use": "DateTimePicker",
      "why": "this is fixed to days; a moment's bound such as \"not before now\" needs the time too"
    },
    {
      "when": "one of a few days the product defines — four delivery slots",
      "use": "RadioGroup",
      "why": "a choice from a short list, not a date; a month of which four days work reads as a month of refusals"
    }
  ],
  "composition": {
    "order": [
      "Calendar"
    ],
    "note": "`label` names it, joined to the visible month. `value` is YYYY-MM-DD, or null for none yet; `onChange` gets YYYY-MM-DD and never null. Bound it with `minValue` and `maxValue`, and refuse single days with `isDateUnavailable`. With nothing selected it opens on today, or on `minValue` when today is before it, or on `defaultFocusedValue`.",
    "example": "<Calendar label=\"Resume on\" value={day} onChange={setDay} minValue={tomorrow} maxValue={inNinetyDays} description=\"At the start of the day, UTC.\" />"
  },
  "a11y": {
    "requires": [
      "a `label`: it is the calendar's name, and the only thing that says what the day is for"
    ],
    "guarantees": [
      "named by `label` and then the visible month — \"Resume on October 2026\" — so paging months says where you are",
      "arrow keys move by day and week, Page Up and Page Down by month, Home and End to the week's ends; Enter or Space picks the focused day",
      "every day is named by its full date in the reader's language, with today and the selected day said as such; a newly picked day is announced",
      "days before `minValue`, after `maxValue` or refused by `isDateUnavailable` cannot be picked, and the month arrows stop at the bounds",
      "a value it refuses marks it invalid on its own — `errorMessage`, when given, replaces the description — and the frame turns to the error border",
      "`description` or the error is the calendar's accessible description",
      "disabled, it keeps showing the chosen day, on the disabled surface, and no day can be picked or moved to"
    ],
    "notes": [
      "No clearing: a day is changed by picking another. Offer a separate control when \"no day\" is an answer.",
      "Always one month; for two months side by side, the range is DateRangePicker's."
    ]
  },
  "antiPatterns": [
    {
      "dont": "a Calendar for a date of birth or any date the person knows",
      "do": "<DatePicker label=\"Date of birth\" />",
      "why": "paging back decades through months is the worst way to enter a date someone can type in a second"
    },
    {
      "dont": "a DatePicker inside a Modal whose only question is the day",
      "do": "<Calendar label=\"Resume on\" /> in the Modal",
      "why": "the picker's calendar opens a popover over the dialog; the day is the dialog's whole content, so show the month"
    },
    {
      "dont": "a Calendar without bounds for a day that has them",
      "do": "minValue and maxValue",
      "why": "an unbounded month lets someone pick yesterday and learn only on save that it was never possible"
    }
  ],
  "stylesheet": null,
  "tokens": [],
  "props": {
    "label": {
      "type": "React.ReactNode",
      "required": true,
      "origin": "own",
      "description": "Names the calendar. It has no field and no trigger, so this is the only\nthing that says what the day is for — \"Resume on\", \"Deliver on\"."
    },
    "description": {
      "type": "React.ReactNode",
      "required": false,
      "origin": "own",
      "description": "Helper text under the month."
    },
    "errorMessage": {
      "type": "React.ReactNode",
      "required": false,
      "origin": "own",
      "description": "Replaces the helper text while invalid — `isInvalid`, or its own bounds."
    },
    "isInvalid": {
      "type": "boolean | undefined",
      "required": false,
      "origin": "own"
    },
    "isDisabled": {
      "type": "boolean | undefined",
      "required": false,
      "origin": "own"
    },
    "isReadOnly": {
      "type": "boolean | undefined",
      "required": false,
      "origin": "own",
      "description": "Shows the day and lets it be read and moved through, not changed."
    },
    "value": {
      "type": "string | null | undefined",
      "required": false,
      "origin": "own",
      "description": "The selected day as `YYYY-MM-DD`; `null` is none yet."
    },
    "defaultValue": {
      "type": "string | undefined",
      "required": false,
      "origin": "own",
      "description": "The initial day as `YYYY-MM-DD`, for an uncontrolled calendar."
    },
    "onChange": {
      "type": "((value: IsoDate) => void) | undefined",
      "required": false,
      "origin": "own",
      "description": "Fires with `YYYY-MM-DD`. Never with `null`: a day in a grid is changed\nby picking another, not cleared."
    },
    "minValue": {
      "type": "string | undefined",
      "required": false,
      "origin": "own",
      "description": "Earliest selectable day, `YYYY-MM-DD`. Earlier months cannot be reached."
    },
    "maxValue": {
      "type": "string | undefined",
      "required": false,
      "origin": "own",
      "description": "Latest selectable day, `YYYY-MM-DD`."
    },
    "isDateUnavailable": {
      "type": "((date: IsoDate) => boolean) | undefined",
      "required": false,
      "origin": "own",
      "description": "Single days refused inside the bounds — weekends, holidays, booked days."
    },
    "defaultFocusedValue": {
      "type": "string | undefined",
      "required": false,
      "origin": "own",
      "description": "The month to open on, and the day focus lands on, while nothing is\nselected. Defaults to today — or `minValue`, when today is before it."
    },
    "name": {
      "type": "string | undefined",
      "required": false,
      "origin": "own",
      "description": "Posts the value under this name, for an uncontrolled form."
    },
    "id": {
      "type": "string | undefined",
      "required": false,
      "origin": "own"
    },
    "className": {
      "type": "string | undefined",
      "required": false,
      "origin": "own"
    }
  },
  "propCounts": {
    "own": 16,
    "aria": 0,
    "dom": 0,
    "other": 0
  }
}
