Switch
An on/off toggle (role="switch") for settings that take effect immediately.
'use client';
import { Switch } from '@akhatmirzo/ui';
export default function SwitchBasic() {
return (
<div className="flex flex-col gap-4">
<Switch label="Bildirishnomalar" defaultChecked />
<Switch label="Avtomatik saqlash" />
</div>
);
}
Import
import { Switch } from '@akhatmirzo/ui';When to use
- When a setting applies right away — notifications, dark theme, opening or closing a store. No "Save" click needed.
- In forms with a "Save" button, use a
Checkbox— there the choice only takes effect on submit. - Name the setting, not the state: "Notifications", not "On/Off" — the switch itself shows the state.
- If the change takes time (a server request), confirm it with a
toastor roll the value back on error.
Sizes
sm is 32×18px and md (default) is 40×24px. The thumb slides with a spring animation.
'use client';
import { Switch } from '@akhatmirzo/ui';
export default function SwitchSizes() {
return (
<div className="flex flex-wrap items-start gap-8">
<Switch size="sm" label="Kichik · 32×18" defaultChecked />
<Switch size="md" label="O'rta · 40×24" defaultChecked />
</div>
);
}
With a description
description appears under the label and is linked with aria-describedby.
'use client';
import { Switch } from '@akhatmirzo/ui';
export default function SwitchDescription() {
return (
<div className="flex max-w-sm flex-col gap-4">
<Switch label="Qorong'i mavzu" description="Tizim sozlamasidan qat'i nazar" defaultChecked />
<Switch size="sm" label="Ovozli signal" description="Yangi buyurtma kelganda" />
</div>
);
}
Controlled
With checked and onCheckedChange, the value lives in your state. Use defaultChecked for
uncontrolled mode.
'use client';
import { Switch } from '@akhatmirzo/ui';
import { useState } from 'react';
export default function SwitchControlled() {
const [open, setOpen] = useState(true);
return (
<div className="flex flex-wrap items-center gap-4">
<Switch label="Do'kon ochiq" checked={open} onCheckedChange={setOpen} />
<span className="text-sm text-text-muted">
{open ? 'Buyurtmalar qabul qilinmoqda' : "Buyurtmalar to'xtatilgan"}
</span>
</div>
);
}
States
disabled dims the switch and blocks clicks. invalid draws a red ring around the track and sets
aria-invalid on the input.
'use client';
import { Switch } from '@akhatmirzo/ui';
export default function SwitchStates() {
return (
<div className="flex flex-wrap items-center gap-6">
<Switch label="O'chirilgan" disabled />
<Switch label="O'chirilgan, yoqilgan" disabled defaultChecked />
<Switch label="Xato" invalid />
</div>
);
}
With Field
The Field label is linked to the switch with htmlFor and the hint goes into
aria-describedby — no need for the switch's own label.
Har kirishda SMS kod so'raladi
'use client';
import { Field, Switch } from '@akhatmirzo/ui';
export default function SwitchWithField() {
return (
<div className="max-w-sm">
<Field label="Ikki bosqichli tasdiqlash" description="Har kirishda SMS kod so'raladi">
<Switch />
</Field>
</div>
);
}
Props
Switch accepts every other <input> attribute (name, value, form, onChange ...), and
ref points to the inner <input>. className goes to the root <label>.
| Prop | Type | Default | Description |
|---|---|---|---|
checked | boolean | — | Controlled value |
defaultChecked | boolean | false | Initial value (uncontrolled) |
onCheckedChange | (checked: boolean) => void | — | Called when the user toggles it |
label | ReactNode | — | Text next to the switch |
description | ReactNode | — | Hint under the label |
size | 'sm' | 'md' | 'md' | Size: 32×18 / 40×24px |
invalid | boolean | — | Error state (automatic inside a Field with an error) |
disabled | boolean | — | Disabled state |
className | string | — | Class for the root <label> |
Data attributes
On the root <label>: data-state (checked · unchecked), data-size (sm · md),
data-disabled and data-invalid.
Accessibility
- Native
<input type="checkbox" role="switch">— screen readers announce "switch, on", it toggles withSpaceand submits with the form. - Clicking the label toggles it too — the whole component is a
<label>. - The hit area is larger than the track, so it's easy to tap.
- The focus ring shows only for keyboard focus.
- For a switch without a label, pass
aria-label.