this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

layout

+218 -224
+22
src/components/strategy-page-layout.tsx
··· 1 1 import { ChapterPager } from "~/components/chapter-navigation"; 2 + import { SectionHeader } from "~/components/console/section-header"; 2 3 3 4 interface StrategyPageLayoutProps { 4 5 sidebar?: React.ReactNode; ··· 16 17 </> 17 18 ); 18 19 } 20 + 21 + interface StrategyChapterLayoutProps { 22 + children: React.ReactNode; 23 + headerSubtitle?: string; 24 + headerTitle: string; 25 + sidebar?: React.ReactNode; 26 + } 27 + 28 + export function StrategyChapterLayout(props: StrategyChapterLayoutProps) { 29 + const { children, headerSubtitle, headerTitle, sidebar } = props; 30 + 31 + return ( 32 + <main className="min-h-screen bg-(--bg-primary) p-6"> 33 + <div className="max-w-7xl mx-auto"> 34 + <SectionHeader title={headerTitle} subtitle={headerSubtitle} /> 35 + 36 + <StrategyPageLayout sidebar={sidebar}>{children}</StrategyPageLayout> 37 + </div> 38 + </main> 39 + ); 40 + }
+15 -20
src/routes/basic.tsx
··· 1 1 import { createFileRoute } from "@tanstack/react-router"; 2 2 import { useSuspenseQuery } from "@tanstack/react-query"; 3 3 import * as v from "valibot"; 4 - import { StrategyPageLayout } from "~/components/strategy-page-layout"; 4 + import { StrategyChapterLayout } from "~/components/strategy-page-layout"; 5 5 import { ConsoleCard } from "~/components/console/console-card"; 6 - import { SectionHeader } from "~/components/console/section-header"; 7 6 import { 8 7 PokedexPagination, 9 8 PokedexTableResults, ··· 32 31 const { Article } = Route.useLoaderData(); 33 32 34 33 return ( 35 - <main className="min-h-screen bg-(--bg-primary) p-6"> 36 - <div className="max-w-7xl mx-auto"> 37 - <SectionHeader title="01_basic" subtitle="// No prefetching (baseline)" /> 38 - 39 - <StrategyPageLayout sidebar={Article}> 40 - <ConsoleCard className="mb-6"> 41 - <PokedexTableSection 42 - currentOffset={currentOffset} 43 - fallbackPagination={ 44 - <PokedexPagination prevOffset={null} nextOffset={null} to="/basic" /> 45 - } 46 - > 47 - <PokemonTableContent currentOffset={currentOffset} /> 48 - </PokedexTableSection> 49 - </ConsoleCard> 50 - </StrategyPageLayout> 51 - </div> 52 - </main> 34 + <StrategyChapterLayout 35 + headerTitle="01_basic" 36 + headerSubtitle="// No prefetching (baseline)" 37 + sidebar={Article} 38 + > 39 + <ConsoleCard className="mb-6"> 40 + <PokedexTableSection 41 + currentOffset={currentOffset} 42 + fallbackPagination={<PokedexPagination prevOffset={null} nextOffset={null} to="/basic" />} 43 + > 44 + <PokemonTableContent currentOffset={currentOffset} /> 45 + </PokedexTableSection> 46 + </ConsoleCard> 47 + </StrategyChapterLayout> 53 48 ); 54 49 } 55 50
+40 -44
src/routes/debounced-preload-filters.tsx
··· 4 4 import { queryOptions, useQueryClient, useSuspenseQuery } from "@tanstack/react-query"; 5 5 import * as v from "valibot"; 6 6 import { FilterForm, FilterSubmitContext } from "~/components/filter-form"; 7 - import { StrategyPageLayout } from "~/components/strategy-page-layout"; 7 + import { StrategyChapterLayout } from "~/components/strategy-page-layout"; 8 8 import { ConsoleCard } from "~/components/console/console-card"; 9 - import { SectionHeader } from "~/components/console/section-header"; 10 9 import { 11 10 PokedexPagination, 12 11 PokedexTableResults, ··· 102 101 const navigate = Route.useNavigate(); 103 102 104 103 return ( 105 - <main className="min-h-screen bg-(--bg-primary) p-6"> 106 - <div className="max-w-7xl mx-auto"> 107 - <SectionHeader title="06_debounced" subtitle="// Advanced filter prefetch" /> 104 + <StrategyChapterLayout 105 + headerTitle="06_debounced" 106 + headerSubtitle="// Advanced filter prefetch" 107 + sidebar={Article} 108 + > 109 + <ConsoleCard className="mb-6"> 110 + <h2 className="text-sm font-semibold mb-4 text-(--text-primary) uppercase tracking-wider"> 111 + Filters 112 + </h2> 113 + <p className="text-sm text-(--text-muted) mb-4"> 114 + Preloads results while typing (debounced 100ms) 115 + </p> 116 + <PreloadFilterSubmitContextProvider 117 + initialName={nameFilter} 118 + handleSubmit={(newNameFilter) => { 119 + void navigate({ 120 + search: { name: newNameFilter }, 121 + }); 122 + }} 123 + > 124 + <FilterForm /> 125 + </PreloadFilterSubmitContextProvider> 126 + </ConsoleCard> 108 127 109 - <StrategyPageLayout sidebar={Article}> 110 - {/* Filter UI */} 111 - <ConsoleCard className="mb-6"> 112 - <h2 className="text-sm font-semibold mb-4 text-(--text-primary) uppercase tracking-wider"> 113 - Filters 114 - </h2> 115 - <p className="text-sm text-(--text-muted) mb-4"> 116 - Preloads results while typing (debounced 100ms) 117 - </p> 118 - <PreloadFilterSubmitContextProvider 119 - initialName={nameFilter} 120 - handleSubmit={(newNameFilter) => { 121 - void navigate({ 122 - search: { name: newNameFilter }, 123 - }); 124 - }} 125 - > 126 - <FilterForm /> 127 - </PreloadFilterSubmitContextProvider> 128 - </ConsoleCard> 129 - 130 - <ConsoleCard> 131 - <PokedexTableSection 132 - currentOffset={currentOffset} 133 - nameFilter={nameFilter} 134 - fallbackPagination={ 135 - <PokedexPagination 136 - prevOffset={null} 137 - nextOffset={null} 138 - to="/debounced-preload-filters" 139 - /> 140 - } 141 - > 142 - <PokemonTableContent nameFilter={nameFilter} /> 143 - </PokedexTableSection> 144 - </ConsoleCard> 145 - </StrategyPageLayout> 146 - </div> 147 - </main> 128 + <ConsoleCard> 129 + <PokedexTableSection 130 + currentOffset={currentOffset} 131 + nameFilter={nameFilter} 132 + fallbackPagination={ 133 + <PokedexPagination 134 + prevOffset={null} 135 + nextOffset={null} 136 + to="/debounced-preload-filters" 137 + /> 138 + } 139 + > 140 + <PokemonTableContent nameFilter={nameFilter} /> 141 + </PokedexTableSection> 142 + </ConsoleCard> 143 + </StrategyChapterLayout> 148 144 ); 149 145 } 150 146
+34 -38
src/routes/filters.tsx
··· 3 3 import { queryOptions, useSuspenseQuery } from "@tanstack/react-query"; 4 4 import * as v from "valibot"; 5 5 import { FilterForm, FilterSubmitContext } from "~/components/filter-form"; 6 - import { StrategyPageLayout } from "~/components/strategy-page-layout"; 6 + import { StrategyChapterLayout } from "~/components/strategy-page-layout"; 7 7 import { ConsoleCard } from "~/components/console/console-card"; 8 - import { SectionHeader } from "~/components/console/section-header"; 9 8 import { 10 9 PokedexPagination, 11 10 PokedexTableResults, ··· 73 72 const navigate = Route.useNavigate(); 74 73 75 74 return ( 76 - <main className="min-h-screen bg-(--bg-primary) p-6"> 77 - <div className="max-w-7xl mx-auto"> 78 - <SectionHeader title="05_filters" subtitle="// Search with prefetch" /> 75 + <StrategyChapterLayout 76 + headerTitle="05_filters" 77 + headerSubtitle="// Search with prefetch" 78 + sidebar={Article} 79 + > 80 + <ConsoleCard className="mb-6"> 81 + <h2 className="text-sm font-semibold mb-4 text-(--text-primary) uppercase tracking-wider"> 82 + Filters 83 + </h2> 84 + <FilterSubmitContextProvider 85 + key={`filter-submit-context-provider-${nameFilter}`} 86 + initialName={nameFilter} 87 + handleSubmit={(newNameFilter) => { 88 + void navigate({ 89 + search: { name: newNameFilter }, 90 + }); 91 + }} 92 + > 93 + <FilterForm /> 94 + </FilterSubmitContextProvider> 95 + </ConsoleCard> 79 96 80 - <StrategyPageLayout sidebar={Article}> 81 - {/* Filter UI */} 82 - <ConsoleCard className="mb-6"> 83 - <h2 className="text-sm font-semibold mb-4 text-(--text-primary) uppercase tracking-wider"> 84 - Filters 85 - </h2> 86 - <FilterSubmitContextProvider 87 - key={`filter-submit-context-provider-${nameFilter}`} 88 - initialName={nameFilter} 89 - handleSubmit={(newNameFilter) => { 90 - void navigate({ 91 - search: { name: newNameFilter }, 92 - }); 93 - }} 94 - > 95 - <FilterForm /> 96 - </FilterSubmitContextProvider> 97 - </ConsoleCard> 98 - 99 - <ConsoleCard> 100 - <PokedexTableSection 101 - currentOffset={currentOffset} 102 - nameFilter={nameFilter} 103 - fallbackPagination={ 104 - <PokedexPagination prevOffset={null} nextOffset={null} to="/filters" /> 105 - } 106 - > 107 - <PokemonTableContent nameFilter={nameFilter} /> 108 - </PokedexTableSection> 109 - </ConsoleCard> 110 - </StrategyPageLayout> 111 - </div> 112 - </main> 97 + <ConsoleCard> 98 + <PokedexTableSection 99 + currentOffset={currentOffset} 100 + nameFilter={nameFilter} 101 + fallbackPagination={ 102 + <PokedexPagination prevOffset={null} nextOffset={null} to="/filters" /> 103 + } 104 + > 105 + <PokemonTableContent nameFilter={nameFilter} /> 106 + </PokedexTableSection> 107 + </ConsoleCard> 108 + </StrategyChapterLayout> 113 109 ); 114 110 } 115 111
+17 -20
src/routes/intent-preloading.tsx
··· 1 1 import { createFileRoute, useRouteContext } from "@tanstack/react-router"; 2 2 import { queryOptions, useSuspenseQuery } from "@tanstack/react-query"; 3 3 import * as v from "valibot"; 4 - import { StrategyPageLayout } from "~/components/strategy-page-layout"; 4 + import { StrategyChapterLayout } from "~/components/strategy-page-layout"; 5 5 import { ConsoleCard } from "~/components/console/console-card"; 6 - import { SectionHeader } from "~/components/console/section-header"; 7 6 import { 8 7 PokedexPagination, 9 8 PokedexTableResults, ··· 48 47 const { Article } = Route.useLoaderData(); 49 48 50 49 return ( 51 - <main className="min-h-screen bg-(--bg-primary) p-6"> 52 - <div className="max-w-7xl mx-auto"> 53 - <SectionHeader title="03_intent-preloading" subtitle="// Hover-based prefetch" /> 54 - 55 - <StrategyPageLayout sidebar={Article}> 56 - <ConsoleCard className="mb-6"> 57 - <PokedexTableSection 58 - currentOffset={currentOffset} 59 - fallbackPagination={ 60 - <PokedexPagination prevOffset={null} nextOffset={null} to="/intent-preloading" /> 61 - } 62 - > 63 - <PokemonTableContent /> 64 - </PokedexTableSection> 65 - </ConsoleCard> 66 - </StrategyPageLayout> 67 - </div> 68 - </main> 50 + <StrategyChapterLayout 51 + headerTitle="03_intent-preloading" 52 + headerSubtitle="// Hover-based prefetch" 53 + sidebar={Article} 54 + > 55 + <ConsoleCard className="mb-6"> 56 + <PokedexTableSection 57 + currentOffset={currentOffset} 58 + fallbackPagination={ 59 + <PokedexPagination prevOffset={null} nextOffset={null} to="/intent-preloading" /> 60 + } 61 + > 62 + <PokemonTableContent /> 63 + </PokedexTableSection> 64 + </ConsoleCard> 65 + </StrategyChapterLayout> 69 66 ); 70 67 } 71 68
+39 -42
src/routes/live-query-filters.tsx
··· 2 2 import { createFileRoute } from "@tanstack/react-router"; 3 3 import { useLiveSuspenseQuery, eq, ilike, toArray } from "@tanstack/react-db"; 4 4 import * as v from "valibot"; 5 - import { StrategyPageLayout } from "~/components/strategy-page-layout"; 5 + import { StrategyChapterLayout } from "~/components/strategy-page-layout"; 6 6 import { ConsoleCard } from "~/components/console/console-card"; 7 - import { SectionHeader } from "~/components/console/section-header"; 8 7 import { FilterForm, FilterSubmitContext } from "~/components/filter-form"; 9 8 import { 10 9 PokedexPagination, ··· 62 61 const navigate = Route.useNavigate(); 63 62 64 63 return ( 65 - <main className="min-h-screen bg-(--bg-primary) p-6"> 66 - <div className="max-w-7xl mx-auto"> 67 - <SectionHeader title="08_live-query-filters" subtitle="// Electric SQL live search" /> 68 - 69 - <StrategyPageLayout sidebar={Article}> 70 - <div> 71 - <ConsoleCard className="mb-6"> 72 - <h2 className="text-sm font-semibold mb-4 text-(--text-primary) uppercase tracking-wider"> 73 - Filters 74 - </h2> 75 - <FilterSubmitContextProvider 76 - key={`live-filter-submit-context-provider-${nameFilter}`} 77 - initialName={nameFilter} 78 - handleSubmit={(newNameFilter) => { 79 - void navigate({ 80 - search: { offset: 0, name: newNameFilter }, 81 - }); 82 - }} 83 - > 84 - <FilterForm /> 85 - </FilterSubmitContextProvider> 86 - </ConsoleCard> 64 + <StrategyChapterLayout 65 + headerTitle="08_live-query-filters" 66 + headerSubtitle="// Electric SQL live search" 67 + sidebar={Article} 68 + > 69 + <div> 70 + <ConsoleCard className="mb-6"> 71 + <h2 className="text-sm font-semibold mb-4 text-(--text-primary) uppercase tracking-wider"> 72 + Filters 73 + </h2> 74 + <FilterSubmitContextProvider 75 + key={`live-filter-submit-context-provider-${nameFilter}`} 76 + initialName={nameFilter} 77 + handleSubmit={(newNameFilter) => { 78 + void navigate({ 79 + search: { offset: 0, name: newNameFilter }, 80 + }); 81 + }} 82 + > 83 + <FilterForm /> 84 + </FilterSubmitContextProvider> 85 + </ConsoleCard> 87 86 88 - <ConsoleCard> 89 - <PokedexTableSection 90 - currentOffset={currentOffset} 87 + <ConsoleCard> 88 + <PokedexTableSection 89 + currentOffset={currentOffset} 90 + nameFilter={nameFilter} 91 + fallbackPagination={ 92 + <PokedexPagination 91 93 nameFilter={nameFilter} 92 - fallbackPagination={ 93 - <PokedexPagination 94 - nameFilter={nameFilter} 95 - nextOffset={null} 96 - prevOffset={null} 97 - to="/live-query-filters" 98 - /> 99 - } 100 - > 101 - <PokemonTableContent currentOffset={currentOffset} nameFilter={nameFilter} /> 102 - </PokedexTableSection> 103 - </ConsoleCard> 104 - </div> 105 - </StrategyPageLayout> 94 + nextOffset={null} 95 + prevOffset={null} 96 + to="/live-query-filters" 97 + /> 98 + } 99 + > 100 + <PokemonTableContent currentOffset={currentOffset} nameFilter={nameFilter} /> 101 + </PokedexTableSection> 102 + </ConsoleCard> 106 103 </div> 107 - </main> 104 + </StrategyChapterLayout> 108 105 ); 109 106 } 110 107
+17 -20
src/routes/live-query.tsx
··· 1 1 import { createFileRoute } from "@tanstack/react-router"; 2 2 import { useLiveSuspenseQuery, eq, toArray } from "@tanstack/react-db"; 3 3 import * as v from "valibot"; 4 - import { StrategyPageLayout } from "~/components/strategy-page-layout"; 4 + import { StrategyChapterLayout } from "~/components/strategy-page-layout"; 5 5 import { ConsoleCard } from "~/components/console/console-card"; 6 - import { SectionHeader } from "~/components/console/section-header"; 7 6 import { 8 7 PokedexPagination, 9 8 PokedexTableResults, ··· 38 37 const { Article } = Route.useLoaderData(); 39 38 40 39 return ( 41 - <main className="min-h-screen bg-(--bg-primary) p-6"> 42 - <div className="max-w-7xl mx-auto"> 43 - <SectionHeader title="07_live-query" subtitle="// Electric SQL synced collection" /> 44 - 45 - <StrategyPageLayout sidebar={Article}> 46 - <ConsoleCard className="mb-6"> 47 - <PokedexTableSection 48 - currentOffset={currentOffset} 49 - fallbackPagination={ 50 - <PokedexPagination prevOffset={null} nextOffset={null} to="/live-query" /> 51 - } 52 - > 53 - <PokemonTableContent currentOffset={currentOffset} /> 54 - </PokedexTableSection> 55 - </ConsoleCard> 56 - </StrategyPageLayout> 57 - </div> 58 - </main> 40 + <StrategyChapterLayout 41 + headerTitle="07_live-query" 42 + headerSubtitle="// Electric SQL synced collection" 43 + sidebar={Article} 44 + > 45 + <ConsoleCard className="mb-6"> 46 + <PokedexTableSection 47 + currentOffset={currentOffset} 48 + fallbackPagination={ 49 + <PokedexPagination prevOffset={null} nextOffset={null} to="/live-query" /> 50 + } 51 + > 52 + <PokemonTableContent currentOffset={currentOffset} /> 53 + </PokedexTableSection> 54 + </ConsoleCard> 55 + </StrategyChapterLayout> 59 56 ); 60 57 } 61 58
+17 -20
src/routes/pagination.tsx
··· 1 1 import { createFileRoute, useRouteContext } from "@tanstack/react-router"; 2 2 import { queryOptions, useSuspenseQuery } from "@tanstack/react-query"; 3 3 import * as v from "valibot"; 4 - import { StrategyPageLayout } from "~/components/strategy-page-layout"; 4 + import { StrategyChapterLayout } from "~/components/strategy-page-layout"; 5 5 import { ConsoleCard } from "~/components/console/console-card"; 6 - import { SectionHeader } from "~/components/console/section-header"; 7 6 import { 8 7 PokedexPagination, 9 8 PokedexTableResults, ··· 48 47 const { Article } = Route.useLoaderData(); 49 48 50 49 return ( 51 - <main className="min-h-screen bg-(--bg-primary) p-6"> 52 - <div className="max-w-7xl mx-auto"> 53 - <SectionHeader title="04_pagination" subtitle="// Preloading next/prev pages" /> 54 - 55 - <StrategyPageLayout sidebar={Article}> 56 - <ConsoleCard className="mb-6"> 57 - <PokedexTableSection 58 - currentOffset={currentOffset} 59 - fallbackPagination={ 60 - <PokedexPagination prevOffset={null} nextOffset={null} to="/pagination" /> 61 - } 62 - > 63 - <PokemonTableContent /> 64 - </PokedexTableSection> 65 - </ConsoleCard> 66 - </StrategyPageLayout> 67 - </div> 68 - </main> 50 + <StrategyChapterLayout 51 + headerTitle="04_pagination" 52 + headerSubtitle="// Preloading next/prev pages" 53 + sidebar={Article} 54 + > 55 + <ConsoleCard className="mb-6"> 56 + <PokedexTableSection 57 + currentOffset={currentOffset} 58 + fallbackPagination={ 59 + <PokedexPagination prevOffset={null} nextOffset={null} to="/pagination" /> 60 + } 61 + > 62 + <PokemonTableContent /> 63 + </PokedexTableSection> 64 + </ConsoleCard> 65 + </StrategyChapterLayout> 69 66 ); 70 67 } 71 68
+17 -20
src/routes/preloading.tsx
··· 1 1 import { createFileRoute, useRouteContext } from "@tanstack/react-router"; 2 2 import { queryOptions, useSuspenseQuery } from "@tanstack/react-query"; 3 3 import * as v from "valibot"; 4 - import { StrategyPageLayout } from "~/components/strategy-page-layout"; 4 + import { StrategyChapterLayout } from "~/components/strategy-page-layout"; 5 5 import { ConsoleCard } from "~/components/console/console-card"; 6 - import { SectionHeader } from "~/components/console/section-header"; 7 6 import { 8 7 PokedexPagination, 9 8 PokedexTableResults, ··· 48 47 const { Article } = Route.useLoaderData(); 49 48 50 49 return ( 51 - <main className="min-h-screen bg-(--bg-primary) p-6"> 52 - <div className="max-w-7xl mx-auto"> 53 - <SectionHeader title="02_preloading" subtitle="// Route-level prefetch" /> 54 - 55 - <StrategyPageLayout sidebar={Article}> 56 - <ConsoleCard className="mb-6"> 57 - <PokedexTableSection 58 - currentOffset={currentOffset} 59 - fallbackPagination={ 60 - <PokedexPagination prevOffset={null} nextOffset={null} to="/preloading" /> 61 - } 62 - > 63 - <PokemonTableContent /> 64 - </PokedexTableSection> 65 - </ConsoleCard> 66 - </StrategyPageLayout> 67 - </div> 68 - </main> 50 + <StrategyChapterLayout 51 + headerTitle="02_preloading" 52 + headerSubtitle="// Route-level prefetch" 53 + sidebar={Article} 54 + > 55 + <ConsoleCard className="mb-6"> 56 + <PokedexTableSection 57 + currentOffset={currentOffset} 58 + fallbackPagination={ 59 + <PokedexPagination prevOffset={null} nextOffset={null} to="/preloading" /> 60 + } 61 + > 62 + <PokemonTableContent /> 63 + </PokedexTableSection> 64 + </ConsoleCard> 65 + </StrategyChapterLayout> 69 66 ); 70 67 } 71 68