From 22af888ec059eac53827d07f498de1edf8859abf Mon Sep 17 00:00:00 2001 From: Martin Dvorak Date: Thu, 8 Oct 2026 19:19:20 +0000 Subject: [PATCH] Redesign the quick-action CTAs: two ways in (study deck vs. homework) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Library empty state ("Your icebox") - Replace the single "Make your first deck" button with two quick-action cards: "Create interactive test" (primary, ice-gradient icon + subtle accent border) and "Help me with my homework" (glass card, sparkles icon). Stacked on phones, side by side from 640px up; both >=44px tall. /create - Replace the "Got homework instead of notes?" banner with a two-card mode switcher above "1. Add your notes": "Study Deck & Quizzes" (the current view — aria-current, accent tint, ice icon) and "Homework Solver" (a shortcut to /homework). Icon-on-top tiles on phones, inline rows from 640px up; glass tokens + backdrop blur in both themes. Strings - New keys in both dictionaries: emptyStateCreateDeck, emptyStateHomework, actionStudyDeck, actionHomework. Drop the now-unused homework.entry and library.makeFirst keys. Drive-by AA fix (light mode, /create only) - The "New folder" dashed button and the difficulty blurbs move from frost-500 to frost-600 (4.0:1 -> ~6:1). Dark mode is unchanged. Service worker: freezmo-v8. Verified: redesign suite 32/32 (stacked/side-by-side layouts, 360/390/1280, dark+light, en+cs, >=44px targets, both cards navigate, no overflow, axe contrast), mobile 49/49, i18n 27/27, desktop regression 73/73. Lint + build clean. --- components/LibraryScreen.tsx | 37 +++++++++++++++++++++--- components/UploadScreen.tsx | 54 +++++++++++++++++++++++------------- lib/i18n-dict.ts | 16 ++++++++--- public/sw.js | 2 +- 4 files changed, 81 insertions(+), 28 deletions(-) diff --git a/components/LibraryScreen.tsx b/components/LibraryScreen.tsx index ec618ea..2beeea5 100644 --- a/components/LibraryScreen.tsx +++ b/components/LibraryScreen.tsx @@ -5,7 +5,7 @@ import { useMemo, useRef, useState, useSyncExternalStore } from "react"; import { DeckCard } from "@/components/DeckCard"; import { FolderBar } from "@/components/FolderBar"; -import { FolderIcon, UploadIcon } from "@/components/icons"; +import { FolderIcon, SnowflakeIcon, SparklesIcon, UploadIcon } from "@/components/icons"; import { Button, EmptyState } from "@/components/ui"; import { folderStore, renameFolder } from "@/lib/folders"; import { useI18n } from "@/lib/i18n"; @@ -224,9 +224,38 @@ export function LibraryScreen() { - {t("library.makeFirst")} - + /* Two ways in: build a study deck from notes, or hand over an + assignment. Stacked on phones, side by side from 640px up. */ +
+ + + + + + {t("emptyStateCreateDeck")} + + + + + + + + {t("emptyStateHomework")} + + +
} > {t("library.emptyBody")} diff --git a/components/UploadScreen.tsx b/components/UploadScreen.tsx index 8cbac2c..ce488f2 100644 --- a/components/UploadScreen.tsx +++ b/components/UploadScreen.tsx @@ -33,7 +33,7 @@ import { UNORGANIZED_ID, type Difficulty } from "@/lib/schemas"; import { upsertDeck } from "@/lib/storage"; import { openSettings } from "@/lib/ui-events"; import { cn, uid } from "@/lib/utils"; -import { CameraIcon, ChevronRightIcon, FolderIcon, IceCubeIcon, PlusIcon, SnowflakeIcon, SparklesIcon, SunIcon } from "@/components/icons"; +import { CameraIcon, FolderIcon, IceCubeIcon, PlusIcon, SnowflakeIcon, SparklesIcon, SunIcon } from "@/components/icons"; import { Button, ProgressBar } from "@/components/ui"; type Phase = "idle" | "preparing" | "loading" | "error"; @@ -321,23 +321,39 @@ export function UploadScreen() {

- {/* The other thing you can bring here: an assignment. */} - - + - - - - {t("homework.entry")} - {t("homework.nav")} → - - - + + + + + {t("actionStudyDeck")} + + + + + + + + {t("actionHomework")} + + + {error ? ( @@ -676,7 +692,7 @@ export function UploadScreen() { @@ -705,7 +721,7 @@ export function UploadScreen() { {option.icon} {t(option.labelKey)} - {t(option.blurbKey)} + {t(option.blurbKey)} ); })} diff --git a/lib/i18n-dict.ts b/lib/i18n-dict.ts index 337951e..75d59b4 100644 --- a/lib/i18n-dict.ts +++ b/lib/i18n-dict.ts @@ -172,7 +172,6 @@ const en: Record = { "homework.title": "Make my homework", "homework.subtitle": "Paste the assignment, snap a photo or add a document — then choose whether I should just do it, or guide you through it.", - "homework.entry": "Got homework instead of notes?", "homework.source.title": "1. The assignment", "homework.source.help": "Paste its text, drop photos, or add a document.", "homework.source.textLabel": "Assignment text", @@ -224,6 +223,12 @@ const en: Record = { "homework.history.openTitle": "Open “{title}”", "homework.history.deleteConfirm": "Delete this result?", + /* quick actions (library empty state + /create switcher) ----------- */ + "emptyStateCreateDeck": "Create interactive test", + "emptyStateHomework": "Help me with my homework", + "actionStudyDeck": "Study Deck & Quizzes", + "actionHomework": "Homework Solver", + /* library --------------------------------------------------------- */ "library.title": "Your icebox", "library.subtitle": "Decks frozen from your notes, saved in this browser.", @@ -235,7 +240,6 @@ const en: Record = { "library.deckMoved": "Deck moved.", "library.deckMovedUnorganized": "Deck moved to Unorganized.", "library.noDecks": "No decks yet", - "library.makeFirst": "Make your first deck", "library.emptyBody": "Freeze a page of notes into a feed of flashcards and quizzes.", "library.emptyHint": "Using your own Ollama models —", "library.emptySettings": "check the connection in Settings", @@ -752,7 +756,6 @@ const cs: Record = { "homework.title": "Udělej mi úkol", "homework.subtitle": "Vlož zadání, vyfoť ho nebo přidej dokument — a pak si vyber, jestli to mám rovnou udělat, nebo tě tím provést.", - "homework.entry": "Máš místo poznámek úkol?", "homework.source.title": "1. Zadání", "homework.source.help": "Vlož jeho text, přetáhni fotky nebo přidej dokument.", "homework.source.textLabel": "Text zadání", @@ -804,6 +807,12 @@ const cs: Record = { "homework.history.openTitle": "Otevřít „{title}“", "homework.history.deleteConfirm": "Smazat tento výsledek?", + /* quick actions (library empty state + /create switcher) ----------- */ + "emptyStateCreateDeck": "Vytvořit interaktivní test", + "emptyStateHomework": "Pomoct s úkolem", + "actionStudyDeck": "Studijní balíček a testy", + "actionHomework": "Řešitel úkolů", + /* library --------------------------------------------------------- */ "library.title": "Tvoje mraznička", "library.subtitle": "Sady zmrazené z tvých poznámek, uložené v tomto prohlížeči.", @@ -815,7 +824,6 @@ const cs: Record = { "library.deckMoved": "Sada přesunuta.", "library.deckMovedUnorganized": "Sada přesunuta do Nezařazených.", "library.noDecks": "Zatím žádné sady", - "library.makeFirst": "Vytvoř si první sadu", "library.emptyBody": "Zmraz stránku poznámek do feedu kartiček a kvízů.", "library.emptyHint": "S tvými vlastními modely Ollama —", "library.emptySettings": "zkontroluj připojení v Nastavení", diff --git a/public/sw.js b/public/sw.js index e0eb9b5..717801b 100644 --- a/public/sw.js +++ b/public/sw.js @@ -9,7 +9,7 @@ * * Bumping CACHE_VERSION is how a new deploy invalidates old assets. */ -const CACHE_VERSION = "freezmo-v7"; +const CACHE_VERSION = "freezmo-v8"; const SHELL_CACHE = `${CACHE_VERSION}-shell`; const ASSET_CACHE = `${CACHE_VERSION}-assets`;