本文へ移動
uiify

Carousel

タッチジェスチャーと前後の移動操作に対応するスライドカルーセル。

ブラウザー
Chrome 123+Firefox 121+Safari 17.5+
ティア
2
圧縮後のサイズ
7.17 kB
強制レイアウトの上限
0 ms
axe の上限
0
SSR 対応
はい
公開された契約
テストハーネス

プレイグラウンド

Carousel

注目のカード

矢印で記事を切り替えるか、ドットでスライドを選択します。

レスポンシブなカード列

右から左

ブロック軸

同期するコントロールとネイティブコマンド

停止・開始できる自動再生

フォーカスすると、開始を押すまで自動切り替えを停止します。ホバー中は一時停止します。

任意のマウスドラッグ操作

CSSトランジションによるフェード

"use client";

import { CarouselClient } from "@gunkin/uiify/components/carousel/client";

const items = ["One", "Two", "Three"].map((label) => ({
  id: label,
  label,
  className: "",
  children: <div className="">{label}</div>,
}));

export default function Example() {
  return <CarouselClient id="featured" aria-label="Featured cards" className="" items={items} />;
}
/* Optional carousel skin. The native scrollbar is only hidden once real controls replace it. */
@layer components {
  [data-uiify-carousel] {
    position: relative;
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: var(--space-sm);
    inline-size: 100%;
    max-inline-size: 40rem;
  }

  /* Full-width rows: an optional rotation button, the viewport, and the status text. */
  [data-uiify-carousel] > [data-part="viewport"],
  [data-uiify-carousel] > [data-part="status"],
  [data-uiify-carousel] > button[data-part="controls"][data-carousel-action="rotation"] {
    grid-column: 1 / -1;
  }

  /*
   * Hide the scrollbar only once the carousel is attached AND renders buttons that can
   * take over from it. Without scripting the scrollbar is the sole indication that the
   * content scrolls at all, so the static carousel keeps it. `scrollbar-width` alone is
   * enough for the supported engines — no prefixed fallback.
   */
  [data-uiify-carousel][data-enhanced]:has(> button[data-part="controls"])
    > [data-part="viewport"] {
    scrollbar-width: none;
  }

  [data-uiify-carousel]
    > [data-part="viewport"]
    > [data-part="slide"]
    > [data-part="slide-content"] {
    display: flex;
    container-type: inline-size;
    min-block-size: 18rem;
    aspect-ratio: 1;
    align-items: center;
    justify-content: center;
    border: var(--border-width) solid var(--border);
    border-radius: var(--radius-xl);
    corner-shape: squircle;
    background-color: var(--card);
    color: var(--foreground);
    font-size: 2.25rem;
    font-weight: var(--weight-semibold);
    line-height: 1;
    box-shadow: var(--shadow-popover);
  }

  /* The controls are Button-skinned (`outline`; previous/next at the icon size). */
  [data-uiify-carousel] > button[data-part="controls"][data-carousel-action="rotation"] {
    justify-self: start;
    margin-block-end: var(--space-sm);
  }

  [data-uiify-carousel] > button[data-part="controls"][data-carousel-action="previous"],
  [data-uiify-carousel] > button[data-part="controls"][data-carousel-action="next"] {
    font-size: 1.25rem;
    line-height: 1;
  }

  [data-uiify-carousel] > [data-part="dots"] > a:focus-visible {
    outline: none;
    box-shadow: 0 0 0 var(--ring-width) color-mix(in oklch, var(--ring) 16%, transparent);
  }

  [data-uiify-carousel] > [data-part="dots"] {
    /* Explicit middle column: pagination stays centred whether or not the
       previous/next buttons exist to occupy the outer columns. */
    grid-column: 2;
    justify-self: stretch;
    display: flex;
    justify-content: center;
    gap: var(--space-xs);
  }

  [data-uiify-carousel] > [data-part="dots"] > a {
    display: inline-grid;
    place-items: center;
    inline-size: 2.75rem;
    block-size: 2.75rem;
    border-radius: var(--radius-full);
    background-color: transparent;
    color: var(--muted-foreground);
    text-decoration: none;
    transition: var(--transition-colors);
    font-size: 0;
  }
  [data-uiify-carousel] > [data-part="dots"] > a::after {
    content: "";
    inline-size: 0.5rem;
    block-size: 0.5rem;
    border-radius: 50%;
    background: var(--input);
  }
  [data-uiify-carousel] > [data-part="dots"] > a[aria-current="true"]::after {
    background: var(--primary);
  }
}

@layer components {
  [data-uiify-carousel] [data-part="story"] {
    display: grid;
    grid-template-rows: auto 1fr auto;
    inline-size: 100%;
    block-size: 100%;
    min-inline-size: 0;
    min-block-size: 0;
    padding: clamp(0.875rem, 4cqi, 1.5rem);
    text-align: start;
  }

  [data-uiify-carousel] [data-part="story-topline"],
  [data-uiify-carousel] [data-part="story-footer"] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.5rem;
    color: var(--muted-foreground);
    font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
    font-size: 0.75rem;
    font-weight: 500;
    letter-spacing: 0.08em;
  }

  [data-uiify-carousel] [data-part="story-body"] {
    display: grid;
    align-content: center;
    gap: 0.75rem;
    min-inline-size: 0;
    padding-block: 1rem;
  }

  [data-uiify-carousel] [data-part="story-eyebrow"] {
    color: var(--primary);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.1em;
  }

  [data-uiify-carousel] [data-part="story-body"] > h3 {
    max-inline-size: 12ch;
    margin: 0;
    color: var(--foreground);
    font-size: clamp(1.25rem, 6cqi, 2rem);
    font-weight: 600;
    letter-spacing: -0.045em;
    line-height: 1.08;
    white-space: pre-line;
  }

  [data-uiify-carousel] [data-part="story-body"] > p {
    max-inline-size: 30ch;
    margin: 0;
    color: var(--muted-foreground);
    font-size: 0.875rem;
    line-height: 1.55;
  }
}
"use client";

import { CarouselClient } from "@gunkin/uiify/components/carousel/client";

const items = ["One", "Two", "Three"].map((label) => ({
  id: label,
  label,
  className: "",
  children: <div className="">{label}</div>,
}));

export default function Example() {
  return (
    <CarouselClient
      id="featured"
      aria-label="Featured cards"
      className={
        "relative grid [grid-template-columns:auto_1fr_auto] items-center gap-sm [inline-size:100%] [max-inline-size" +
        ":40rem] [&>button[data-part=controls]]:relative [&>button[data-part=controls]]:isolate [&>button[data-part=" +
        "controls]]:inline-flex [&>button[data-part=controls]]:items-center [&>button[data-part=controls]]:justify-c" +
        "enter [&>button[data-part=controls][hidden]]:hidden [&>button[data-part=controls]]:min-h-11 [&>button[data-" +
        "part=controls]]:min-w-11 [&>button[data-part=controls]]:gap-1.5 [&>button[data-part=controls]]:px-5 [&>butt" +
        "on[data-part=controls]]:py-0 [&>button[data-part=controls]]:border-[length:var(--border-width)] [&>button[d" +
        "ata-part=controls]]:border-solid [&>button[data-part=controls]]:[border-color:color-mix(in_oklch,_var(--for" +
        "eground)_20%,_transparent)] [&>button[data-part=controls]]:rounded-full [&>button[data-part=controls]]:bg-t" +
        "ransparent [&>button[data-part=controls]]:bg-clip-padding [&>button[data-part=controls]]:text-foreground [&" +
        ">button[data-part=controls]]:font-medium [&>button[data-part=controls]]:text-base [&>button[data-part=contr" +
        "ols]]:leading-6 [&>button[data-part=controls]]:[font-family:inherit] [&>button[data-part=controls]]:no-unde" +
        "rline [&>button[data-part=controls]]:cursor-pointer [&>button[data-part=controls]]:[transition:var(--transi" +
        "tion-colors)] [&>button[data-part=controls]]:disabled:opacity-50 [&>button[data-part=controls]]:disabled:cu" +
        "rsor-not-allowed [&>button[data-part=controls]]:focus-visible:outline-none [&>button[data-part=controls]]:f" +
        "ocus-visible:[box-shadow:0_0_0_var(--ring-width)_color-mix(in_oklch,_var(--ring)_16%,_transparent)] [@media" +
        "_(any-hover:_hover)_and_(any-pointer:_fine)]:[&>button[data-part=controls]:hover:not(:disabled)]:[backgroun" +
        "d-color:color-mix(in_oklch,_var(--foreground)_10%,_transparent)] [&>button[data-part=controls]:active:not(:" +
        "disabled)]:[background-color:color-mix(in_oklch,_var(--foreground)_16%,_transparent)] [&>button[data-part=c" +
        "ontrols]]:before:content-none [&>button[data-part=controls]]:after:content-[''] [&>button[data-part=control" +
        "s]]:after:absolute [&>button[data-part=controls]]:after:[inset:calc(-1_*_var(--border-width))] [&>button[da" +
        "ta-part=controls]]:after:z-[-1] [&>button[data-part=controls]]:after:rounded-[inherit] [&>button[data-part=" +
        "controls]]:after:pointer-events-none [&>button[data-part=controls]]:after:[padding:var(--border-width)] [&>" +
        "button[data-part=controls]]:after:[background-image:linear-gradient(to_bottom,_color-mix(in_oklch,_var(--fo" +
        "reground)_25%,_transparent),_transparent_75%)] [&>button[data-part=controls]]:after:[mask:linear-gradient(#" +
        "fff_0_0)_content-box_exclude,_linear-gradient(#fff_0_0)] [&>[data-part=viewport]]:[grid-column:1_/_-1] [&>[" +
        "data-part=status]]:[grid-column:1_/_-1] [&>button[data-part=controls][data-carousel-action=rotation]]:[grid" +
        "-column:1_/_-1] data-[enhanced]:[&:has(>button[data-part=controls])>[data-part=viewport]]:[scrollbar-width:" +
        "none] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:flex [&>[data-part=viewport]>[da" +
        "ta-part=slide]>[data-part=slide-content]]:[container-type:inline-size] [&>[data-part=viewport]>[data-part=s" +
        "lide]>[data-part=slide-content]]:[min-block-size:18rem] [&>[data-part=viewport]>[data-part=slide]>[data-par" +
        "t=slide-content]]:[aspect-ratio:1] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:ite" +
        "ms-center [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:justify-center [&>[data-part" +
        "=viewport]>[data-part=slide]>[data-part=slide-content]]:border-[length:var(--border-width)] [&>[data-part=v" +
        "iewport]>[data-part=slide]>[data-part=slide-content]]:border-solid [&>[data-part=viewport]>[data-part=slide" +
        "]>[data-part=slide-content]]:border-border [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-conte" +
        "nt]]:rounded-xl [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:[corner-shape:squircle" +
        "] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:bg-card [&>[data-part=viewport]>[dat" +
        "a-part=slide]>[data-part=slide-content]]:text-foreground [&>[data-part=viewport]>[data-part=slide]>[data-pa" +
        "rt=slide-content]]:[font-size:2.25rem] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]" +
        ":font-[number:var(--weight-semibold)] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:" +
        "leading-none [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:shadow-popover [&>button[" +
        "data-part=controls][data-carousel-action=rotation]]:[justify-self:start] [&>button[data-part=controls][data" +
        "-carousel-action=rotation]]:[margin-block-end:var(--space-sm)] [&>button[data-part=controls][data-carousel-" +
        "action=previous]]:[font-size:1.25rem] [&>button[data-part=controls][data-carousel-action=previous]]:leading" +
        "-none [&>button[data-part=controls][data-carousel-action=next]]:[font-size:1.25rem] [&>button[data-part=con" +
        "trols][data-carousel-action=next]]:leading-none [&>[data-part=dots]>a:focus-visible]:[outline:none] [&>[dat" +
        "a-part=dots]>a:focus-visible]:[box-shadow:0_0_0_var(--ring-width)_color-mix(in_oklch,_var(--ring)_16%,_tran" +
        "sparent)] [&>[data-part=dots]]:[grid-column:2] [&>[data-part=dots]]:[justify-self:stretch] [&>[data-part=do" +
        "ts]]:flex [&>[data-part=dots]]:justify-center [&>[data-part=dots]]:gap-xs [&>[data-part=dots]>a]:inline-gri" +
        "d [&>[data-part=dots]>a]:place-items-center [&>[data-part=dots]>a]:[inline-size:2.75rem] [&>[data-part=dots" +
        "]>a]:[block-size:2.75rem] [&>[data-part=dots]>a]:rounded-[var(--radius-full)] [&>[data-part=dots]>a]:bg-tra" +
        "nsparent [&>[data-part=dots]>a]:text-muted-foreground [&>[data-part=dots]>a]:no-underline [&>[data-part=dot" +
        "s]>a]:[transition:var(--transition-colors)] [&>[data-part=dots]>a]:[font-size:0] [&>[data-part=dots]>a::aft" +
        "er]:content-[''] [&>[data-part=dots]>a::after]:[inline-size:0.5rem] [&>[data-part=dots]>a::after]:[block-si" +
        "ze:0.5rem] [&>[data-part=dots]>a::after]:rounded-[50%] [&>[data-part=dots]>a::after]:bg-input [&>[data-part" +
        "=dots]>a[aria-current=true]::after]:bg-primary [&_[data-part=story]]:grid [&_[data-part=story]]:[grid-templ" +
        "ate-rows:auto_1fr_auto] [&_[data-part=story]]:[inline-size:100%] [&_[data-part=story]]:[block-size:100%] [&" +
        "_[data-part=story]]:[min-inline-size:0] [&_[data-part=story]]:[min-block-size:0] [&_[data-part=story]]:[pad" +
        "ding:clamp(0.875rem,_4cqi,_1.5rem)] [&_[data-part=story]]:text-start [&_[data-part=story-topline]]:flex [&_" +
        "[data-part=story-topline]]:items-center [&_[data-part=story-topline]]:justify-between [&_[data-part=story-t" +
        "opline]]:flex-wrap [&_[data-part=story-topline]]:[gap:0.5rem] [&_[data-part=story-topline]]:text-muted-fore" +
        "ground [&_[data-part=story-topline]]:[font-family:ui-monospace,_\"SF_Mono\",_Menlo,_Consolas,_monospace] [&_[" +
        "data-part=story-topline]]:[font-size:0.75rem] [&_[data-part=story-topline]]:[font-weight:500] [&_[data-part" +
        "=story-topline]]:[letter-spacing:0.08em] [&_[data-part=story-footer]]:flex [&_[data-part=story-footer]]:ite" +
        "ms-center [&_[data-part=story-footer]]:justify-between [&_[data-part=story-footer]]:flex-wrap [&_[data-part" +
        "=story-footer]]:[gap:0.5rem] [&_[data-part=story-footer]]:text-muted-foreground [&_[data-part=story-footer]" +
        "]:[font-family:ui-monospace,_\"SF_Mono\",_Menlo,_Consolas,_monospace] [&_[data-part=story-footer]]:[font-size" +
        ":0.75rem] [&_[data-part=story-footer]]:[font-weight:500] [&_[data-part=story-footer]]:[letter-spacing:0.08e" +
        "m] [&_[data-part=story-body]]:grid [&_[data-part=story-body]]:[align-content:center] [&_[data-part=story-bo" +
        "dy]]:[gap:0.75rem] [&_[data-part=story-body]]:[min-inline-size:0] [&_[data-part=story-body]]:[padding-block" +
        ":1rem] [&_[data-part=story-eyebrow]]:text-primary [&_[data-part=story-eyebrow]]:[font-size:0.75rem] [&_[dat" +
        "a-part=story-eyebrow]]:[font-weight:600] [&_[data-part=story-eyebrow]]:[letter-spacing:0.1em] [&_[data-part" +
        "=story-body]>h3]:[max-inline-size:12ch] [&_[data-part=story-body]>h3]:m-0 [&_[data-part=story-body]>h3]:tex" +
        "t-foreground [&_[data-part=story-body]>h3]:[font-size:clamp(1.25rem,_6cqi,_2rem)] [&_[data-part=story-body]" +
        ">h3]:[font-weight:600] [&_[data-part=story-body]>h3]:[letter-spacing:-0.045em] [&_[data-part=story-body]>h3" +
        "]:[line-height:1.08] [&_[data-part=story-body]>h3]:[white-space:pre-line] [&_[data-part=story-body]>p]:[max" +
        "-inline-size:30ch] [&_[data-part=story-body]>p]:m-0 [&_[data-part=story-body]>p]:text-muted-foreground [&_[" +
        "data-part=story-body]>p]:[font-size:0.875rem] [&_[data-part=story-body]>p]:[line-height:1.55]"
      }
      items={items}
    />
  );
}
/* app.css */

@layer reset, ui, app, tokens, base, demo, components, utilities, theme;

@import "@gunkin/uiify/styles/reset";

@import "@gunkin/uiify/components/behavior.css";

@import "@gunkin/uiify/styles/tokens";

@import "@gunkin/uiify/styles/tailwind";

@import "tailwindcss/utilities.css";

@theme { --spacing: 0.25rem; --font-weight-normal: 400; --font-weight-medium: 500; --font-weight-semibold: 600; --font-weight-bold: 700; }

@source inline('relative grid [grid-template-columns:auto_1fr_auto] items-center gap-sm [inline-size:100%] [max-inline-size:40rem] [&>button[data-part=controls]]:relative [&>button[data-part=controls]]:isolate [&>button[data-part=controls]]:inline-flex [&>button[data-part=controls]]:items-center [&>button[data-part=controls]]:justify-center [&>button[data-part=controls][hidden]]:hidden [&>button[data-part=controls]]:min-h-11 [&>button[data-part=controls]]:min-w-11 [&>button[data-part=controls]]:gap-1.5 [&>button[data-part=controls]]:px-5 [&>button[data-part=controls]]:py-0 [&>button[data-part=controls]]:border-[length:var(--border-width)] [&>button[data-part=controls]]:border-solid [&>button[data-part=controls]]:[border-color:color-mix(in_oklch,_var(--foreground)_20%,_transparent)] [&>button[data-part=controls]]:rounded-full [&>button[data-part=controls]]:bg-transparent [&>button[data-part=controls]]:bg-clip-padding [&>button[data-part=controls]]:text-foreground [&>button[data-part=controls]]:font-medium [&>button[data-part=controls]]:text-base [&>button[data-part=controls]]:leading-6 [&>button[data-part=controls]]:[font-family:inherit] [&>button[data-part=controls]]:no-underline [&>button[data-part=controls]]:cursor-pointer [&>button[data-part=controls]]:[transition:var(--transition-colors)] [&>button[data-part=controls]]:disabled:opacity-50 [&>button[data-part=controls]]:disabled:cursor-not-allowed [&>button[data-part=controls]]:focus-visible:outline-none [&>button[data-part=controls]]:focus-visible:[box-shadow:0_0_0_var(--ring-width)_color-mix(in_oklch,_var(--ring)_16%,_transparent)] [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:[&>button[data-part=controls]:hover:not(:disabled)]:[background-color:color-mix(in_oklch,_var(--foreground)_10%,_transparent)] [&>button[data-part=controls]:active:not(:disabled)]:[background-color:color-mix(in_oklch,_var(--foreground)_16%,_transparent)] [&>button[data-part=controls]]:before:content-none [&>button[data-part=controls]]:after:absolute [&>button[data-part=controls]]:after:[inset:calc(-1_*_var(--border-width))] [&>button[data-part=controls]]:after:z-[-1] [&>button[data-part=controls]]:after:rounded-[inherit] [&>button[data-part=controls]]:after:pointer-events-none [&>button[data-part=controls]]:after:[padding:var(--border-width)] [&>button[data-part=controls]]:after:[background-image:linear-gradient(to_bottom,_color-mix(in_oklch,_var(--foreground)_25%,_transparent),_transparent_75%)] [&>button[data-part=controls]]:after:[mask:linear-gradient(#fff_0_0)_content-box_exclude,_linear-gradient(#fff_0_0)] [&>[data-part=viewport]]:[grid-column:1_/_-1] [&>[data-part=status]]:[grid-column:1_/_-1] [&>button[data-part=controls][data-carousel-action=rotation]]:[grid-column:1_/_-1] data-[enhanced]:[&:has(>button[data-part=controls])>[data-part=viewport]]:[scrollbar-width:none] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:flex [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:[container-type:inline-size] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:[min-block-size:18rem] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:[aspect-ratio:1] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:items-center [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:justify-center [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:border-[length:var(--border-width)] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:border-solid [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:border-border [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:rounded-xl [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:[corner-shape:squircle] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:bg-card [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:text-foreground [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:[font-size:2.25rem] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:font-[number:var(--weight-semibold)] [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:leading-none [&>[data-part=viewport]>[data-part=slide]>[data-part=slide-content]]:shadow-popover [&>button[data-part=controls][data-carousel-action=rotation]]:[justify-self:start] [&>button[data-part=controls][data-carousel-action=rotation]]:[margin-block-end:var(--space-sm)] [&>button[data-part=controls][data-carousel-action=previous]]:[font-size:1.25rem] [&>button[data-part=controls][data-carousel-action=previous]]:leading-none [&>button[data-part=controls][data-carousel-action=next]]:[font-size:1.25rem] [&>button[data-part=controls][data-carousel-action=next]]:leading-none [&>[data-part=dots]>a:focus-visible]:[outline:none] [&>[data-part=dots]>a:focus-visible]:[box-shadow:0_0_0_var(--ring-width)_color-mix(in_oklch,_var(--ring)_16%,_transparent)] [&>[data-part=dots]]:[grid-column:2] [&>[data-part=dots]]:[justify-self:stretch] [&>[data-part=dots]]:flex [&>[data-part=dots]]:justify-center [&>[data-part=dots]]:gap-xs [&>[data-part=dots]>a]:inline-grid [&>[data-part=dots]>a]:place-items-center [&>[data-part=dots]>a]:[inline-size:2.75rem] [&>[data-part=dots]>a]:[block-size:2.75rem] [&>[data-part=dots]>a]:rounded-[var(--radius-full)] [&>[data-part=dots]>a]:bg-transparent [&>[data-part=dots]>a]:text-muted-foreground [&>[data-part=dots]>a]:no-underline [&>[data-part=dots]>a]:[transition:var(--transition-colors)] [&>[data-part=dots]>a]:[font-size:0] [&>[data-part=dots]>a::after]:[inline-size:0.5rem] [&>[data-part=dots]>a::after]:[block-size:0.5rem] [&>[data-part=dots]>a::after]:rounded-[50%] [&>[data-part=dots]>a::after]:bg-input [&>[data-part=dots]>a[aria-current=true]::after]:bg-primary [&_[data-part=story]]:grid [&_[data-part=story]]:[grid-template-rows:auto_1fr_auto] [&_[data-part=story]]:[inline-size:100%] [&_[data-part=story]]:[block-size:100%] [&_[data-part=story]]:[min-inline-size:0] [&_[data-part=story]]:[min-block-size:0] [&_[data-part=story]]:[padding:clamp(0.875rem,_4cqi,_1.5rem)] [&_[data-part=story]]:text-start [&_[data-part=story-topline]]:flex [&_[data-part=story-topline]]:items-center [&_[data-part=story-topline]]:justify-between [&_[data-part=story-topline]]:flex-wrap [&_[data-part=story-topline]]:[gap:0.5rem] [&_[data-part=story-topline]]:text-muted-foreground [&_[data-part=story-topline]]:[font-family:ui-monospace,_"SF_Mono",_Menlo,_Consolas,_monospace] [&_[data-part=story-topline]]:[font-size:0.75rem] [&_[data-part=story-topline]]:[font-weight:500] [&_[data-part=story-topline]]:[letter-spacing:0.08em] [&_[data-part=story-footer]]:flex [&_[data-part=story-footer]]:items-center [&_[data-part=story-footer]]:justify-between [&_[data-part=story-footer]]:flex-wrap [&_[data-part=story-footer]]:[gap:0.5rem] [&_[data-part=story-footer]]:text-muted-foreground [&_[data-part=story-footer]]:[font-family:ui-monospace,_"SF_Mono",_Menlo,_Consolas,_monospace] [&_[data-part=story-footer]]:[font-size:0.75rem] [&_[data-part=story-footer]]:[font-weight:500] [&_[data-part=story-footer]]:[letter-spacing:0.08em] [&_[data-part=story-body]]:grid [&_[data-part=story-body]]:[align-content:center] [&_[data-part=story-body]]:[gap:0.75rem] [&_[data-part=story-body]]:[min-inline-size:0] [&_[data-part=story-body]]:[padding-block:1rem] [&_[data-part=story-eyebrow]]:text-primary [&_[data-part=story-eyebrow]]:[font-size:0.75rem] [&_[data-part=story-eyebrow]]:[font-weight:600] [&_[data-part=story-eyebrow]]:[letter-spacing:0.1em] [&_[data-part=story-body]>h3]:[max-inline-size:12ch] [&_[data-part=story-body]>h3]:m-0 [&_[data-part=story-body]>h3]:text-foreground [&_[data-part=story-body]>h3]:[font-size:clamp(1.25rem,_6cqi,_2rem)] [&_[data-part=story-body]>h3]:[font-weight:600] [&_[data-part=story-body]>h3]:[letter-spacing:-0.045em] [&_[data-part=story-body]>h3]:[line-height:1.08] [&_[data-part=story-body]>h3]:[white-space:pre-line] [&_[data-part=story-body]>p]:[max-inline-size:30ch] [&_[data-part=story-body]>p]:m-0 [&_[data-part=story-body]>p]:text-muted-foreground [&_[data-part=story-body]>p]:[font-size:0.875rem] [&_[data-part=story-body]>p]:[line-height:1.55]');

@source inline("[&>button[data-part=controls]]:after:content-[''] [&>[data-part=dots]>a::after]:content-['']");

@layer base { :root { --uiify-control-text: var(--text-sm); } @media (pointer: coarse) { :root { --uiify-control-text: var(--text-base); } } }

/* Authored animation and registered properties used by the Tailwind skin.
 * Visual rules belong in utility recipes; only at-rule definitions live here. */
@layer components {
  @keyframes uiify-presence-in {
    from {
      opacity: 0;
      scale: var(--presence-scale);
    }
  }
}

@layer components {
  @keyframes uiify-presence-out {
    to {
      opacity: 0;
      scale: var(--presence-scale);
    }
  }
}

@property --uiify-spinner-tail {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

@property --uiify-spinner-length {
  syntax: "<angle>";
  inherits: false;
  initial-value: 36deg;
}

@layer components {
  @keyframes uiify-spinner-rotate {
    to {
      transform: rotate(360deg);
    }
  }
}

@layer components {
  @keyframes uiify-spinner-orbit {
    0% {
      --uiify-spinner-tail: 0deg;
      --uiify-spinner-length: 36deg;
    }

    50% {
      --uiify-spinner-tail: 90deg;
      --uiify-spinner-length: 324deg;
    }

    100% {
      --uiify-spinner-tail: 360deg;
      --uiify-spinner-length: 36deg;
    }
  }
}

@layer components {
  @keyframes uiify-skeleton-pulse {
    50% {
      opacity: 0.45;
    }
  }
}

@layer components {
  @keyframes uiify-skeleton-shimmer {
    to {
      background-position: -200% 0;
    }
  }
}

@layer components {
  @keyframes uiify-skeleton-reveal {
    from {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
  }
}

@property --candle-body-height {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 0%;
}

@property --candle-body-top {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 50%;
}

@property --candle-slot {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 100%;
}

@property --candle-wick-height {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 0%;
}

@property --candle-wick-top {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 50%;
}

@property --candle-x {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 0%;
}

@property --candle-scale {
  syntax: "<number>";
  inherits: true;
  initial-value: 1;
}

@property --line-y {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 50%;
}

@property --line-prev-y {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 50%;
}

@property --line-count {
  syntax: "<integer>";
  inherits: false;
  initial-value: 1;
}

@property --line-scale {
  syntax: "<number>";
  inherits: true;
  initial-value: 1;
}

@layer components {
  @keyframes uiify-otp-input-caret-blink {
    50% {
      opacity: 0;
    }
  }
}

API

Carousel

CarouselClient — @gunkin/uiify/components/carousel/client

Prop型既定値説明
defaultValue / valuenumber—初期または制御される項目インデックス。観測した停止確定状態に従ってコントロールが更新されます。
rewindbooleanfalseスライドを複製せず、両端で循環します。
mouseDragbooleanfalse明示的に有効にするマウスドラッグ。タッチとホイールはネイティブのままです。
autoplayboolean | CarouselAutoplayOptionsfalse遅延の既定値は5000msです。オプションはdelay、paused、cycles、stopOnInteractionです。可視の停止・開始操作を含みます。
onSelect / beforeChange / afterChange / onSwipecallbacks—実際に停止が確定した変更とその理由を通知します。制御時と移動中断時の意味はCarouselガイドを参照してください。
refRef<CarouselClientHandle>—next、previous、goTo、start、stop、reset。

FadeCarouselClient — @gunkin/uiify/components/carousel/fade

Prop型既定値説明
swipebooleantrueタッチ・ペンのスワイプ。マウスにはmouseDragが必要です。axis以外のクライアントpropsを継承します。非アクティブなスライドはinertになります。

キーボード

キー操作
Tab / Enterネイティブのスライドリンクにフォーカスして移動、拡張ボタンはSpaceでも実行
Arrow keysビューポートにフォーカスがある間、ネイティブのスクロールを使用

アクセシビリティ

基本のCarouselは、ネイティブのスクロール、スナップ、端で終わるフラグメントナビゲーションを備えたサーバーコンポーネントです。対話的な/clientエントリーはTier 2で、同期するドット、常時表示の矢印、コールバック、自動再生、マウスドラッグにはハイドレーションが必要です。/fadeはCSSの不透明度トランジションを追加します。フォーカスするとStartまで自動再生を停止し、ホバー中は一時停止します。動きを減らす設定では、既定で自動切り替えを無効にします。CSS生成コントロールのラボは実験的なものです。

スタイリングのフック

data-uiify-carouseldata-axisdata-enhanceddata-modedata-carousel-indexdata-statedata-dragging--uiify-carousel-slide-size--uiify-carousel-gap--uiify-carousel-fade-duration