Files
backnotprop__plannotator/packages/ui/theme.css
T
Michael Ramos dd04e6b1cd feat: add Conventional Comments support to code review (#501)
* feat: add Conventional Comments support to code review

Add structured label system based on the Conventional Comments spec
(conventionalcomments.org) to the code review annotation toolbar.

- Label picker with 9 default labels (suggestion, nit, question, issue,
  praise, thought, note, todo, chore) shown above the comment textarea
- Per-label blocking/non-blocking toggle for labels where severity is
  ambiguous (issue, suggestion, todo, chore)
- Labels exported as `**label** (decoration): text` in markdown feedback,
  naturally readable on GitHub and machine-parseable
- Label badges shown on inline annotations and sidebar cards
- Settings tab (Comments) with: master on/off toggle, editable label
  list with add/remove/rename, per-label blocking decorator toggle,
  educational intro with spec link and example output
- Feature is off by default, persisted via config store
- Custom labels supported via settings (up to 12)

For provenance purposes, this commit was AI assisted.

* fix(review): address conventional comments review feedback

Fix label clearing bug where editing an annotation to remove its
conventional label silently preserved the old value. Fix parseCCLabels
accepting 'non-blocking' as a truthy blocking value. Fix duplicate
custom label identities when adding multiple labels. Prepend
conventional prefix to platform PR/MR inline comments.

For provenance purposes, this commit was AI assisted.

* fix(server): persist conventionalComments setting to config.json

All six server config handlers (bun plan/review/annotate + pi
plan/review/annotate) now accept and save the conventionalComments
boolean, so the setting survives server restarts.

For provenance purposes, this commit was AI assisted.

* fix: add conventionalComments to server config round-trip

getServerConfig() was not returning the conventionalComments value
from config.json, so the setting silently reset to false on cookie
clear or new browser sessions. Also adds the field to the
PlannotatorConfig interface so saveConfig() is properly typed.

For provenance purposes, this commit was AI assisted.

* fix: label display, export, and draft persistence for conventional comments

- Remove slug derivation from label editing — store display text
  verbatim so badges and exports show what the user typed
- Emit conventional prefix in export even when annotation has no
  prose text (suggestion-only annotations were losing their label)
- Include conventionalLabel in draft save condition so label
  selection persists across file switches

For provenance purposes, this commit was AI assisted.

* fix: spec-compliant export format and empty label support

- Wrap label + decorations + colon in markdown bold per the
  Conventional Comments spec examples (was bolding only the label)
- Allow users to clear all labels — empty array no longer falls
  back to defaults in either the picker or the settings parser
- Enable blocking decorator on the question label by default; the
  spec permits blocking questions and they sometimes are critical

For provenance purposes, this commit was AI assisted.

* fix: server-sync conventionalLabels and small cleanups

- Sync conventionalLabels to ~/.plannotator/config.json so custom
  label configurations survive cookie clears and remote/SSH
  sessions, matching the persistence story for conventionalComments.
  Stored as a parsed array on disk; serialized as JSON string in
  the local config store to match the cookie format.
- Remove no-op intermediate variable in handleSubmitAnnotation;
  pass conventionalLabel/decorations directly with proper coalescing
  per call path (edit preserves null, add coalesces to undefined).
- Use index-prefixed key in the picker label list to avoid React
  warnings if duplicate labels ever exist.

For provenance purposes, this commit was AI assisted.
2026-04-06 22:27:47 -07:00

137 lines
4.2 KiB
CSS

/* Plannotator Theme System — imports all themes, provides Tailwind bridge + base styles */
/* Theme files — each defines .theme-{name} (dark) and .theme-{name}.light */
@import "./themes/plannotator.css";
@import "./themes/claude-plus.css";
@import "./themes/soft-pop.css";
@import "./themes/adwaita.css";
@import "./themes/caffeine.css";
@import "./themes/synthwave-84.css";
@import "./themes/catppuccin.css";
@import "./themes/rose-pine.css";
@import "./themes/monokai-pro.css";
@import "./themes/doom-64.css";
@import "./themes/dracula.css";
@import "./themes/gruvbox.css";
@import "./themes/paulmillr.css";
@import "./themes/quantum-rose.css";
@import "./themes/solar-dusk.css";
@import "./themes/terminal.css";
@import "./themes/tokyo-night.css";
@import "./themes/tinacious.css";
@import "./themes/cursor.css";
@import "./themes/cursor-hc.css";
@import "./themes/cursor-midnight.css";
@import "./print.css";
/* Tailwind bridge — maps CSS vars to utility classes */
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-destructive-foreground: var(--destructive-foreground);
--color-success: var(--success);
--color-success-foreground: var(--success-foreground);
--color-warning: var(--warning);
--color-warning-foreground: var(--warning-foreground);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--font-sans: var(--font-sans);
--font-mono: var(--font-mono);
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
}
/* Base styles — apply regardless of theme */
@layer base {
* {
border-color: var(--border);
}
}
body {
font-family: var(--font-sans);
background: var(--background);
color: var(--foreground);
font-feature-settings: "ss01", "ss02", "cv01";
}
/* Subtle grid background */
.bg-grid {
background-image:
linear-gradient(to right, oklch(0.32 0.02 260 / 0.5) 1px, transparent 1px),
linear-gradient(to bottom, oklch(0.32 0.02 260 / 0.5) 1px, transparent 1px);
background-size: 24px 24px;
}
.light .bg-grid {
background-image:
linear-gradient(to right, oklch(0.90 0.01 260 / 0.6) 1px, transparent 1px),
linear-gradient(to bottom, oklch(0.90 0.01 260 / 0.6) 1px, transparent 1px);
}
/* Glow effects */
.glow-primary {
box-shadow: 0 0 20px oklch(from var(--primary) l c h / 0.15), 0 0 40px oklch(from var(--primary) l c h / 0.05);
}
.glow-sm {
box-shadow: 0 0 10px oklch(from var(--primary) l c h / 0.1);
}
/* Custom scrollbar */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--muted-foreground); }
/* Selection */
::selection {
background: oklch(from var(--primary) l c h / 0.3);
}
/* Smooth transitions for theme switching and hover states.
Only color properties — transform/opacity are handled per-component
to avoid interfering with scroll compositing. */
* {
transition-property: color, background-color, border-color, box-shadow;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}
/* Focus states */
:focus-visible {
outline: 2px solid var(--ring);
outline-offset: 2px;
}
/* Flash highlight for annotated files in sidebar */
.file-annotation-flash {
animation: file-flash 1.2s ease-out;
}
@keyframes file-flash {
0% { background: transparent; }
10% { background: var(--muted); }
30% { background: transparent; }
45% { background: var(--muted); }
65% { background: transparent; }
100% { background: transparent; }
}