# Handoff: SummerCMS Admin Panel — Direction C ("Generic modern dashboard") ## Overview This is the admin panel for SummerCMS, a CMS framework. The mocks use data from one real app: **Płytarium**, a home catalogue of vinyl, CD and cassette releases. The panel is a **schema-driven Vue 3 SPA**. Every list and form is generated from YAML-defined `columns` and `fields`. Build generic components, not screens: one DataTable, one FormField row, one Tabs component, one RelationManager. The UI language is **Polish**, and all copy below is final. Screens covered: Login, Navigation shell (multi-plugin: Płytarium + Użytkownicy), List (Albumy) with its selected/empty/loading states, Form (Edycja albumu) with tabs and 422 errors, and the relation manager (Kolekcje → Redaktorzy) with its "Dodaj redaktora" modal. Light and dark mode are both included, plus tablet width. ## About the Design Files `Direction C v2.dc.html` is a **design reference built in HTML**, not production code. Recreate it in the target Vue 3 codebase using its existing patterns. If the codebase has no UI setup yet, use Vue 3 + Vite + Tailwind with headless primitives (e.g. Radix Vue / Reka UI) and lucide-vue-next icons. To view it, open `Direction C v2.dc.html` in a browser. `support.js` must be in the same folder, and you need internet access for the fonts and icons. The component's props act as a state switcher: - `plugin`: `plytarium | users` (use `users` with `screen=list` to see the Users plugin list) - `flyout`: boolean; with `narrow`, shows the collapsed-rail flyout - `screen`: `login | list | form | relation` - `listState`: `default | selected | empty | loading` - `tab`: `basic | details` - `dark`, `narrow` (tablet), `errors` (422), `toast`, `modal`, `userMenu`: booleans All sample data sits in the `ALBUMS`, `EDITORS` and `CANDS` constants in the logic class. ## Fidelity **High-fidelity.** Colours, type, spacing, radii and copy are final. Match them closely. --- ## Design Tokens ### Colours | Token | Light | Dark | Use | |---|---|---|---| | bg | `#f4f6f9` | `#111726` | App background behind cards | | surface | `#ffffff` | `#182033` | Cards, header, inputs, footer bar | | subtle | `#f3f5f8` | `#1f283d` | Table header, search input fill, chips, avatar bg | | border | `#e6e9ef` | `#29334b` | Card borders, row dividers | | borderStrong | `#d2d8e2` | `#3a4661` | Input borders, unchecked checkbox, switch off | | text | `#141b2d` | `#eef1f6` | Primary text | | muted | `#566175` | `#a9b3c6` | Secondary text, column headers, icons | | placeholder | `#6b7588` | `#8a95ab` | Input placeholder | | primary | `#22304d` (navy) | `#fcd34d` (yellow) | Primary buttons, checked checkbox | | onPrimary | `#ffffff` | `#1b2540` | Text on primary | | danger | `#c62828` | `#f58a8a` | Destructive, errors | | dangerSoft | `#fdf0f0` | `#3a1d24` | Error banner bg, destructive hover | | okBg / okText | `#e3f4e8` / `#1c6b35` | `#173826` / `#8fdfa8` | "Tak" badge | | ring | `rgba(252,196,40,.55)` | `rgba(252,211,77,.45)` | Focus ring (3px) | | hover | `#f1f3f7` | `#212b42` | Hover bg for ghost buttons/rows | | sel | `#fdf3cf` | `#3a3622` | Selected row bg, current page button | | skel | `#eceff4` | `#263049` | Skeleton bars | | overlay | `rgba(20,27,45,.5)` | `rgba(5,8,16,.7)` | Modal backdrop | | side | `#1d2740` | `#0d1320` | Sidebar bg (sidebar is dark in both modes; dark mode adds a `#222b40` right border) | | accent | `#fcd34d` | same | Brand yellow: logo, active nav, avatar | | onAccent | `#1b2540` | same | Text on accent | | sidebar text | `#c3cbda` idle, `#9aa6bd` section label, `#ffffff` hover, `#fcd34d` active | | | | card shadow | `0 1px 2px rgba(20,27,45,.04), 0 4px 16px rgba(20,27,45,.05)` | `none` | | The brand is **dark navy + sunny yellow**. In light mode the primary is navy and yellow is only an accent. In dark mode yellow becomes the primary. ### Typography - UI font: **DM Sans** (Google Fonts, opsz 9..40, weights 400/500/600/700). Base size 14px, line-height 1.5. - Mono: **DM Mono** 400/500. Used for the Półka shelf code and the `colorpicker` token. - Datetimes use DM Sans with `font-variant-numeric: tabular-nums`, 13px, muted colour. | Role | Size / weight / tracking | |---|---| | Page title (list) | 26px / 700 / -0.02em | | Record title (form) | 24px / 700 / -0.02em | | Login title | 22px / 700 / -0.02em | | Modal title | 20px / 700 / -0.01em | | Section title (Redaktorzy) | 17px / 700 | | Body / cell | 14px / 400 (Nazwa cell 600) | | Field label | 14px / 600 | | Column header | 12px / 600, muted (the sorted column uses the text colour) | | Helper / meta / error text | 13px | ### Radii Inputs, buttons and selects: 10px. Cards: 16px. Login card: 16px. Modal: 20px. Inner table container and toggle cards: 12px. Tabs track: 12px, tab pill: 9px. Checkbox: 5px (6px in the form and modal). Pagination buttons: 8px. Badges, chips and switch: 999px. Avatars: 50%. ### Spacing Page padding is 28px top/bottom and 32px left/right. Gaps between cards and blocks are 20px. Form card padding is 28px. The form grid gap is 22px (rows) × 24px (columns). Table cells use 14px horizontal padding, with 20px on the first and last columns. ### Control heights - Primary/secondary buttons and search: **42px** - Form inputs, selects and login inputs: **44px** - Table header row: 44px. Body row: **54px** (56px in the relation manager). Modal option row: 54px. - Pagination buttons: 34px - Top header: 64px. Sidebar nav item: 40px. ### Focus Every interactive element shows a visible **3px yellow ring** (`box-shadow: 0 0 0 3px var(--ring)`). Inputs also switch their border to `primary`. Buttons use `outline: 3px solid var(--ring); outline-offset: 2px`. Style `:focus-visible` this way and never remove it. --- ## Screens ### 1. Login (`screen=login`) - Full-viewport background: `radial-gradient(ellipse at 50% 35%, #2b3a5c 0%, #1d2740 60%)`. - A centred column, max-width 400px, gap 24px: - **Wordmark**: sun icon (lucide `sun`, 20px, yellow) in a 34px circle filled `rgba(252,211,77,.14)`, followed by "Summer**CMS**" at 18px/700 in white, with "CMS" in yellow. This is the only branding, because the admin URL is custom (e.g. `/plytadmin`). - **Card**: white background, radius 16, padding 32, gap 18, shadow `0 24px 60px rgba(0,0,0,.35)`. - Title: "Witaj ponownie" - Field "Login lub e-mail" (input 44px) - Field "Hasło" (password) - Error state: the password input gets a danger border and `aria-invalid`. Below it sits an alert block (`role="alert"`, dangerSoft bg, danger text, radius 10, padding 12×14, `circle-alert` icon 18px) reading **"Nieprawidłowe dane logowania"**. - Full-width primary button **"Zaloguj"** (44px). ### 2. Navigation shell — multi-plugin (rail + section panel) SummerCMS replaces WinterCMS. It is a backend that hosts many plugins, and each plugin registers navigation the way Winter's `registerNavigation()` does: **one main-menu item** (label, icon, order, permissions) plus **its own side menu** (items, icons, permissions). Płytarium is just one of these plugins. The shell is built from that registry, and nothing in it is hardcoded per plugin. **Plugin rail (level 1 = Winter main menu)** - Always visible. Width 80px, colour `side` (`#1d2740` light / `#0d1320` dark), padding 14px 0 12px, column gap 6, centred. - Top: brand badge, a 40px rounded square (radius 12) filled `rgba(252,211,77,.14)` holding a `sun` icon (22px, yellow). `title="SummerCMS"`, bottom margin 14. - One item per registered main-menu entry, sorted by `order`: - 68px wide, padding 8/6, radius 12, letter-spacing -0.01em. - 20px icon, with the label below it at 11px (line-height 1.2, centred). - Idle: `#c3cbda`. Hover: `rgba(255,255,255,.08)` with white text. - Active: bg `rgba(252,211,77,.14)`, text/icon `#fcd34d`, weight 700, `aria-current="page"`. - Focus: 3px ring. - Mock entries: **Płytarium** (`disc-3`), **Użytkownicy** (`users`), **Media** (`image`). - A flex spacer, then **Ustawienia** (`settings`) pinned to the bottom. Settings is a separate area where plugins register settings pages, the same as Winter. - When the panel is collapsed, a 40px "Rozwiń menu" button (`panel-left-open`) appears above Ustawienia. - Wrap the rail in `