Skip to content

Commit

Permalink
Fixed the inconsistencies in checbox group
Browse files Browse the repository at this point in the history
  • Loading branch information
Shubhdeep12 committed Oct 18, 2024
1 parent a58636a commit 075b729
Show file tree
Hide file tree
Showing 11 changed files with 144 additions and 1,757 deletions.
15 changes: 4 additions & 11 deletions apps/docs/src/examples/checkbox-group.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,7 @@ export function BasicExample() {

export function DefaultValueExample() {
return (
<CheckboxGroup
class={style["checkbox-group"]}
defaultValues={[{ id: "News", value: "News" }]}
>
<CheckboxGroup class={style["checkbox-group"]} defaultValues={["News"]}>
<CheckboxGroup.Label class={style["checkbox-group__label"]}>
Subscribe to topics
</CheckboxGroup.Label>
Expand All @@ -62,7 +59,7 @@ export function DefaultValueExample() {
}

export function ControlledExample() {
const [value, setValue] = createSignal([{ id: "News", value: "News" }]);
const [value, setValue] = createSignal(["News"]);

return (
<>
Expand Down Expand Up @@ -131,18 +128,14 @@ export function DescriptionExample() {
}

export function ErrorMessageExample() {
const [value, setValue] = createSignal([{ id: "News", value: "News" }]);
const [value, setValue] = createSignal(["News"]);

return (
<CheckboxGroup
class={style["checkbox-group"]}
values={value()}
onChange={setValue}
validationState={
!value().some((val) => val.id === "News" && val.value === "News")
? "invalid"
: "valid"
}
validationState={!value().includes("News") ? "invalid" : "valid"}
>
<CheckboxGroup.Label class={style["checkbox-group__label"]}>
What would you like to subscribe to?
Expand Down
134 changes: 94 additions & 40 deletions apps/docs/src/routes/docs/core/components/checkbox-group.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -202,11 +202,21 @@ An initial, uncontrolled value can be provided using the `defaultValue` prop, wh
</Preview>

```tsx {0,4}
<CheckboxGroup defaultValue="Orange">
<CheckboxGroup.Label>Favorite fruit</CheckboxGroup.Label>
<CheckboxGroup defaultValues={["News"]}>
<CheckboxGroup.Label>Subscribe to topics</CheckboxGroup.Label>
<div role="presentation">
<For each={["Apple", "Orange", "Watermelon"]}>
{fruit => <CheckboxGroup.Item value={fruit}>...</CheckboxGroup.Item>}
<For each={["News", "Updates", "Offers"]}>
{topic => (
<CheckboxGroup.Item id={topic} value={topic}>
<CheckboxGroup.ItemInput />
<CheckboxGroup.ItemControl>
<CheckboxGroup.ItemIndicator>
<CheckIcon />
</CheckboxGroup.ItemIndicator>
</CheckboxGroup.ItemControl>
<CheckboxGroup.ItemLabel>{topic}</CheckboxGroup.ItemLabel>
</CheckboxGroup.Item>
)}
</For>
</div>
</CheckboxGroup>
Expand All @@ -226,20 +236,27 @@ The `value` prop, which accepts a value corresponding with the `value` prop of e
import { createSignal } from "solid-js";
function ControlledExample() {
const [value, setValue] = createSignal("Orange");
const [value, setValue] = createSignal(["News"]);
return (
<>
<CheckboxGroup value={value()} onChange={setValue}>
<CheckboxGroup.Label>Favorite fruit</CheckboxGroup.Label>
<CheckboxGroup values={value()} onChange={setValue}>
<CheckboxGroup.Label>What would you like to subscribe to?</CheckboxGroup.Label>
<div role="presentation">
<For each={["Apple", "Orange", "Watermelon"]}>
{fruit => <CheckboxGroup.Item value={fruit}>...</CheckboxGroup.Item>}
<For each={["News", "Updates", "Offers"]}>
{option => (
<CheckboxGroup.Item id={option} value={option}>
<CheckboxGroup.ItemInput />
<CheckboxGroup.ItemControl>
<CheckboxGroup.ItemIndicator>
<CheckIcon />
</CheckboxGroup.ItemIndicator>
</CheckboxGroup.ItemControl>
<CheckboxGroup.ItemLabel>{option}</CheckboxGroup.ItemLabel>
</CheckboxGroup.Item>
)}
</For>
</div>
</CheckboxGroup>
<p>Your favorite fruit is: {value()}.</p>
</>
);
}
```
Expand All @@ -254,13 +271,25 @@ The `CheckboxGroup.Description` component can be used to associate additional he

```tsx {7}
<CheckboxGroup>
<CheckboxGroup.Label>Favorite fruit</CheckboxGroup.Label>
<CheckboxGroup.Label>What would you like to subscribe to?</CheckboxGroup.Label>
<div role="presentation">
<For each={["Apple", "Orange", "Watermelon"]}>
{fruit => <CheckboxGroup.Item value={fruit}>...</CheckboxGroup.Item>}
<For each={["News", "Updates", "Offers"]}>
{option => (
<CheckboxGroup.Item value={option}>
<CheckboxGroup.ItemInput />
<CheckboxGroup.ItemControl>
<CheckboxGroup.ItemIndicator>
<CheckIcon />
</CheckboxGroup.ItemIndicator>
</CheckboxGroup.ItemControl>
<CheckboxGroup.ItemLabel>{option}</CheckboxGroup.ItemLabel>
</CheckboxGroup.Item>
)}
</For>
</div>
<CheckboxGroup.Description>Choose the fruit you like the most.</CheckboxGroup.Description>
<CheckboxGroup.Description>
Select the types of updates you'd like to receive.
</CheckboxGroup.Description>
</CheckboxGroup>
```

Expand All @@ -278,21 +307,31 @@ By default, it will render only when the `validationState` prop is set to `inval
import { createSignal } from "solid-js";
function ErrorMessageExample() {
const [value, setValue] = createSignal("Orange");
const [value, setValue] = createSignal(["News"]);
return (
<CheckboxGroup
value={value()}
values={value()}
onChange={setValue}
validationState={value() !== "Apple" ? "invalid" : "valid"}
validationState={!value().includes("News") ? "invalid" : "valid"}
>
<CheckboxGroup.Label>Favorite fruit</CheckboxGroup.Label>
<CheckboxGroup.Label>What would you like to subscribe to?</CheckboxGroup.Label>
<div role="presentation">
<For each={["Apple", "Orange", "Watermelon"]}>
{fruit => <CheckboxGroup.Item value={fruit}>...</CheckboxGroup.Item>}
<For each={["News", "Updates", "Offers"]}>
{option => (
<CheckboxGroup.Item id={option} value={option}>
<CheckboxGroup.ItemInput />
<CheckboxGroup.ItemControl>
<CheckboxGroup.ItemIndicator>
<CheckIcon />
</CheckboxGroup.ItemIndicator>
</CheckboxGroup.ItemControl>
<CheckboxGroup.ItemLabel>{option}</CheckboxGroup.ItemLabel>
</CheckboxGroup.Item>
)}
</For>
</div>
<CheckboxGroup.ErrorMessage>Hmm, I prefer apples.</CheckboxGroup.ErrorMessage>
<CheckboxGroup.ErrorMessage>Please select News to stay informed.</CheckboxGroup.ErrorMessage>
</CheckboxGroup>
);
}
Expand All @@ -308,17 +347,32 @@ The checkbox group `name` prop, paired with the checkbox `value` prop, can be us

```tsx {7,11}
function HTMLFormExample() {
let formRef: HTMLFormElement | undefined;
const onSubmit = (e: SubmitEvent) => {
// handle form submission.
e.preventDefault();
e.stopPropagation();
const formData = new FormData(formRef);
alert(JSON.stringify(Object.fromEntries(formData), null, 2));
};
return (
<form onSubmit={onSubmit}>
<CheckboxGroup name="favorite-fruit">
<CheckboxGroup.Label>Favorite fruit</CheckboxGroup.Label>
<form ref={formRef} onSubmit={onSubmit}>
<CheckboxGroup name="subscriptions">
<CheckboxGroup.Label>What would you like to subscribe to?</CheckboxGroup.Label>
<div role="presentation">
<For each={["Apple", "Orange", "Watermelon"]}>
{fruit => <CheckboxGroup.Item value={fruit}>...</CheckboxGroup.Item>}
<For each={["News", "Updates", "Offers"]}>
{option => (
<CheckboxGroup.Item id={option} value={option}>
<CheckboxGroup.ItemInput />
<CheckboxGroup.ItemControl>
<CheckboxGroup.ItemIndicator>
<CheckIcon />
</CheckboxGroup.ItemIndicator>
</CheckboxGroup.ItemControl>
<CheckboxGroup.ItemLabel>{option}</CheckboxGroup.ItemLabel>
</CheckboxGroup.Item>
)}
</For>
</div>
</CheckboxGroup>
Expand All @@ -337,17 +391,17 @@ function HTMLFormExample() {

`CheckboxGroup` is equivalent to the `Root` import from `@kobalte/core/checkbox-group` (and deprecated `CheckboxGroup.Root`).

| Prop | Description |
| :-------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| values | `[{id: string, value: string}]` <br/> The controlled values of the checkboxes to check. |
| defaultValues | `[{id: string, value: string}]` <br/> The value of the checkboxes that should be checked when initially rendered. Useful when you do not need to control the state of the checkboxes. |
| onChange | `(value: string) => void` <br/> Event handler called when the value changes. |
| orientation | `'horizontal' \| 'vertical'` <br/> The axis the checkbox group items should align with. |
| name | `string` <br/> The name of the checkbox group. Submitted with its owning form as part of a name/value pair. |
| validationState | `'valid' \| 'invalid'` <br/> Whether the checkbox group should display its "valid" or "invalid" visual styling. |
| required | `boolean` <br/> Whether the user must check a checkbox group item before the owning form can be submitted. |
| disabled | `boolean` <br/> Whether the checkbox group is disabled. |
| readOnly | `boolean` <br/> Whether the checkbox group items can be selected but not changed by the user. |
| Prop | Description |
| :-------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| values | `string[]` <br/> The controlled values of the checkboxes to check. |
| defaultValues | `string[]` <br/> The value of the checkboxes that should be checked when initially rendered. Useful when you do not need to control the state of the checkboxes. |
| onChange | `(value: string) => void` <br/> Event handler called when the value changes. |
| orientation | `'horizontal' \| 'vertical'` <br/> The axis the checkbox group items should align with. |
| name | `string` <br/> The name of the checkbox group. Submitted with its owning form as part of a name/value pair. |
| validationState | `'valid' \| 'invalid'` <br/> Whether the checkbox group should display its "valid" or "invalid" visual styling. |
| required | `boolean` <br/> Whether the user must check a checkbox group item before the owning form can be submitted. |
| disabled | `boolean` <br/> Whether the checkbox group is disabled. |
| readOnly | `boolean` <br/> Whether the checkbox group items can be selected but not changed by the user. |

| Data attribute | Description |
| :------------- | :---------------------------------------------------------------------------------------------- |
Expand Down
100 changes: 0 additions & 100 deletions packages/core/dev/App.module.css

This file was deleted.

33 changes: 1 addition & 32 deletions packages/core/dev/App.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,3 @@
import { createSignal, For } from "solid-js";
import { CheckboxGroup } from "../src";
import style from "./App.module.css";

export default function App() {
const [value, setValue] = createSignal(["cats"]);

return (
<CheckboxGroup.Root
class={style["checkbox-group"]}
values={value()}
onChange={setValue}
>
<CheckboxGroup.Label class={style["checkbox-group__label"]}>
Favorite fruit
</CheckboxGroup.Label>
<div class={style["checkbox-group__items"]} role="presentation">
<For each={["Apple", "Orange", "Watermelon"]}>
{(fruit) => (
<CheckboxGroup.Item value={fruit} class={style.checkbox}>
<CheckboxGroup.ItemInput class={style.checkbox__input} />
<CheckboxGroup.ItemControl class={style.checkbox__control}>
<CheckboxGroup.ItemIndicator class={style.checkbox__indicator} />
</CheckboxGroup.ItemControl>
<CheckboxGroup.ItemLabel class={style.checkbox__label}>
{fruit}
</CheckboxGroup.ItemLabel>
</CheckboxGroup.Item>
)}
</For>
</div>
</CheckboxGroup.Root>
);
return (<></>);
}
5 changes: 2 additions & 3 deletions packages/core/src/checkbox-group/checkbox-group-context.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { type Accessor, createContext, useContext } from "solid-js";
import type { CheckboxGroupItemValue } from "./checkbox-group-root";

export interface CheckboxGroupContextValue {
ariaDescribedBy: Accessor<string | undefined>;
isSelectedValue: (value: CheckboxGroupItemValue) => boolean;
setSelectedValue: (value: CheckboxGroupItemValue) => void;
isSelectedValue: (value: string) => boolean;
setSelectedValue: (value: string) => void;
}

export const CheckboxGroupContext = createContext<CheckboxGroupContextValue>();
Expand Down
Loading

0 comments on commit 075b729

Please sign in to comment.