戻したページのリセット
stimeo--reset-on-restore
戻ったページを書かれたときの状態へ戻し、操作の途中から始まらないようにします。
Turbo はページの写しを取っておき、戻ったときに素早く見せます。その写しには、開いたままのメニューや入力しかけの値、消し損ねたお知らせも残っていて、戻った画面が操作の途中で固まって見えます。この部品は、写しから戻ったページで、そうした一時的な状態をページが書かれたときの形へまとめて戻します。画面に出ているページには手を付けないので、入力中の内容は消えません。何を戻すかはマークアップで指定します。属性を外す、クラスを外す、フォームを元に戻す、ひとつの入力欄だけを書いたときの状態へ戻す、隠し直す、取り除く、といった指定を並べられます。ページに 1 つ置けば、その範囲の中をまとめて見ます。
実行中
詳細を開き、値を入力し、トーストを表示してから、ページを戻す操作を擬似実行してください。別のページへ移ってブラウザの戻るで戻っても同じです。
開いてみる
このパネルは開いています。戻したページでは閉じた状態に戻ります。
一時的なトースト — 戻したページでは隠れます。
キーボード操作
このコンポーネント自体はキーボード操作を持ちません。
<%# Markup for the restore reset demo.
When Turbo restores a page from its cache (the Back button), the controller returns the
transient UI it covers to the way the page was written. A page still on screen is never
reset. "Simulate a restore" stands in for the Back button: demo.js puts a copy of the
covered region in its place, as Turbo does with a cached page, and the copy is reset as
it connects. Open the details, type in the field, and show the toast first. %>
<div class="reset-demo">
<p class="reset-demo__note"><%= t("components.reset_on_restore.demo.note") %></p>
<div class="reset-demo__page" data-reset-demo="page" data-controller="stimeo--reset-on-restore">
<details class="reset-demo__details" data-reset-attr="open">
<summary><%= t("components.reset_on_restore.demo.details_summary") %></summary>
<p><%= t("components.reset_on_restore.demo.details_body") %></p>
</details>
<label class="reset-demo__field">
<span><%= t("components.reset_on_restore.demo.input_label") %></span>
<input type="text" class="demo-input" data-reset-value
placeholder="<%= t("components.reset_on_restore.demo.input_placeholder") %>">
</label>
<div class="reset-demo__toast" data-reset-demo="toast" data-reset-hidden hidden role="status">
<%= t("components.reset_on_restore.demo.toast_text") %>
</div>
</div>
<div class="reset-demo__controls">
<button type="button" class="demo-trigger" data-reset-demo="show-toast">
<%= t("components.reset_on_restore.demo.show_toast") %>
</button>
<button type="button" class="demo-trigger" data-reset-demo="simulate">
<%= t("components.reset_on_restore.demo.simulate") %>
</button>
</div>
<p class="reset-demo__status" data-reset-demo="status" aria-live="polite"
data-done-text="<%= t("components.reset_on_restore.demo.done") %>"></p>
</div>
/*
* Presentation-only styles for the restore reset demo.
* The library only mutates the marked elements of a restored page (removing
* attributes, restoring fields to their authored state, re-hiding, removing
* nodes); this CSS owns layout.
*/
.reset-demo {
display: flex;
flex-direction: column;
gap: 0.75rem;
max-width: 32rem;
}
.reset-demo__note {
margin: 0;
font-size: 0.85rem;
color: var(--color-text-muted);
}
.reset-demo__page {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.reset-demo__status {
margin: 0;
min-height: 1.25rem;
font-size: 0.85rem;
color: var(--color-text-muted);
}
.reset-demo__details {
padding: 0.6rem 0.8rem;
border: 1px solid var(--border);
border-radius: 0.5rem;
}
.reset-demo__field {
display: flex;
flex-direction: column;
gap: 0.25rem;
font-size: 0.85rem;
}
.reset-demo__toast {
padding: 0.5rem 0.75rem;
border: 1px solid var(--leaf-500);
border-radius: 0.5rem;
background: var(--leaf-50);
color: var(--leaf-700);
font-size: 0.9rem;
}
.reset-demo__toast[hidden] {
display: none;
}
.reset-demo__controls {
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
}
// Consumer-side JS for the restore reset demo (demo-only).
// The Back button restores a page from Turbo's cache: a copy of the page taken earlier,
// which a new controller instance connects to. "Simulate a restore" does the same to the
// covered region — it puts a copy of it in its place — so the copy is reset as it connects.
// The controls sit outside the copied region, so their listeners survive the swap.
const demo = document.querySelector(".reset-demo");
const showToast = document.querySelector("[data-reset-demo='show-toast']");
const simulate = document.querySelector("[data-reset-demo='simulate']");
const status = document.querySelector("[data-reset-demo='status']");
if (showToast) {
showToast.addEventListener("click", () => {
const toast = document.querySelector("[data-reset-demo='toast']");
if (toast) toast.hidden = false;
});
}
if (simulate) {
simulate.addEventListener("click", () => {
if (status) status.textContent = "";
const page = document.querySelector("[data-reset-demo='page']");
if (page) page.replaceWith(page.cloneNode(true));
});
}
// The controller reports a reset once a restored copy has been put back.
if (demo && status) {
demo.addEventListener("stimeo--reset-on-restore:reset", () => {
status.textContent = status.dataset.doneText || "";
});
}
これらのスタイルは共通のデザイントークン(ライト/ダーク両対応)を使います。共通スタイルも一緒にコピーし、ルート要素の data-theme を切り替えればダークになります。
このコンポーネントを動かすために HTML へ記述する data-* 属性です。ルート要素に下の data-controller を付け、その内側に各 target / value / action を配置します。
ルート要素に付与
data-controller="stimeo--reset-on-restore"
値(Values)
| 名前 | 説明 | 属性 |
|---|---|---|
scope
|
走査を子孫に絞るセレクタ。空なら配下全体を走査する。 | data-stimeo--reset-on-restore-scope-value |
アクション
| 名前 | 説明 | アクション |
|---|---|---|
reset
|
リセット走査を今すぐ実行する(戻したページでは接続時に自動で走る)。 | stimeo--reset-on-restore#reset |
イベント
| 名前 | 説明 | イベント |
|---|---|---|
reset
|
リセット走査の実行後に発火する(戻したページの接続時と、手動実行のとき)。 | stimeo--reset-on-restore:reset |