deckhearth/.cursor/rules/ui-and-theming.mdc
Randall Stillwell ac8c998935 feat(brand): in-repo display + comment sweep for Deck Hearth (B1 of 2)
Mechanical sweep of 7 internal files — AGENTS.md branding note, two
Cursor rules (ui-and-theming, auth-and-permissions), scripts/README.md,
two pages/api/cards/import-* User-Agent strings, scripts/import-lorcana.js
comment block. Applies D1 (Deck Hearth) + D2 (deck-hearth) per operator
gate-1 ratification.

EXCLUDES (B2 owns): lib/rate-limit.js Redis prefix, package.json name,
package-lock.json regen, README.md, TESTING_GUIDE.md, three seed scripts,
pages/login.js demo-credential pre-fill, test/lib/permission-middleware
regression-lock literal (PRESERVED per Risk 4).

Verification:
- npm run lint: 128 problems (baseline preserved)
- npm run test:run: 21/21 pass
- Grep: 0 hits for `TCG Vault` in B1's seven files; expected B2 hits remain
- git diff --name-only matches B1 spec exactly

Architect brief: .convoys/pick-a-name/brief-1-display-and-comment-sweep.md
Architect commit: 50ce9ab
Operator gate-1: D1+D2 ratified.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-25 01:52:11 -05:00

61 lines
3.2 KiB
Text

---
description: Tailwind + CSS-variable theming, component patterns, and a11y reminders
globs: components/**/*.js,pages/**/*.js
---
# UI + theming
## Theming model
Two systems coexist:
1. **Tailwind utility classes** (`text-gray-700`, `bg-white`, `dark:bg-gray-800`) — used for layout, spacing, and structural styles.
2. **CSS variables** (`var(--bg-primary)`, `var(--text-primary)`, `var(--accent-ember)`, `var(--accent-flame)`, `var(--border)`) — used for colors that need to switch with theme (light/dark).
**Don't mix and match within a single style declaration.** Pick one source per property. Generally:
- Backgrounds + text colors: CSS variables (via `style={{ backgroundColor: 'var(--bg-primary)' }}`).
- Spacing, sizing, flex, grid: Tailwind classes.
- Focus rings: CSS variables for color, Tailwind for everything else (`focus:outline-none focus:ring-2 focus:ring-offset-2` + `'--tw-ring-color': 'var(--accent-ember)'`).
Theme switching: `useTheme()` from `lib/theme-context.js`. Provider is wired in `pages/_app.js`.
## Component conventions
- Functional components, default-exported by name (`export default function CardItem(...)`).
- Props destructured in the signature with defaults: `function Layout({ children, user = null, showSearch = false })`.
- **Avoid hardcoded default values for `user` props.** `Layout` currently defaults `user` to a real email address — every page passing through Layout should pass `user` explicitly. New components must default to `null` and render a logged-out state.
## Layout
Pages render inside `<Layout user={user} showSearch={...}>{children}</Layout>`. Layout owns:
- Desktop sidebar + mobile bottom-nav (`components/MobileNavigation.js`).
- Theme toggle.
- User profile dropdown.
Don't duplicate navigation in a page — extend `NavigationContent` inside Layout instead.
## Accessibility
- Every interactive element needs a label: `aria-label`, `aria-labelledby`, or visible text.
- Modals need `role="dialog"`, `aria-modal="true"`, and focus management (trap focus + restore on close).
- Color contrast: stick to the documented theme tokens — they're tuned for AA.
- Keyboard: every `onClick` on a non-`<button>` needs `tabIndex={0}` + `onKeyDown` for Enter/Space.
## Common UI patterns to reuse
| Need | Where |
| --- | --- |
| Card grid item | `components/CardItem.js` |
| Bulk-action toolbar | `components/BulkSelectionToolbar.js` |
| Modal | `components/CollectionSelectionModal.js`, `components/ShareModal.js` |
| Image upload | `components/UploadImageModal.js` |
| Camera scanner | `components/CameraScanner.js` |
| Auth-required wrapper | `components/ProtectedRoute.js` |
| Admin-only wrapper | `components/AdminProtected.js` |
| Public-or-auth wrapper | inline in `pages/cards.js` (`PublicCardsView` / `AuthenticatedCards`) — pattern to copy |
## Branding
The canonical product brand is **Deck Hearth** (two words, internal cap), ratified 2026-05-24 in the `pick-a-name` convoy. The repo directory + GitHub project name remain `tcg-vault` until the queued `rename-repo-and-vercel-project` convoy ships. New UI copy MUST use `Deck Hearth` verbatim — do not introduce a third name, do not abbreviate to "DH" outside the logo glyph (currently used in `components/Layout.js` lines 621, 714 as the sidebar logo monogram).