Comprehensive design sweep across the rest of the app following the shipped Liquid Glass + corner-border-light system (#116). ## Three classes of finding ### 1. Broken Tailwind token classes (HIGH — pages were unstyled) The decks / deck-builder / deck-detail cluster relied on Tailwind classes that don't exist in `tailwind.config.js` (no `bg-bg-*`, `text-text-*`, `border-border`, `bg-accent-ember`, `focus:ring-accent-ember`, `hover:bg-accent-ember-dark`). Those classes produced ZERO CSS — backgrounds were transparent, borders invisible, hover states absent. Rewrote with inline `style={{ ... CSS vars ... }}` + the `<Button>` / `<SearchBar>` primitives + `glass-panel` surfaces: - `pages/decks.js` (full page) - `pages/deck/[id].js` (header, stats sidebar, group-by controls, card list) - `pages/deck-builder.js` (loading spinner) - `components/DeckBuilderView.js` (toolbar + main panel) - `components/DeckBuilderCardBrowser.js` (full rewrite; integrated `<SearchBar>` for the card-picker input) - `components/DeckBuilderDeckList.js` (full rewrite) - `components/DeckBuilderStatsBar.js` - `components/ManaSymbolSettings.js` - `components/ManaSymbols.js` (single `text-text-secondary`) - `pages/admin/card-editor.js` cluster was already clean ### 2. Duplicative / stale page searches Replaced raw `<input>` search controls with the `<SearchBar>` primitive (adds clear button, ember focus ring, system-consistent rounded corners). Kept page-specific filter searches (they filter the visible list — distinct from the global TopSearchBar command palette): - `pages/my-cards.js` - `pages/community/collections.js` - `components/CardsPageView.js` - `components/CollectionPageView.js` - `components/DeckBuilderCardBrowser.js` `pages/my-cards.js` filter wrapper also lifted into a `glass-panel` chip instead of a solid `var(--bg-primary)` band. ### 3. Square corners + stale palette in shared views - `components/CollectionPageView.js`: 10 action buttons (`rounded-lg` + `hover:bg-gray-50`) → `rounded-xl` + `nav-item-hover`; 4 filter selects (`focus:ring-purple-500 rounded-lg`) → `.input-field`; view-mode toggle (`bg-white text-gray-900` — invisible in dark mode) → tokenised; SYSTEM badge gradient (`from-blue-500 to-purple-600`) → ember↔flame; tooltip (`bg-gray-900`) → `glass-panel-strong`; search-results dropdown (`bg-white border-gray-200` — invisible in dark mode) → `glass-panel-strong`; Activity / game-count / TCG-game badges palette-aligned. - `components/CardsPageView.js`: "Load More Cards" button (`bg-gradient-to-r from-blue-500 to-purple-600 rounded-lg`) → `<Button variant="primary" size="lg">`. - `components/CollectionsPageView.js`: matching SYSTEM badge + tooltip cleanup. - `components/ShareModal.js`: user-search dropdown (`border-gray-200 hover:bg-gray-50`) and email-invite card moved onto `glass-panel` + `nav-item-hover`; social-share buttons `rounded-lg hover:bg-gray-50` → `rounded-xl nav-item-hover`. - `components/Layout.js`: profile-menu dropdown row (`hover:bg-gray-50 dark:hover:bg-gray-700`) → `nav-item-hover`. - `components/CardItem.js`: bulk-select checkbox `focus:ring-purple-500` → ember. ### 4. `dark:` modifier classes (broken with `[data-theme]` theming) This app uses `[data-theme="dark"]` CSS selector theming, not Tailwind's `class` strategy, so `dark:bg-green-900/20` etc. produced no CSS in dark mode. Affected alerts on `pages/settings.js` and `pages/profile.js` — replaced with `glass-panel` + semantic border colour (flame for success, #dc2626 for error). `pages/settings.js` sidebar nav also moved off its hardcoded full-ember fill onto the system `nav-item` / `nav-item-active` / `nav-item-hover` pattern for consistency with the global sidebar. ## Verification - `npm run build` — green (Next 16 + Turbopack) - `npm run lint` — 0 errors, 1 unrelated pre-existing warning - `npm run test:run` — 113/113 pass (no test changes needed) Co-authored-by: Cursor <cursoragent@cursor.com>
134 lines
4.6 KiB
JavaScript
134 lines
4.6 KiB
JavaScript
import Link from 'next/link';
|
|
import DeckBuilderCardBrowser from './DeckBuilderCardBrowser';
|
|
import DeckBuilderDeckList from './DeckBuilderDeckList';
|
|
import DeckBuilderStatsBar from './DeckBuilderStatsBar';
|
|
import { Button } from './ui';
|
|
import { computeDeckStats } from '../lib/deck-builder-stats';
|
|
|
|
/* 2026-06-04 design-sweep pass: replaced broken Tailwind token
|
|
classes (bg-bg-secondary, text-text-primary, bg-accent-ember, etc.
|
|
— none of which are defined in tailwind.config.js and produced
|
|
zero CSS) with inline style={{ ... CSS vars ... }} + the Button
|
|
primitive + `glass-panel` + `rounded-2xl` so this view actually
|
|
renders with the Liquid Glass design system. */
|
|
|
|
export default function DeckBuilderView({
|
|
addCardToDeck,
|
|
clearFilters,
|
|
deck,
|
|
deckCards,
|
|
filters,
|
|
manaSymbolSettings,
|
|
removeCardFromDeck,
|
|
searchLoading,
|
|
searchQuery,
|
|
searchResults,
|
|
selectedCard,
|
|
setFilters,
|
|
setManaSymbolSettings,
|
|
setSearchQuery,
|
|
setSelectedCard,
|
|
setShowFilters,
|
|
setShowSettings,
|
|
setSidebarOpen,
|
|
setViewMode,
|
|
showFilters,
|
|
showSettings,
|
|
sidebarOpen,
|
|
toggleColorFilter,
|
|
viewMode,
|
|
}) {
|
|
const stats = computeDeckStats(deckCards);
|
|
|
|
return (
|
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
|
<div className="flex justify-between items-center mb-6">
|
|
<div>
|
|
<div className="flex items-center space-x-3">
|
|
<Link
|
|
href="/decks"
|
|
className="hover:underline"
|
|
style={{ color: 'var(--accent-ember)' }}
|
|
>
|
|
← Back to Decks
|
|
</Link>
|
|
</div>
|
|
<h1 className="text-3xl font-bold mt-2" style={{ color: 'var(--text-primary)' }}>
|
|
{deck.name}
|
|
</h1>
|
|
<p style={{ color: 'var(--text-secondary)' }}>
|
|
{deck.format} • {stats.totalCards}/100 cards
|
|
</p>
|
|
</div>
|
|
<div className="flex space-x-3">
|
|
<Button type="button" variant="secondary">
|
|
Save Deck
|
|
</Button>
|
|
<Link href={`/deck/${deck.id}`}>
|
|
<Button variant="primary">View Deck</Button>
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex gap-6 h-[calc(100vh-12rem)]">
|
|
<div className="flex-1 transition-all duration-300">
|
|
<div className="glass-panel rounded-2xl p-6 h-full flex flex-col">
|
|
<div className="flex justify-between items-center mb-6">
|
|
<h2 className="text-xl font-semibold" style={{ color: 'var(--text-primary)' }}>
|
|
Deck Cards ({stats.totalCards})
|
|
</h2>
|
|
<Button
|
|
type="button"
|
|
variant="primary"
|
|
onClick={() => setSidebarOpen(!sidebarOpen)}
|
|
trailingIcon={<span aria-hidden="true">{sidebarOpen ? '→' : '←'}</span>}
|
|
>
|
|
{sidebarOpen ? 'Hide' : 'Show'} Browser
|
|
</Button>
|
|
</div>
|
|
|
|
<DeckBuilderStatsBar stats={stats} />
|
|
|
|
<DeckBuilderDeckList
|
|
deckCards={deckCards}
|
|
sidebarOpen={sidebarOpen}
|
|
onOpenSidebar={() => setSidebarOpen(true)}
|
|
manaSymbolSettings={manaSymbolSettings}
|
|
onAddCard={(card, quantity) => addCardToDeck(card, quantity)}
|
|
onRemoveCard={(cardId, quantity) => removeCardFromDeck(cardId, quantity)}
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<div className={`transition-all duration-300 ${sidebarOpen ? 'w-96' : 'w-0 overflow-hidden'}`}>
|
|
<DeckBuilderCardBrowser
|
|
selectedCard={selectedCard}
|
|
onSelectCard={setSelectedCard}
|
|
onClearSelectedCard={() => setSelectedCard(null)}
|
|
viewMode={viewMode}
|
|
onViewModeChange={setViewMode}
|
|
showSettings={showSettings}
|
|
onToggleSettings={() => setShowSettings(!showSettings)}
|
|
onCollapseSidebar={() => setSidebarOpen(false)}
|
|
searchQuery={searchQuery}
|
|
onSearchQueryChange={setSearchQuery}
|
|
showFilters={showFilters}
|
|
onToggleFilters={() => setShowFilters(!showFilters)}
|
|
filters={filters}
|
|
onFiltersChange={setFilters}
|
|
onClearFilters={clearFilters}
|
|
onToggleColorFilter={toggleColorFilter}
|
|
searchLoading={searchLoading}
|
|
searchResults={searchResults}
|
|
manaSymbolSettings={manaSymbolSettings}
|
|
onManaSymbolSettingsChange={setManaSymbolSettings}
|
|
onAddCardToDeck={(card) => {
|
|
addCardToDeck(card);
|
|
setSelectedCard(null);
|
|
}}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|