Replace the UI with the Organic design handoff (docs/design_handoff_pansy_ui)
The frontend is rebuilt screen by screen from the handoff: warm cream ground, terracotta + sage accents, Caprasimo over Figtree, every control a pill. Same React/Vite/TanStack stack and the same lib/ data layer; the presentation is new. - Tokens: web/src/styles/index.css declares the handoff's styles.css variables through Tailwind's @theme under the same names; dark mode is those variables overridden on <html> by the handoff's pansy-theme.js, inlined in index.html so it runs before first paint. Lucide glyphs at stroke 2.75; a small pill kit (Button, Dialog, Field, Seg, Toggle, Tag, toast). - Login / Register: the centered column over soft accent circles; OIDC button and signup footer still follow /auth/providers. - Gardens: cards with a real SVG plot thumbnail (objects + plant-colored dots from /full), a `plan` tag for "<name> — <year>" copies, shares line, Open + share/copy/edit/delete; New garden / Share / Plan-a-season dialogs. - Plants: monogram markers derived from the name (collision-resolved across the catalog — replaces emoji icons), category chips, expandable lot cards, the scan-packet flow as a two-step dialog that never auto-creates. - Settings: Appearance (theme seg), Who gets in (read-only sign-in config), Garden assistant (self-saving toggle + chat/vision model fields), You. - Editor: a new canvas with the prototype's pointer model (wheel-to-cursor, pinch about the centroid, 3″ snap, one PATCH per drop, semantic-zoom monograms/labels), plus corner resize handles; desktop three-card workspace (toolkit | plan | rail with Plot/Journal/History/Assistant) and, below 760px of container width, the phone chrome (header, peek panel, tool strip, mode bar). Seasons as a segmented control over the years with data plus plan copies; Undo re-reads history before reverting the newest step. - Public read-only view and the register page restyled to match. - GET /settings gains a read-only `auth` view (registration mode, local auth, OIDC issuer) so the Settings page can show what's in force. - README / DESIGN.md / CLAUDE.md updated; @use-gesture/react dropped. Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
@@ -202,3 +202,28 @@ export function spacingFromCm(cm: number, unit: UnitPref): number {
|
||||
export function spacingUnitLabel(unit: UnitPref): string {
|
||||
return unit === 'imperial' ? 'in' : 'cm'
|
||||
}
|
||||
|
||||
// --- Compact imperial display ----------------------------------------------
|
||||
// The editor and the cards label sizes the way a gardener says them — 3′, 1′4″,
|
||||
// 8″ — rather than the always-both "4′ 0″" the entry fields round-trip through.
|
||||
// Display only; nothing here is parsed back.
|
||||
|
||||
/** Centimeters → nearest inch, shown as feet/inches with zero parts dropped:
|
||||
* 91 → "3′", 40 → "1′4″", 20 → "8″". */
|
||||
export function formatFtIn(cm: number): string {
|
||||
const inches = Math.round(Math.abs(cm) / CM_PER_INCH)
|
||||
const feet = Math.floor(inches / INCHES_PER_FOOT)
|
||||
const rest = inches - feet * INCHES_PER_FOOT
|
||||
const s = feet ? (rest ? `${feet}′${rest}″` : `${feet}′`) : `${rest}″`
|
||||
return cm < 0 && inches ? `-${s}` : s
|
||||
}
|
||||
|
||||
/** One length in the garden's unit: compact feet/inches, or meters. */
|
||||
export function formatLength(cm: number, unit: UnitPref): string {
|
||||
return unit === 'imperial' ? formatFtIn(cm) : formatCm(cm, 'metric')
|
||||
}
|
||||
|
||||
/** "3′ × 6′" / "0.91 m × 1.83 m". */
|
||||
export function formatSize(widthCm: number, heightCm: number, unit: UnitPref): string {
|
||||
return `${formatLength(widthCm, unit)} × ${formatLength(heightCm, unit)}`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user