Skip to content

Commit

Permalink
feat(Checkbox): add defaultSelected prop and uncontrolled behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
DSil committed Oct 18, 2024
1 parent c0e15ac commit ec54a30
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const meta: Meta<typeof Checkbox> = {
parameters: {
info: "Additionally you can add tooltip to this component.",
controls: {
exclude: ["onChange"],
exclude: ["onChange", "defaultChecked"],
},
},

Expand Down
35 changes: 18 additions & 17 deletions packages/orbit-components/src/Checkbox/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,28 @@ After adding import into your project you can use it simply like:

Table below contains all types of the props available in Checkbox component.

| Name | Type | Default | Description |
| :------- | :------------------------- | :------ | :----------------------------------------------------------------------------------------------------------- |
| checked | `boolean` | `false` | If `true`, the Checkbox will be checked. |
| 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 |
| tooltip | `Element<Tooltip>` | | Optional property when you need to attach Tooltip to the Checkbox. [See Functional specs](#functional-specs) |
| value | `string` | | The value of the Checkbox. |
| Name | Type | Default | Description |
| :------------- | :------------------------- | :------ | :----------------------------------------------------------------------------------------------------------- |
| 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 |
| tooltip | `Element<Tooltip>` | | Optional property when you need to attach Tooltip to the Checkbox. [See Functional specs](#functional-specs) |
| value | `string` | | The value of the Checkbox. |

## Functional specs

- The `hasError` prop will be visible only when the Checkbox has `checked` or `disabled` prop set on **false**.
- The `hasError` prop will be visible only when the Checkbox is not checked nor disabled.

- `ref` can be used for example auto-focus the elements immediately after render.
- `ref` can be used, for example, to control focus or to get the status (checked) of the element.

```jsx
import * as React from "react";
Expand Down
23 changes: 22 additions & 1 deletion packages/orbit-components/src/Checkbox/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import CheckBox from "..";
describe("CheckBox", () => {
const user = userEvent.setup();

it("default", async () => {
it("can be controlled", async () => {
const onChange = jest.fn();
render(
<CheckBox
Expand All @@ -24,7 +24,28 @@ describe("CheckBox", () => {
expect(checkbox).toHaveAttribute("value", "option");
expect(checkbox).toHaveAttribute("name", "name");
expect(checkbox).toHaveAttribute("tabIndex", "-1");
expect(checkbox).not.toHaveAttribute("checked");
await user.click(checkbox);
expect(onChange).toHaveBeenCalled();
});

it("can be uncontrolled", async () => {
const onChange = jest.fn();
render(
<CheckBox
label="Checkbox"
onChange={onChange}
value="option"
dataTest="test"
name="name"
defaultChecked
/>,
);
expect(screen.getByTestId("test")).toBeInTheDocument();
const checkbox = screen.getByRole("checkbox", { name: "Checkbox" }) as HTMLInputElement;
expect(checkbox.checked).toBeTruthy();
await user.click(checkbox);
expect(onChange).toHaveBeenCalled();
expect(checkbox.checked).toBeFalsy();
});
});
32 changes: 18 additions & 14 deletions packages/orbit-components/src/Checkbox/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ const Checkbox = React.forwardRef<HTMLInputElement, Props>((props, ref) => {
value,
hasError = false,
disabled = false,
checked = false,
checked,
defaultChecked,
name,
onChange,
dataTest,
Expand All @@ -33,19 +34,24 @@ const Checkbox = React.forwardRef<HTMLInputElement, Props>((props, ref) => {
"flex flex-row",
"relative w-full",
"[&_.orbit-checkbox-icon-container]:hover:shadow-none",
"[&_.orbit-checkbox-icon-container]:has-[:checked]:bg-blue-normal [&_.orbit-checkbox-icon-container]:has-[:checked]:hover:bg-blue-dark",
disabled
? "cursor-not-allowed"
? [
"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]:hover:border-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",
!checked &&
!hasError &&
"[&_.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",
!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",
],
)}
>
Expand All @@ -59,7 +65,8 @@ const Checkbox = React.forwardRef<HTMLInputElement, Props>((props, ref) => {
disabled={disabled}
name={name}
tabIndex={tabIndex ? Number(tabIndex) : undefined}
checked={checked}
checked={checked || undefined}
defaultChecked={defaultChecked}
onChange={!readOnly ? onChange : undefined}
onClick={e => readOnly && e.stopPropagation()}
ref={ref}
Expand All @@ -77,15 +84,12 @@ const Checkbox = React.forwardRef<HTMLInputElement, Props>((props, ref) => {
"rounded-150 de:rounded-100",
"duration-fast transition-all ease-in-out",
"peer-focus:outline-blue-normal peer-focus:outline peer-focus:outline-2",
"peer-checked:[&>svg]:visible",
"[&>svg]:size-icon-small",
"[&>svg]:flex [&>svg]:items-center [&>svg]:justify-center",
"active:scale-95",
checked ? "[&>svg]:visible" : "[&>svg]:invisible",
disabled && [
"border-cloud-dark",
checked && "bg-cloud-dark",
!checked && "bg-form-element-disabled-background",
],
disabled && ["border-cloud-dark"],
)}
>
<Check customColor="white" />
Expand Down
1 change: 1 addition & 0 deletions packages/orbit-components/src/Checkbox/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export interface Props extends Common.Globals {
readonly hasError?: boolean;
readonly disabled?: boolean;
readonly checked?: boolean;
readonly defaultChecked?: boolean;
readonly name?: string;
readonly info?: React.ReactNode;
readonly tabIndex?: string | number;
Expand Down

0 comments on commit ec54a30

Please sign in to comment.