UNPKG

@kiwicom/orbit-components

Version:

Orbit-components is a React component library which provides developers with the easiest possible way of building Kiwi.com's products.

135 lines (134 loc) 7.04 kB
"use client"; import * as React from "react"; import cx from "clsx"; import handleKeyDown from "../utils/handleKeyDown"; /** * @orbit-doc-start * README * ---------- * # Switch * * To implement the Switch component into your project you'll need to add the import: * * ```jsx * import Switch from "@kiwicom/orbit-components/lib/Switch"; * ``` * * After adding import to your project you can use it simply like: * * ```jsx * <Switch checked={isChecked} onChange={handleOnChange} /> * ``` * * ## Props * * The table below contains all types of the props available in the Switch component. * * | Name | Type | Default | Description | * | :------------- | :---------------------- | :----------- | :----------------------------------------- | * | dataTest | `string` | | Optional prop for testing purposes. | * | id | `string` | | Set `id` for `Switch` input. | * | **onChange** | `() => void \| Promise` | | Function for handling onChange event. | * | onFocus | `() => void \| Promise` | | Function for handling onFocus event. | * | onBlur | `() => void \| Promise` | | Function for handling onBlur event. | * | **checked** | `boolean` | | If `true`, the Switch will be checked. | * | icon | `React.Node` | `<Circle />` | Optional property for custom icon. | * | disabled | `boolean` | `false` | If `true`, the Switch will be disabled. | * | ariaControls | `string` | | Optional prop for `aria-controls` value. | * | ariaLabel | `string` | | Optional prop for `aria-label` value. | * | ariaLabelledby | `string` | | Optional prop for `aria-labelledby` value. | * * * Accessibility * ------------- * ## Accessibility * * The Switch component has been designed with accessibility in mind. * * It supports keyboard navigation and includes the following properties that provide additional information to screen readers: * * | Name | Type | Description | * | :------------- | :------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | * | ariaControls | `string` | Allows you to specify an `aria-controls` attribute to establish the relationship between the Switch and element which is controlled by it. `ariaControls` works only with a unique `id` of an element. | * | ariaLabel | `string` | Allows you to specify an `aria-label` attribute of the component. | * | ariaLabelledby | `string` | Allows you to specify an `aria-labelledby` attribute of the component. This attribute references the id(s) of element(s) that label(s) the Switch, separated by a space. The elements with those ids can be hidden, so that their text is only announced by screen readers. | * * While these props are optional, we recommend including them to ensure proper functionality with assistive technologies. * This helps users better understand the component's context and improves the overall experience. * * ### Example * * The following code snippet shows how to use these properties: * * ```jsx * <Card * title="Billing details" * actions={ * <Switch * checked={isExpanded} * onChange={handleShowBillingDetails} * ariaLabel="Toggle billing details section" * ariaControls="BillingDetailsForm" * /> * } * > * {isExpanded && ( * <CardSection> * <BillingDetailsForm id="BillingDetailsForm" /> * </CardSection> * )} * </Card> * ``` * * Using the `ariaLabel` prop enables screen readers to properly announce the Switch component. * Alternatively, you can use the `ariaLabelledby` prop to reference another element that serves as a label for the Switch component. * * For enhanced accessibility, it is recommended to have these label strings translated and dynamically updated based on the user's current journey state * (e.g. if a billing details section is expanded and the user is about to collapse it, the screen reader should properly announce it). * * The `ariaControls` prop establishes a connection between the Switch and the element it controls. * This relationship enables users to navigate directly from the Switch to this element, improving the overall navigation experience. * * * @orbit-doc-end */ const Switch = ({ onChange, checked, dataTest, id, icon, onBlur, onFocus, disabled, ariaControls, ariaLabel, ariaLabelledby, ref }) => { return /*#__PURE__*/React.createElement("label", { className: "inline-block" }, /*#__PURE__*/React.createElement("div", { className: cx("duration-fast h-600 w-form-box-normal relative flex items-center justify-between rounded-full transition-colors", disabled ? "cursor-not-allowed opacity-50" : "cursor-pointer", checked ? "bg-blue-normal" : "bg-cloud-dark") }, /*#__PURE__*/React.createElement("input", { className: cx("peer absolute inset-0 m-0 size-full p-0 opacity-0", !disabled && "cursor-pointer"), ref: ref, checked: checked, disabled: disabled, "aria-checked": checked, role: "switch", onKeyDown: !disabled ? handleKeyDown(undefined, onChange) : undefined, onBlur: !disabled ? onBlur : undefined, onChange: !disabled ? onChange : undefined, onFocus: !disabled ? onFocus : undefined, type: "checkbox", "data-test": dataTest, id: id, "aria-controls": ariaControls, "aria-label": ariaLabel, "aria-labelledby": ariaLabelledby }), /*#__PURE__*/React.createElement("div", { className: cx("bg-white-normal duration-fast shadow-switch size-500 absolute box-border inline-flex items-center justify-center rounded-full", "peer-focus:outline-blue-normal peer-focus:outline peer-focus:outline-2", "[&_svg]:size-300", !disabled && "active:shadow-level2", !checked && (icon ? "[&_svg]:text-ink-normal" : "[&_svg]:text-cloud-dark"), checked ? "[&_svg]:text-blue-normal rtl:-translate-x-50 ltr:translate-x-[calc(100%+2px)]" : "left-50") }, icon || null))); }; export default Switch;