共有トランジション基盤
stimeo--transition
出入りのアニメーションの土台。終わりを見届けてから隠します。
要素を出したり隠したりするときのアニメーションの土台です。表示するときは、まず見えるようにしてから開始の状態を当て、次の描画で終了の状態へ移すので、CSS のトランジションが確実に走ります。隠すときはその逆で、動きが終わってから実際に隠します。終わりの判定はブラウザからの合図で行い、届かなかったときのために時間による保険も持っています。途中で向きを変えることもできます。いまどの段階かは CSS から読めます。動きを減らす設定の利用者には、すぐ切り替えます。アニメーションそのものは利用側の CSS で、この部品はいつ切り替えるかだけを決めます。
実行中
段階クラスでフェード&スライドします。reduced-motion では即時切替になります。
キーボード操作
このコンポーネント自体はキーボード操作を持ちません。
<%# Transition demo: the panel is the controller element; enter/leave class values point
at the demo.css classes that define the timing and start/end states. The toggle button
lives outside the (hideable) panel, so it invokes the controller's toggle action through
the playground's exposed Stimulus app (window.Stimulus) in demo.js. The library only
stages the classes and reflects data-transition-state / hidden; demo.css owns the look. %>
<div class="transition-demo">
<button
type="button"
class="demo-trigger"
data-transition-demo-toggle
aria-expanded="false"
aria-controls="transition-demo-panel">
<%= t("components.transition.demo.toggle") %>
</button>
<div
id="transition-demo-panel"
class="transition-demo__panel"
data-controller="stimeo--transition"
data-stimeo--transition-enter-value="te-enter"
data-stimeo--transition-enter-from-value="te-from"
data-stimeo--transition-enter-to-value="te-to"
data-stimeo--transition-leave-value="te-leave"
data-stimeo--transition-leave-from-value="te-to"
data-stimeo--transition-leave-to-value="te-from"
hidden>
<%= t("components.transition.demo.panel") %>
</div>
</div>
/*
* Presentation-only styles for the transition demo. The library stages the te-* classes
* (named by the controller's enter/leave values) and toggles hidden; these classes define
* the timing and the start/end states. After a transition completes the controller strips
* the stage classes, so the panel rests at the te-to (visible) state by default.
*/
.transition-demo {
display: flex;
flex-direction: column;
gap: 0.75rem;
align-items: flex-start;
}
.transition-demo__panel {
max-width: 22rem;
padding: 1rem;
border: 1px solid var(--border);
border-radius: 0.5rem;
background: var(--surface-subtle);
}
/* Stage classes referenced by the controller's enter/leave value attributes. */
.te-enter {
transition:
opacity 0.3s ease-out,
transform 0.3s ease-out;
}
.te-leave {
transition:
opacity 0.2s ease-in,
transform 0.2s ease-in;
}
.te-from {
opacity: 0;
transform: translateY(-0.5rem);
}
.te-to {
opacity: 1;
transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
.te-enter,
.te-leave {
transition: none;
}
}
// Transition demo (consumer-side JS).
//
// The toggle button sits outside the hideable panel, so a plain data-action can't reach
// the panel's controller. The playground exposes its Stimulus application as
// window.Stimulus, so we fetch the controller instance and call its toggle() action — and
// mirror the open state onto aria-expanded from the controller's entered/left events.
document.querySelectorAll(".transition-demo").forEach((root) => {
const panel = root.querySelector('[data-controller~="stimeo--transition"]');
const button = root.querySelector("[data-transition-demo-toggle]");
if (!panel || !button) return;
// Idempotent: Turbo can re-run this inline module on navigation; wire each root once so a
// single click does not toggle twice (which flashes the panel open then shut). The marker
// is a property, not an attribute: Turbo copies attributes into its page snapshot, so an
// attribute one comes back set on a restored page whose elements carry no listeners.
if (root.demoWired) return;
root.demoWired = true;
button.addEventListener("click", () => {
window.Stimulus?.getControllerForElementAndIdentifier(panel, "stimeo--transition")?.toggle();
});
panel.addEventListener("stimeo--transition:entered", () => {
button.setAttribute("aria-expanded", "true");
});
panel.addEventListener("stimeo--transition:left", () => {
button.setAttribute("aria-expanded", "false");
});
});
これらのスタイルは共通のデザイントークン(ライト/ダーク両対応)を使います。共通スタイルも一緒にコピーし、ルート要素の data-theme を切り替えればダークになります。
このコンポーネントを動かすために HTML へ記述する data-* 属性です。ルート要素に下の data-controller を付け、その内側に各 target / value / action を配置します。
ルート要素に付与
data-controller="stimeo--transition"
値(Values)
| 名前 | 説明 | 属性 |
|---|---|---|
enter
|
enter 全体に適用するクラス(タイミング/イージング等)。 | data-stimeo--transition-enter-value |
enterFrom
|
enter 開始状態のクラス(最初に適用し次フレームで除去)。 | data-stimeo--transition-enter-from-value |
enterTo
|
enter 終了状態のクラス(次フレームで適用しトランジションを走らせる)。 | data-stimeo--transition-enter-to-value |
leave
|
leave 全体に適用するクラス。 | data-stimeo--transition-leave-value |
leaveFrom
|
leave 開始状態のクラス。 | data-stimeo--transition-leave-from-value |
leaveTo
|
leave 終了状態のクラス。 | data-stimeo--transition-leave-to-value |
timeout
|
完了検知の安全タイマ(ミリ秒、0=計算済み duration から自動)。 | data-stimeo--transition-timeout-value |
アクション
| 名前 | アクション |
|---|---|
enter
|
stimeo--transition#enter |
leave
|
stimeo--transition#leave |
toggle
|
stimeo--transition#toggle |
イベント
| 名前 | 説明 | イベント |
|---|---|---|
entered
|
enter トランジション完了時に発火。 | stimeo--transition:entered |
left
|
leave トランジション完了時に発火。 | stimeo--transition:left |
状態フック
ライブラリが操作するのはこれらの ARIA / data 属性、カスタムプロパティだけです。見た目は利用側 CSS がこれらに反応して作ります([aria-selected] / [aria-expanded] / var(--stimeo--…) などのセレクタでフックします)。
| フック | 対象 | 意味 |
|---|---|---|
data-transition-state |
コントローラ要素 | entering / entered / leaving / left。 |
hidden |
コントローラ要素 | enter 開始で除去、leave 完了で付与。 |