Skip to content
fandhe-frontendcore v0.4.3
GitHub

Carousel

スライド送り UI です。fandhe-frontend-headless-ui の carousel mod は Root / Control / PrevTrigger / NextTrigger / ItemGroup / Item / IndicatorGroup / Indicator の 8 anatomy パーツと、role="region"・aria-roledescription・自動生成の aria-label を提供します。Themes 版と異なりトランジション CSS やレイアウトを持たず、SSR での属性出力と決定的な状態機械のみを担います。

アクセシビリティ・参考サイトとの対応(イシュー #1660): zag.js(ark-ui の内部実装)と突合し、data-orientation を全 8 パーツへ拡張、item/indicator に data-index(0-origin)、item に data-inview を追加しました。一方、非表示スライドへの aria-hidden 付与は本モジュールが CSS 前提の見た目を持たない SSR 静的マークアップのため意図的に見送っています(非 current を実際に隠さない構成で aria-hidden のみ付けると全スライドが可視のまま支援技術からのみ隠れる不整合になるため)。非 current を CSS で隠す場合は呼び出し側で attrs に ("aria-hidden", "true") を渡してください。同様に aria-controls(trigger → item-group)・各パーツの id/dir も headless-ui に生成機構がないため、必要な場合は item_group の attrs に id、trigger の attrs に aria-controls を明示的に渡す運用とします。

キーボード操作(現状の対応範囲): 状態機械 Carousel は決定的な dispatch action を提供します("next"/"prev" が横向き ArrowRight/ArrowLeft・縦向き ArrowDown/ArrowUp 相当、"first"/"last" が Home/End 相当)。ただし実際のキーボードイベント配線(keydown リスナー登録・orientation に応じたキー選別)は fandhe-frontend-wasm-full(クライアントランタイム)側の後続責務であり、本イシューのスコープ外です。trigger/indicator は native button のためクリック(Enter/Space)は標準の DOM 挙動でカバーされます。

スタイル済みの表示例は Carousel を参照してください。

関連 API: fandhe-frontend-headless-ui API

Demo

枠線・余白は docs サイト側のデモ枠であり、fandhe-frontend-headless-ui 自体はスタイルを持ちません。

Slide 1
Slide 2
Slide 3

Features

  • Root / Control / PrevTrigger / NextTrigger / ItemGroup / Item / IndicatorGroup / Indicator の 8 anatomy パーツを提供する(carousel.rs 冒頭)。
  • root は role="region" + aria-roledescription="carousel" + 呼び出し側指定の aria-label を固定出力する(carousel.rs::root)。
  • item は role="group" + aria-roledescription="slide" + "{n} of {m}" 形式の aria-label を自動生成する(carousel.rs::item)。
  • autoplay 非対応の初期実装のため item_group の aria-live は常に "polite" 固定(carousel.rs::item_group)。
  • index==slide_count-1 かつ loop=true のとき Next は先頭へ循環し、prev/next とも disabled にならない決定的な遷移規則を持つ(carousel.rs モジュール doc「決定的な遷移規則」節)。
  • zag.js との参照突合(イシュー #1660)により data-orientation を全 8 パーツへ拡張し、item/indicator に data-index(0-origin)、item に data-inview を追加した(carousel.rs モジュール doc「参考サイトとの突合」節)。
  • dispatch に Home/End キー相当の "first"/"last"(CarouselAction::First/Last)を追加した(carousel.rs::CarouselAction)。DOM keydown 配線自体は wasm-full 側の後続責務のためスコープ外(下記キーボード操作参照)。

Anatomy

root
  item-group
    item
  control
    prev-trigger
    indicator-group
      indicator
    next-trigger

API Reference

Arguments

NameTypeDefaultDescription
root/control/prev_trigger/next_trigger/item_group/item/indicator_group/indicator: orientationOrientation—carousel のレイアウト方向。全 8 パーツが data-orientation を出力する(carousel.rs、イシュー #1660)。
root: label&str—aria-label に出力する説明文(carousel.rs::root、必須)。
prev_trigger/next_trigger: disabledboolfalse端かつ loop=false のとき true(native disabled + data-disabled、carousel.rs::prev_trigger/next_trigger)。
item: index, count, currentusize, usize, bool—スライド位置・総数・現在表示中かどうか(aria-label/data-index/data-inview/data-current 生成元、carousel.rs::item)。
indicator: index, currentusize, bool—インジケータの位置・現在位置かどうか(aria-label/data-index/aria-current/data-current 生成元、carousel.rs::indicator)。
Carousel::new: index, slide_count, loop_, orientationusize, usize, bool, Orientation—状態機械の初期値(carousel.rs::Carousel::new)。

Data Attributes

PartAttributeObserved Values
controldata-orientationhorizontal
indicatordata-current(値なし)
indicatordata-index0, 1, 2
indicatordata-orientationhorizontal
indicator-groupdata-orientationhorizontal
itemdata-current(値なし)
itemdata-index0, 1, 2
itemdata-inview(値なし)
itemdata-orientationhorizontal
item-groupdata-orientationhorizontal
next-triggerdata-orientationhorizontal
prev-triggerdata-disabled(値なし)
prev-triggerdata-orientationhorizontal
rootdata-orientationhorizontal

Examples

縦方向レイアウト・loop 有効で末尾スライドを表示した例です(Demo は水平・非 loop)。

Slide 1
Slide 2
Slide 3

自前 CSS の最小例

data-scope/data-part/data-orientation/data-current/data-disabled 属性セレクタでトラック移動・インジケータ強調・trigger 減光のスタイルを当てる例です。

利用者が data-scope / data-part / data-orientation / data-current / data-disabled 属性セレクタで自前 CSS を当てる最小例です。headless-ui 自体はスタイルを持ちません(root を表示領域〔overflow: hidden〕、item-group をトラックとして分離し、item_group の style="--fandhe-carousel-index: N" を calc() で参照する transform〔水平は translateX、縦方向は translateY〕で現在位置までスライドを移動します)。

Slide 1
Slide 2
Slide 3
CSS
[data-scope="carousel"][data-part="root"] {
  overflow: hidden;
  width: 100%;
}
[data-scope="carousel"][data-part="item-group"] {
  display: flex;
  transform: translateX(calc(var(--fandhe-carousel-index) * -100%));
  transition: transform 0.2s;
}
[data-scope="carousel"][data-part="item"] {
  flex: 0 0 100%;
  min-width: 0;
  min-height: 0;
  overflow: hidden;
}
[data-scope="carousel"][data-part="item-group"][data-orientation="vertical"] {
  flex-direction: column;
  height: 12rem;
  overflow: hidden;
  transform: none;
}
[data-scope="carousel"][data-part="item"][data-orientation="vertical"] {
  transition: transform 0.2s;
  transform: translateY(calc(var(--fandhe-carousel-index) * -100%));
}
[data-scope="carousel"][data-part="indicator"][data-current] {
  background: #2563eb;
}
[data-scope="carousel"][data-part="prev-trigger"][data-disabled],
[data-scope="carousel"][data-part="next-trigger"][data-disabled] {
  opacity: 0.4;
  cursor: not-allowed;
}

Accessibility

WAI-ARIA

AttributeDescription
role="region" / aria-roledescription="carousel" / aria-labelroot に固定出力する(carousel.rs::root)。
role="group" / aria-roledescription="slide" / aria-labelitem に固定出力し、aria-label は "{n} of {m}" 形式(carousel.rs::item)。
aria-live="polite"item_group に固定出力する(carousel.rs::item_group)。
aria-labelprev_trigger/next_trigger/indicator に呼び出し側指定または自動生成の説明文を出力する(carousel.rs::prev_trigger/next_trigger/indicator)。
aria-current="true"indicator が current のときのみ出力する(carousel.rs::indicator。zag.js には存在しない超集合)。