挿入要素の強調
stimeo--highlight
挿入された要素に一時フックを付け、CSS で一瞬強調/フェードイン後に自動解除。
stimeo--highlight コントローラは挿入された要素に data-highlight を一時付与し、CSS で一瞬強調またはフェードインさせ、duration ミリ秒後にフックを除去します。手書きの setTimeout 管理を不要にします。既定(自己)モードでは connect 時にコントローラ要素自身を 1 回強調し、observe を付けるとコンテナモードに切り替わり、MutationObserver が追加された要素子(Turbo Stream の append 等)をそれぞれ強調します。強調開始で stimeo--highlight:start、解除で stimeo--highlight:end を発火し、いずれも detail.element を伴います。挙動のみで色やアニメーションは持たずフックのみ提供します(CSS と、非視覚通知は Announcer / Flash と組む)。prefers-reduced-motion 下では強調を完全に抑制します(要素はそのまま表示)。自己フックは duration 前に除去するため Turbo キャッシュに残らず、 observer と保留タイマは disconnect(Turbo 遷移含む)で破棄します。
- 項目 1
- 項目 2
追加された行が一瞬強調され、元に戻ります。コンテナは observe モードで動作します。
<%# Highlight-on-insert demo: the list runs in container (observe) mode, so the
controller highlights each <li> added to it. This catalog has no Turbo Stream
backend, so demo.js appends rows on click — exactly the mutation a Turbo Stream
append would make. The library only toggles data-highlight; demo.css owns the
flash/fade transition keyed on that hook. %>
<div class="highlight-demo">
<button
type="button"
class="demo-trigger"
data-highlight-add
data-item-label="<%= t("components.highlight.demo.item") %>">
<%= t("components.highlight.demo.add") %>
</button>
<ul
class="highlight-demo__list"
data-controller="stimeo--highlight"
data-stimeo--highlight-observe-value="true">
<li><%= t("components.highlight.demo.item") %> 1</li>
<li><%= t("components.highlight.demo.item") %> 2</li>
</ul>
<p class="highlight-demo__note"><%= t("components.highlight.demo.note") %></p>
</div>
/*
* Presentation-only styles for the highlight demo. The library only toggles
* data-highlight on each inserted row; this CSS owns the flash/fade: rows transition
* their background back to normal, and a highlighted row briefly shows the accent.
* Under reduced motion the controller never sets the hook, so no transition runs.
*/
.highlight-demo {
display: flex;
flex-direction: column;
gap: 0.75rem;
max-width: 28rem;
}
.highlight-demo__list {
list-style: none;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.highlight-demo__list li {
padding: 0.5rem 0.75rem;
border: 1px solid var(--border);
border-radius: 0.375rem;
background: var(--surface-card);
transition: background-color 1s ease-out;
}
.highlight-demo__list li[data-highlight] {
background: var(--amber-50);
transition: none;
}
.highlight-demo__note {
margin: 0;
color: var(--color-text-muted);
}
// Highlight-on-insert demo (consumer-side JS).
//
// The list runs in container (observe) mode, so the controller highlights each <li>
// it gains on its own. This catalog has no Turbo Stream backend, so the button appends
// rows — the same mutation a Turbo Stream append makes — and the controller reacts.
document.querySelectorAll(".highlight-demo").forEach((root) => {
const list = root.querySelector(".highlight-demo__list");
const label = root.querySelector("[data-highlight-add]")?.dataset.itemLabel;
if (!list) return;
// Idempotent: Turbo can re-run this inline module on navigation; wire each root once
// so a click never appends two rows.
if (root.dataset.demoWired) return;
root.dataset.demoWired = "1";
let count = list.children.length;
root.querySelector("[data-highlight-add]")?.addEventListener("click", () => {
const li = document.createElement("li");
li.textContent = `${label ?? "Item"} ${(count += 1)}`;
list.appendChild(li);
});
});
これらのスタイルは共通のデザイントークン(ライト/ダーク両対応)を使います。 共通スタイルも一緒にコピーし、ルート要素の data-theme を切り替えればダークになります。
このコンポーネントを動かすために HTML へ記述する data-* 属性です。ルート要素に下の data-controller を付け、その内側に各 target / value / action を配置します。
ルート要素に付与
data-controller="stimeo--highlight"
値(Values)
| 名前 | 説明 | 属性 |
|---|---|---|
duration
|
data-highlight フックを付与しておくミリ秒(既定 1500)。 |
data-stimeo--highlight-duration-value |
observe
|
コンテナモード。追加された要素子を監視してそれぞれ強調(既定 false)。 |
data-stimeo--highlight-observe-value |
イベント
| 名前 | 説明 | イベント |
|---|---|---|
start
|
要素の強調開始時に発火。detail.element を伴う。 |
stimeo--highlight:start |
end
|
強調解除時に発火。detail.element を伴う。 |
stimeo--highlight:end |
状態フック
ライブラリが操作するのはこれらの ARIA / data 属性、カスタムプロパティだけです。見た目は利用側 CSS がこれらに反応して作ります([aria-selected] / [aria-expanded] / var(--stimeo--…) などのセレクタでフックします)。
| フック | 対象 | 意味 |
|---|---|---|
data-highlight |
強調対象の要素(自身または追加された子) | 強調中に付与(値は true)。duration 後に除去。 |