{
  "name": "Slider",
  "source": "src/components/Slider.tsx",
  "propsType": "SliderProps",
  "description": "Slider — a value, or a range, picked along a track.\n\nWHEN A SLIDER, AND WHEN NOT\n\nFor a rough value in a known range, where where-it-sits matters more than\nthe exact number: a threshold, a zoom, a \"between 30s and 2m\" filter. When\nthe number itself matters — a price, a budget — NumberInput: dragging to\nexactly 4,250 is a test of hand steadiness.\n\nHOW IT IS BUILT\n\n  - Each thumb is a real `<input type=\"range\">`, visually hidden, so the\n    platform's slider keyboard and screen-reader model come for free:\n    arrows step, Page Up/Down jump a tenth, Home/End go to the bounds.\n    `aria-valuetext` carries the formatted value, so \"45%\" is read, not\n    \"0.45\".\n  - A range's thumbs cannot cross: each one's bounds are the other's value.\n  - Pressing the track moves the nearest thumb there.\n  - Every thumb's hit area is 24px square — WCAG 2.5.8 — around a 20px knob,\n    and the track is 24px tall for the same reason, around a 4px rail.\n  - In a right-to-left locale the track runs right to left, keys included.",
  "import": "import { Slider } from 'ionbase-ui';",
  "status": "stable",
  "summary": "A value, or a low–high range, picked along a track. For a rough value in a known range, where where-it-sits matters more than the exact number.",
  "useWhen": [
    "the value is a position in a known range and roughly right is right — a threshold, a zoom, a volume",
    "a filter bounds a quantity from both ends — \"between 30s and 2m\", \"$20 to $80\" — pass `[low, high]`",
    "seeing the value's place in the range helps the choice more than typing it would"
  ],
  "useInstead": [
    {
      "when": "the exact number matters — a price, a budget, a count someone will be held to",
      "use": "NumberInput",
      "why": "dragging to exactly 4,250 is a test of hand steadiness; a field takes the number as typed"
    },
    {
      "when": "there are a few named choices, not a continuum — Low, Medium, High",
      "use": "SegmentedControl",
      "why": "a slider with three stops hides the names behind positions and reads out numbers nobody chose"
    },
    {
      "when": "the value is on or off",
      "use": "Toggle"
    },
    {
      "when": "showing how far something has got, not asking for a value",
      "use": "ProgressBar",
      "why": "a track with a knob invites a drag; progress is not something the user sets"
    }
  ],
  "a11y": {
    "requires": [
      "`label` or `aria-label` — the group's name, and every thumb's name through it",
      "`formatOptions` whenever the number has a unit — the formatted value is what is read out, so a percentage without it is announced as \"0.7\""
    ],
    "guarantees": [
      "every thumb is a visually hidden `<input type=\"range\">`: arrows step, Page Up and Down jump a tenth of the range, Home and End go to the bounds",
      "`aria-valuetext` carries the formatted value — \"70%\", \"120 sec\" — in the user's locale",
      "a range's thumbs are named with the label — \"Minimum Duration\" and \"Maximum Duration\" — and cannot cross; each stops at the other's value",
      "pressing the track moves the nearest thumb there",
      "every thumb's target is 24px square, around a 20px knob, and the track is 24px tall — WCAG 2.5.8",
      "thumbs at the bounds stay inside the component; the track is inset by half a thumb",
      "in a right-to-left locale the track runs right to left, and the arrow keys follow it",
      "a disabled slider's thumbs are disabled inputs, out of the tab order",
      "`description` is linked to every thumb with `aria-describedby`",
      "a range with `name={[low, high]}` submits two form fields"
    ],
    "notes": [
      "the value beside the label is an `<output>` with `aria-live=\"off\"`: the thumb already announces each change, and a second voice would read every step twice",
      "`onChange` fires on every step of a drag; `onChangeEnd` fires once when it ends. Fetch, filter a server or save on `onChangeEnd`",
      "`thumbLabels` names a range's two thumbs and defaults to English \"Minimum\" and \"Maximum\" — pass translations"
    ]
  },
  "antiPatterns": [
    {
      "dont": "<Slider label=\"Monthly budget\" maxValue={5000000} />",
      "do": "<NumberInput label=\"Monthly budget\" />",
      "why": "an exact number across millions is out of reach by drag — each pixel is thousands"
    },
    {
      "dont": "fetching on `onChange`",
      "do": "`onChangeEnd={(v) => refetch(v)}`",
      "why": "`onChange` fires on every pixel of a drag — dozens of requests for one gesture, answered out of order"
    },
    {
      "dont": "<Slider label=\"Threshold\" minValue={0} maxValue={1} step={0.01} />",
      "do": "<Slider label=\"Threshold\" minValue={0} maxValue={1} step={0.01} formatOptions={{ style: 'percent' }} />",
      "why": "without a format the value is shown and read as \"0.7\"; with it, \"70%\""
    },
    {
      "dont": "two Sliders for the low and high end of one filter",
      "do": "<Slider label=\"Duration\" defaultValue={[30, 120]} />",
      "why": "two separate sliders can cross — a minimum above the maximum — and read as two unrelated settings"
    },
    {
      "dont": "a Slider with three steps standing in for Low, Medium, High",
      "do": "<SegmentedControl label=\"Effort\">…</SegmentedControl>",
      "why": "the choices have names; a slider reads them out as 1, 2 and 3"
    }
  ],
  "stylesheet": "src/styles/slider.css",
  "tokens": [
    "--border-disabled",
    "--border-focus",
    "--border-width-thick",
    "--font-family-sans",
    "--font-weight-medium",
    "--ion-duration-fast",
    "--ion-ease-out",
    "--ion-shadow-shadow-xs",
    "--ion-slider-fill",
    "--ion-slider-from",
    "--ion-slider-knob",
    "--ion-slider-rail",
    "--ion-slider-thumb",
    "--ion-slider-to",
    "--radius-full",
    "--spacing-20",
    "--spacing-24",
    "--spacing-4",
    "--spacing-6",
    "--spacing-8",
    "--surface-default",
    "--surface-muted",
    "--surface-primary",
    "--text-default",
    "--text-disabled",
    "--text-secondary",
    "--text-tertiary",
    "--type-body-sm",
    "--type-body-sm-line-height"
  ],
  "props": {
    "label": {
      "type": "React.ReactNode",
      "required": false,
      "origin": "own",
      "description": "Visible label. Names the group, and every thumb through it."
    },
    "aria-label": {
      "type": "string | undefined",
      "required": false,
      "origin": "own",
      "description": "Only when there is no visible label."
    },
    "description": {
      "type": "React.ReactNode",
      "required": false,
      "origin": "own",
      "description": "Helper text under the track, linked to every thumb."
    },
    "value": {
      "type": "V | undefined",
      "required": false,
      "origin": "own",
      "description": "A number for one thumb, `[low, high]` for two. The shape of `value` or\n`defaultValue` decides which slider this is."
    },
    "defaultValue": {
      "type": "V | undefined",
      "required": false,
      "origin": "own"
    },
    "onChange": {
      "type": "((value: Widen<V>) => void) | undefined",
      "required": false,
      "origin": "own",
      "description": "Fires on every step of a drag or key press."
    },
    "onChangeEnd": {
      "type": "((value: Widen<V>) => void) | undefined",
      "required": false,
      "origin": "own",
      "description": "Fires once, when a drag ends or a key is released. Use this, not\n`onChange`, for anything that fetches or saves."
    },
    "minValue": {
      "type": "number | undefined",
      "required": false,
      "origin": "own",
      "description": "Default 0."
    },
    "maxValue": {
      "type": "number | undefined",
      "required": false,
      "origin": "own",
      "description": "Default 100."
    },
    "step": {
      "type": "number | undefined",
      "required": false,
      "origin": "own",
      "description": "Default 1. Page Up and Page Down move by a tenth of the range."
    },
    "formatOptions": {
      "type": "Intl.NumberFormatOptions | undefined",
      "required": false,
      "origin": "own",
      "description": "How values are shown and announced — `{ style: 'percent' }`,\n`{ style: 'unit', unit: 'second' }`, currency. In the user's locale."
    },
    "thumbLabels": {
      "type": "readonly [string, string] | undefined",
      "required": false,
      "origin": "own",
      "description": "A range's two thumbs, named. Each is read before the label — \"Minimum\nDuration\". Pass translations here."
    },
    "showValue": {
      "type": "boolean | undefined",
      "required": false,
      "origin": "own",
      "description": "The current value beside the label. On by default."
    },
    "isDisabled": {
      "type": "boolean | undefined",
      "required": false,
      "origin": "own"
    },
    "name": {
      "type": "(V extends number ? string : readonly [string, string]) | undefined",
      "required": false,
      "origin": "own",
      "description": "The form field name. A range submits two fields, so it takes a pair."
    },
    "id": {
      "type": "string | undefined",
      "required": false,
      "origin": "own"
    },
    "className": {
      "type": "string | undefined",
      "required": false,
      "origin": "own"
    }
  },
  "propCounts": {
    "own": 17,
    "aria": 0,
    "dom": 0,
    "other": 0
  }
}
