Scaffold CommiTea: yarn workspaces, Electron shell, core label schema, design system
- apps/desktop: electron-vite + React + Tailwind mapped onto design tokens (preflight off; tokens/base.css owns the reset); boots to a Reginald placeholder proving fonts/tokens/core wiring - packages/core: pure TS; gitea label schema (est/*, p/*, deadline/hard) with pessimistic conflict resolution + 15 unit tests - docs/design: full design handoff (tokens, 16 component contracts, interactive 14-screen prototype, Reginald voice rules) - docs/PLAN.md: product plan (purity rule, pm-state repo, deterministic scheduler + Monte Carlo, directive log) - Deliberate deviation from novelpad stack: no ElectricSQL/PGlite — local store is a rebuildable cache over gitea REST/webhooks (better-sqlite3 in main process, arriving in P1) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
124
docs/PLAN.md
Normal file
@@ -0,0 +1,124 @@
|
||||
# CommiTea — AI-PM on Gitea
|
||||
|
||||
Plan file. Created 2026-07-07 from brainstorm session. Status: **pre-design** —
|
||||
design session next, phases below get actuals as they complete.
|
||||
|
||||
## Concept
|
||||
|
||||
Lightweight project tracking/management system. Gitea = core engine for
|
||||
milestones/tickets. Local-ish LLM agent acts as project manager: captures work
|
||||
via interview, maps capacity, forecasts deadlines, adjusts priorities on
|
||||
directives. Electron app, one window, "tell me what to do" experience.
|
||||
|
||||
## Goals (numeric where possible)
|
||||
|
||||
1. **Forecast honesty**: milestone forecasts as Monte Carlo cones (e.g. "80%
|
||||
land Mar 3–12"), never point dates. Calibration curve active after ≥20
|
||||
closed issues with estimates.
|
||||
2. **Capture speed**: braindump → approved ticket set (estimates, deps,
|
||||
milestone) in < 2 min via agent interview.
|
||||
3. **Responsiveness**: full gitea reconcile < 5 s @ 500 issues; scheduler +
|
||||
Monte Carlo run < 1 s @ 200 open issues; webhook-driven updates visible
|
||||
< 2 s.
|
||||
4. **Agent economy**: hot context ≤ 2k tokens; works with a 4B local model for
|
||||
prose/ritual tasks (bigger model only for decomposition/negotiation).
|
||||
5. **Zero pollution**: managed work repos gain only human-meaningful labels
|
||||
(`est/*`, `p/*`, `deadline/hard`) — no bot comments, no body frontmatter,
|
||||
no synthetic issues.
|
||||
|
||||
## Core architecture decisions (settled in brainstorm)
|
||||
|
||||
- **Purity rule**: gitea holds *human-authored intent* (issues, milestones +
|
||||
due dates, dependencies, assignees, labels, comments). Sidecar holds
|
||||
*machine-derived state* (forecasts, calibration, inferred lifecycle
|
||||
timestamps, capacity, agent memory). Test: delete sidecar → resync → no
|
||||
truth lost.
|
||||
- **`pm-state` repo in gitea** = shared sidecar store. Versioned files;
|
||||
directive log is append-only JSONL (merges conflict-free). Local SQLite is
|
||||
a rebuildable cache/index only.
|
||||
- **Estimates/priority visible in gitea** as fixed label sets: `est/1d 2d 3d
|
||||
5d 8d`, `p/1..4`; `deadline/hard` label on milestones (agent asks hard/soft
|
||||
at creation). Estimate unit = days.
|
||||
- **LLM never does math.** Deterministic scheduler (code) computes forecasts,
|
||||
critical path, next-unit-of-work from estimates + deps + capacity +
|
||||
priority. Evidence-based scheduling: Monte Carlo over the team's own
|
||||
estimate-vs-actual history. LLM captures/negotiates inputs and explains
|
||||
outputs.
|
||||
- **Lifecycle inference, no manual time tracking**: issue opened → diagnosis;
|
||||
labeled/milestoned → triage; first branch/commit ref → work start; PR
|
||||
merged → deploy; closed → complete. Timestamps from gitea events feed
|
||||
actuals.
|
||||
- **Directives are first-class**: append-only log entry (who/when/what/why) →
|
||||
scheduler re-run → agent presents consequence diff ("X today, milestone Y
|
||||
+6d — accept?"). Directive-giver is a role; v1 = one PM (Stephen).
|
||||
- **Model layer**: OpenAI-wire-protocol client, base-URL + model per role.
|
||||
Router: small local (gemma-4b class) for summaries/standup prose; big model
|
||||
(remote LM Studio box or OpenAI API) for decomposition/estimate
|
||||
negotiation. Few, fat tools (e.g. one `query_project`) so small models
|
||||
survive.
|
||||
- **Agent conduct**: interview > dumping for capture; propose-approve for
|
||||
destructive ops, direct-act for additive; morning-standup ritual (drift
|
||||
report, today's plan, stale-blocker nagging).
|
||||
- **Memory**: hot (charter + active directives + focus snapshot, ≤2k tok) /
|
||||
warm (append-only event log, weekly digests) / cold (gitea + sidecar via
|
||||
tools — ticket data never copied into memory). No graph in v1.
|
||||
- **Sync**: per-instance gitea webhooks while running + full reconcile on
|
||||
launch + light poll fallback.
|
||||
- **Multi-contributor v1**: gitea users as identities; per-person capacity =
|
||||
hours/day × focus factor + standing allocation slices (dev/compliance/
|
||||
pilots). Multi-*writer* (concurrent directive-givers) deferred.
|
||||
- **Repos**: CommiTea source lives in its own repo (`commitea`) on
|
||||
gitea.stephenmann.io; targets N work repos via config (v1: one). Dogfood:
|
||||
CommiTea's own backlog is the first managed project.
|
||||
- **Stack**: Electron + React + Tailwind (novelpad patterns), one window.
|
||||
|
||||
## UI (to be designed — design session)
|
||||
|
||||
- Hero: **Now/Next/Later focus card** — scheduler-picked next unit, agent's
|
||||
one-line rationale.
|
||||
- **Burn-up with forecast cone** (ahead/behind as geometry), **runway view**
|
||||
(capacity vs milestone dates).
|
||||
- Secondary drill-ins: dependency graph / Gantt, kanban.
|
||||
- Chat = write-path (mutations via agent), UI = read-path. Exact split to be
|
||||
settled in design session.
|
||||
|
||||
## Phases
|
||||
|
||||
Deliverables per phase; replace TBD with actuals at phase close.
|
||||
|
||||
- **P0 — Scaffold** — repo, Electron shell, gitea API client + token auth,
|
||||
`pm-state` repo bootstrap. Actual: TBD
|
||||
- **P1 — Sync + data model** — read mirror into SQLite cache, webhook
|
||||
listener + reconcile-on-launch, lifecycle inference from event stream,
|
||||
label schema applied. Actual: TBD
|
||||
- **P2 — Scheduler + Monte Carlo** — deterministic forecast engine, capacity
|
||||
model, calibration store (cold-start: default distributions until n≥20),
|
||||
directive log + consequence diff. Actual: TBD
|
||||
- **P3 — UI views** — focus card, burn-up cone, runway, drill-ins. Actual: TBD
|
||||
- **P4 — Agent** — model router, fat tools, capture interview, propose-
|
||||
approve loop, standup ritual, memory layers. Actual: TBD
|
||||
- **P5 — Dogfood + polish** — manage CommiTea with CommiTea; calibrate.
|
||||
Actual: TBD
|
||||
|
||||
(Order note: P3 before P4 so the agent has something to point at; thin
|
||||
vertical slices within phases where possible.)
|
||||
|
||||
## Not doing (v1)
|
||||
|
||||
- Google Calendar capacity import (phase 2: free/busy read-only per member)
|
||||
- Phone/push notifications
|
||||
- Agent code review / PR content reading (PR *events* are in for lifecycle)
|
||||
- Graph-structured agent memory
|
||||
- PTO/meeting calendars
|
||||
- Concurrent multi-PM directive writing
|
||||
- Cloud LLM as *requirement* (it's a config option, not a dependency)
|
||||
|
||||
## Open items for design session
|
||||
|
||||
- Chat-as-only-write-path: strict or soft (UI edits allowed but agent
|
||||
observes/objects)?
|
||||
- `pm-state` file formats (JSONL event log settled; capacity/calibration
|
||||
schemas TBD)
|
||||
- Tool schema for the fat `query_project` tool
|
||||
- Webhook endpoint mechanics per instance (port allocation, cleanup on quit)
|
||||
- Cold-start estimate distributions (industry priors vs uniform pessimism)
|
||||
74
docs/design/README.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# Handoff: CommiTea App
|
||||
|
||||
## Overview
|
||||
CommiTea is an AI-project-manager built on Gitea: an Electron desktop app (one window) where an LLM agent persona ("Reginald") captures work via interview, forecasts milestones as Monte Carlo ranges, and manages issues through labels only. This package contains the complete design system plus a fully interactive HTML prototype of the app with 11 screens.
|
||||
|
||||
## About the Design Files
|
||||
**The files in this bundle are design references created in HTML** — prototypes showing intended look and behavior, not production code to copy directly. Your task is to **recreate these designs in the target codebase's environment**. The product plan specifies **Electron + React + Tailwind**; if that scaffold doesn't exist yet, that is the intended stack. Map the CSS custom properties in `tokens/` to Tailwind theme config; reimplement the `components/` primitives as your base component library.
|
||||
|
||||
`ui_kits/app/index.html` opens directly in a browser (via a local static server) — use it as the living spec. Everything is real: navigation, drill-ins, theme toggle, offline simulation.
|
||||
|
||||
## Fidelity
|
||||
**High-fidelity.** Colors, typography, spacing, radii, shadows, copy, and interactions are final. Recreate pixel-perfectly using the token values (all defined in `tokens/*.css`). The fixture data in `ui_kits/app/data.js` is demo content — replace with real Gitea/scheduler data.
|
||||
|
||||
## Design System (source of truth)
|
||||
- `design_system_readme.md` — brand context, CONTENT FUNDAMENTALS (Reginald's voice rules: dry wit, no emoji, sentence case, forecasts always ranges), VISUAL FOUNDATIONS, ICONOGRAPHY.
|
||||
- `styles.css` → imports `tokens/fonts.css` (self-hosted woff2 in `assets/fonts/`), `tokens/colors.css` (light `:root` + dark `[data-theme="dark"]`), `tokens/typography.css`, `tokens/spacing.css`, `tokens/base.css`.
|
||||
- `components/{core,forms,feedback}/` — 16 React primitives (Button, IconButton, Badge, Tag, Card, Tabs, Icon, Input, Select, Checkbox, Radio, Switch, Dialog, Toast, Tooltip). Each has `<Name>.jsx` (reference implementation), `<Name>.d.ts` (props contract), `<Name>.prompt.md` (usage + rules). Reuse these contracts verbatim.
|
||||
- `_ds_bundle.js` — compiled bundle the prototype loads; not for production.
|
||||
|
||||
### Type voices (strictly cast — never mix)
|
||||
- `--text-display/title/hero`: Libre Caslon Display — headlines, hero numerals
|
||||
- `--text-agent(-lg)`: Libre Caslon Text, **upright** — ONLY for Reginald's speech
|
||||
- `--text-body/small/caption`: Instrument Sans — all UI
|
||||
- `--text-data/label`: IBM Plex Mono — machine data verbatim: `est/3d`, `p/1`, `#87`, dates, deltas
|
||||
|
||||
### Key color tokens (light / dark)
|
||||
- Surfaces: `--paper-0` #F0F4F0/#121C18 (app), `--paper-1` #FAFCF9/#182420 (card), `--paper-2` inset, `--paper-3` pressed
|
||||
- Ink: `--ink-1` #1D2522/#E4EEE7, `--ink-2`, `--ink-3`; hairlines `--line-1/2`
|
||||
- Brand: `--accent` (spruce #275546/#3A7260), hover/pressed darker steps; `--jade` #46996F/#6FC694 (small accents + key-card top rule `--shadow-jade-line` only — never large fills)
|
||||
- Status: `--ok --warn --danger --info` + `*-tint` pairs; label chips `--label-p1..p4`, `--label-est-*`, `--label-hard`
|
||||
- Forecast: `--cone-fill`, `--cone-line`, `--cone-actual`
|
||||
- Radii 4/6/10px; spacing 4px scale (`--space-1..10`); motion 120–320ms `--ease-out`, no bounces; focus = 2px `--focus-ring` outline offset 2.
|
||||
|
||||
## Screens (all in `ui_kits/app/`, routed by `Shell.jsx`)
|
||||
Layout shell: 208px left rail (nav + connection status + theme switch) · main column (max 1120px, 24/28px padding) · 330px right chat panel. Page headers: Caslon display title over a `3px double` rule, mono subtitle. One `jade` (top-ruled) card per view maximum.
|
||||
|
||||
1. **Shell** (`Shell.jsx`) — nav, routing, dark mode (`data-theme` on `<html>`), offline simulation (click connection dot), issue navigation with back-stack of one.
|
||||
2. **Standup** (`StandupScreen.jsx`) — morning ritual as a typeset letter: drift report (dot + text + mono delta), per-person plan, stale-blocker nag (warn tint, clickable). Sections fade in once, 90ms stagger, reduced-motion-safe.
|
||||
3. **Morning service / Focus** (`FocusScreen.jsx`) — Now/Next/Later cards (Now = jade + footer actions), burn-up cone card (`Chart.jsx` BurnUpCone SVG).
|
||||
4. **Inbox** (`InboxScreen.jsx`) — day-grouped notifications, filter Tabs, unread dots, live rail badge; rows navigate to issue/directives; "Mark all read".
|
||||
5. **Capture** (`CaptureScreen.jsx`) — braindump → chip-answered interview (running mm:ss clock, amber past 2:00) → editable tray review with consequence line → filed. State machine: dump | interview | review | filed.
|
||||
6. **The pot / Board** (`BoardScreen.jsx`) — 5-column lifecycle kanban (Diagnosis/Triage/Steeping/In review/Done), live search with empty state, Tabs to drill-ins.
|
||||
7. **Gantt** (`GanttView.jsx`) — scheduler bars by state, critical rows inset-ruled, dotted 80% tails, today rule (jade), milestone band + due diamond.
|
||||
8. **Dependencies** (`DepsGraph.jsx`) — layered DAG, SVG bezier edges w/ arrowheads, critical path in accent, milestone capsule terminal.
|
||||
9. **Runway** (`RunwayScreen.jsx`) — milestone range bars (due marker vs 80% band), capacity list, calibration teaser → **Calibration** (`CalibrationScreen.jsx`): scatter + honest diagonal + ×1.18 fit, bias-by-label bars, per-person bias, forecast effect. Milestone rows → **Milestone detail** (`MilestoneScreen.jsx`): stats strip, cone, grouped issue list.
|
||||
10. **Issue detail** (`IssueScreen.jsx`) — human intent left (description, comments, composer "writes to gitea, as you"), machine-derived right (inferred lifecycle timeline, per-issue forecast, dependency chips, provenance note).
|
||||
11. **Directives** (`DirectivesScreen.jsx`) — pending consequence diff (before → after mono rows; Make it so / Amend / Withdraw) + append-only ledger (seq, who/when/why, verbatim quote, status badge).
|
||||
12. **Settings** (`SettingsScreen.jsx`) — connection, sync switches, model router, read-only label schema, rituals, appearance radios, single danger action.
|
||||
13. **Onboarding** (`OnboardingScreen.jsx`, "First run") — full-window: welcome → connect (test gate) → repo pick → propose-approve bootstrap.
|
||||
14. **States** (`StatesGallery.jsx`) — EmptyState/OfflineBanner/ModelAwayState components + gallery of all empty & trouble states.
|
||||
|
||||
## Interactions & Behavior
|
||||
- Hovers: surfaces step one paper darker; buttons darken (`--accent-hover`); never opacity on text. Press: one step darker again, no shrink.
|
||||
- All fake async (connection test ~1.1s, chat reply ~0.9s, bootstrap ticks 700ms) represent real network calls.
|
||||
- Offline mode: amber banner (copy in `StatesGallery.jsx`), chat composer disabled + queue note, red rail dot. Reads work from cache; writes queue.
|
||||
- Issue click anywhere → issue page; Back returns to origin view.
|
||||
- Chat = the only write path for mutations; destructive ops always propose-approve (Dialog or consequence diff).
|
||||
|
||||
## State Management (suggested)
|
||||
- `view` routing + `prevView` (back), `dark`, `offline`, `issue` selection, inbox `readIds`, capture state machine, directives pending/ledger. In production: Gitea REST + webhooks fill a local cache (SQLite per plan); scheduler output feeds focus/gantt/runway; all copy rules live in the design-system readme.
|
||||
|
||||
## Assets
|
||||
- `assets/fonts/` — Libre Caslon Display/Text, Instrument Sans, IBM Plex Mono (woff2, latin, self-hosted; Google Fonts sources)
|
||||
- `assets/icons/` — 69 Lucide SVGs (lucide-static v0.462.0, ISC). In production use the `lucide-react` package at strokeWidth 1.5.
|
||||
- `assets/logo.jpeg` (original), `assets/logo-icon.png` (cropped, rounded) — provided brand mark; never redraw.
|
||||
|
||||
## Files
|
||||
- `ui_kits/app/index.html` — entry; open with a static server from this folder's root
|
||||
- `ui_kits/app/*.jsx` — one file per screen (see Screens above); `data.js` — all fixture data
|
||||
- `styles.css`, `tokens/`, `components/`, `assets/` — the design system
|
||||
- `SKILL.md` — agent-facing skill entry (works with Claude Code as an Agent Skill)
|
||||
|
||||
## Note on file suffixes
|
||||
Reference source files in this bundle carry a `.txt` suffix (`*.js.txt`, `*.d-ts.txt`) so the design tool's compiler ignores these copies — the originals live in the design project. They are ordinary JSX/TypeScript inside; strip the suffix after copying into your repo. `ui_kits/app/index.html` still runs as-is (Babel loads the .txt files by src).
|
||||
16
docs/design/SKILL.md
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
name: commitea-design
|
||||
description: Use this skill to generate well-branded interfaces and assets for CommiTea, either for production or throwaway prototypes/mocks/etc. Contains essential design guidelines, colors, type, fonts, assets, and UI kit components for prototyping.
|
||||
user-invocable: true
|
||||
---
|
||||
|
||||
Read the README.md file within this skill, and explore the other available files.
|
||||
If creating visual artifacts (slides, mocks, throwaway prototypes, etc), copy assets out and create static HTML files for the user to view. If working on production code, you can copy assets and read the rules here to become an expert in designing with this brand.
|
||||
If the user invokes this skill without any other guidance, ask them what they want to build or design, ask some questions, and act as an expert designer who outputs HTML artifacts _or_ production code, depending on the need.
|
||||
|
||||
Key facts:
|
||||
- Brand: CommiTea — AI project manager on Gitea. The agent persona is **Reginald**: brilliant English gentleman PM, dry wit, numbers sacred. No emoji, sentence case, forecasts are ranges never point dates. Reginald's speech renders in upright Caslon serif; never italic, never "the AI".
|
||||
- Global CSS entry: `styles.css` (imports `tokens/*.css`). Fonts self-hosted in `assets/fonts/`; icons are local Lucide SVGs in `assets/icons/`.
|
||||
- Type voices, strictly cast: Libre Caslon Display (headlines/hero numerals), Libre Caslon Text upright (Reginald's speech only — the agent persona), Instrument Sans (UI), IBM Plex Mono (machine data: labels, dates, ids).
|
||||
- Components live in `components/{core,forms,feedback}/` — each has a `.prompt.md` with usage.
|
||||
- Full app reference: `ui_kits/app/index.html`.
|
||||
6692
docs/design/_ds_bundle.js
Normal file
BIN
docs/design/assets/fonts/caslon-display-normal-400.woff2
Normal file
BIN
docs/design/assets/fonts/caslon-text-italic-400.woff2
Normal file
BIN
docs/design/assets/fonts/caslon-text-normal-400.woff2
Normal file
BIN
docs/design/assets/fonts/caslon-text-normal-700.woff2
Normal file
BIN
docs/design/assets/fonts/instrument-sans-italic-400-700.woff2
Normal file
BIN
docs/design/assets/fonts/instrument-sans-normal-400-700.woff2
Normal file
BIN
docs/design/assets/fonts/plex-mono-normal-400.woff2
Normal file
BIN
docs/design/assets/fonts/plex-mono-normal-500.woff2
Normal file
BIN
docs/design/assets/fonts/plex-mono-normal-600.woff2
Normal file
3
docs/design/assets/icons/activity.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg class="lucide lucide-activity" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 362 B |
4
docs/design/assets/icons/arrow-left.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-arrow-left" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="m12 19-7-7 7-7"></path>
|
||||
<path d="M19 12H5"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 285 B |
4
docs/design/assets/icons/arrow-right.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-arrow-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M5 12h14"></path>
|
||||
<path d="m12 5 7 7-7 7"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 285 B |
4
docs/design/assets/icons/arrow-up-right.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-arrow-up-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M7 7h10v10"></path>
|
||||
<path d="M7 17 17 7"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 287 B |
4
docs/design/assets/icons/bell.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-bell" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"></path>
|
||||
<path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 328 B |
6
docs/design/assets/icons/calendar.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg class="lucide lucide-calendar" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M8 2v4"></path>
|
||||
<path d="M16 2v4"></path>
|
||||
<rect width="18" height="18" x="3" y="4" rx="2"></rect>
|
||||
<path d="M3 10h18"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 361 B |
4
docs/design/assets/icons/chart-line.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-chart-line" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M3 3v16a2 2 0 0 0 2 2h16"></path>
|
||||
<path d="m19 9-5 5-4-4-3 3"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 304 B |
5
docs/design/assets/icons/chart-no-axes-gantt.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg class="lucide lucide-chart-no-axes-gantt" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M8 6h10"></path>
|
||||
<path d="M6 12h9"></path>
|
||||
<path d="M11 18h7"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 315 B |
3
docs/design/assets/icons/check.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg class="lucide lucide-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M20 6 9 17l-5-5"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 252 B |
3
docs/design/assets/icons/chevron-down.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg class="lucide lucide-chevron-down" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="m6 9 6 6 6-6"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 256 B |
3
docs/design/assets/icons/chevron-left.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg class="lucide lucide-chevron-left" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="m15 18-6-6 6-6"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 258 B |
3
docs/design/assets/icons/chevron-right.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg class="lucide lucide-chevron-right" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="m9 18 6-6-6-6"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 258 B |
3
docs/design/assets/icons/chevron-up.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg class="lucide lucide-chevron-up" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="m18 15-6-6-6 6"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 256 B |
5
docs/design/assets/icons/circle-alert.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg class="lucide lucide-circle-alert" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<line x1="12" x2="12" y1="8" y2="12"></line>
|
||||
<line x1="12" x2="12.01" y1="16" y2="16"></line>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 364 B |
4
docs/design/assets/icons/circle-check.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-circle-check" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<path d="m9 12 2 2 4-4"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 300 B |
10
docs/design/assets/icons/circle-dashed.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<svg class="lucide lucide-circle-dashed" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M10.1 2.182a10 10 0 0 1 3.8 0"></path>
|
||||
<path d="M13.9 21.818a10 10 0 0 1-3.8 0"></path>
|
||||
<path d="M17.609 3.721a10 10 0 0 1 2.69 2.7"></path>
|
||||
<path d="M2.182 13.9a10 10 0 0 1 0-3.8"></path>
|
||||
<path d="M20.279 17.609a10 10 0 0 1-2.7 2.69"></path>
|
||||
<path d="M21.818 10.1a10 10 0 0 1 0 3.8"></path>
|
||||
<path d="M3.721 6.391a10 10 0 0 1 2.7-2.69"></path>
|
||||
<path d="M6.391 20.279a10 10 0 0 1-2.69-2.7"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 646 B |
4
docs/design/assets/icons/circle-dot.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-circle-dot" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<circle cx="12" cy="12" r="1"></circle>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 306 B |
3
docs/design/assets/icons/circle.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg class="lucide lucide-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 260 B |
4
docs/design/assets/icons/clock-3.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-clock-3" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<polyline points="12 6 12 12 16.5 12"></polyline>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 313 B |
4
docs/design/assets/icons/clock.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-clock" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<polyline points="12 6 12 12 16 14"></polyline>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 309 B |
6
docs/design/assets/icons/coffee.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg class="lucide lucide-coffee" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M10 2v2"></path>
|
||||
<path d="M14 2v2"></path>
|
||||
<path d="M16 8a1 1 0 0 1 1 1v8a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4V9a1 1 0 0 1 1-1h14a4 4 0 1 1 0 8h-1"></path>
|
||||
<path d="M6 2v2"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 408 B |
4
docs/design/assets/icons/copy.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-copy" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect width="14" height="14" x="8" y="8" rx="2" ry="2"></rect>
|
||||
<path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 356 B |
5
docs/design/assets/icons/ellipsis.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg class="lucide lucide-ellipsis" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="1"></circle>
|
||||
<circle cx="19" cy="12" r="1"></circle>
|
||||
<circle cx="5" cy="12" r="1"></circle>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 344 B |
5
docs/design/assets/icons/external-link.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg class="lucide lucide-external-link" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M15 3h6v6"></path>
|
||||
<path d="M10 14 21 3"></path>
|
||||
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 363 B |
4
docs/design/assets/icons/eye.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-eye" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0"></path>
|
||||
<circle cx="12" cy="12" r="3"></circle>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 378 B |
3
docs/design/assets/icons/filter.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg class="lucide lucide-filter" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"></polygon>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 292 B |
4
docs/design/assets/icons/flag.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-flag" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z"></path>
|
||||
<line x1="4" x2="4" y1="22" y2="15"></line>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 339 B |
4
docs/design/assets/icons/gauge.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-gauge" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="m12 14 4-4"></path>
|
||||
<path d="M3.34 19a10 10 0 1 1 17.32 0"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 296 B |
6
docs/design/assets/icons/git-branch.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg class="lucide lucide-git-branch" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<line x1="6" x2="6" y1="3" y2="15"></line>
|
||||
<circle cx="18" cy="6" r="3"></circle>
|
||||
<circle cx="6" cy="18" r="3"></circle>
|
||||
<path d="M18 9a9 9 0 0 1-9 9"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 388 B |
5
docs/design/assets/icons/git-commit-horizontal.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg class="lucide lucide-git-commit-horizontal" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="3"></circle>
|
||||
<line x1="3" x2="9" y1="12" y2="12"></line>
|
||||
<line x1="15" x2="21" y1="12" y2="12"></line>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 368 B |
5
docs/design/assets/icons/git-merge.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg class="lucide lucide-git-merge" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="18" cy="18" r="3"></circle>
|
||||
<circle cx="6" cy="6" r="3"></circle>
|
||||
<path d="M6 21V9a9 9 0 0 0 9 9"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 344 B |
6
docs/design/assets/icons/git-pull-request.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg class="lucide lucide-git-pull-request" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="18" cy="18" r="3"></circle>
|
||||
<circle cx="6" cy="6" r="3"></circle>
|
||||
<path d="M13 6h3a2 2 0 0 1 2 2v7"></path>
|
||||
<line x1="6" x2="6" y1="9" y2="21"></line>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 398 B |
5
docs/design/assets/icons/history.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg class="lucide lucide-history" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"></path>
|
||||
<path d="M3 3v5h5"></path>
|
||||
<path d="M12 7v5l4 2"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 349 B |
4
docs/design/assets/icons/inbox.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-inbox" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="22 12 16 12 14 15 10 15 8 12 2 12"></polyline>
|
||||
<path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 410 B |
5
docs/design/assets/icons/info.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg class="lucide lucide-info" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<path d="M12 16v-4"></path>
|
||||
<path d="M12 8h.01"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 318 B |
11
docs/design/assets/icons/keyboard.svg
Normal file
@@ -0,0 +1,11 @@
|
||||
<svg class="lucide lucide-keyboard" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M10 8h.01"></path>
|
||||
<path d="M12 12h.01"></path>
|
||||
<path d="M14 8h.01"></path>
|
||||
<path d="M16 12h.01"></path>
|
||||
<path d="M18 8h.01"></path>
|
||||
<path d="M6 8h.01"></path>
|
||||
<path d="M7 16h10"></path>
|
||||
<path d="M8 12h.01"></path>
|
||||
<rect width="20" height="16" x="2" y="4" rx="2"></rect>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 517 B |
5
docs/design/assets/icons/layers.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg class="lucide lucide-layers" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="m12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z"></path>
|
||||
<path d="m22 17.65-9.17 4.16a2 2 0 0 1-1.66 0L2 17.65"></path>
|
||||
<path d="m22 12.65-9.17 4.16a2 2 0 0 1-1.66 0L2 12.65"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 476 B |
4
docs/design/assets/icons/leaf.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-leaf" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M11 20A7 7 0 0 1 9.8 6.1C15.5 5 17 4.48 19 2c1 2 2 4.18 2 8 0 5.5-4.78 10-10 10Z"></path>
|
||||
<path d="M2 21c0-3 1.85-5.36 5.08-6C9.5 14.52 12 13 13 12"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 385 B |
4
docs/design/assets/icons/link.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-link" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path>
|
||||
<path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 376 B |
5
docs/design/assets/icons/list-filter.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg class="lucide lucide-list-filter" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M3 6h18"></path>
|
||||
<path d="M7 12h10"></path>
|
||||
<path d="M10 18h4"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 308 B |
8
docs/design/assets/icons/list.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<svg class="lucide lucide-list" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M3 12h.01"></path>
|
||||
<path d="M3 18h.01"></path>
|
||||
<path d="M3 6h.01"></path>
|
||||
<path d="M8 12h13"></path>
|
||||
<path d="M8 18h13"></path>
|
||||
<path d="M8 6h13"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 390 B |
3
docs/design/assets/icons/loader-circle.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg class="lucide lucide-loader-circle" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21 12a9 9 0 1 1-6.219-8.56"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 272 B |
3
docs/design/assets/icons/message-square.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg class="lucide lucide-message-square" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 307 B |
5
docs/design/assets/icons/milestone.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg class="lucide lucide-milestone" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M12 13v8"></path>
|
||||
<path d="M12 3v3"></path>
|
||||
<path d="M4 6a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1h13a2 2 0 0 0 1.152-.365l3.424-2.317a1 1 0 0 0 0-1.635l-3.424-2.318A2 2 0 0 0 17 6z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 415 B |
3
docs/design/assets/icons/minus.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg class="lucide lucide-minus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M5 12h14"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 245 B |
3
docs/design/assets/icons/moon.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg class="lucide lucide-moon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 270 B |
7
docs/design/assets/icons/network.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg class="lucide lucide-network" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect x="16" y="16" width="6" height="6" rx="1"></rect>
|
||||
<rect x="2" y="16" width="6" height="6" rx="1"></rect>
|
||||
<rect x="9" y="2" width="6" height="6" rx="1"></rect>
|
||||
<path d="M5 16v-3a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v3"></path>
|
||||
<path d="M12 12V8"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 480 B |
4
docs/design/assets/icons/panel-left.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-panel-left" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect width="18" height="18" x="3" y="3" rx="2"></rect>
|
||||
<path d="M9 3v18"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 307 B |
4
docs/design/assets/icons/pause.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-pause" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect x="14" y="4" width="4" height="16" rx="1"></rect>
|
||||
<rect x="6" y="4" width="4" height="16" rx="1"></rect>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 331 B |
4
docs/design/assets/icons/pencil.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-pencil" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"></path>
|
||||
<path d="m15 5 4 4"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 396 B |
3
docs/design/assets/icons/play.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg class="lucide lucide-play" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polygon points="6 3 20 12 6 21 6 3"></polygon>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 265 B |
4
docs/design/assets/icons/plus.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-plus" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M5 12h14"></path>
|
||||
<path d="M12 5v14"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 273 B |
6
docs/design/assets/icons/refresh-cw.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg class="lucide lucide-refresh-cw" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"></path>
|
||||
<path d="M21 3v5h-5"></path>
|
||||
<path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"></path>
|
||||
<path d="M8 16H3v5"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 425 B |
4
docs/design/assets/icons/search.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-search" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="11" cy="11" r="8"></circle>
|
||||
<path d="m21 21-4.3-4.3"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 294 B |
4
docs/design/assets/icons/send.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-send" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z"></path>
|
||||
<path d="m21.854 2.147-10.94 10.939"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 410 B |
6
docs/design/assets/icons/settings-2.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg class="lucide lucide-settings-2" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M20 7h-9"></path>
|
||||
<path d="M14 17H5"></path>
|
||||
<circle cx="17" cy="17" r="3"></circle>
|
||||
<circle cx="7" cy="7" r="3"></circle>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 361 B |
4
docs/design/assets/icons/settings.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-settings" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"></path>
|
||||
<circle cx="12" cy="12" r="3"></circle>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 847 B |
7
docs/design/assets/icons/sparkles.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg class="lucide lucide-sparkles" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"></path>
|
||||
<path d="M20 3v4"></path>
|
||||
<path d="M22 5h-4"></path>
|
||||
<path d="M4 17v2"></path>
|
||||
<path d="M5 18H3"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 604 B |
6
docs/design/assets/icons/square-kanban.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg class="lucide lucide-square-kanban" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect width="18" height="18" x="3" y="3" rx="2"></rect>
|
||||
<path d="M8 7v7"></path>
|
||||
<path d="M12 7v4"></path>
|
||||
<path d="M16 7v9"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 365 B |
11
docs/design/assets/icons/sun.svg
Normal file
@@ -0,0 +1,11 @@
|
||||
<svg class="lucide lucide-sun" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="4"></circle>
|
||||
<path d="M12 2v2"></path>
|
||||
<path d="M12 20v2"></path>
|
||||
<path d="m4.93 4.93 1.41 1.41"></path>
|
||||
<path d="m17.66 17.66 1.41 1.41"></path>
|
||||
<path d="M2 12h2"></path>
|
||||
<path d="M20 12h2"></path>
|
||||
<path d="m6.34 17.66-1.41 1.41"></path>
|
||||
<path d="m19.07 4.93-1.41 1.41"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 538 B |
4
docs/design/assets/icons/tag.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-tag" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M12.586 2.586A2 2 0 0 0 11.172 2H4a2 2 0 0 0-2 2v7.172a2 2 0 0 0 .586 1.414l8.704 8.704a2.426 2.426 0 0 0 3.42 0l6.58-6.58a2.426 2.426 0 0 0 0-3.42z"></path>
|
||||
<circle cx="7.5" cy="7.5" r=".5" fill="currentColor"></circle>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 448 B |
5
docs/design/assets/icons/target.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg class="lucide lucide-target" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<circle cx="12" cy="12" r="6"></circle>
|
||||
<circle cx="12" cy="12" r="2"></circle>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 344 B |
7
docs/design/assets/icons/trash-2.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg class="lucide lucide-trash-2" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M3 6h18"></path>
|
||||
<path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"></path>
|
||||
<path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"></path>
|
||||
<line x1="10" x2="10" y1="11" y2="17"></line>
|
||||
<line x1="14" x2="14" y1="11" y2="17"></line>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 455 B |
4
docs/design/assets/icons/trending-up.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-trending-up" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="22 7 13.5 15.5 8.5 10.5 2 17"></polyline>
|
||||
<polyline points="16 7 22 7 22 13"></polyline>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 333 B |
5
docs/design/assets/icons/triangle-alert.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg class="lucide lucide-triangle-alert" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3"></path>
|
||||
<path d="M12 9v4"></path>
|
||||
<path d="M12 17h.01"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 377 B |
4
docs/design/assets/icons/user.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-user" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"></path>
|
||||
<circle cx="12" cy="7" r="4"></circle>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 318 B |
6
docs/design/assets/icons/users.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg class="lucide lucide-users" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"></path>
|
||||
<circle cx="9" cy="7" r="4"></circle>
|
||||
<path d="M22 21v-2a4 4 0 0 0-3-3.87"></path>
|
||||
<path d="M16 3.13a4 4 0 0 1 0 7.75"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 411 B |
4
docs/design/assets/icons/x.svg
Normal file
@@ -0,0 +1,4 @@
|
||||
<svg class="lucide lucide-x" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M18 6 6 18"></path>
|
||||
<path d="m6 6 12 12"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 274 B |
3
docs/design/assets/icons/zap.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg class="lucide lucide-zap" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 390 B |
BIN
docs/design/assets/logo-icon.png
Normal file
|
After Width: | Height: | Size: 296 KiB |
BIN
docs/design/assets/logo.jpeg
Normal file
|
After Width: | Height: | Size: 43 KiB |
12
docs/design/components/core/Badge.d-ts.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Status pill — muted tint background, colored text. For state words like "ahead", "behind", "steeping".
|
||||
*/
|
||||
export interface BadgeProps {
|
||||
/** @default 'neutral' */
|
||||
tone?: 'ok' | 'warn' | 'danger' | 'info' | 'neutral' | 'jade';
|
||||
/** Leading status dot @default false */
|
||||
dot?: boolean;
|
||||
children?: React.ReactNode;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
export declare function Badge(props: BadgeProps): JSX.Element;
|
||||
32
docs/design/components/core/Badge.js.txt
Normal file
@@ -0,0 +1,32 @@
|
||||
import React from 'react';
|
||||
|
||||
const CSS = `
|
||||
.ct-badge {
|
||||
display: inline-flex; align-items: center; gap: 6px;
|
||||
font: 500 12px/1 var(--font-sans);
|
||||
padding: 4px 9px;
|
||||
border-radius: var(--radius-round);
|
||||
}
|
||||
.ct-badge__dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
|
||||
.ct-badge--ok { background: var(--ok-tint); color: var(--ok); }
|
||||
.ct-badge--warn { background: var(--warn-tint); color: var(--warn); }
|
||||
.ct-badge--danger { background: var(--danger-tint); color: var(--danger); }
|
||||
.ct-badge--info { background: var(--info-tint); color: var(--info); }
|
||||
.ct-badge--neutral { background: var(--paper-2); color: var(--ink-2); }
|
||||
.ct-badge--jade { background: var(--jade-tint); color: var(--jade-7); }
|
||||
`;
|
||||
(function inject() {
|
||||
if (typeof document !== 'undefined' && !document.getElementById('ct-badge-css')) {
|
||||
const s = document.createElement('style'); s.id = 'ct-badge-css'; s.textContent = CSS;
|
||||
document.head.appendChild(s);
|
||||
}
|
||||
})();
|
||||
|
||||
export function Badge({ tone = 'neutral', dot = false, children, style, ...rest }) {
|
||||
return (
|
||||
<span className={`ct-badge ct-badge--${tone}`} style={style} {...rest}>
|
||||
{dot ? <span className="ct-badge__dot"></span> : null}
|
||||
{children}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
9
docs/design/components/core/Badge.prompt.md
Normal file
@@ -0,0 +1,9 @@
|
||||
Status pill for state words (ahead / behind / steeping / blocked); sans text on a muted tint.
|
||||
|
||||
```jsx
|
||||
<Badge tone="ok" dot>ahead</Badge>
|
||||
<Badge tone="warn" dot>drifting</Badge>
|
||||
<Badge tone="danger">blocked</Badge>
|
||||
```
|
||||
|
||||
Tones: ok, warn, danger, info, neutral, jade (jade = agent/forecast flavor). Use `Tag` instead for verbatim gitea labels like `est/3d`.
|
||||
18
docs/design/components/core/Button.d-ts.txt
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* CommiTea button. Plain verbs only ("Approve", "Brew plan", "Defer") — never witty.
|
||||
*/
|
||||
export interface ButtonProps {
|
||||
/** @default 'primary' */
|
||||
variant?: 'primary' | 'secondary' | 'ghost' | 'danger';
|
||||
/** @default 'md' */
|
||||
size?: 'sm' | 'md';
|
||||
/** Lucide icon name rendered before the label */
|
||||
icon?: string;
|
||||
/** Lucide icon name rendered after the label */
|
||||
iconRight?: string;
|
||||
disabled?: boolean;
|
||||
onClick?: (e: React.MouseEvent) => void;
|
||||
children?: React.ReactNode;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
export declare function Button(props: ButtonProps): JSX.Element;
|
||||
63
docs/design/components/core/Button.js.txt
Normal file
@@ -0,0 +1,63 @@
|
||||
import React from 'react';
|
||||
|
||||
const CSS = `
|
||||
.ct-btn {
|
||||
display: inline-flex; align-items: center; justify-content: center; gap: 8px;
|
||||
font: 600 14px/1 var(--font-sans);
|
||||
border-radius: var(--radius-2);
|
||||
border: 1px solid transparent;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
transition: background var(--duration-fast) var(--ease-out),
|
||||
border-color var(--duration-fast) var(--ease-out),
|
||||
color var(--duration-fast) var(--ease-out);
|
||||
}
|
||||
.ct-btn:disabled { opacity: 0.45; cursor: not-allowed; }
|
||||
.ct-btn--md { height: 34px; padding: 0 14px; }
|
||||
.ct-btn--sm { height: 28px; padding: 0 10px; font-size: 13px; }
|
||||
.ct-btn--primary { background: var(--accent); color: var(--text-on-accent); }
|
||||
.ct-btn--primary:hover:not(:disabled) { background: var(--accent-hover); }
|
||||
.ct-btn--primary:active:not(:disabled) { background: var(--accent-pressed); }
|
||||
.ct-btn--secondary { background: var(--surface-card); border-color: var(--line-2); color: var(--ink-1); }
|
||||
.ct-btn--secondary:hover:not(:disabled) { background: var(--paper-2); }
|
||||
.ct-btn--secondary:active:not(:disabled) { background: var(--paper-3); }
|
||||
.ct-btn--ghost { background: transparent; color: var(--ink-2); }
|
||||
.ct-btn--ghost:hover:not(:disabled) { background: var(--paper-2); color: var(--ink-1); }
|
||||
.ct-btn--ghost:active:not(:disabled) { background: var(--paper-3); }
|
||||
.ct-btn--danger { background: var(--danger); color: var(--ink-inverse); }
|
||||
.ct-btn--danger:hover:not(:disabled) { filter: brightness(0.92); }
|
||||
`;
|
||||
(function inject() {
|
||||
if (typeof document !== 'undefined' && !document.getElementById('ct-button-css')) {
|
||||
const s = document.createElement('style'); s.id = 'ct-button-css'; s.textContent = CSS;
|
||||
document.head.appendChild(s);
|
||||
}
|
||||
})();
|
||||
|
||||
import { Icon } from './Icon';
|
||||
|
||||
export function Button({
|
||||
variant = 'primary',
|
||||
size = 'md',
|
||||
icon,
|
||||
iconRight,
|
||||
disabled = false,
|
||||
children,
|
||||
style,
|
||||
...rest
|
||||
}) {
|
||||
const iconSize = size === 'sm' ? 15 : 17;
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className={`ct-btn ct-btn--${size} ct-btn--${variant}`}
|
||||
disabled={disabled}
|
||||
style={style}
|
||||
{...rest}
|
||||
>
|
||||
{icon ? <Icon name={icon} size={iconSize} /> : null}
|
||||
{children}
|
||||
{iconRight ? <Icon name={iconRight} size={iconSize} /> : null}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
10
docs/design/components/core/Button.prompt.md
Normal file
@@ -0,0 +1,10 @@
|
||||
Button for all actions; labels are plain sentence-case verbs — the wit lives elsewhere.
|
||||
|
||||
```jsx
|
||||
<Button onClick={approve}>Approve</Button>
|
||||
<Button variant="secondary" icon="sparkles">Brew plan</Button>
|
||||
<Button variant="ghost" size="sm">Defer</Button>
|
||||
<Button variant="danger">Delete milestone</Button>
|
||||
```
|
||||
|
||||
Variants: `primary` (spruce fill — one per view), `secondary` (hairline outline), `ghost` (bare), `danger` (madder red, destructive confirms only). Sizes `md` 34px / `sm` 28px. `icon`/`iconRight` take Lucide names.
|
||||
21
docs/design/components/core/Card.d-ts.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Paper card — hairline border, 10px radius, whispered shadow. `jade` adds the jade top rule
|
||||
* reserved for the view's key card (e.g. the Focus card).
|
||||
*/
|
||||
export interface CardProps {
|
||||
/** Caslon title */
|
||||
title?: React.ReactNode;
|
||||
/** Small uppercase label above the title */
|
||||
overline?: string;
|
||||
/** Right-aligned header actions (IconButtons) */
|
||||
actions?: React.ReactNode;
|
||||
/** Footer row below a hairline */
|
||||
footer?: React.ReactNode;
|
||||
/** Jade top rule — one per view @default false */
|
||||
jade?: boolean;
|
||||
/** Remove body padding (tables, charts) @default false */
|
||||
flush?: boolean;
|
||||
children?: React.ReactNode;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
export declare function Card(props: CardProps): JSX.Element;
|
||||
58
docs/design/components/core/Card.js.txt
Normal file
@@ -0,0 +1,58 @@
|
||||
import React from 'react';
|
||||
|
||||
const CSS = `
|
||||
.ct-card {
|
||||
background: var(--surface-card);
|
||||
border: 1px solid var(--border-hairline);
|
||||
border-radius: var(--radius-3);
|
||||
box-shadow: var(--shadow-1);
|
||||
}
|
||||
.ct-card--jade { box-shadow: var(--shadow-jade-line), var(--shadow-1); }
|
||||
.ct-card__header {
|
||||
display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
|
||||
padding: 16px 20px 0;
|
||||
}
|
||||
.ct-card__title {
|
||||
font: var(--text-title);
|
||||
color: var(--ink-1);
|
||||
margin: 0;
|
||||
}
|
||||
.ct-card__overline {
|
||||
font: var(--text-overline);
|
||||
letter-spacing: var(--letter-spacing-wide);
|
||||
text-transform: uppercase;
|
||||
color: var(--ink-3);
|
||||
margin: 0 0 6px;
|
||||
}
|
||||
.ct-card__body { padding: 14px 20px 18px; }
|
||||
.ct-card__body--flush { padding: 0; }
|
||||
.ct-card__footer {
|
||||
display: flex; align-items: center; gap: 8px;
|
||||
padding: 12px 20px;
|
||||
border-top: 1px solid var(--border-hairline);
|
||||
}
|
||||
`;
|
||||
(function inject() {
|
||||
if (typeof document !== 'undefined' && !document.getElementById('ct-card-css')) {
|
||||
const s = document.createElement('style'); s.id = 'ct-card-css'; s.textContent = CSS;
|
||||
document.head.appendChild(s);
|
||||
}
|
||||
})();
|
||||
|
||||
export function Card({ title, overline, actions, footer, jade = false, flush = false, children, style, ...rest }) {
|
||||
return (
|
||||
<section className={`ct-card${jade ? ' ct-card--jade' : ''}`} style={style} {...rest}>
|
||||
{(title || overline || actions) ? (
|
||||
<header className="ct-card__header">
|
||||
<div>
|
||||
{overline ? <p className="ct-card__overline">{overline}</p> : null}
|
||||
{title ? <h2 className="ct-card__title">{title}</h2> : null}
|
||||
</div>
|
||||
{actions ? <div style={{ display: 'flex', gap: '4px', flexShrink: 0 }}>{actions}</div> : null}
|
||||
</header>
|
||||
) : null}
|
||||
<div className={`ct-card__body${flush ? ' ct-card__body--flush' : ''}`}>{children}</div>
|
||||
{footer ? <footer className="ct-card__footer">{footer}</footer> : null}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
11
docs/design/components/core/Card.prompt.md
Normal file
@@ -0,0 +1,11 @@
|
||||
Paper card container; title is set in Caslon, elevation is whispered.
|
||||
|
||||
```jsx
|
||||
<Card overline="Now" title="Fix lifecycle inference" jade
|
||||
actions={<IconButton icon="ellipsis" label="More" size="sm" />}
|
||||
footer={<Button size="sm">Start</Button>}>
|
||||
Body content.
|
||||
</Card>
|
||||
```
|
||||
|
||||
`jade` (jade top rule) marks the single most important card in a view. `flush` removes body padding for tables/charts.
|
||||
15
docs/design/components/core/Icon.d-ts.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Inline Lucide icon (1.5px stroke), tinted by currentColor.
|
||||
*/
|
||||
export interface IconProps {
|
||||
/** Lucide icon name, e.g. "circle-dot", "sparkles", "git-branch" */
|
||||
name: string;
|
||||
/** Square size in px. 16 inline, 18–20 in buttons/nav. @default 16 */
|
||||
size?: number;
|
||||
/** @default 1.5 */
|
||||
strokeWidth?: number;
|
||||
/** Accessible label; omit for decorative icons */
|
||||
title?: string;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
export declare function Icon(props: IconProps): JSX.Element;
|
||||
32
docs/design/components/core/Icon.js.txt
Normal file
8
docs/design/components/core/Icon.prompt.md
Normal file
@@ -0,0 +1,8 @@
|
||||
Inline SVG icon from the local Lucide set (69 icons, 1.5px stroke); color inherits currentColor.
|
||||
|
||||
```jsx
|
||||
<Icon name="circle-dot" />
|
||||
<Icon name="sparkles" size={18} style={{ color: 'var(--jade)' }} />
|
||||
```
|
||||
|
||||
Domain mapping: issues circle-dot · milestones milestone · board square-kanban · forecast chart-line · deps network · agent sparkles · standup coffee · capacity gauge · directives flag. ICON_NAMES export lists all available names. Icons are decorative by default (aria-hidden); pass title for meaningful ones.
|
||||
17
docs/design/components/core/IconButton.d-ts.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Square icon-only button; label is mandatory (becomes aria-label + title).
|
||||
*/
|
||||
export interface IconButtonProps {
|
||||
/** Lucide icon name */
|
||||
icon: string;
|
||||
/** Required accessible label (also the tooltip) */
|
||||
label: string;
|
||||
/** @default 'ghost' */
|
||||
variant?: 'ghost' | 'outline';
|
||||
/** @default 'md' */
|
||||
size?: 'sm' | 'md';
|
||||
disabled?: boolean;
|
||||
onClick?: (e: React.MouseEvent) => void;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
export declare function IconButton(props: IconButtonProps): JSX.Element;
|
||||
51
docs/design/components/core/IconButton.js.txt
Normal file
@@ -0,0 +1,51 @@
|
||||
import React from 'react';
|
||||
import { Icon } from './Icon';
|
||||
|
||||
const CSS = `
|
||||
.ct-iconbtn {
|
||||
display: inline-flex; align-items: center; justify-content: center;
|
||||
border-radius: var(--radius-2);
|
||||
border: 1px solid transparent;
|
||||
background: transparent;
|
||||
color: var(--ink-2);
|
||||
cursor: pointer;
|
||||
transition: background var(--duration-fast) var(--ease-out), color var(--duration-fast) var(--ease-out);
|
||||
}
|
||||
.ct-iconbtn:hover:not(:disabled) { background: var(--paper-2); color: var(--ink-1); }
|
||||
.ct-iconbtn:active:not(:disabled) { background: var(--paper-3); }
|
||||
.ct-iconbtn:disabled { opacity: 0.45; cursor: not-allowed; }
|
||||
.ct-iconbtn--md { width: 34px; height: 34px; }
|
||||
.ct-iconbtn--sm { width: 28px; height: 28px; }
|
||||
.ct-iconbtn--outline { border-color: var(--line-2); background: var(--surface-card); }
|
||||
.ct-iconbtn--outline:hover:not(:disabled) { background: var(--paper-2); }
|
||||
`;
|
||||
(function inject() {
|
||||
if (typeof document !== 'undefined' && !document.getElementById('ct-iconbtn-css')) {
|
||||
const s = document.createElement('style'); s.id = 'ct-iconbtn-css'; s.textContent = CSS;
|
||||
document.head.appendChild(s);
|
||||
}
|
||||
})();
|
||||
|
||||
export function IconButton({
|
||||
icon,
|
||||
label,
|
||||
variant = 'ghost',
|
||||
size = 'md',
|
||||
disabled = false,
|
||||
style,
|
||||
...rest
|
||||
}) {
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className={`ct-iconbtn ct-iconbtn--${size}${variant === 'outline' ? ' ct-iconbtn--outline' : ''}`}
|
||||
aria-label={label}
|
||||
title={label}
|
||||
disabled={disabled}
|
||||
style={style}
|
||||
{...rest}
|
||||
>
|
||||
<Icon name={icon} size={size === 'sm' ? 15 : 17} />
|
||||
</button>
|
||||
);
|
||||
}
|
||||
8
docs/design/components/core/IconButton.prompt.md
Normal file
@@ -0,0 +1,8 @@
|
||||
Icon-only square button for toolbars and row actions; `label` is required and doubles as the tooltip.
|
||||
|
||||
```jsx
|
||||
<IconButton icon="ellipsis" label="More actions" />
|
||||
<IconButton icon="refresh-cw" label="Reconcile now" variant="outline" size="sm" />
|
||||
```
|
||||
|
||||
Variants: `ghost` (default), `outline`. Sizes `md` 34px / `sm` 28px.
|
||||
19
docs/design/components/core/Tabs.d-ts.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Underline tabs for view switching (Board / Gantt / Dependencies).
|
||||
*/
|
||||
export interface TabItem {
|
||||
id: string;
|
||||
label: string;
|
||||
/** Lucide icon name */
|
||||
icon?: string;
|
||||
/** Mono count rendered after the label */
|
||||
count?: number;
|
||||
}
|
||||
export interface TabsProps {
|
||||
items: TabItem[];
|
||||
/** id of the active tab */
|
||||
active: string;
|
||||
onChange?: (id: string) => void;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
export declare function Tabs(props: TabsProps): JSX.Element;
|
||||