Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Checkbox group component #502

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions apps/docs/src/examples/checkbox-group.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
@import "./checkbox.module.css";

.checkbox-group {
display: flex;
flex-direction: column;
gap: 8px;
}

.checkbox-group__label {
color: hsl(240 6% 10%);
font-size: 14px;
font-weight: 500;
user-select: none;
}

.checkbox-group__description {
color: hsl(240 5% 26%);
font-size: 12px;
user-select: none;
}

.checkbox-group__error-message {
color: hsl(0 72% 51%);
font-size: 12px;
user-select: none;
}

.checkbox-group__items {
display: flex;
gap: 16px;
}

[data-kb-theme="dark"] .checkbox-group__label {
color: hsl(240 5% 84%);
}

[data-kb-theme="dark"] .checkbox-group__description {
color: hsl(240 5% 65%);
}
233 changes: 233 additions & 0 deletions apps/docs/src/examples/checkbox-group.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
import { CheckboxGroup } from "@kobalte/core/checkbox-group";
import { For, createSignal } from "solid-js";

import { CheckIcon } from "../components";
import style from "./checkbox-group.module.css";

export function BasicExample() {
return (
<CheckboxGroup class={style["checkbox-group"]}>
<CheckboxGroup.Label class={style["checkbox-group__label"]}>
Subscribe to topics
</CheckboxGroup.Label>
<div class={style["checkbox-group__items"]} role="presentation">
<For each={["News", "Updates", "Offers"]}>
{(topic) => (
<CheckboxGroup.Item value={topic} class={style.checkbox}>
<CheckboxGroup.ItemInput class={style.checkbox__input} />
<CheckboxGroup.ItemControl class={style.checkbox__control}>
<CheckboxGroup.ItemIndicator>
<CheckIcon />
</CheckboxGroup.ItemIndicator>
</CheckboxGroup.ItemControl>
<CheckboxGroup.ItemLabel class={style.checkbox__label}>
{topic}
</CheckboxGroup.ItemLabel>
</CheckboxGroup.Item>
)}
</For>
</div>
</CheckboxGroup>
);
}

export function DefaultValueExample() {
return (
<CheckboxGroup class={style["checkbox-group"]} defaultValues={["News"]}>
<CheckboxGroup.Label class={style["checkbox-group__label"]}>
Subscribe to topics
</CheckboxGroup.Label>
<div class={style["checkbox-group__items"]} role="presentation">
<For each={["News", "Updates", "Offers"]}>
{(topic) => (
<CheckboxGroup.Item id={topic} value={topic} class={style.checkbox}>
<CheckboxGroup.ItemInput class={style.checkbox__input} />
<CheckboxGroup.ItemControl class={style.checkbox__control}>
<CheckboxGroup.ItemIndicator>
<CheckIcon />
</CheckboxGroup.ItemIndicator>
</CheckboxGroup.ItemControl>
<CheckboxGroup.ItemLabel class={style.checkbox__label}>
{topic}
</CheckboxGroup.ItemLabel>
</CheckboxGroup.Item>
)}
</For>
</div>
</CheckboxGroup>
);
}

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

return (
<>
<CheckboxGroup
class={style["checkbox-group"]}
values={value()}
onChange={setValue}
>
<CheckboxGroup.Label class={style["checkbox-group__label"]}>
What would you like to subscribe to?
</CheckboxGroup.Label>
<div class={style["checkbox-group__items"]} role="presentation">
<For each={["News", "Updates", "Offers"]}>
{(option) => (
<CheckboxGroup.Item
id={option}
value={option}
class={style.checkbox}
>
<CheckboxGroup.ItemInput class={style.checkbox__input} />
<CheckboxGroup.ItemControl class={style.checkbox__control}>
<CheckboxGroup.ItemIndicator>
<CheckIcon />
</CheckboxGroup.ItemIndicator>
</CheckboxGroup.ItemControl>
<CheckboxGroup.ItemLabel class={style.checkbox__label}>
{option}
</CheckboxGroup.ItemLabel>
</CheckboxGroup.Item>
)}
</For>
</div>
</CheckboxGroup>
</>
);
}

export function DescriptionExample() {
return (
<CheckboxGroup class={style["checkbox-group"]}>
<CheckboxGroup.Label class={style["checkbox-group__label"]}>
What would you like to subscribe to?
</CheckboxGroup.Label>
<div class={style["checkbox-group__items"]} role="presentation">
<For each={["News", "Updates", "Offers"]}>
{(option) => (
<CheckboxGroup.Item value={option} class={style.checkbox}>
<CheckboxGroup.ItemInput class={style.checkbox__input} />
<CheckboxGroup.ItemControl class={style.checkbox__control}>
<CheckboxGroup.ItemIndicator>
<CheckIcon />
</CheckboxGroup.ItemIndicator>
</CheckboxGroup.ItemControl>
<CheckboxGroup.ItemLabel class={style.checkbox__label}>
{option}
</CheckboxGroup.ItemLabel>
</CheckboxGroup.Item>
)}
</For>
</div>
<CheckboxGroup.Description class={style["checkbox-group__description"]}>
Select the types of updates you'd like to receive.
</CheckboxGroup.Description>
</CheckboxGroup>
);
}

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

return (
<CheckboxGroup
class={style["checkbox-group"]}
values={value()}
onChange={setValue}
validationState={!value().includes("News") ? "invalid" : "valid"}
>
<CheckboxGroup.Label class={style["checkbox-group__label"]}>
What would you like to subscribe to?
</CheckboxGroup.Label>
<div class={style["checkbox-group__items"]} role="presentation">
<For each={["News", "Updates", "Offers"]}>
{(option) => (
<CheckboxGroup.Item
id={option}
value={option}
class={style.checkbox}
>
<CheckboxGroup.ItemInput class={style.checkbox__input} />
<CheckboxGroup.ItemControl class={style.checkbox__control}>
<CheckboxGroup.ItemIndicator>
<CheckIcon />
</CheckboxGroup.ItemIndicator>
</CheckboxGroup.ItemControl>
<CheckboxGroup.ItemLabel class={style.checkbox__label}>
{option}
</CheckboxGroup.ItemLabel>
</CheckboxGroup.Item>
)}
</For>
</div>
<CheckboxGroup.ErrorMessage
class={style["checkbox-group__error-message"]}
>
Please select News to stay informed.
</CheckboxGroup.ErrorMessage>
</CheckboxGroup>
);
}

export function HTMLFormExample() {
let formRef: HTMLFormElement | undefined;

const onSubmit = (e: SubmitEvent) => {
e.preventDefault();
e.stopPropagation();

const formData = new FormData(formRef);
const subscriptions = Array.from(formData.getAll("subscriptions"));

const result = {
...Object.fromEntries(formData),
subscriptions,
};

alert(JSON.stringify(result, null, 2));
};

return (
<form
ref={formRef}
onSubmit={onSubmit}
class="flex flex-col items-center space-y-6"
>
<CheckboxGroup class={style["checkbox-group"]} name="subscriptions">
<CheckboxGroup.Label class={style["checkbox-group__label"]}>
What would you like to subscribe to?
</CheckboxGroup.Label>
<div class={style["checkbox-group__items"]} role="presentation">
<For each={["News", "Updates", "Offers"]}>
{(option) => (
<CheckboxGroup.Item
id={option}
value={option}
class={style.checkbox}
>
<CheckboxGroup.ItemInput class={style.checkbox__input} />
<CheckboxGroup.ItemControl class={style.checkbox__control}>
<CheckboxGroup.ItemIndicator>
<CheckIcon />
</CheckboxGroup.ItemIndicator>
</CheckboxGroup.ItemControl>
<CheckboxGroup.ItemLabel class={style.checkbox__label}>
{option}
</CheckboxGroup.ItemLabel>
</CheckboxGroup.Item>
)}
</For>
</div>
</CheckboxGroup>
<div class="flex space-x-2">
<button type="reset" class="kb-button">
Reset
</button>
<button type="submit" class="kb-button-primary">
Submit
</button>
</div>
</form>
);
}
5 changes: 5 additions & 0 deletions apps/docs/src/routes/docs/core.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ const CORE_NAV_SECTIONS: NavSection[] = [
title: "Checkbox",
href: "/docs/core/components/checkbox",
},
{
title: "Checkbox Group",
href: "/docs/core/components/checkbox-group",
status: "new",
},
{
title: "Collapsible",
href: "/docs/core/components/collapsible",
Expand Down
Loading