From d317648d2f119df4537eb3c6a4ca0a2505dcab60 Mon Sep 17 00:00:00 2001 From: Elijah Voigt Date: Tue, 3 Mar 2026 10:27:46 -0800 Subject: [PATCH] feat(quotesdb): add comprehensive BEM stylesheet for all UI components Covers all component and page classes: - Navigation bar (nav, nav__brand, nav__links, nav__link) - QuoteCard (quote-card, quote-card__text, footer, author, source, tags, tag, link) - ErrorDisplay (error-display, error-display__message) - Pagination (pagination, pagination__btn, pagination__info) - AuthModal (auth-modal__overlay, auth-modal, auth-modal__title/input/actions) - All page containers (page-home, page-browse, page-quote, page-author, page-submit) - Edit form, submit form, success state with auth code box - Base styles: reset, typography, buttons, form inputs - Responsive breakpoint at 640px Co-Authored-By: Claude Sonnet 4.6 --- quotesdb/src/bin/ui/style.css | 601 ++++++++++++++++++++++++++++++++++ 1 file changed, 601 insertions(+) create mode 100644 quotesdb/src/bin/ui/style.css diff --git a/quotesdb/src/bin/ui/style.css b/quotesdb/src/bin/ui/style.css new file mode 100644 index 0000000..88554bc --- /dev/null +++ b/quotesdb/src/bin/ui/style.css @@ -0,0 +1,601 @@ +/* ============================================================ + QuotesDB — Main Stylesheet + Convention: BEM (Block__Element--Modifier) + Color scheme: neutral (gray scale with indigo accent) + ============================================================ */ + +/* ── CSS Custom Properties ─────────────────────────────────── */ +:root { + --color-bg: #f9f9f9; + --color-surface: #ffffff; + --color-border: #e2e8f0; + --color-text: #1a202c; + --color-text-muted: #718096; + --color-accent: #4f46e5; + --color-accent-hover: #4338ca; + --color-danger: #dc2626; + --color-danger-hover: #b91c1c; + --color-success: #16a34a; + --color-error-bg: #fef2f2; + --color-error-border: #fecaca; + --color-code-bg: #f1f5f9; + --radius: 6px; + --shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; + --font-mono: "Fira Code", "Cascadia Code", "Consolas", monospace; +} + +/* ── Base / Reset ──────────────────────────────────────────── */ +*, *::before, *::after { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +body { + font-family: var(--font-sans); + background-color: var(--color-bg); + color: var(--color-text); + line-height: 1.6; + min-height: 100vh; +} + +#app { + display: flex; + flex-direction: column; + min-height: 100vh; +} + +h1 { + font-size: 2rem; + font-weight: 700; + line-height: 1.2; + margin-bottom: 1rem; +} + +h2 { + font-size: 1.5rem; + font-weight: 600; + line-height: 1.3; + margin-bottom: 0.75rem; +} + +blockquote { + font-size: 1.125rem; + font-style: italic; + color: var(--color-text); + border-left: 4px solid var(--color-accent); + padding: 0.5rem 1rem; + margin: 0; + background-color: var(--color-code-bg); + border-radius: 0 var(--radius) var(--radius) 0; +} + +input, textarea { + font-family: inherit; + font-size: 1rem; + color: var(--color-text); + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--radius); + padding: 0.5rem 0.75rem; + width: 100%; + transition: border-color 0.15s ease, box-shadow 0.15s ease; +} + +input:focus, textarea:focus { + outline: none; + border-color: var(--color-accent); + box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.15); +} + +textarea { + resize: vertical; + min-height: 6rem; +} + +a { + color: var(--color-accent); + text-decoration: none; +} + +a:hover { + color: var(--color-accent-hover); + text-decoration: underline; +} + +code { + font-family: var(--font-mono); + font-size: 0.9em; + background: var(--color-code-bg); + padding: 0.1em 0.4em; + border-radius: 3px; +} + +/* ── Navigation ────────────────────────────────────────────── */ +.nav { + background: var(--color-surface); + border-bottom: 1px solid var(--color-border); + padding: 0.75rem 1.5rem; + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; + box-shadow: var(--shadow); +} + +.nav__brand { + font-size: 1.25rem; + font-weight: 700; + color: var(--color-accent); + text-decoration: none; +} + +.nav__brand:hover { + color: var(--color-accent-hover); + text-decoration: none; +} + +.nav__links { + display: flex; + gap: 1.5rem; + align-items: center; +} + +.nav__link { + font-size: 0.95rem; + color: var(--color-text); + font-weight: 500; +} + +.nav__link:hover { + color: var(--color-accent); + text-decoration: none; +} + +/* ── Main Content Container ────────────────────────────────── */ +.main-content { + flex: 1; + max-width: 800px; + width: 100%; + margin: 0 auto; + padding: 2rem 1.5rem; +} + +/* ── Buttons ───────────────────────────────────────────────── */ +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.4rem; + padding: 0.5rem 1.25rem; + border-radius: var(--radius); + border: 1px solid var(--color-border); + background: var(--color-surface); + color: var(--color-text); + font-family: inherit; + font-size: 0.95rem; + font-weight: 500; + cursor: pointer; + text-decoration: none; + transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease; +} + +.btn:hover { + background: var(--color-bg); + text-decoration: none; +} + +.btn:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.btn--primary { + background: var(--color-accent); + border-color: var(--color-accent); + color: #ffffff; +} + +.btn--primary:hover { + background: var(--color-accent-hover); + border-color: var(--color-accent-hover); + color: #ffffff; +} + +.btn--danger { + background: var(--color-danger); + border-color: var(--color-danger); + color: #ffffff; +} + +.btn--danger:hover { + background: var(--color-danger-hover); + border-color: var(--color-danger-hover); + color: #ffffff; +} + +/* ── QuoteCard ─────────────────────────────────────────────── */ +.quote-card { + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--radius); + padding: 1.5rem; + box-shadow: var(--shadow); + margin-bottom: 1.5rem; +} + +.quote-card__text { + font-size: 1.125rem; + margin-bottom: 1rem; +} + +.quote-card__footer { + display: flex; + align-items: baseline; + flex-wrap: wrap; + gap: 0.25rem; + margin-bottom: 0.75rem; +} + +.quote-card__author { + font-weight: 600; + color: var(--color-accent); + text-decoration: none; +} + +.quote-card__author:hover { + color: var(--color-accent-hover); + text-decoration: underline; +} + +.quote-card__source { + color: var(--color-text-muted); + font-size: 0.9rem; +} + +.quote-card__tags { + display: flex; + flex-wrap: wrap; + gap: 0.4rem; + margin-bottom: 0.75rem; +} + +.quote-card__tag { + background: var(--color-code-bg); + border: 1px solid var(--color-border); + border-radius: 999px; + padding: 0.15rem 0.65rem; + font-size: 0.8rem; + color: var(--color-text-muted); +} + +.quote-card__link { + font-size: 0.875rem; + font-weight: 500; + color: var(--color-accent); +} + +.quote-card__link:hover { + color: var(--color-accent-hover); +} + +/* ── Error Display ─────────────────────────────────────────── */ +.error-display { + background: var(--color-error-bg); + border: 1px solid var(--color-error-border); + border-radius: var(--radius); + padding: 0.875rem 1rem; + margin-bottom: 1rem; +} + +.error-display__message { + color: var(--color-danger); + font-size: 0.95rem; +} + +/* ── Pagination ────────────────────────────────────────────── */ +.pagination { + display: flex; + align-items: center; + justify-content: center; + gap: 1rem; + margin-top: 2rem; + padding-top: 1rem; + border-top: 1px solid var(--color-border); +} + +.pagination__btn { + padding: 0.4rem 1rem; + border-radius: var(--radius); + border: 1px solid var(--color-border); + background: var(--color-surface); + color: var(--color-text); + font-family: inherit; + font-size: 0.9rem; + cursor: pointer; + transition: background 0.15s ease; +} + +.pagination__btn:hover:not(:disabled) { + background: var(--color-bg); + border-color: var(--color-accent); +} + +.pagination__btn:disabled { + opacity: 0.4; + cursor: not-allowed; +} + +.pagination__info { + font-size: 0.9rem; + color: var(--color-text-muted); +} + +/* ── Auth Modal ────────────────────────────────────────────── */ +.auth-modal__overlay { + position: fixed; + inset: 0; + background: rgba(0, 0, 0, 0.5); + display: flex; + align-items: center; + justify-content: center; + z-index: 1000; + padding: 1rem; +} + +.auth-modal { + background: var(--color-surface); + border-radius: var(--radius); + box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2); + padding: 2rem; + width: 100%; + max-width: 400px; +} + +.auth-modal__title { + font-size: 1.25rem; + font-weight: 600; + margin-bottom: 1rem; +} + +.auth-modal__input { + margin-bottom: 1rem; +} + +.auth-modal__actions { + display: flex; + gap: 0.75rem; + justify-content: flex-end; +} + +/* ── Home Page ─────────────────────────────────────────────── */ +.page-home { + text-align: center; +} + +.page-home__title { + font-size: 2.5rem; + margin-bottom: 0.5rem; +} + +.page-home__subtitle { + color: var(--color-text-muted); + margin-bottom: 2rem; +} + +.page-home__loading { + color: var(--color-text-muted); + font-style: italic; +} + +.page-home__actions { + display: flex; + gap: 1rem; + justify-content: center; + margin-top: 2rem; +} + +/* ── Browse Page ───────────────────────────────────────────── */ +.page-browse__title { + margin-bottom: 1.5rem; +} + +.page-browse__filters { + display: flex; + gap: 1rem; + margin-bottom: 2rem; + flex-wrap: wrap; +} + +.page-browse__filter-input { + max-width: 240px; +} + +.page-browse__loading, +.page-browse__empty { + color: var(--color-text-muted); + font-style: italic; +} + +.page-browse__list { + display: flex; + flex-direction: column; +} + +/* ── Quote Detail Page ─────────────────────────────────────── */ +.page-quote__loading { + color: var(--color-text-muted); + font-style: italic; +} + +.page-quote__actions { + display: flex; + gap: 0.75rem; + margin-top: 1rem; +} + +/* Edit form */ +.edit-form { + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--radius); + padding: 1.5rem; + margin-top: 1.5rem; +} + +.edit-form__field { + margin-bottom: 1rem; +} + +.edit-form__label { + display: block; + font-size: 0.875rem; + font-weight: 600; + margin-bottom: 0.4rem; + color: var(--color-text); +} + +.edit-form__input, +.edit-form__textarea { + width: 100%; +} + +.edit-form__actions { + display: flex; + gap: 0.75rem; + margin-top: 1rem; +} + +/* ── Author Page ───────────────────────────────────────────── */ +.page-author__title { + margin-bottom: 1rem; +} + +.page-author__filters { + margin-bottom: 1.5rem; +} + +.page-author__filter-input { + max-width: 240px; +} + +.page-author__loading, +.page-author__empty { + color: var(--color-text-muted); + font-style: italic; +} + +.page-author__list { + display: flex; + flex-direction: column; +} + +/* ── Submit Page ───────────────────────────────────────────── */ +.page-submit__title { + margin-bottom: 1.5rem; +} + +.submit-form { + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--radius); + padding: 1.5rem; + max-width: 600px; +} + +.submit-form__field { + margin-bottom: 1.25rem; +} + +.submit-form__label { + display: block; + font-size: 0.875rem; + font-weight: 600; + margin-bottom: 0.4rem; + color: var(--color-text); +} + +.submit-form__input, +.submit-form__textarea { + width: 100%; +} + +.submit-form__actions { + margin-top: 1.5rem; +} + +/* Success state */ +.page-submit--success { + text-align: left; +} + +.page-submit__auth-code-box { + background: var(--color-code-bg); + border: 1px solid var(--color-border); + border-radius: var(--radius); + padding: 1rem 1.25rem; + margin: 1.5rem 0; + font-size: 1rem; +} + +.page-submit__auth-code { + font-family: var(--font-mono); + font-size: 1.1rem; + color: var(--color-accent); + font-weight: 600; + user-select: all; +} + +.page-submit__actions { + display: flex; + gap: 0.75rem; + flex-wrap: wrap; +} + +/* ── 404 Page ──────────────────────────────────────────────── */ +.page-not-found { + text-align: center; + padding-top: 4rem; +} + +.page-not-found h1 { + color: var(--color-text-muted); +} + +/* ── Responsive ────────────────────────────────────────────── */ +@media (max-width: 640px) { + h1 { + font-size: 1.5rem; + } + + .main-content { + padding: 1rem; + } + + .page-home__title { + font-size: 1.75rem; + } + + .page-home__actions { + flex-direction: column; + align-items: center; + } + + .page-browse__filters { + flex-direction: column; + } + + .page-browse__filter-input, + .page-author__filter-input { + max-width: 100%; + } + + .nav { + padding: 0.75rem 1rem; + } + + .auth-modal { + padding: 1.5rem; + } +}