diff --git a/src/App.tsx b/src/App.tsx index 0bb840d..d6e71d2 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -16,6 +16,7 @@ import { formatRelativeTime, HoverPreviewProvider, IconButton, + OpenDeckProvider, Icons, StatTile, UndoBar, @@ -241,6 +242,18 @@ export default function App() { const [status, setStatus] = useState(null); const [libStats, setLibStats] = useState(null); const [tab, setTab] = usePersistedState("active-tab", "add"); + // A deck a chip elsewhere asked to open; DeckView picks it up and clears it. + const [openDeckId, setOpenDeckId] = useState(null); + // Deck chips only carry the deck's name, which is unique per library. + const openDeck = useCallback( + async (name: string) => { + const deck = (await api.listDecks()).find((d) => d.name === name); + if (!deck) return; + setOpenDeckId(deck.id); + setTab("decks"); + }, + [setTab], + ); const [progress, setProgress] = useState(null); const [busy, setBusy] = useState(false); // Library sync state: signed in or not, and how the last sync went. Fetched @@ -598,6 +611,7 @@ export default function App() { if (status) setOpenLibrary(status.library.id); return ( +
- + {compact && (
diff --git a/src/styles.css b/src/styles.css index 8c49eb8..c12b9a7 100644 --- a/src/styles.css +++ b/src/styles.css @@ -1671,6 +1671,19 @@ tbody tr:hover { color: var(--text); margin-right: 4px; } +/* A deck chip that opens its deck (see `DeckChip`): keeps the chip's own + look rather than the global button's, plus a hover cue. */ +.deck-chip-link { + line-height: inherit; + cursor: pointer; +} +.deck-chip.deck-chip-link { + font-weight: inherit; +} +.deck-chip-link:hover { + border-color: var(--accent); + color: var(--text-strong); +} /* ============================================================ Bulk-selection action bar (Library tab) diff --git a/src/views/CardSearch.tsx b/src/views/CardSearch.tsx index ebe4062..c739545 100644 --- a/src/views/CardSearch.tsx +++ b/src/views/CardSearch.tsx @@ -3,6 +3,7 @@ import { api, Deck, LibraryCard, LibraryFacets, PreviewContext } from "../api"; import { CardThumb, CardTile, + DeckChip, ColorPips, GroupBySelect, GroupMode, @@ -253,9 +254,7 @@ export function CardSearch({ {c.decks.map((d) => ( - - {d} - + ))} @@ -310,11 +309,7 @@ export function CardSearch({ } footer={ c.decks.length > 0 - ? c.decks.map((d) => ( - - {d} - - )) + ? c.decks.map((d) => ) : undefined } /> diff --git a/src/views/DeckView.tsx b/src/views/DeckView.tsx index 9c37617..4b38fc2 100644 --- a/src/views/DeckView.tsx +++ b/src/views/DeckView.tsx @@ -427,7 +427,16 @@ function computeDeckLegality(deck: Deck | null | undefined, contents: DeckEntry[ * card list, mana curve, and legality tile recompute immediately instead of * only on the next mount. */ -export function DeckView({ refreshSignal }: { refreshSignal?: number }) { +export function DeckView({ + refreshSignal, + openDeckId, + onOpenedDeck, +}: { + refreshSignal?: number; + /** A deck to open, e.g. from a deck chip elsewhere; `onOpenedDeck` clears it. */ + openDeckId?: number | null; + onOpenedDeck?: () => void; +}) { const [decks, setDecks] = useState([]); const [selected, setSelected] = usePersistedState(libraryKey("deck-selected"), null); const [newName, setNewName] = useState(""); @@ -444,6 +453,14 @@ export function DeckView({ refreshSignal }: { refreshSignal?: number }) { // this only matters below the .deck-layout stacking breakpoint; CSS keeps // both panes visible side by side above it regardless of this flag. const [mobileShowList, setMobileShowList] = useState(true); + + // Open a deck asked for from outside — straight to its building screen. + useEffect(() => { + if (openDeckId == null) return; + setSelected(openDeckId); + setMobileShowList(false); + onOpenedDeck?.(); + }, [openDeckId]); // Android back from the deck-building screen returns to the deck list, like // its ← button. Only while they're separate screens (the ≤720px // `.deck-layout` breakpoint): side by side, flipping the flag changes diff --git a/src/views/LibraryBrowser.tsx b/src/views/LibraryBrowser.tsx index 91b35d4..ad2eb70 100644 --- a/src/views/LibraryBrowser.tsx +++ b/src/views/LibraryBrowser.tsx @@ -12,6 +12,7 @@ import { import { CardThumb, CardTile, + DeckChip, DialogFrame, ColorPips, GroupBySelect, @@ -299,11 +300,7 @@ export function LibraryBrowser({ onSaved={() => setRefreshKey((k) => k + 1)} /> ) : ( - c.decks.map((d) => ( - - {d} - - )) + c.decks.map((d) => ) ); // Under the spares filter, how many copies are free — only worth saying for