Checkbox Card
CheckboxCardは、チェックボックスとカードUIを組み合わせた選択UI向けコンポーネントです。
checkbox_card/default is coming soon.
<script lang="ts">
import CheckboxCard from '$lib/components/ui/modules/CheckboxCard.svelte';
</script>
<div class="flex items-center justify-center size-full min-h-screen">
<CheckboxCard id="option-1" class="w-80" value="choice1">
<div>
<div class="font-normal text-sm/tight mb-1.5">選択肢1</div>
<div class="font-normal text-base-foreground-muted text-sm">ここに補足文が入ります。</div>
</div>
</CheckboxCard>
</div>
プロパティ
CheckboxCardは、以下のプロパティをサポートしています。
| 名前 | 型 | デフォルト値 | 説明 |
|---|---|---|---|
children |
Snippet<[]> |
カード内に表示するコンテンツ | |
group |
any[] |
選択値(bind:group で双方向バインド) |
|
isError |
boolean |
false |
true の場合はエラースタイルを適用します。 |
checked |
boolean |
チェック状態を制御します。 | |
value |
any |
チェックボックスの値です。 | |
indeterminate |
boolean |
false |
一部のみ選択された状態や、不確定な状態を表します。 |
インストールの手順
以下のコンポーネントのコードを、使いたいプロジェクトにコピー&ペーストします。
パスは実際のプロジェクトの構成にあわせて更新します。
modules/CheckboxCard.svelte
<!--
@component
## 概要
- チェックボックスとカードUIを組み合わせた選択用コンポーネントです。
## 機能
- カード全体をクリックしてチェックボックス選択できます
- groupバインディングで選択状態を外部と同期できます
- disabled / isError に応じて状態別スタイルを適用します
## Props
- children: カード内に表示する Snippet
- group: 選択値(bind:groupで双方向バインド)
- isError: trueの場合はエラースタイルを適用します
- class: 追加クラス
- checked: チェックしているかどうか
- value: 値
- indeterminate: 一部のみ選択された状態や、不確定な状態です
## Usage
```svelte
<CheckboxCard value="option-a" bind:group={selected}>
<div>選択肢A</div>
</CheckboxCard>
```
-->
<script lang="ts" module>
import type { Snippet } from 'svelte';
import type { ClassValue, HTMLInputAttributes } from 'svelte/elements';
import { cva } from 'class-variance-authority';
export const checkboxCardVariants = cva('flex size-full gap-2 p-4 border border-base-stroke-default rounded-md cursor-pointer hover:bg-base-container-accent/90 has-[:focus-visible]:ring-2 has-[:focus-visible]:ring-offset-2 has-[:focus-visible]:ring-offset-base-container-default has-[:focus-visible]:ring-primary', {
variants: {
/** 操作できるかどうか */
disabled: {
true: ['opacity-50 pointer-events-none'],
false: ['cursor-pointer'],
},
/** エラーかどうか */
isError: {
true: ['border-destructive'],
false: ['has-checked:border-primary'],
},
},
});
export interface CheckboxCardProps extends HTMLInputAttributes {
/** カードの中身 */
children: Snippet<[]>;
/** 選択されている値を保持する変数(双方向バインド用) */
group?: any[];
/** エラー状態(スタイル制御用) */
isError?: boolean;
/** クラス */
class?: ClassValue;
/** チェックしているかどうか */
checked?: boolean;
/** 値 */
value?: any;
/** 不確定な要素かどうか */
indeterminate?: boolean;
}
</script>
<script lang="ts">
import Checkbox from '$lib/components/ui/atoms/Checkbox.svelte';
import Label from '$lib/components/ui/atoms/Label.svelte';
let { children, group = $bindable(), checked, indeterminate = false, isError = false, class: className, value, ...inputAttributes }: CheckboxCardProps = $props();
let checkboxCardVariantClass = $derived(checkboxCardVariants({ class: className, disabled: inputAttributes.disabled, isError }));
</script>
<Label for={inputAttributes.id}>
<div class={['group', checkboxCardVariantClass]}>
<Checkbox class="*:outline-none" {...inputAttributes} {checked} {indeterminate} bind:group {isError} {value} />
{@render children()}
</div>
</Label>
依存コンポーネント
CheckboxCardを使うときは、以下のコンポーネントもダウンロードが必要です。
使い方
checkbox_card/default is coming soon.
<script lang="ts">
import CheckboxCard from '$lib/components/ui/modules/CheckboxCard.svelte';
</script>
<div class="flex items-center justify-center size-full min-h-screen">
<CheckboxCard id="option-1" class="w-80" value="choice1">
<div>
<div class="font-normal text-sm/tight mb-1.5">選択肢1</div>
<div class="font-normal text-base-foreground-muted text-sm">ここに補足文が入ります。</div>
</div>
</CheckboxCard>
</div>
サンプル
Default
特に操作が行われていない、デフォルトの状態です。
checkbox_card/default is coming soon.
<script lang="ts">
import CheckboxCard from '$lib/components/ui/modules/CheckboxCard.svelte';
</script>
<div class="flex items-center justify-center size-full min-h-screen">
<CheckboxCard id="option-1" class="w-80" value="choice1">
<div>
<div class="font-normal text-sm/tight mb-1.5">選択肢1</div>
<div class="font-normal text-base-foreground-muted text-sm">ここに補足文が入ります。</div>
</div>
</CheckboxCard>
</div>
Error
入力内容に問題があり、エラーが表示されている状態です。
checkbox_card/error is coming soon.
<script lang="ts">
import CheckboxCard from '$lib/components/ui/modules/CheckboxCard.svelte';
</script>
<div class="flex items-center justify-center size-full min-h-screen">
<CheckboxCard id="option-1" class="w-80" isError value="choice1">
<div>
<div class="font-normal text-sm/tight mb-1.5">選択肢1</div>
<div class="font-normal text-base-foreground-muted text-sm">ここに補足文が入ります。</div>
</div>
</CheckboxCard>
</div>
Disabled
利用不可の状態です。
checkbox_card/disabled is coming soon.
<script lang="ts">
import CheckboxCard from '$lib/components/ui/modules/CheckboxCard.svelte';
</script>
<div class="flex items-center justify-center size-full min-h-screen">
<CheckboxCard id="option-1" class="w-80" disabled>
<div>
<div class="font-normal text-sm/tight mb-1.5">選択肢1</div>
<div class="font-normal text-base-foreground-muted text-sm">ここに補足文が入ります。</div>
</div>
</CheckboxCard>
</div>
GroupText
bind:groupを使うことで、複数のチェックボックスをグループ化し、同じ値を共有できます。
checkbox_card/group_text is coming soon.
<script lang="ts">
import Label from '$lib/components/ui/atoms/Label.svelte';
import CheckboxCard from '$lib/components/ui/modules/CheckboxCard.svelte';
const textList = [
{ id: 'option-1', name: 'selection-group-1', value: 'choice1', text: '選択肢1' },
{ id: 'option-2', name: 'selection-group-2', value: 'choice2', text: '選択肢2' },
{ id: 'option-3', name: 'selection-group-3', value: 'choice3', text: '選択肢3' },
];
let selectedValue = $state(['choice1']);
</script>
<div class="flex flex-col items-center justify-center size-full min-h-screen py-12">
<div class="flex flex-col">
<Label class="mb-1.5">ラベル</Label>
<div class="font-normal text-base-foreground-muted text-sm mb-4">ここに補足文が入ります。</div>
<div class="flex flex-col gap-2">
{#each textList as text}
<CheckboxCard id={text.id} class="w-80" bind:group={selectedValue} value={text.value} name={text.name}>
<div class="flex flex-col gap-1.5">
<div class="font-normal text-sm/tight">{text.text}</div>
<div class="font-normal text-base-foreground-muted text-sm">ここに補足文が入ります。</div>
</div>
</CheckboxCard>
{/each}
</div>
</div>
</div>
GroupImage
bind:groupを使うことで、複数のチェックボックスをグループ化し、同じ値を共有できます。
checkbox_card/group_image is coming soon.
<script lang="ts">
import Label from '$lib/components/ui/atoms/Label.svelte';
import CheckboxCard from '$lib/components/ui/modules/CheckboxCard.svelte';
const cardList = [
{ id: 'option-1', name: 'selection-group-1', value: 'choice1', text: '選択肢1', image: '/images/sample-rectangle.png' },
{ id: 'option-2', name: 'selection-group-2', value: 'choice2', text: '選択肢2', image: '/images/sample-rectangle.png' },
{ id: 'option-3', name: 'selection-group-3', value: 'choice3', text: '選択肢3', image: '/images/sample-rectangle.png' },
];
let selectedValue = $state(['choice1']);
</script>
<div class="flex justify-center size-full min-h-screen py-12 flexitems-center">
<div class="w-xs">
<Label class="mb-1.5">ラベル</Label>
<div class="font-normal text-base-foreground-muted text-sm mb-4">ここに補足文が入ります。</div>
<div class="flex flex-col gap-2">
{#each cardList as list}
<CheckboxCard id={list.id} name={list.name} bind:group={selectedValue} value={list.value}>
<div class="flex flex-col gap-1.5">
<div class="font-normal text-sm/tight">{list.text}</div>
<img class="w-full rounded-md object-contain" src={list.image} alt="">
</div>
</CheckboxCard>
{/each}
</div>
</div>
</div>