Button

Buttonは、押下することで特定の操作を実行するコンポーネントです。
ボタン内部の構造はテキストやアイコン等に柔軟に変更できます。

プロパティ

Buttonは、以下のプロパティをサポートしています。

名前 デフォルト値 説明
variant string primary ボタンのスタイルを指定します。primary, secondary, success, danger のいずれかを選択できます。
size string medium ボタンのサイズを指定します。small, medium, large のいずれかを選択できます。
tone string solid ボタンのトーンを指定します。solid, ghost のいずれかを選択できます。
isSquare boolean false ボタンを正方形にします。
disabled boolean false ボタンを無効化します。無効化されたボタンはクリックできません。

インストールの手順

以下のコンポーネントのコードを、使いたいプロジェクトにコピー&ペーストします。 パスは実際のプロジェクトの構成にあわせて更新します。

atoms/Button.svelte
        <!--
@component
## 概要
- buttonタグのように、クリックなどのユーザー操作に対応する汎用的なボタンコンポーネントです
- 色(variant)、サイズ(size)、塗り(tone)を組み合わせて見た目を柔軟に変更できます

## 機能
- buttonタグと同様に、クリックやフォーカスなどのインタラクションに対応します
- 見た目を変更するためのいくつかのスタイル用Propsが追加されています(詳細はPropsセクションを参照)

## Props
- variant: ボタンの意味を指定すると、それに合わせたスタイルになります
- tone: 塗りのスタイルを指定します
- isSquare: trueにすると正方形のボタンになります
- size: サイズを指定します
- disabled: 指定するとグレーアウトされ、クリック不可になります

## Usage
```svelte
<Button variant="primary" tone="solid" size="medium">ボタン</Button>
```
-->

<script module lang="ts">
  import type { Snippet } from 'svelte';
  import type { ClassValue, HTMLButtonAttributes } from 'svelte/elements';
  import { cva, type VariantProps } from 'class-variance-authority';

  export const buttonVariants = cva('inline-flex items-center justify-center gap-2 rounded-md leading-tight text-sm outline-primary transition-colors cursor-pointer focus-visible:outline-[0.125rem] focus-visible:outline-offset-[0.125rem] focus-visible:outline-primary', {
    variants: {
      /** ボタンの使用用途 */
      variant: {
        primary: [],
        secondary: [],
        success: [],
        danger: [],
      },
      /** ボタンのサイズ */
      size: {
        small: ['min-h-9 px-3 py-2'],
        medium: ['min-h-10 px-4 py-2.5'],
        large: ['min-h-11 px-8 py-3'],
      },
      /** ボタンの塗りの値 */
      tone: {
        solid: [],
        ghost: [],
      },
      /** ボタンを正方形にするか */
      isSquare: {
        true: ['aspect-square'],
        false: [],
      },
      /** 操作できるかどうか */
      disabled: {
        true: ['opacity-50 !text-base-foreground-default pointer-events-none'],
        false: [],
      },
    },
    compoundVariants: [
      {
        variant: 'primary',
        tone: 'solid',
        class:
            'bg-primary border border-primary text-primary-on-fill active:bg-primary/80 hover:bg-primary/90 hover:border-primary/10 active:border-primary/80',
      },
      {
        variant: 'primary',
        tone: 'ghost',
        class:
            'border border-transparent text-primary active:bg-base-container-accent/80 hover:bg-base-container-accent/90 active:border-base-container-accent/80 hover:border-base-container-accent/90',
      },
      {
        variant: 'secondary',
        tone: 'solid',
        class:
            'border border-base-stroke-default text-base-foreground-default active:bg-base-container-accent/80 hover:bg-base-container-accent/90',
      },
      {
        variant: 'secondary',
        tone: 'ghost',
        class:
            'border border-transparent text-base-foreground-default active:bg-base-container-accent/80 hover:bg-base-container-accent/90 active:border-base-container-accent/80 hover:border-base-container-accent/90',
      },
      {
        variant: 'success',
        tone: 'solid',
        class:
            'bg-success border border-success text-success-on-fill active:bg-success/80 hover:bg-success/90 hover:border-success/10 active:border-success/80',
      },
      {
        variant: 'success',
        tone: 'ghost',
        class:
            'border border-transparent text-success active:bg-base-container-accent/80 hover:bg-base-container-accent/90 active:border-base-container-accent/80 hover:border-base-container-accent/90',
      },
      {
        variant: 'danger',
        tone: 'solid',
        class:
            'bg-destructive border border-destructive text-destructive-on-fill active:bg-destructive/80 hover:bg-destructive/90 hover:border-destructive/10 active:border-destructive/80',
      },
      {
        variant: 'danger',
        tone: 'ghost',
        class:
            'border border-transparent text-destructive active:bg-base-container-accent/80 hover:bg-base-container-accent/90 active:border-base-container-accent/80 hover:border-base-container-accent/90',
      },
      {
        variant: 'primary',
        disabled: true,
        tone: 'solid',
        class: '!bg-base-container-muted !border-base-container-muted !text-base-foreground-default',
      },
      {
        variant: 'success',
        disabled: true,
        tone: 'solid',
        class: '!bg-base-container-muted !border-base-container-muted !text-base-foreground-default',
      },
      {
        variant: 'danger',
        disabled: true,
        tone: 'solid',
        class: '!bg-base-container-muted !border-base-container-muted !text-base-foreground-default',
      },
      {
        isSquare: true,
        size: 'small',
        class: '!p-2.25',
      },
      {
        isSquare: true,
        size: 'medium',
        class: '!p-2.75',
      },
      {
        isSquare: true,
        size: 'large',
        class: '!p-3.25',
      },
    ],
    defaultVariants: {
      variant: 'primary',
      tone: 'solid',
      size: 'medium',
    },
  });

  export type ButtonVariants = VariantProps<typeof buttonVariants>;

  export interface ButtonProps extends ButtonVariants, HTMLButtonAttributes {
    /** クラス */
    class?: ClassValue;
    children?: Snippet<[]>;
  }
</script>

<script lang="ts">
  let { tone, isSquare, variant, size, class: className, children, ...buttonAttributes }: ButtonProps = $props();

  let buttonVariantClass = $derived(buttonVariants({ class: className, tone, isSquare, variant, disabled: buttonAttributes.disabled, size }));
</script>

<button class={buttonVariantClass} {...buttonAttributes}>
  {@render children?.()}
</button>

      

使い方


サンプル

Default

最も優先度の高いアクションに使うコンポーネントです。
基本的には1画面に1つのみ使用します。

Disabled

利用不可の状態です。

Variants

ボタンのタイプを変更することもできます。

Sizes

ボタンのサイズを変更することもできます。

Tones

ボタンのトーンを変更することもできます。

Square

ボタンを正方形にすることもできます。

Click

一般的な<button>と同様に、クリック時のイベントを登録できます。

With Icon

アイコンを追加することもできます。

Loading

ローディング状態です。

Only Style

<a> タグ等に Buttonのクラスやスタイルのみを適用することで、同じ見た目を再現できます。

Toggle Button

フラグで variant 属性や中身のコンテンツを切り替えることで Toggle Button を実現することができます。