docs(design): sync design guidance with the shipped system + new Stripe mark (#1211)

* docs(design): sync design guidance with the shipped frame-layout system

The design-scan skills and workflow predate the 2026-07 UI migration; they
delegated to .claude/rules/design.md but their inline checklists knew nothing
of the locked conventions, so scans could not flag violations of frame layout,
one-line rows, chips-as-exceptions or .attn. This adds the conventions to
scout-design, loop-design-scan, the /create-ticket design prompt and the
design-scan workflow contract.

design.md itself gets the two post-migration decisions it was missing: the
fiscal-year primitive is FyPicker (ContextPicker chip-dropdown, convention 8),
not the legacy FiscalYearSelector, and the founder-chosen Fonster settings
language (flat hairline rows, switches, dirty-only sticky save bar, 920x680
modal, replaceState tab switching) is now convention 15.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(import): swap the Stripe chip to the current parallelogram mark

Replaces the pre-rebrand Stripe wordmark svg with the current white-on-purple
parallelogram icon (same asset the website repo uses). stripe.svg had exactly
one reference; it is removed rather than left orphaned.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jakob Wennberg
2026-07-26 14:34:04 +02:00
committed by GitHub
co-authored by Claude Fable 5
parent 1270b6daeb
commit c210a01db5
8 changed files with 49 additions and 9 deletions
+3 -1
View File
@@ -53,6 +53,7 @@ Decided during the 2026-07 concept work (dev_docs/ui_migration_plan.md); they ap
12. **Status colors are data, not chrome**: sage/ochre/terracotta only in numbers, exception chips and `.attn`.
13. **Overlays**: centered modal for create/confirm (template, assistant, confirmations, settings); right slide-over for reviewing an object (Granskning detail). Both with veil, Esc, and click-outside.
14. **Manual base, AI as opt-in.** Base flows work without AI; AI entry points are clearly labeled discrete choices (e.g. "Skapa med assistenten") and no AI suggestion posts without Granskning.
15. **Settings speak "Fönster"** (founder-chosen 2026-07-25, applies to every settings tab). Settings content is flat hairline rows, never boxed cards: `SettingsGroup` / `SettingsRow` / `SettingsSectionHeader` from `components/settings/SettingsRows.tsx`. Toggles are switches, not checkboxes. Saving is a sticky bar that fades in only when the form is dirty (`components/settings/SettingsFormWrapper.tsx`); no always-visible save button. The settings surface is a 920x680 modal (`components/settings/SettingsModal.tsx`); switching tabs inside it updates the URL shallowly via `history.replaceState` (`SettingsRail.tsx`), never `router.replace`, which would remount the modal.
## Design System Tokens
@@ -89,7 +90,8 @@ Compact metric cards (e.g. dashboard tiles, salary KPI row) use `p-4`. Detail ca
| No-data state | `components/ui/empty-state.tsx` `EmptyState` | Don't hand-roll `<div className="flex flex-col items-center py-12">…</div>`. Preset variants exist (`EmptyInvoices`, `EmptyCustomers`, `EmptyTransactions`, etc.). |
| Loading placeholder | `components/ui/skeleton.tsx` `<Skeleton>` | Don't hand-roll `bg-muted rounded animate-pulse` divs. |
| Inline help / formulas | `components/ui/info-tooltip.tsx` `InfoTooltip` | Hover-revealed; don't use always-visible info buttons. |
| Fiscal year picker | `components/common/FiscalYearSelector.tsx` | Don't use raw `<select>` for fiscal periods. |
| Fiscal year picker | `components/common/FyPicker.tsx` | The chip-dropdown context picker of convention 8 (wraps `ContextPicker`). `FiscalYearSelector` is the legacy pre-frame control: don't add new uses. Never use a raw `<select>` for fiscal periods. |
| Settings rows / save | `components/settings/SettingsRows.tsx`, `SettingsFormWrapper.tsx` | Fönster language (convention 15): flat hairline rows, dirty-only sticky save bar. Don't hand-roll settings cards or per-field save buttons. |
**Tabular display rules.**
- All financial values get `tabular-nums`.
+14 -1
View File
@@ -2,7 +2,7 @@
## Perspective
You are scanning for design and UX issues in the Accounted interface. The app follows an editorial-monochrome aesthetic: paper-white surfaces, hairline borders, serif headlines; considered and quiet. Evaluate against the Accounted design system: achromatic palette (semantic sage/ochre/terracotta are data-only: charts and financial deltas, never chrome), Hedvig Letters Serif display headings, Geist body, generous whitespace, functional (non-decorative) motion.
You are scanning for design and UX issues in the Accounted interface. The app follows an editorial-monochrome aesthetic: paper-white surfaces, hairline borders, serif headlines; considered and quiet. Evaluate against the Accounted design system: achromatic palette (semantic sage/ochre/terracotta are data-only: charts and financial deltas, never chrome), Hedvig Letters Serif display headings, Geist body, generous whitespace, functional (non-decorative) motion. Since 2026-07 the app uses the frame layout (rounded page panel on a warm `--frame`, pill buttons, flat shadow-free cards); the locked conventions live in `.claude/rules/design.md`.
## Checklist
@@ -15,6 +15,19 @@ You are scanning for design and UX issues in the Accounted interface. The app fo
- [ ] Icon sizes consistent (15px nav, larger for empty states)
- [ ] Borders are full-opacity `border-border` on cards/surfaces (no `border-border/60`)
### Locked UI-migration conventions (2026-07, full list in `.claude/rules/design.md`)
- [ ] Page title via `PageHeader` (24px/32px serif); no hand-rolled `<h1>`
- [ ] Buttons keep the app-wide pill radius (no per-call-site `rounded-*` on `<Button>`)
- [ ] Cards flat and shadow-free (`rounded-lg`, hairline border); shadows only on overlays
- [ ] Table rows are one line; no sub-rows (secondary info in detail view or popup)
- [ ] Chips mark exceptions only; normal states are muted text, not a Badge on every row
- [ ] Attention is one `.attn` sentence, not a banner; max one per page
- [ ] Help behind the "?" popover after the H1; no instructional copy in the page flow
- [ ] One context picker per page, far right in the toolbar (`FyPicker`/`ContextPicker`)
- [ ] Actions that post/send confirm up front in a dialog; no outcome text written into the page
- [ ] `.stagger-enter` on list/table content entry
- [ ] Settings tabs use the Fönster language (flat hairline rows, switches, dirty-only sticky save bar)
### Loading & Empty States
- [ ] Pages have loading states (skeletons preferred over spinners)
- [ ] Empty states exist with message and CTA when no data
+7
View File
@@ -33,6 +33,13 @@ Flag concrete deviations, each tied to `file:line` and a rule:
- **Motion**: press-scale / hover-lift / spring overshoot (all forbidden); missing `transition-colors`.
- **A11y**: contrast < AA, icon-only button without `aria-label`, no visible focus ring, touch target < 40px.
- **UX friction**: unclear labels, redundant `PageHeader.description`, slow paths for the 90-second session.
- **Locked migration conventions** (2026-07, the numbered list in `.claude/rules/design.md`): sub-rows or
two-line rows in list tables; the same Badge on every row (chips mark exceptions only); banners instead
of one `.attn` sentence; instructional copy in the page flow instead of the "?" popover after the H1;
context picker missing, duplicated, or not far-right (`FyPicker`/`ContextPicker`); per-call-site radius
overrides on `<Button>` (pills are app-wide); `shadow-*` on cards; outcome text written into the page
instead of an up-front confirm dialog; settings tabs not using the Fönster language (flat hairline rows,
switches, dirty-only sticky save bar).
## 4. Adversarial verification (kill false positives)
Prefer the **`.claude/workflows/design-scan.js`** workflow: it fans out one agent per page, then runs a
+16 -2
View File
@@ -37,6 +37,20 @@ Read ALL files in the resolved scope (pages + components). For each file, evalua
- Are icon sizes consistent (15px nav, larger for empty states)?
- Are borders full-opacity `border-border` on cards/surfaces (no opacity-suffixed border classes like `border-border/60`)?
**Locked UI-migration conventions (2026-07; full list in `.claude/rules/design.md`)**
- Frame layout intact: content lives inside the rounded page panel; no per-page restyling of `MAIN_PANEL_CLASS`, no `window`-scroll assumptions on dashboard pages.
- Page title via `PageHeader` (24px/32px serif); buttons keep the app-wide pill radius (no per-call-site `rounded-*` overrides on `<Button>`).
- Cards are flat: no `shadow-*`, `rounded-lg` only; shadows survive only on dialogs/popovers.
- Table rows are one line; secondary info belongs in the detail view or a click-popup, never sub-rows.
- Chips mark exceptions only: normal states render as muted text; the same Badge on every row means the chip is wrong.
- Attention is one ochre `.attn` sentence, never a banner; max one per page.
- Help lives behind the "?" button after the H1; no instructional copy in the page flow.
- One context picker per page, far right in the toolbar (`FyPicker` / `ContextPicker` chip-dropdown).
- Primary action in the page header; actions that post or send confirm up front in a dialog instead of writing outcome text into the page.
- `.stagger-enter` on list/table content entry (server render and client-fetch alike).
- Overlays: centered modal to create/confirm, right slide-over to review an object.
- Settings speak Fönster: flat hairline rows (`SettingsRows.tsx`), switches not checkboxes, dirty-only sticky save bar.
**Loading & Empty States**
- Does the page/component have a loading state? (skeleton, spinner, or shimmer)
- Is there an empty state when no data exists? (illustration, message, CTA)
@@ -127,9 +141,9 @@ After creating tickets, list them with their Linear identifiers so the user can
## Important Notes
- Be specific. "The button looks off" is not actionable. "The primary button in InvoiceForm uses `rounded-lg` while all other forms use `rounded-md`" is.
- Be specific. "The button looks off" is not actionable. "The primary button in InvoiceForm overrides the app-wide pill radius with `rounded-lg`" is.
- Reference exact Tailwind classes, component names, and line numbers.
- Don't flag things that are intentional design choices documented in CLAUDE.md.
- Don't flag things that are intentional design choices documented in `.claude/rules/design.md` or `DECISIONS.md` (e.g. the LedgerGraph always-dark panel and SalaryCalendar's categorical absence colors are sanctioned exceptions).
- Don't suggest adding features, only flag design/UX issues with what already exists.
- Keep findings focused on visual design, interaction design, and frontend polish. Not code quality or architecture.
- If a component is very small or trivial (e.g., a simple redirect page), skip it.
+8 -1
View File
@@ -22,7 +22,14 @@ status colors via <Badge variant> only (no bg-blue-100 / bg-emerald-500/10 as ch
primitives PageHeader/Table/EmptyState/Skeleton/InfoTooltip (hand-rolled equivalents are violations);
Hedvig serif display must NOT be font-medium; financial numbers need tabular-nums; motion is
transition-colors only (no press-scale/hover-lift/spring); a11y WCAG AA, aria-label on icon buttons,
visible focus, touch targets >=40px. A "finding" must cite file:line and the exact rule it breaks.`
visible focus, touch targets >=40px. Locked 2026-07 migration conventions (numbered list in design.md):
frame layout with pill Buttons (per-call-site rounded-* overrides are violations); cards flat and
shadow-free (shadow-* on a card is a violation; overlays keep shadows); one-line table rows (sub-rows
are violations); chips mark exceptions only (same Badge on every row is a violation); attention is one
.attn sentence, banners are violations; help behind the "?" popover after the H1; one context picker
far right in the toolbar (FyPicker/ContextPicker); confirm-up-front dialogs, not outcome text written
into the page; .stagger-enter on list entry; settings tabs use the Fonster row language (flat hairline
rows, switches, dirty-only sticky save bar). A "finding" must cite file:line and the exact rule it breaks.`
const FINDINGS_SCHEMA = {
type: 'object',
+1 -1
View File
@@ -2098,7 +2098,7 @@ export default function ImportPage() {
<ImportRow
title={t('stripe_title')}
sub={t('stripe_description')}
chips={<LogoChip src="/logos/stripe.svg" name="Stripe" />}
chips={<LogoChip src="/logos/stripeicon.jpeg" name="Stripe" />}
disabled={stripeDisabled}
onClick={() => setMode('stripe')}
/>
-3
View File
@@ -1,3 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" style="enable-background:new 0 0 468 222.5;" xml:space="preserve" viewBox="54 36 360.02 149.84"> <style type="text/css"> .st0{fill-rule:evenodd;clip-rule:evenodd;fill:#635BFF;} </style> <g> <path class="st0" d="M414,113.4c0-25.6-12.4-45.8-36.1-45.8c-23.8,0-38.2,20.2-38.2,45.6c0,30.1,17,45.3,41.4,45.3 c11.9,0,20.9-2.7,27.7-6.5v-20c-6.8,3.4-14.6,5.5-24.5,5.5c-9.7,0-18.3-3.4-19.4-15.2h48.9C413.8,121,414,115.8,414,113.4z M364.6,103.9c0-11.3,6.9-16,13.2-16c6.1,0,12.6,4.7,12.6,16H364.6z"></path> <path class="st0" d="M301.1,67.6c-9.8,0-16.1,4.6-19.6,7.8l-1.3-6.2h-22v116.6l25-5.3l0.1-28.3c3.6,2.6,8.9,6.3,17.7,6.3 c17.9,0,34.2-14.4,34.2-46.1C335.1,83.4,318.6,67.6,301.1,67.6z M295.1,136.5c-5.9,0-9.4-2.1-11.8-4.7l-0.1-37.1 c2.6-2.9,6.2-4.9,11.9-4.9c9.1,0,15.4,10.2,15.4,23.3C310.5,126.5,304.3,136.5,295.1,136.5z"></path> <polygon class="st0" points="223.8,61.7 248.9,56.3 248.9,36 223.8,41.3 "></polygon> <rect x="223.8" y="69.3" class="st0" width="25.1" height="87.5"></rect> <path class="st0" d="M196.9,76.7l-1.6-7.4h-21.6v87.5h25V97.5c5.9-7.7,15.9-6.3,19-5.2v-23C214.5,68.1,202.8,65.9,196.9,76.7z"></path> <path class="st0" d="M146.9,47.6l-24.4,5.2l-0.1,80.1c0,14.8,11.1,25.7,25.9,25.7c8.2,0,14.2-1.5,17.5-3.3V135 c-3.2,1.3-19,5.9-19-8.9V90.6h19V69.3h-19L146.9,47.6z"></path> <path class="st0" d="M79.3,94.7c0-3.9,3.2-5.4,8.5-5.4c7.6,0,17.2,2.3,24.8,6.4V72.2c-8.3-3.3-16.5-4.6-24.8-4.6 C67.5,67.6,54,78.2,54,95.9c0,27.6,38,23.2,38,35.1c0,4.6-4,6.1-9.6,6.1c-8.3,0-18.9-3.4-27.3-8v23.8c9.3,4,18.7,5.7,27.3,5.7 c20.8,0,35.1-10.3,35.1-28.2C117.4,100.6,79.3,105.9,79.3,94.7z"></path> </g> </svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB