Desktop library pass: alignment, card weight, sidebar and theme
Layout (desktop / lg+ only): - 40px top padding above the page title. - Deck grid uses minmax(320px, 1fr), so two cards fill the content width and share a right edge with the header (same max-width container). - Group headings only render once real folders exist; with none, a single quiet "All decks" label replaces "Unorganized". - Import JSON becomes a plain text button (mobile keeps the pill). Deck cards (desktop): - The whole card is a link; Study is a compact secondary button instead of a full-width solid pill. - The ... control is a 32px ghost button with a real ellipsis icon, aligned to the title's centre. - Meta line always shows the same fields (activities · runs / Not played yet); the score is a separate quiet "Best 53%" stat. - 12px rhythm between title/meta/tags/summary, 16px before the actions. - Hover: lighter surface, stronger border, soft shadow and a 2px lift in light mode (pointer devices only, so touch has no sticky hover). Sidebar (desktop rail): - All decks + Unorganized are views above the FOLDERS label; only user-created folders sit under it. - Count only on All decks. The mobile drawer is unchanged. Theme: - Dark: sidebar is a step darker (#181818 to #141414 vs #212121 page). - Light: cards get a slightly stronger border (#e2e2e2) and a soft shadow; the sidebar divider and edge shadow are stronger too. - Medium difficulty darkened to #7a5300 (6.2:1 on the light chip). Mobile is untouched: layout changes are behind lg: (or the desktop prop); theme tweaks are shared tokens. Verified: key-gate 49/49, install sheet 64/64, retry 14/14, zoom 6/6, deck chrome 15/15, deck fixes 15/15, final ux 12/12, contrast 20/20, security 8/8, pwa 16/16.
This commit is contained in:
parent
190664c1a5
commit
3aae6f3199
5 changed files with 196 additions and 67 deletions
|
|
@ -98,6 +98,9 @@ export function LibraryScreen() {
|
|||
};
|
||||
|
||||
const isEmpty = sorted.length === 0 && folderList.length === 0;
|
||||
// Group headings only earn their keep once real folders exist; with none,
|
||||
// desktop shows a single quiet “All decks” label instead of “Unorganized”.
|
||||
const hasFolders = folderList.length > 0;
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
|
|
@ -114,10 +117,23 @@ export function LibraryScreen() {
|
|||
</div>
|
||||
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<Button variant="secondary" size="md" onClick={() => importRef.current?.click()}>
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="md"
|
||||
className="lg:hidden"
|
||||
onClick={() => importRef.current?.click()}
|
||||
>
|
||||
<UploadIcon className="size-4" />
|
||||
Import JSON
|
||||
</Button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => importRef.current?.click()}
|
||||
className="hidden items-center gap-1.5 text-[13px] font-medium text-[var(--text-muted)] transition hover:text-[var(--text)] hover:underline lg:inline-flex"
|
||||
>
|
||||
<UploadIcon className="size-4" />
|
||||
Import JSON
|
||||
</button>
|
||||
<input
|
||||
ref={importRef}
|
||||
type="file"
|
||||
|
|
@ -211,7 +227,7 @@ export function LibraryScreen() {
|
|||
return (
|
||||
<section key={group.id} aria-label={group.name}>
|
||||
{/* group header -------------------------------------- */}
|
||||
<div className="mb-4 flex items-center gap-2">
|
||||
<div className={cn("mb-4 flex items-center gap-2", !hasFolders && "lg:hidden")}>
|
||||
<FolderIcon className="size-4 shrink-0 text-[var(--text-subtle)]" />
|
||||
|
||||
{isEditing && editingFolder ? (
|
||||
|
|
@ -288,6 +304,13 @@ export function LibraryScreen() {
|
|||
) : null}
|
||||
</div>
|
||||
|
||||
{/* One quiet label replaces the redundant single-group heading. */}
|
||||
{!hasFolders ? (
|
||||
<p className="mb-4 hidden text-[12px] font-medium text-[var(--text-subtle)] lg:block">
|
||||
All decks
|
||||
</p>
|
||||
) : null}
|
||||
|
||||
{confirmDelete === group.id ? (
|
||||
<p className="mb-3 text-[12.5px] text-[var(--text-muted)]">
|
||||
The {group.decks.length} deck{group.decks.length === 1 ? "" : "s"} inside will move to
|
||||
|
|
@ -302,7 +325,7 @@ export function LibraryScreen() {
|
|||
: "Empty folder — freeze a deck into it or move one over from Unorganized."}
|
||||
</div>
|
||||
) : (
|
||||
<ul className="grid list-none grid-cols-[repeat(auto-fill,minmax(280px,1fr))] gap-4">
|
||||
<ul className="grid list-none grid-cols-[repeat(auto-fill,minmax(280px,1fr))] gap-4 lg:grid-cols-[repeat(auto-fill,minmax(320px,1fr))]">
|
||||
{group.decks.map((deck) => (
|
||||
<DeckCard
|
||||
key={deck.id}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue