From 878b113f621d432fcdf35abe8c2bccf6c881fc8d Mon Sep 17 00:00:00 2001 From: Kato Hiroki Date: Wed, 1 Apr 2026 11:33:13 +0000 Subject: [PATCH 1/2] fix: Suppress spinner on same-route navigation in layout Use $app/state's navigating instead of $app/stores, and limit spinner display to cross-route navigation by comparing route IDs. Fixes content flash caused by same-route param changes (e.g. workbooks filters). Co-Authored-By: Claude Sonnet 4.6 --- .claude/rules/svelte-components.md | 14 ++++++++ .claude/rules/sveltekit.md | 6 ++++ .../layout-navigation-spinner/plan.md | 33 +++++++++++++++++++ src/routes/+layout.svelte | 17 +++++++--- 4 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 docs/dev-notes/2026-04-01/layout-navigation-spinner/plan.md diff --git a/.claude/rules/svelte-components.md b/.claude/rules/svelte-components.md index c3e93a773..e9fa8ca40 100644 --- a/.claude/rules/svelte-components.md +++ b/.claude/rules/svelte-components.md @@ -37,6 +37,20 @@ Import from `flowbite-svelte`. Use Tailwind CSS v4 utility classes. Dark mode: ` When copying button styles from a reference component, always check all three axes: `color`, `size`, and `class`. Omitting `color` applies Flowbite's default (filled blue). +## Complex `{#if}` Conditions — Extract to Named Functions + +When a template condition requires API-specific knowledge or combines multiple null checks, extract it to a private function in `
@@ -29,9 +38,7 @@ - - -{#if $navigating} +{#if isCrossRouteNavigation()} {:else} {@render children?.()} From 041b2fad41bf8e7f4ae4ab524c38f5053794744f Mon Sep 17 00:00:00 2001 From: Kato Hiroki Date: Wed, 1 Apr 2026 11:34:12 +0000 Subject: [PATCH 2/2] refactor: Remove old plan (#3338) --- .../layout-navigation-spinner/plan.md | 33 ------------------- 1 file changed, 33 deletions(-) delete mode 100644 docs/dev-notes/2026-04-01/layout-navigation-spinner/plan.md diff --git a/docs/dev-notes/2026-04-01/layout-navigation-spinner/plan.md b/docs/dev-notes/2026-04-01/layout-navigation-spinner/plan.md deleted file mode 100644 index 4fbff716d..000000000 --- a/docs/dev-notes/2026-04-01/layout-navigation-spinner/plan.md +++ /dev/null @@ -1,33 +0,0 @@ -# `+layout.svelte` チラつき修正: 同一ルート内ナビゲーションでコンテンツを維持する - -## 背景・経緯 - -PR #3296 で `/workbooks` のボタンクリックを `goto()` + URL パラメータ変更に移行した結果、`$navigating` が truthy になるたびにコンテンツ全体が `` に置き換わるチラつきが発生。 - ---- - -## アプローチ選択と決定 - -| 観点 | A: スピナー条件修正(採用) | B: `pushState` + `invalidate` | -| -------------- | ------------------------------- | ----------------------------- | -| 変更ファイル数 | 1 | 3 | -| テスト追加 | 不要 | 要確認 | -| UX | 古いコンテンツが見えたまま更新 | 同上(差異はほぼなし) | -| 適用範囲 | サイト全体に波及(layout 変更) | workbooks ページのみ | - -A を採用。変更が最小で UX として十分。B は「素早い連続クリックが多い場合」に有効だが現時点ではオーバーエンジニアリング。 - ---- - -## 設計検討 Q&A - -### Q1. `$app/state` の `navigating` — なぜ `from !== null` で判定するのか? - -`$app/stores` はナビゲーション中でないとき `$navigating === null`(オブジェクトごと null)。 -`$app/state` はオブジェクトが常に存在し、`navigating.from === null` が非ナビゲーション状態を表す。 - -以前 `$app/state` で動かなかったのは `from !== null` の判定を入れていなかったため。 - -### Q2. スピナー修正で「変わった部分だけ再計算」は根本解決できるか? - -チラつきは解消されるが、サーバーへのラウンドトリップはなくならない(`goto()` のたびに `load()` が再実行される)。サーバーリクエスト自体をなくすにはクライアントサイドフィルタリングへの設計変更が必要だが、今回のスコープを超える。A 案で UX 的に十分と判断。