Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 110 additions & 0 deletions .agents/skills/frontend-workflow/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
---
name: frontend-workflow
description: Frontend and UI work in surfsense_web and surfsense_local/frontend — building, refactoring, styling, animating, or reviewing React and Next.js components, shadcn/ui, color tokens and themes, visual polish, and motion. Load this first for any UI task, including adding or changing a shadcn/ui component (dialog, button, dropdown, form, sidebar, table) in a tree with components.json — it owns the color palette, polish rules, and the precedence order, then routes to the separate shadcn skill for component wiring and the CLI. Use for any frontend component, page, style, animation, hover state, icon, layout, or UI review task.
---

# Frontend Workflow

Single entry point for frontend work in `surfsense_web` and
`surfsense_local/frontend`. Both are React + Tailwind + shadcn/ui with their own
`components.json`. Detect which tree the task touches, and treat that tree's
`package.json`, `components.json`, and styling setup as authoritative. All
guidance lives in this skill's own folders; load only what the task touches.

## Reference Map

| Read this | When |
|---|---|
| [react-performance/SKILL.md](./react-performance/SKILL.md) | React or Next.js code — components, pages, data fetching, bundles, re-renders |
| [../shadcn/SKILL.md](../shadcn/SKILL.md) | shadcn/ui components, or any project with `components.json`. Separate skill — it inspects the project live and grants its own CLI. |
| [color/SKILL.md](./color/SKILL.md) | Colors, themes, charts, design tokens, borders, shadows |
| [polish/SKILL.md](./polish/SKILL.md) | Typography, surfaces, icons, micro-interactions, enter/exit transitions |
| [motion/apple-design.md](./motion/apple-design.md) | Gesture-driven or physical motion — drag, swipe, sheets, springs, momentum, interruptible transitions, translucent materials |

Each entry is an index. Open its supporting files only when the touched code
needs them:

- `react-performance/rules/` holds one file per rule. Load the applicable ones.
`react-performance/rules-compiled.md` is the same rules compiled into one
document — do not load it by default.
- `polish/` splits into `typography.md`, `surfaces.md`, `animations.md`,
`icons.md`, `performance.md`.
- `../shadcn/rules/` splits by concern; `../shadcn/cli.md`, `registry.md`,
`customization.md` cover tooling and theming.
- `color/PALETTE.css` is the canonical palette contract.

Do not load motion references for work with no motion concern.
Apple-style motion is for gesture, physics, and material work; a hover state or
a color change does not need it.

## Workflow

1. **Understand the task**
- Inspect the relevant implementation and trace the affected interaction.
- Clarify only decisions that materially change behavior or design.
- Reuse existing components, helpers, tokens, and patterns.

2. **Select guidance**
- Use the reference map above.
- Read detailed files only when the touched code needs them.
- Treat current project configuration and installed APIs as authoritative.

3. **Implement**
- Make the smallest complete change that satisfies the request.
- Preserve established visual language and component APIs.
- Cover loading, empty, error, disabled, responsive, keyboard, focus, and
reduced-motion states when they are relevant.

4. **Validate**
- Run the smallest relevant lint, type, and test checks.
- For visible interaction changes, verify the rendered behavior when a
runnable frontend is available.
- If visual details or motion changed, apply the polish review only after
functional implementation is complete and resolve blocking findings
within scope.

5. **Report**
- Summarize the user-visible result, checks run, and unresolved risks.
- Use the polish review format only when the user requested a review. For
implementation tasks, include relevant visual or motion findings in the
normal completion summary.

## Precedence and Conflicts

Resolve conflicting guidance in this order:

1. The user's explicit requirements.
2. Correctness, security, and accessibility.
3. Existing project conventions and configuration.
4. The canonical color system and shadcn/ui composition rules.
5. React and Next.js performance guidance.
6. Motion behavior for gesture-driven and interruptible interactions.
7. Interface and motion polish.

Specific overlaps:

- **Icons** — `../shadcn/rules/icons.md` governs icon usage inside shadcn
components (`data-icon`, sizing, passing icons as objects). `polish/icons.md`
governs stroke weight, optical detail, states via `currentColor`, and RTL
flipping. Apply the shadcn rule to component wiring, the polish rule to
visual detail.
- **Color** — `color/SKILL.md` and `color/PALETTE.css` are canonical. Where
`../shadcn/rules/styling.md` or `../shadcn/customization.md` describe theming,
follow them for mechanism and the palette for values.
- **Motion** — `motion/apple-design.md` governs how motion behaves;
`polish/animations.md` governs concrete values and static detail. Where they
conflict, prefer springs and current-value interpolation for anything the
user can touch or interrupt, and CSS transitions for everything else.

Never sacrifice correctness or accessibility for visual polish or a
micro-optimization. If a rule conflicts with the installed library version or
project configuration, verify the current API and follow the project's actual
version.

## Notes

The `SKILL.md` and `.md` files inside `react-performance/`, `color/`, `polish/`,
and `motion/` retain their original frontmatter from when they were separate
skills. That frontmatter is inert here — these are reference files, not
independently discovered skills. Read their bodies and ignore their
`name`, `description`, and invocation fields.
146 changes: 146 additions & 0 deletions .agents/skills/frontend-workflow/color/PALETTE.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
:root {
--card: #fbfaf7;
--ring: #2e2e2e;
--input: #d6d6d6;
--muted: #ebeae6;
--accent: #e5e4df;
--border: #dedede;
--radius: 0.5rem;
--chart-1: #f26a4b;
--chart-2: #1e1e1e;
--chart-3: #626262;
--chart-4: #9b9b9b;
--chart-5: #c9c9c9;
--popover: #fbfaf7;
--primary: #2e2e2e;
--sidebar: #f3f2ee;
--spacing: 0.25rem;
--font-mono: "IBM Plex Mono", monospace;
--font-sans: "Instrument Sans", sans-serif;
--secondary: #f1f0ec;
--background: #f7f6f2;
--app-shell: #f3f2ee;
--font-serif: "Newsreader", serif;
--foreground: #1e1e1e;
--destructive: #dc2626;
--notice: #3f74c8;
--shadow-blur: 10px;
--shadow-color: #000000;
--sidebar-ring: #2e2e2e;
--shadow-spread: 0px;
--letter-spacing: 0.01em;
--shadow-opacity: 0.1;
--sidebar-accent: #e5e4df;
--sidebar-border: #dedede;
--card-foreground: #1e1e1e;
--shadow-offset-x: 0px;
--shadow-offset-y: 4px;
--sidebar-primary: #2e2e2e;
--muted-foreground: #626262;
--accent-foreground: #2e2e2e;
--popover-foreground: #1e1e1e;
--primary-foreground: #f7f7f7;
--sidebar-foreground: #1e1e1e;
--secondary-foreground: #2e2e2e;
--destructive-foreground: #ffffff;
--sidebar-accent-foreground: #2e2e2e;
--sidebar-primary-foreground: #f7f7f7;
}

.dark {
--card: #1c1c1c;
--ring: #d1cfc0;
--input: #2c2c2c;
--muted: #2a2a2a;
--accent: #363636;
--border: #2c2c2c;
--radius: 0.5rem;
--chart-1: #f26a4b;
--chart-2: #d9cfc2;
--chart-3: #8e8a83;
--chart-4: #5c5a56;
--chart-5: #3b3b3b;
--popover: #1c1c1c;
--primary: #d9aa90;
--sidebar: #141414;
--spacing: 0.25rem;
--font-mono: "IBM Plex Mono", monospace;
--font-sans: "Instrument Sans", sans-serif;
--secondary: #222222;
--background: #141414;
--app-shell: #101010;
--font-serif: "Newsreader", serif;
--foreground: #e8e3da;
--destructive: #ef4444;
--notice: #3f74c8;
--shadow-blur: 15px;
--shadow-color: #000000;
--sidebar-ring: #d1cfc0;
--shadow-spread: 0px;
--letter-spacing: 0.01em;
--shadow-opacity: 0.3;
--sidebar-accent: #363636;
--sidebar-border: #2c2c2c;
--card-foreground: #e8e3da;
--shadow-offset-x: 0px;
--shadow-offset-y: 6px;
--sidebar-primary: #d1cfc0;
--muted-foreground: #8e8a83;
--accent-foreground: #d1cfc0;
--popover-foreground: #e8e3da;
--primary-foreground: #363636;
--sidebar-foreground: #e8e3da;
--secondary-foreground: #d1cfc0;
--destructive-foreground: #ffffff;
--sidebar-accent-foreground: #d1cfc0;
--sidebar-primary-foreground: #363636;
}

@theme inline {
--color-card: var(--card);
--color-ring: var(--ring);
--color-input: var(--input);
--color-muted: var(--muted);
--color-accent: var(--accent);
--color-border: var(--border);
--color-radius: var(--radius);
--color-chart-1: var(--chart-1);
--color-chart-2: var(--chart-2);
--color-chart-3: var(--chart-3);
--color-chart-4: var(--chart-4);
--color-chart-5: var(--chart-5);
--color-popover: var(--popover);
--color-primary: var(--primary);
--color-sidebar: var(--sidebar);
--color-spacing: var(--spacing);
--color-font-mono: var(--font-mono);
--color-font-sans: var(--font-sans);
--color-secondary: var(--secondary);
--color-background: var(--background);
--color-app-shell: var(--app-shell);
--color-font-serif: var(--font-serif);
--color-foreground: var(--foreground);
--color-destructive: var(--destructive);
--color-notice: var(--notice);
--color-shadow-blur: var(--shadow-blur);
--color-shadow-color: var(--shadow-color);
--color-sidebar-ring: var(--sidebar-ring);
--color-shadow-spread: var(--shadow-spread);
--color-letter-spacing: var(--letter-spacing);
--color-shadow-opacity: var(--shadow-opacity);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-border: var(--sidebar-border);
--color-card-foreground: var(--card-foreground);
--color-shadow-offset-x: var(--shadow-offset-x);
--color-shadow-offset-y: var(--shadow-offset-y);
--color-sidebar-primary: var(--sidebar-primary);
--color-muted-foreground: var(--muted-foreground);
--color-accent-foreground: var(--accent-foreground);
--color-popover-foreground: var(--popover-foreground);
--color-primary-foreground: var(--primary-foreground);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-secondary-foreground: var(--secondary-foreground);
--color-destructive-foreground: var(--destructive-foreground);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
}
86 changes: 86 additions & 0 deletions .agents/skills/frontend-workflow/color/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<!-- Inert: bundled reference file, not a discovered skill. The frontmatter below has no effect. -->
---
name: color-system
description: Applies and reviews SurfSense's canonical light and dark color palette, semantic design tokens, typography, charts, borders, shadows, and theme mappings. Use when creating or changing frontend colors, themes, component styling, data visualizations, or design tokens.
---

# SurfSense Color System

Use [PALETTE.css](PALETTE.css) as the canonical palette contract. Preserve its
token names and values unless the user explicitly requests a palette change.

## Principles

1. Use semantic tokens such as `background`, `foreground`, `primary`,
`muted`, `accent`, `destructive`, `border`, and their foreground pairs.
Do not use raw hex values in components.
2. Use the matching foreground token for text and icons placed on a semantic
surface: `primary-foreground` on `primary`, `card-foreground` on `card`,
and so on.
3. Use `chart-1` through `chart-5` for data series. Do not repurpose chart
colors as component state colors.
4. Use `ring` for focus indicators and `border` or `input` for boundaries.
Never remove a visible keyboard focus indicator.
5. Use `muted-foreground` only for secondary text. Do not use it for small or
essential text unless its contrast passes WCAG.
6. Use `destructive` only for destructive actions, errors, or dangerous
states. Do not use chart colors to communicate errors.
7. Support both `:root` and `.dark`; never add a light-only semantic token.
8. Prefer existing semantic tokens over creating new aliases. Add a token only
when it represents a reusable semantic role that the palette does not cover.

## Workflow

1. Locate the active global CSS file from the target app's `components.json`;
this repository contains more than one frontend.
2. Compare the active theme with [PALETTE.css](PALETTE.css). Do not overwrite
unrelated CSS, animation, layout, or framework directives.
3. Apply palette values at the global token layer, not inside individual
components.
4. In components, use the project's semantic utility classes or CSS variables,
for example `bg-background text-foreground`, `bg-card
text-card-foreground`, and `border-border`.
5. Check affected foreground/background pairs in both themes. WCAG targets:
4.5:1 for normal text, 3:1 for large text and meaningful UI boundaries.
6. Verify focus, hover, active, selected, disabled, destructive, chart, and
sidebar states when affected.

## Guardrails

- Do not invent intermediate shades to make one component look better.
- Do not use opacity to compensate for an incorrect semantic token when it
reduces text contrast.
- Do not replace the palette wholesale when the requested change concerns one
component.
- Report a contrast failure instead of silently changing canonical values.
- Treat the palette's `@theme inline` block as Tailwind v4 configuration.
Before applying it, verify the target app uses Tailwind v4 and preserve any
required non-color namespaces already present in its global stylesheet.

## Known Accessibility Constraint

The canonical dark `muted-foreground` (`#7a706a`) does not reach 4.5:1 for
normal text on dark `background` (4.11:1), `card` (3.90:1), or `muted`
(3.64:1). Preserve the palette, but do not use this token for essential or
small normal-weight dark-mode text. Report the conflict and request a palette
decision when no existing foreground token fits.

## Coordination

- For shadcn/ui composition and styling, also use `../../shadcn/SKILL.md`.
- For React or Next.js implementation, also use
`../react-performance/SKILL.md`.
- For interface polish, color transitions, or reduced-motion behavior, use
`../polish/SKILL.md` after implementation.

## Output

For implementation tasks, report:

- which app and global stylesheet received the palette;
- whether both themes were updated;
- contrast or state risks that remain;
- validation performed.

For audits, cite each issue by token pair and usage location, then recommend a
semantic-token correction before proposing a new color.
Loading
Loading