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.

236 lines (235 loc) 14.5 kB
"use strict"; "use client"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default; exports.__esModule = true; exports.default = exports.FakeCheckbox = void 0; var React = _interopRequireWildcard(require("react")); var _clsx = _interopRequireDefault(require("clsx")); var _Check = _interopRequireDefault(require("../icons/Check")); var _getFieldDataState = _interopRequireDefault(require("../common/getFieldDataState")); var _FakeCheckbox = _interopRequireDefault(require("./FakeCheckbox")); exports.FakeCheckbox = _FakeCheckbox.default; /** * @orbit-doc-start * README * ---------- * # Checkbox * * To implement Checkbox component into your project you'll need to add the import: * * ```jsx * import Checkbox from "@kiwicom/orbit-components/lib/Checkbox"; * ``` * * After adding import into your project you can use it simply like: * * ```jsx * <Checkbox label="Checkbox" /> * ``` * * ## Props * * Table below contains all types of the props available in Checkbox component. * * | Name | Type | Default | Description | * | :-------------- | :------------------------- | :------ | :--------------------------------------------------------------------------------------------- | * | ariaControls | `string` | | Identifies the element whose contents or presence are controlled by the Checkbox. | * | ariaDescribedby | `string` | | Identifies the element that describes the Checkbox, providing additional information. | * | checked | `boolean` | | If `true`, the Checkbox will be checked. | * | defaultChecked | `boolean` | | If `true`, the Checkbox will be checked by default. Only to be used in uncontrolled. | * | disabled | `boolean` | `false` | If `true`, the Checkbox will be set up as disabled. | * | dataTest | `string` | | Optional prop for testing purposes. | * | id | `string` | | Set `id` for `Checkbox` | * | hasError | `boolean` | `false` | If `true`, the border of the Checkbox will turn red. [See Functional specs](#functional-specs) | * | info | `React.Node` | | The additional info about the Checkbox. | * | label | `string` | | The label of the Checkbox. | * | name | `string` | | The name for the Checkbox. | * | onChange | `event => void \| Promise` | | Function for handling onChange event. | * | ref | `func` | | Prop for forwarded ref of the Checkbox. [See Functional specs](#functional-specs) | * | tabIndex | `string \| number` | | Specifies the tab order of an element | * | value | `string` | | The value of the Checkbox. | * * ## Functional specs * * - The `hasError` prop will be visible only when the Checkbox is not checked nor disabled. * * - `ref` can be used, for example, to control focus or to get the status (checked) of the element. * * # FakeCheckbox * * The FakeCheckbox component was created for accessibility reasons and offers only a visual presentation of the Checkbox component. It does not have any functionality and accepts only state props - `disabled`, `checked`, `hasError`. * * ## Props * * Table below contains all types of the props available in FakeCheckbox component. * * | Name | Type | Default | Description | * | :------- | :-------- | :------ | :------------------------------------------------------------------------------------------------------------------ | --- | * | checked | `boolean` | `false` | If `true`, the FakeCheckbox will be checked. | * | disabled | `boolean` | `false` | If `true`, the FakeCheckbox will be set up as disabled. | * | hasError | `boolean` | `false` | If `true`, the border of the FakeCheckbox will turn red. [See Functional specs](#functional-specs-for-fakecheckbox) | | * * ## Functional specs for FakeCheckbox * * - The `hasError` prop will be visible only when the FakeCheckbox is not checked nor disabled. * * ## Example * * ```jsx * import * as React from "react"; * * <div role="checkbox" onChange={() => {}}> * <Text>Item title</Text> * <FakeCheckbox checked={selected} disabled={disabled} /> * </div>; * ``` * * * Accessibility * ------------- * ## Accessibility * * The Checkbox component has been designed with accessibility in mind, providing standard checkbox functionality with keyboard navigation and screen reader support. * * ### Accessibility Props * * **Checkbox props:** * * | Name | Type | Description | * | :-------------- | :--------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | * | ariaControls | string | Identifies the element whose contents or presence are controlled by the Checkbox. Use this to connect the Checkbox to related elements that are shown/hidden based on the Checkbox state. | * | ariaDescribedby | string | Identifies the element that describes the Checkbox. Typically used to connect error messages or additional information to the Checkbox. | * | hasError | boolean | When true, applies a visual error state and sets aria-invalid="true" to indicate an error to screen readers. | * | label | React.Node | Provides an accessible name for the Checkbox through its label content. | * | disabled | boolean | When true, prevents interaction with the Checkbox and communicates this state to assistive technology. | * | tabIndex | string \| number | Controls the tab order of the checkbox within the page. | * * ### Automatic Accessibility Features * * - The component automatically manages ARIA attributes: * - Uses native HTML `<input type="checkbox">` element which has an implicit `role="checkbox"` for screen readers * - Automatically announces checked/unchecked states for screen readers * - Provides visual feedback for error states that is also communicated to screen readers * - Supports keyboard focus management with visible focus indicators * - Disabled state is properly communicated to screen readers * * ### Best Practices * * - Always provide a descriptive label for the Checkbox to ensure screen reader users understand its purpose * - Use `ariaControls` to establish relationships between a Checkbox and the content it shows/hides or controls * - Use `ariaDescribedby` to connect supplementary information to the Checkbox, such as error messages, help text, or additional context for better screen reader communication * - Group related Checkboxes with appropriate heading elements or fieldsets with legends * - Ensure sufficient color contrast between the checkbox, its label, and the background * - When using the hasError state, make sure to provide an accessible error message using ariaDescribedby * - Use the Checkbox's native state management rather than creating custom checkbox-like components * * ### Keyboard Navigation * * - **Tab**: Moves focus to the Checkbox * - **Space**: Toggles the checked state of the Checkbox * - When focused, the Checkbox has a visible focus indicator * * ### Examples * * #### Basic Checkbox with Label * * ```jsx * <Checkbox label="I agree to the terms and conditions" /> * ``` * * Screen reader announces: "I agree to the terms and conditions, checkbox, not checked" * * #### Checkbox with Error State * * ```jsx * <div> * <Checkbox * label="I agree to the terms and conditions" * hasError={true} * ariaDescribedby="checkbox-error" * /> * <div id="checkbox-error">You must accept the terms to continue</div> * </div> * ``` * * Screen reader announces: "I agree to the terms and conditions, You must accept the terms to continue, invalid, not checked, checkbox" * * #### Checkbox Controlling Content Display * * ```jsx * <div> * <Checkbox label="Show advanced options" ariaControls="advanced-options" /> * <div id="advanced-options">{/* Advanced options content *\/}</div> * </div> * ``` * * Screen reader announces: "Show advanced options, checkbox, not checked" and indicates that the checkbox controls other content. * * #### Checkbox with Additional Information * * ```jsx * <Checkbox * label="Subscribe to newsletter" * info="Receive weekly updates about our products and services" * /> * ``` * * Screen reader announces: "Subscribe to newsletter, Receive weekly updates about our products and services, checkbox, not checked" * * * @orbit-doc-end */ const Checkbox = props => { const { label, value, hasError = false, disabled = false, checked, defaultChecked, name, onChange, dataTest, id, info, tabIndex, ariaControls, ariaDescribedby, ref } = props; const Component = label ? "label" : "div"; return /*#__PURE__*/React.createElement(Component, { htmlFor: label ? id : undefined, className: (0, _clsx.default)("orbit-checkbox-label", "font-base", "flex flex-row", "relative w-full", "[&_.orbit-checkbox-icon-container]:hover:shadow-none", "[&_.orbit-checkbox-icon-container]:has-[:focus]:outline-blue-normal [&_.orbit-checkbox-icon-container]:has-[:focus]:outline [&_.orbit-checkbox-icon-container]:has-[:focus]:outline-2", "[&_.orbit-checkbox-icon-container>svg]:has-[:checked]:visible", disabled ? ["cursor-not-allowed", "[&_.orbit-checkbox-icon-container]:bg-form-element-disabled-background", "[&_.orbit-checkbox-icon-container]:has-[:checked]:bg-cloud-dark", checked && "[&_.orbit-checkbox-icon-container]:bg-cloud-dark"] : ["cursor-pointer", "[&_.orbit-checkbox-icon-container]:has-[:checked]:border-blue-normal [&_.orbit-checkbox-icon-container]:has-[:checked]:bg-blue-normal [&_.orbit-checkbox-icon-container]:has-[:checked]:hover:border-blue-dark [&_.orbit-checkbox-icon-container]:has-[:checked]:hover:bg-blue-dark", checked && !hasError && "[&_.orbit-checkbox-icon-container]:bg-blue-normal [&_.orbit-checkbox-icon-container]:border-blue-normal [&_.orbit-checkbox-icon-container]:hover:bg-blue-dark [&_.orbit-checkbox-icon-container]:hover:border-blue-dark", !checked && "[&_.orbit-checkbox-icon-container]:bg-form-element-background", !checked && hasError ? "[&_.orbit-checkbox-icon-container]:border-form-element-error" : "[&_.orbit-checkbox-icon-container]:border-form-element-border-color [&_.orbit-checkbox-icon-container]:hover:border-blue-light-active [&_.orbit-checkbox-icon-container]:active:border-form-element-focus"]) }, /*#__PURE__*/React.createElement("input", { className: "-z-default absolute opacity-0", "data-test": dataTest, id: id, "data-state": (0, _getFieldDataState.default)(!!hasError), value: value, type: "checkbox", disabled: disabled, name: name, tabIndex: tabIndex ? Number(tabIndex) : undefined, checked: checked, defaultChecked: defaultChecked, onChange: onChange, ref: ref, "aria-controls": ariaControls, "aria-describedby": ariaDescribedby, "aria-invalid": hasError ? true : undefined }), /*#__PURE__*/React.createElement("div", { className: (0, _clsx.default)("orbit-checkbox-icon-container", "relative box-border", "border border-solid", "flex shrink-0 grow-0 basis-auto items-center justify-center", "size-icon-medium", "rounded-150 de:rounded-100", "duration-fast transition-all ease-in-out", "[&>svg]:size-icon-small", "[&>svg]:flex [&>svg]:items-center [&>svg]:justify-center", checked ? "[&>svg]:visible" : "[&>svg]:invisible", disabled ? ["border-cloud-dark"] : "active:scale-95") }, /*#__PURE__*/React.createElement(_Check.default, { customColor: "white", ariaHidden: true })), (label || info) && /*#__PURE__*/React.createElement("div", { className: (0, _clsx.default)("ms-200 flex flex-1 flex-col", disabled ? "opacity-50" : "opacity-100") }, label && /*#__PURE__*/React.createElement("span", { className: "font-base text-form-element-normal text-form-element-label-foreground [&_.orbit-text]:text-form-element-normal [&_.orbit-text]:text-form-element-label-foreground [&_.orbit-text]:leading-small font-medium leading-normal [&_.orbit-text]:font-medium" }, label), info && /*#__PURE__*/React.createElement("span", { className: "text-small leading-small text-secondary-foreground" }, info))); }; var _default = exports.default = Checkbox;