diff --git a/.design-sync/NOTES.md b/.design-sync/NOTES.md new file mode 100644 index 000000000..62c2ce03b --- /dev/null +++ b/.design-sync/NOTES.md @@ -0,0 +1,55 @@ +# design-sync notes — @reactive-resume/ui + +Syncs to Claude Design project **Reactive Resume** (`3c0f6556-050a-41e5-9886-c3f1ea950517`). + +## Repo shape / build + +- `@reactive-resume/ui` is **source-consumed** (pnpm workspace, no `dist`, exports point at `src/components/*.tsx`). Runs in the converter's **synth-entry mode** (no `--entry`). +- `buildCmd` = `node .design-sync/build-css.mjs`. That one script does three things, all required before every converter run: + 1. Creates the workspace **self-symlink** `packages/ui/node_modules/@reactive-resume/ui -> ../../../ui` (pnpm doesn't self-install it; the converter resolves the DS as `node_modules/` and esbuild needs it for `@reactive-resume/ui/components/*` self-imports). + 2. Emits real **`.d.ts`** to `packages/ui/dist/types` via `tsc -p packages/ui/tsconfig.emit.json`. Without this, synth-entry mode gives weak `{[key]: unknown}` prop contracts; with it the converter's `findTypesRoot` picks up `dist/types` and every component gets real props (variant/size unions, inherited Base UI props). + 3. Compiles Tailwind v4 `globals.css` → self-contained `packages/ui/.ds-compiled.css` (`cfg.cssEntry`): inlines the IBM Plex Sans latin variable woff2 as a data-URI and strips all other `@font-face` (extra scripts + the Phosphor icon web font, which previews don't use — components render Phosphor as inline React SVGs). This is why previews are fully styled with tokens + brand font and there are zero dangling font URLs. +- CSS entry scans `.design-sync/tw-entry.css` which `@import`s globals.css and adds `@source "./previews/*.tsx"` so utility classes used in authored previews are compiled. **Preview layout wrappers use inline styles** anyway (so subagents needn't recompile the shared CSS); only component-level utility classes need the recompile. + +## Card scope + +- The package exports **202 symbols** (39 primary components + 163 compound sub-parts). User chose **~40 primary cards**: `cfg.componentSrcMap` nulls the 163 sub-parts. All 202 stay importable from `window.RRUI` (the bundle exports everything regardless of the card list), so previews compose sub-parts (`RRUI.DialogContent`, etc.) freely. +- Multi-primary files represented by one card: `combobox.tsx`→ComboboxRoot, `form.tsx`→FormItem, `resizable.tsx`→ResizableGroup, `sonner.tsx`→Toaster. + +## Preview authoring conventions (calibrated on Button / Alert / Dialog) + +- Import naturally: `import { Button } from "@reactive-resume/ui/components/button"` — converter rule 2 redirects any exported-component module to `window.RRUI`, and sub-parts resolve too. +- Icons: `@phosphor-icons/react` with the `*Icon` suffix (e.g. `PlusIcon`, `TrashIcon`, `WarningIcon`). Bundles into the preview. +- Base UI compose pattern: `render={ + + + +); diff --git a/.design-sync/previews/AlertDialog.tsx b/.design-sync/previews/AlertDialog.tsx new file mode 100644 index 000000000..ac3a81a6d --- /dev/null +++ b/.design-sync/previews/AlertDialog.tsx @@ -0,0 +1,34 @@ +import { WarningIcon } from "@phosphor-icons/react"; +import { + AlertDialog, + AlertDialogAction, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogMedia, + AlertDialogTitle, +} from "@reactive-resume/ui/components/alert-dialog"; + +// Overlay — rendered open (defaultOpen). cfg.overrides.AlertDialog pins +// cardMode: single + viewport (content is fixed-positioned, centred). +export const Open = () => ( + + + + + + + Delete this resume? + + “Software Engineer” and its entire version history will be permanently removed. This action can’t be undone. + + + + Cancel + Delete resume + + + +); diff --git a/.design-sync/previews/Attachment.tsx b/.design-sync/previews/Attachment.tsx new file mode 100644 index 000000000..d3c238878 --- /dev/null +++ b/.design-sync/previews/Attachment.tsx @@ -0,0 +1,83 @@ +import { DownloadSimpleIcon, FileDocIcon, FilePdfIcon, TrashIcon, WarningIcon } from "@phosphor-icons/react"; +import { + Attachment, + AttachmentAction, + AttachmentActions, + AttachmentContent, + AttachmentDescription, + AttachmentGroup, + AttachmentMedia, + AttachmentTitle, +} from "@reactive-resume/ui/components/attachment"; + +const wrap: React.CSSProperties = { display: "flex", flexDirection: "column", gap: 12, padding: 16, width: 360 }; + +export const WithActions = () => ( +
+ + + + + + Ansel_Bradford_Resume.pdf + 248 KB · PDF + + + + + + + + + + +
+); + +export const States = () => ( +
+ + + + + + cover-letter.docx + Uploading… + + + + + + + + portfolio-2024.zip + Upload failed · file too large + + +
+); + +export const Group = () => ( +
+ + + + + + + Resume.pdf + 248 KB + + + + + + + + cover-letter.docx + 19 KB + + + +
+); diff --git a/.design-sync/previews/Avatar.tsx b/.design-sync/previews/Avatar.tsx new file mode 100644 index 000000000..a383e0e71 --- /dev/null +++ b/.design-sync/previews/Avatar.tsx @@ -0,0 +1,70 @@ +import { CheckIcon } from "@phosphor-icons/react"; +import { + Avatar, + AvatarBadge, + AvatarFallback, + AvatarGroup, + AvatarGroupCount, +} from "@reactive-resume/ui/components/avatar"; + +const row: React.CSSProperties = { display: "flex", alignItems: "center", gap: 16, padding: 20 }; + +export const Fallback = () => ( +
+ + AP + + + JD + + + MK + +
+); + +export const WithStatus = () => ( +
+ + AP + + + + + + SR + + +
+); + +export const Sizes = () => ( +
+ + AP + + + AP + + + AP + +
+); + +export const Group = () => ( +
+ + + AP + + + JD + + + MK + + +5 + +
+); diff --git a/.design-sync/previews/Badge.tsx b/.design-sync/previews/Badge.tsx new file mode 100644 index 000000000..cee796b9e --- /dev/null +++ b/.design-sync/previews/Badge.tsx @@ -0,0 +1,39 @@ +import { CheckCircleIcon, PencilSimpleIcon, SparkleIcon } from "@phosphor-icons/react"; +import { Badge } from "@reactive-resume/ui/components/badge"; + +const row: React.CSSProperties = { display: "flex", flexWrap: "wrap", alignItems: "center", gap: 10, padding: 20 }; + +export const Variants = () => ( +
+ Default + Secondary + Destructive + Outline +
+); + +export const StatusLabels = () => ( +
+ + + Published + + + + Draft + + + + Pro + + Expired +
+); + +export const Counts = () => ( +
+ 12 + New + v5.2 +
+); diff --git a/.design-sync/previews/BrandIcon.tsx b/.design-sync/previews/BrandIcon.tsx new file mode 100644 index 000000000..4f4f84791 --- /dev/null +++ b/.design-sync/previews/BrandIcon.tsx @@ -0,0 +1,34 @@ +import { BrandIcon } from "@reactive-resume/ui/components/brand-icon"; + +// The component builds its src from /logo|/icon static paths that the preview +// server does not serve, so we override `src` with the real inlined SVG assets. +const LOGO_SRC = + "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTEyIiBoZWlnaHQ9IjUxMiIgdmlld0JveD0iMCAwIDUxMiA1MTIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+Cjx0aXRsZT5SZWFjdGl2ZSBSZXN1bWU8L3RpdGxlPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTE4My42MDMgMTg0LjcyMkwxNTYuNzQgMjIwSDE4My41NDVMMTk3LjAzMiAyMDEuNTRMMjA5LjcwMSAyMjBIMjM3LjkzOEwyMTEuMDA4IDE4My44NzRMMjExLjAxMiAxODMuODY4TDIxMC44NTkgMTgzLjY3NUwyMDUuOTI3IDE3Ny40NDRMMTk3Ljg5NCAxNjcuMjk0TDE5Ny44ODIgMTY3LjMxTDE5Ny42OTMgMTY3LjA0MUwxOTYuOTI2IDE2Ni4wNzJMMTk2Ljk4MiAxNjYuMDI3TDE4NS4zNjcgMTQ5LjQ3MkgxNTcuNTJMMTgzLjYwMyAxODQuNzIyWk0yMDAuOTQ4IDE2My4wOTlMMjE0LjEyNyAxNzkuNzQ5TDIzNy4wMjcgMTQ5LjQ3MkgyMTAuODcyTDIwMC45NDggMTYzLjA5OVoiIGZpbGw9IiMwOTA5MEIiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik02OS4xMDg3IDk4LjkxMjVWMTkwSDk0Ljg3MzVWMTY1Ljc5N0gxMDguOTM4TDEwOC45MzggMTY1Ljc5N0MxMDguOTQzIDE2NS43OTcgMTA4Ljk0OCAxNjUuNzk3IDEwOC45NTMgMTY1Ljc5N0MxMTguMzc3IDE2NS4zODEgMTI1LjI4NSAxNjQuNDQ4IDEzMy4wOTQgMTYxLjQ5NEMxMzMuMTk1IDE2MS40NTUgMTMzLjI5NiAxNjEuNDE3IDEzMy4zOTcgMTYxLjM3OEwxMzMuMzgyIDE2MS4zNTZDMTM4Ljg5MyAxNTguNzA1IDE0My4xOSAxNTUuMDY2IDE0Ni4yNzMgMTUwLjQ0MkMxNDkuNTY5IDE0NS40MSAxNTEuMjE4IDEzOS40NjggMTUxLjIxOCAxMzIuNjE1QzE1MS4yMTggMTI1LjY3NSAxNDkuNTY5IDExOS42ODkgMTQ2LjI3MyAxMTQuNjU4QzE0Mi45NzYgMTA5LjUzOSAxMzguMjkyIDEwNS42MzYgMTMyLjIxOSAxMDIuOTQ2QzEyNi4yMzQgMTAwLjI1NyAxMTkuMDc3IDk4LjkxMjUgMTEwLjc0OSA5OC45MTI1SDY5LjEwODdaTTEzNi40NTYgMTY1LjgzNkwxMTEuODY3IDE3MC4wOUwxMjUuNDUzIDE5MEgxNTMuMDM5TDEzNi40NTYgMTY1LjgzNlpNOTQuODczNSAxNDUuODg4SDEwOS4xODdDMTE0LjU2NiAxNDUuODg4IDExOC41NTYgMTQ0LjcxNiAxMjEuMTU5IDE0Mi4zNzRDMTIzLjg0OCAxNDAuMDMyIDEyNS4xOTMgMTM2Ljc3OSAxMjUuMTkzIDEzMi42MTVDMTI1LjE5MyAxMjguMzY0IDEyMy44NDggMTI1LjA2OCAxMjEuMTU5IDEyMi43MjVDMTE4LjU1NiAxMjAuMzgzIDExNC41NjYgMTE5LjIxMiAxMDkuMTg3IDExOS4yMTJIOTQuODczNVYxNDUuODg4WiIgZmlsbD0iIzA5MDkwQiIvPgo8cGF0aCBkPSJNNjkuNiAyODhWMjMySDk1LjJDMTAwLjMyIDIzMiAxMDQuNzIgMjMyLjgyNyAxMDguNCAyMzQuNDhDMTEyLjEzMyAyMzYuMTMzIDExNS4wMTMgMjM4LjUzMyAxMTcuMDQgMjQxLjY4QzExOS4wNjcgMjQ0Ljc3MyAxMjAuMDggMjQ4LjQ1MyAxMjAuMDggMjUyLjcyQzEyMC4wOCAyNTYuOTMzIDExOS4wNjcgMjYwLjU4NyAxMTcuMDQgMjYzLjY4QzExNS4wMTMgMjY2LjcyIDExMi4xMzMgMjY5LjA2NyAxMDguNCAyNzAuNzJDMTA0LjcyIDI3Mi4zMiAxMDAuMzIgMjczLjEyIDk1LjIgMjczLjEySDc4LjRMODUuNDQgMjY2LjQ4VjI4OEg2OS42Wk0xMDQuMjQgMjg4TDkwLjMyIDI2Ny42SDEwNy4yTDEyMS4yIDI4OEgxMDQuMjRaTTg1LjQ0IDI2OC4xNkw3OC40IDI2MC44OEg5NC4yNEM5Ny41NDY3IDI2MC44OCAxMDAgMjYwLjE2IDEwMS42IDI1OC43MkMxMDMuMjUzIDI1Ny4yOCAxMDQuMDggMjU1LjI4IDEwNC4wOCAyNTIuNzJDMTA0LjA4IDI1MC4xMDcgMTAzLjI1MyAyNDguMDggMTAxLjYgMjQ2LjY0QzEwMCAyNDUuMiA5Ny41NDY3IDI0NC40OCA5NC4yNCAyNDQuNDhINzguNEw4NS40NCAyMzcuMlYyNjguMTZaTTE1MC44MTkgMjg4LjcyQzE0NS42OTkgMjg4LjcyIDE0MS4yMTkgMjg3Ljc2IDEzNy4zNzkgMjg1Ljg0QzEzMy41OTIgMjgzLjg2NyAxMzAuNjMyIDI4MS4yIDEyOC40OTkgMjc3Ljg0QzEyNi40MTkgMjc0LjQyNyAxMjUuMzc5IDI3MC41NiAxMjUuMzc5IDI2Ni4yNEMxMjUuMzc5IDI2MS45MiAxMjYuMzkyIDI1OC4wOCAxMjguNDE5IDI1NC43MkMxMzAuNDk5IDI1MS4zMDcgMTMzLjM1MiAyNDguNjY3IDEzNi45NzkgMjQ2LjhDMTQwLjYwNSAyNDQuODggMTQ0LjY4NSAyNDMuOTIgMTQ5LjIxOSAyNDMuOTJDMTUzLjQ4NSAyNDMuOTIgMTU3LjM3OSAyNDQuOCAxNjAuODk5IDI0Ni41NkMxNjQuNDE5IDI0OC4yNjcgMTY3LjIxOSAyNTAuOCAxNjkuMjk5IDI1NC4xNkMxNzEuMzc5IDI1Ny41MiAxNzIuNDE5IDI2MS42IDE3Mi40MTkgMjY2LjRDMTcyLjQxOSAyNjYuOTMzIDE3Mi4zOTIgMjY3LjU0NyAxNzIuMzM5IDI2OC4yNEMxNzIuMjg1IDI2OC45MzMgMTcyLjIzMiAyNjkuNTczIDE3Mi4xNzkgMjcwLjE2SDEzNy44NTlWMjYyLjE2SDE2NC4wOTlMMTU4LjMzOSAyNjQuNEMxNTguMzkyIDI2Mi40MjcgMTU4LjAxOSAyNjAuNzIgMTU3LjIxOSAyNTkuMjhDMTU2LjQ3MiAyNTcuODQgMTU1LjQwNSAyNTYuNzIgMTU0LjAxOSAyNTUuOTJDMTUyLjY4NSAyNTUuMTIgMTUxLjExMiAyNTQuNzIgMTQ5LjI5OSAyNTQuNzJDMTQ3LjQ4NSAyNTQuNzIgMTQ1Ljg4NSAyNTUuMTIgMTQ0LjQ5OSAyNTUuOTJDMTQzLjE2NSAyNTYuNzIgMTQyLjEyNSAyNTcuODY3IDE0MS4zNzkgMjU5LjM2QzE0MC42MzIgMjYwLjggMTQwLjI1OSAyNjIuNTA3IDE0MC4yNTkgMjY0LjQ4VjI2Ni44QzE0MC4yNTkgMjY4LjkzMyAxNDAuNjg1IDI3MC43NzMgMTQxLjUzOSAyNzIuMzJDMTQyLjQ0NSAyNzMuODY3IDE0My43MjUgMjc1LjA2NyAxNDUuMzc5IDI3NS45MkMxNDcuMDMyIDI3Ni43MiAxNDkuMDA1IDI3Ny4xMiAxNTEuMjk5IDI3Ny4xMkMxNTMuNDMyIDI3Ny4xMiAxNTUuMjQ1IDI3Ni44MjcgMTU2LjczOSAyNzYuMjRDMTU4LjI4NSAyNzUuNiAxNTkuODA1IDI3NC42NCAxNjEuMjk5IDI3My4zNkwxNjkuMjk5IDI4MS42OEMxNjcuMjE5IDI4My45NzMgMTY0LjY1OSAyODUuNzMzIDE2MS42MTkgMjg2Ljk2QzE1OC41NzkgMjg4LjEzMyAxNTQuOTc5IDI4OC43MiAxNTAuODE5IDI4OC43MlpNMTk1LjE4NyAyODguNzJDMTkxLjUwNyAyODguNzIgMTg3LjkwNyAyODguMjkzIDE4NC4zODcgMjg3LjQ0QzE4MC45MiAyODYuNTg3IDE3OC4xMiAyODUuNTIgMTc1Ljk4NyAyODQuMjRMMTgwLjU0NyAyNzMuODRDMTgyLjU3NCAyNzUuMDY3IDE4NC45NDcgMjc2LjA1MyAxODcuNjY3IDI3Ni44QzE5MC4zODcgMjc3LjQ5MyAxOTMuMDU0IDI3Ny44NCAxOTUuNjY3IDI3Ny44NEMxOTguMjI3IDI3Ny44NCAxOTkuOTg3IDI3Ny41NzMgMjAwLjk0NyAyNzcuMDRDMjAxLjk2IDI3Ni41MDcgMjAyLjQ2NyAyNzUuNzg3IDIwMi40NjcgMjc0Ljg4QzIwMi40NjcgMjc0LjAyNyAyMDEuOTg3IDI3My40MTMgMjAxLjAyNyAyNzMuMDRDMjAwLjEyIDI3Mi42MTMgMTk4Ljg5NCAyNzIuMjkzIDE5Ny4zNDcgMjcyLjA4QzE5NS44NTQgMjcxLjg2NyAxOTQuMiAyNzEuNjI3IDE5Mi4zODcgMjcxLjM2QzE5MC41NzQgMjcxLjA5MyAxODguNzM0IDI3MC43NDcgMTg2Ljg2NyAyNzAuMzJDMTg1LjA1NCAyNjkuODQgMTgzLjM3NCAyNjkuMTQ3IDE4MS44MjcgMjY4LjI0QzE4MC4zMzQgMjY3LjI4IDE3OS4xMzQgMjY2IDE3OC4yMjcgMjY0LjRDMTc3LjMyIDI2Mi44IDE3Ni44NjcgMjYwLjc3MyAxNzYuODY3IDI1OC4zMkMxNzYuODY3IDI1NS41NDcgMTc3LjY2NyAyNTMuMDkzIDE3OS4yNjcgMjUwLjk2QzE4MC45MiAyNDguNzczIDE4My4zMiAyNDcuMDY3IDE4Ni40NjcgMjQ1Ljg0QzE4OS42MTQgMjQ0LjU2IDE5My40NTQgMjQzLjkyIDE5Ny45ODcgMjQzLjkyQzIwMS4wMjcgMjQzLjkyIDIwNC4wOTQgMjQ0LjI0IDIwNy4xODcgMjQ0Ljg4QzIxMC4zMzQgMjQ1LjQ2NyAyMTIuOTc0IDI0Ni4zNzMgMjE1LjEwNyAyNDcuNkwyMTAuNTQ3IDI1Ny45MkMyMDguNDE0IDI1Ni42OTMgMjA2LjI4IDI1NS44NjcgMjA0LjE0NyAyNTUuNDRDMjAyLjAxNCAyNTQuOTYgMTk5Ljk4NyAyNTQuNzIgMTk4LjA2NyAyNTQuNzJDMTk1LjUwNyAyNTQuNzIgMTkzLjY5NCAyNTUuMDEzIDE5Mi42MjcgMjU1LjZDMTkxLjYxNCAyNTYuMTg3IDE5MS4xMDcgMjU2LjkwNyAxOTEuMTA3IDI1Ny43NkMxOTEuMTA3IDI1OC42MTMgMTkxLjU2IDI1OS4yOCAxOTIuNDY3IDI1OS43NkMxOTMuMzc0IDI2MC4xODcgMTk0LjU3NCAyNjAuNTMzIDE5Ni4wNjcgMjYwLjhDMTk3LjYxNCAyNjEuMDEzIDE5OS4yOTQgMjYxLjI1MyAyMDEuMTA3IDI2MS41MkMyMDIuOTIgMjYxLjczMyAyMDQuNzM0IDI2Mi4wOCAyMDYuNTQ3IDI2Mi41NkMyMDguNDE0IDI2My4wNCAyMTAuMDk0IDI2My43NiAyMTEuNTg3IDI2NC43MkMyMTMuMTM0IDI2NS42MjcgMjE0LjM2IDI2Ni44OCAyMTUuMjY3IDI2OC40OEMyMTYuMTc0IDI3MC4wMjcgMjE2LjYyNyAyNzIuMDI3IDIxNi42MjcgMjc0LjQ4QzIxNi42MjcgMjc3LjE0NyAyMTUuOCAyNzkuNTQ3IDIxNC4xNDcgMjgxLjY4QzIxMi41NDcgMjgzLjgxMyAyMTAuMTQ3IDI4NS41MiAyMDYuOTQ3IDI4Ni44QzIwMy44IDI4OC4wOCAxOTkuODggMjg4LjcyIDE5NS4xODcgMjg4LjcyWk0yNDEuNDE3IDI4OC43MkMyMzcuODk3IDI4OC43MiAyMzQuNzI0IDI4OC4wMjcgMjMxLjg5NyAyODYuNjRDMjI5LjEyNCAyODUuMjUzIDIyNi45MzcgMjgzLjA5MyAyMjUuMzM3IDI4MC4xNkMyMjMuNzkgMjc3LjE3MyAyMjMuMDE3IDI3My40MTMgMjIzLjAxNyAyNjguODhWMjQ0LjY0SDIzOC4yMTdWMjY2LjRDMjM4LjIxNyAyNjkuNzYgMjM4LjgzIDI3Mi4xNiAyNDAuMDU3IDI3My42QzI0MS4zMzcgMjc1LjA0IDI0My4xMjQgMjc1Ljc2IDI0NS40MTcgMjc1Ljc2QzI0Ni45MSAyNzUuNzYgMjQ4LjI3IDI3NS40MTMgMjQ5LjQ5NyAyNzQuNzJDMjUwLjcyNCAyNzQuMDI3IDI1MS43MSAyNzIuOTMzIDI1Mi40NTcgMjcxLjQ0QzI1My4yMDQgMjY5Ljg5MyAyNTMuNTc3IDI2Ny45MiAyNTMuNTc3IDI2NS41MlYyNDQuNjRIMjY4Ljc3N1YyODhIMjU0LjI5N1YyNzUuNzZMMjU3LjA5NyAyNzkuMkMyNTUuNjA0IDI4Mi40IDI1My40NDQgMjg0LjggMjUwLjYxNyAyODYuNEMyNDcuNzkgMjg3Ljk0NyAyNDQuNzI0IDI4OC43MiAyNDEuNDE3IDI4OC43MlpNMzM1LjA0OCAyNDMuOTJDMzM4LjQwOCAyNDMuOTIgMzQxLjM5NCAyNDQuNjEzIDM0NC4wMDggMjQ2QzM0Ni42NzQgMjQ3LjMzMyAzNDguNzU0IDI0OS40MTMgMzUwLjI0OCAyNTIuMjRDMzUxLjc5NCAyNTUuMDY3IDM1Mi41NjggMjU4LjcyIDM1Mi41NjggMjYzLjJWMjg4SDMzNy4zNjhWMjY1LjY4QzMzNy4zNjggMjYyLjU4NyAzMzYuNzgxIDI2MC4zNDcgMzM1LjYwOCAyNTguOTZDMzM0LjQzNCAyNTcuNTIgMzMyLjgzNCAyNTYuOCAzMzAuODA4IDI1Ni44QzMyOS4zNjggMjU2LjggMzI4LjA2MSAyNTcuMTQ3IDMyNi44ODggMjU3Ljg0QzMyNS43MTQgMjU4LjUzMyAzMjQuODA4IDI1OS42IDMyNC4xNjggMjYxLjA0QzMyMy41MjggMjYyLjQyNyAzMjMuMjA4IDI2NC4yNCAzMjMuMjA4IDI2Ni40OFYyODhIMzA4LjAwOFYyNjUuNjhDMzA4LjAwOCAyNjIuNTg3IDMwNy40MjEgMjYwLjM0NyAzMDYuMjQ4IDI1OC45NkMzMDUuMTI4IDI1Ny41MiAzMDMuNTI4IDI1Ni44IDMwMS40NDggMjU2LjhDMzAwLjQ1NCAyNTYuOCAyOTguNjIxIDI1Ny4xNDcgMjk3LjQ0OCAyNTcuODRDMjk2LjMyOCAyNTguNTMzIDI5NS40MjEgMjU5LjYgMjk0LjcyOCAyNjEuMDRDMjk0LjA4OCAyNjIuNDI3IDI5My43NjggMjY0LjI0IDI5My43NjggMjY2LjQ4VjI4OEgyNzguNTY4VjI0NC42NEgyOTMuMDQ4VjI1Ni43MkwyOTAuMTY4IDI1My4yOEMyOTEuNzY4IDI1MC4xODcgMjkzLjk1NCAyNDcuODY3IDI5Ni43MjggMjQ2LjMyQzI5OS41MDEgMjQ0LjcyIDMwMi41OTQgMjQzLjkyIDMwNi4wMDggMjQzLjkyQzMwOS45MDEgMjQzLjkyIDMxMy4zMTQgMjQ0LjkzMyAzMTYuMjQ4IDI0Ni45NkMzMTkuMjM0IDI0OC45MzMgMzIxLjIzNCAyNTIuMDI3IDMyMi4yNDggMjU2LjI0TDMxNy4yODggMjU1LjJDMzE4LjgzNCAyNTEuNjggMzIxLjE1NCAyNDguOTMzIDMyNC4yNDggMjQ2Ljk2QzMyNy4zOTQgMjQ0LjkzMyAzMzAuOTk0IDI0My45MiAzMzUuMDQ4IDI0My45MlpNMzg1LjQyOCAyODguNzJDMzgwLjMwOCAyODguNzIgMzc1LjgyOCAyODcuNzYgMzcxLjk4OCAyODUuODRDMzY4LjIwMSAyODMuODY3IDM2NS4yNDEgMjgxLjIgMzYzLjEwOCAyNzcuODRDMzYxLjAyOCAyNzQuNDI3IDM1OS45ODggMjcwLjU2IDM1OS45ODggMjY2LjI0QzM1OS45ODggMjYxLjkyIDM2MS4wMDEgMjU4LjA4IDM2My4wMjggMjU0LjcyQzM2NS4xMDggMjUxLjMwNyAzNjcuOTYxIDI0OC42NjcgMzcxLjU4OCAyNDYuOEMzNzUuMjE1IDI0NC44OCAzNzkuMjk1IDI0My45MiAzODMuODI4IDI0My45MkMzODguMDk1IDI0My45MiAzOTEuOTg4IDI0NC44IDM5NS41MDggMjQ2LjU2QzM5OS4wMjggMjQ4LjI2NyA0MDEuODI4IDI1MC44IDQwMy45MDggMjU0LjE2QzQwNS45ODggMjU3LjUyIDQwNy4wMjggMjYxLjYgNDA3LjAyOCAyNjYuNEM0MDcuMDI4IDI2Ni45MzMgNDA3LjAwMSAyNjcuNTQ3IDQwNi45NDggMjY4LjI0QzQwNi44OTUgMjY4LjkzMyA0MDYuODQxIDI2OS41NzMgNDA2Ljc4OCAyNzAuMTZIMzcyLjQ2OFYyNjIuMTZIMzk4LjcwOEwzOTIuOTQ4IDI2NC40QzM5My4wMDEgMjYyLjQyNyAzOTIuNjI4IDI2MC43MiAzOTEuODI4IDI1OS4yOEMzOTEuMDgxIDI1Ny44NCAzOTAuMDE1IDI1Ni43MiAzODguNjI4IDI1NS45MkMzODcuMjk1IDI1NS4xMiAzODUuNzIxIDI1NC43MiAzODMuOTA4IDI1NC43MkMzODIuMDk1IDI1NC43MiAzODAuNDk1IDI1NS4xMiAzNzkuMTA4IDI1NS45MkMzNzcuNzc1IDI1Ni43MiAzNzYuNzM1IDI1Ny44NjcgMzc1Ljk4OCAyNTkuMzZDMzc1LjI0MSAyNjAuOCAzNzQuODY4IDI2Mi41MDcgMzc0Ljg2OCAyNjQuNDhWMjY2LjhDMzc0Ljg2OCAyNjguOTMzIDM3NS4yOTUgMjcwLjc3MyAzNzYuMTQ4IDI3Mi4zMkMzNzcuMDU1IDI3My44NjcgMzc4LjMzNSAyNzUuMDY3IDM3OS45ODggMjc1LjkyQzM4MS42NDEgMjc2LjcyIDM4My42MTUgMjc3LjEyIDM4NS45MDggMjc3LjEyQzM4OC4wNDEgMjc3LjEyIDM4OS44NTUgMjc2LjgyNyAzOTEuMzQ4IDI3Ni4yNEMzOTIuODk1IDI3NS42IDM5NC40MTUgMjc0LjY0IDM5NS45MDggMjczLjM2TDQwMy45MDggMjgxLjY4QzQwMS44MjggMjgzLjk3MyAzOTkuMjY4IDI4NS43MzMgMzk2LjIyOCAyODYuOTZDMzkzLjE4OCAyODguMTMzIDM4OS41ODggMjg4LjcyIDM4NS40MjggMjg4LjcyWiIgZmlsbD0iIzA5MDkwQiIvPgo8bGluZSBvcGFjaXR5PSIwLjEiIHgxPSI2MCIgeTE9IjM1OCIgeDI9IjM2MCIgeTI9IjM1OCIgc3Ryb2tlPSIjMDkwOTBCIiBzdHJva2Utd2lkdGg9IjIwIiBzdHJva2UtbWl0ZXJsaW1pdD0iMTYiLz4KPGxpbmUgb3BhY2l0eT0iMC4yIiB4MT0iNjAiIHkxPSIzOTgiIHgyPSIzMDAiIHkyPSIzOTgiIHN0cm9rZT0iIzA5MDkwQiIgc3Ryb2tlLXdpZHRoPSIyMCIgc3Ryb2tlLW1pdGVybGltaXQ9IjE2Ii8+CjxsaW5lIG9wYWNpdHk9IjAuMSIgeDE9IjYwIiB5MT0iNDM4IiB4Mj0iMjQwIiB5Mj0iNDM4IiBzdHJva2U9IiMwOTA5MEIiIHN0cm9rZS13aWR0aD0iMjAiIHN0cm9rZS1taXRlcmxpbWl0PSIxNiIvPgo8L3N2Zz4K"; +const ICON_SRC = + "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjU2IiBoZWlnaHQ9IjI1NiIgdmlld0JveD0iMCAwIDI1NiAyNTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+Cjx0aXRsZT5SZWFjdGl2ZSBSZXN1bWU8L3RpdGxlPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTE3My42MTEgMTY2LjMxMUwxMzIuODc3IDIxOS44MDRIMTczLjUyNEwxOTMuOTczIDE5MS44MTNMMjEzLjE4MyAyMTkuODA0SDI1NkwyMTUuNjczIDE2NS43MDdMMjE1LjE1IDE2NS4wNDZMMjA3LjQ2MSAxNTUuMzMyTDE5NS4zMjkgMTQwLjAwNEwxOTUuMjU4IDEzOS45MTVMMTkzLjgxMyAxMzguMDg5TDE5My45MjMgMTM4LjAwMUwxNzYuMjg2IDExMi44NjFIMTM0LjA2MUwxNzMuNjExIDE2Ni4zMTFaTTE5OS44OSAxMzMuNTU0TDIxNC45NTkgMTEyLjg2MUgyNTQuNjE5TDIxOS44NzQgMTU4LjhMMTk5Ljg5IDEzMy41NTRaIiBmaWxsPSIjMDkwOTBCIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMCAzNi4xOTU5VjE3NC4zMTRIMzkuMDY3OFYxMzcuNjE0SDYwLjM5MzhMNjAuNDMyMyAxMzcuNjcxQzYwLjg0MzYgMTM3LjY1MyA2MS4yNTE4IDEzNy42MzQgNjEuNjU2OSAxMzcuNjE0Qzc1LjA2NjUgMTM2Ljk2OCA4NS4xNDcxIDEzNS41NDkgOTYuMzg0OSAxMzEuMzg1Qzk2Ljc1OTYgMTMxLjI0NiA5Ny4xMzU1IDEzMS4xMDQgOTcuNTEyOCAxMzAuOTU5TDk3LjQ1OTEgMTMwLjg4MUMxMDUuODE2IDEyNi44NiAxMTIuMzMxIDEyMS4zNDQgMTE3LjAwNiAxMTQuMzMxQzEyMi4wMDUgMTA2LjcwMiAxMjQuNTA0IDk3LjY5MTUgMTI0LjUwNCA4Ny4yOTk3QzEyNC41MDQgNzYuNzc2NCAxMjIuMDA1IDY3LjcgMTE3LjAwNiA2MC4wNzA2QzExMi4wMDcgNTIuMzA5NyAxMDQuOTA0IDQ2LjM5MDMgOTUuNjk2NCA0Mi4zMTI1Qzg2LjYyIDM4LjIzNDcgNzUuNzY3OCAzNi4xOTU5IDYzLjEzOTkgMzYuMTk1OUgwWk0xMDIuMTU2IDEzNy43MjVMNjQuODcwNSAxNDQuMTc1TDg1LjQzNjEgMTc0LjMxNEgxMjcuMjY2TDEwMi4xNTYgMTM3LjcyNVpNMzkuMDY3OCAxMDcuNDI2SDYwLjc3MjFDNjguOTI3NyAxMDcuNDI2IDc0Ljk3ODYgMTA1LjY1IDc4LjkyNDggMTAyLjA5OEM4My4wMDI2IDk4LjU0NjUgODUuMDQxNSA5My42MTM3IDg1LjA0MTUgODcuMjk5N0M4NS4wNDE1IDgwLjg1NDIgODMuMDAyNiA3NS44NTU2IDc4LjkyNDggNzIuMzA0Qzc0Ljk3ODYgNjguNzUyMyA2OC45Mjc3IDY2Ljk3NjUgNjAuNzcyMSA2Ni45NzY1SDM5LjA2NzhWMTA3LjQyNloiIGZpbGw9IiMwOTA5MEIiLz4KPC9zdmc+Cg=="; + +const wrap: React.CSSProperties = { display: "flex", alignItems: "center", gap: 32, padding: 24 }; +const cell: React.CSSProperties = { display: "flex", flexDirection: "column", alignItems: "center", gap: 8 }; +const label: React.CSSProperties = { fontSize: 12, color: "var(--muted-foreground)" }; + +export const Logo = () => ( +
+
+ + variant="logo" +
+
+); + +export const Icon = () => ( +
+
+ + variant="icon" +
+
+ + compact +
+
+); diff --git a/.design-sync/previews/Bubble.tsx b/.design-sync/previews/Bubble.tsx new file mode 100644 index 000000000..83d7a8fc3 --- /dev/null +++ b/.design-sync/previews/Bubble.tsx @@ -0,0 +1,47 @@ +import { Bubble, BubbleContent, BubbleGroup, BubbleReactions } from "@reactive-resume/ui/components/bubble"; + +const wrap: React.CSSProperties = { display: "flex", flexDirection: "column", gap: 8, padding: 16, width: 420 }; + +export const Conversation = () => ( +
+ + + Can you make my summary sound more senior without exaggerating? + + + + I tightened it to lead with scope and outcomes. Want me to mirror that tone in your experience bullets too? + + + + Yes, keep it concise. + + +
+); + +export const Variants = () => ( +
+ + Applied 3 edits to your resume. + + + I emphasized measurable launch outcomes in your last role. + + + Draft saved — publish when you're ready. + + + Couldn't reach the AI provider. Retry? + +
+); + +export const WithReactions = () => ( +
+ + Rewrote your headline to target a Senior Product Manager role. + 👍 2 + +
+); diff --git a/.design-sync/previews/Button.tsx b/.design-sync/previews/Button.tsx new file mode 100644 index 000000000..c1a6c86ea --- /dev/null +++ b/.design-sync/previews/Button.tsx @@ -0,0 +1,50 @@ +import { ArrowRightIcon, PlusIcon, TrashIcon } from "@phosphor-icons/react"; +import { Button } from "@reactive-resume/ui/components/button"; + +const row: React.CSSProperties = { display: "flex", flexWrap: "wrap", alignItems: "center", gap: 12, padding: 16 }; + +export const Variants = () => ( +
+ + + + + + +
+); + +export const Sizes = () => ( +
+ + + + +
+); + +export const WithIcons = () => ( +
+ + + + +
+); + +export const Disabled = () => ( +
+ + +
+); diff --git a/.design-sync/previews/ButtonGroup.tsx b/.design-sync/previews/ButtonGroup.tsx new file mode 100644 index 000000000..b884c482c --- /dev/null +++ b/.design-sync/previews/ButtonGroup.tsx @@ -0,0 +1,66 @@ +import { + AlignCenterHorizontalIcon, + AlignLeftIcon, + AlignRightIcon, + ArrowClockwiseIcon, + ArrowCounterClockwiseIcon, + TextBIcon, + TextItalicIcon, + TextUnderlineIcon, +} from "@phosphor-icons/react"; +import { Button } from "@reactive-resume/ui/components/button"; +import { ButtonGroup, ButtonGroupSeparator, ButtonGroupText } from "@reactive-resume/ui/components/button-group"; + +const wrap: React.CSSProperties = { display: "flex", flexDirection: "column", gap: 16, padding: 16 }; + +export const Formatting = () => ( +
+ + + + + + + + + + + + + + +
+); + +export const WithText = () => ( +
+ + Zoom + + + + + + + + + + +
+); diff --git a/.design-sync/previews/ComboboxRoot.tsx b/.design-sync/previews/ComboboxRoot.tsx new file mode 100644 index 000000000..785a38258 --- /dev/null +++ b/.design-sync/previews/ComboboxRoot.tsx @@ -0,0 +1,30 @@ +import { + ComboboxContent, + ComboboxEmpty, + ComboboxInput, + ComboboxItem, + ComboboxList, + ComboboxRoot, +} from "@reactive-resume/ui/components/combobox"; + +const skills = ["TypeScript", "React", "Node.js", "GraphQL", "PostgreSQL", "Kubernetes"]; + +// Base UI Combobox — items passed to Root, rendered open (defaultOpen). +// cfg.overrides.ComboboxRoot pins cardMode: single + viewport with room below. +export const Open = () => ( +
+ + + + No skills found. + + {(item: string) => ( + + {item} + + )} + + + +
+); diff --git a/.design-sync/previews/Command.tsx b/.design-sync/previews/Command.tsx new file mode 100644 index 000000000..351cc1079 --- /dev/null +++ b/.design-sync/previews/Command.tsx @@ -0,0 +1,42 @@ +import { DownloadSimpleIcon, GearIcon, PlusIcon, UserIcon } from "@phosphor-icons/react"; +import { + Command, + CommandGroup, + CommandInput, + CommandItem, + CommandList, + CommandSeparator, + CommandShortcut, +} from "@reactive-resume/ui/components/command"; + +// Command renders inline (cmdk) — a searchable command palette. No overlay. +export const Palette = () => ( +
+
+ + + + + + New resume + ⌘N + + + Export as PDF + + + + + + Profile + + + Settings + ⌘, + + + + +
+
+); diff --git a/.design-sync/previews/ContextMenu.tsx b/.design-sync/previews/ContextMenu.tsx new file mode 100644 index 000000000..0871a2d83 --- /dev/null +++ b/.design-sync/previews/ContextMenu.tsx @@ -0,0 +1,48 @@ +import { + ContextMenu, + ContextMenuContent, + ContextMenuGroup, + ContextMenuItem, + ContextMenuLabel, + ContextMenuSeparator, + ContextMenuShortcut, + ContextMenuTrigger, +} from "@reactive-resume/ui/components/context-menu"; + +// Right-click menu — rendered open (defaultOpen) so the card shows the menu. +// cfg.overrides.ContextMenu pins cardMode: single + viewport. +export const Open = () => ( +
+ + +
+ Right-click a resume card +
+
+ + + Software Engineer + Open + + Rename + F2 + + Duplicate + + + Delete + +
+
+); diff --git a/.design-sync/previews/Dialog.tsx b/.design-sync/previews/Dialog.tsx new file mode 100644 index 000000000..6cadd1b4e --- /dev/null +++ b/.design-sync/previews/Dialog.tsx @@ -0,0 +1,30 @@ +import { Button } from "@reactive-resume/ui/components/button"; +import { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from "@reactive-resume/ui/components/dialog"; + +// Overlay component — rendered open (defaultOpen) so the card shows the real +// dialog surface. cfg.overrides.Dialog pins cardMode: single + a viewport for +// the portal (content is fixed-positioned at the viewport centre). +export const Open = () => ( + + + + Delete resume + + This permanently deletes “Software Engineer” along with its version history. This action cannot be undone. + + + + }>Cancel + }>Delete resume + + + +); diff --git a/.design-sync/previews/DropdownMenu.tsx b/.design-sync/previews/DropdownMenu.tsx new file mode 100644 index 000000000..7592d8e42 --- /dev/null +++ b/.design-sync/previews/DropdownMenu.tsx @@ -0,0 +1,41 @@ +import { CopyIcon, DownloadSimpleIcon, PencilIcon, TrashIcon } from "@phosphor-icons/react"; +import { Button } from "@reactive-resume/ui/components/button"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuGroup, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuTrigger, +} from "@reactive-resume/ui/components/dropdown-menu"; + +// Anchored menu — rendered open (defaultOpen), positioned below its trigger. +// cfg.overrides.DropdownMenu pins cardMode: single + viewport with room below. +export const Open = () => ( +
+ + }>Resume actions + + + Software Engineer + + Rename + + + Duplicate + ⌘D + + + Export PDF + + + + + Delete + + + +
+); diff --git a/.design-sync/previews/FormItem.tsx b/.design-sync/previews/FormItem.tsx new file mode 100644 index 000000000..d681153eb --- /dev/null +++ b/.design-sync/previews/FormItem.tsx @@ -0,0 +1,26 @@ +import { FormControl, FormDescription, FormItem, FormLabel, FormMessage } from "@reactive-resume/ui/components/form"; +import { Input } from "@reactive-resume/ui/components/input"; + +// FormItem carries its own field context (id + error state) — FormLabel / +// FormControl / FormDescription / FormMessage compose under it standalone. +const wrap: React.CSSProperties = { display: "flex", flexDirection: "column", gap: 16, padding: 16, width: 340 }; + +export const Default = () => ( +
+ + Headline + } /> + Shown under your name at the top of the resume. + +
+); + +export const WithError = () => ( +
+ + Email + } /> + + +
+); diff --git a/.design-sync/previews/HoverCard.tsx b/.design-sync/previews/HoverCard.tsx new file mode 100644 index 000000000..c543f5261 --- /dev/null +++ b/.design-sync/previews/HoverCard.tsx @@ -0,0 +1,19 @@ +import { Button } from "@reactive-resume/ui/components/button"; +import { HoverCard, HoverCardContent, HoverCardTrigger } from "@reactive-resume/ui/components/hover-card"; + +// Anchored preview-card overlay — rendered open (defaultOpen). +// cfg.overrides.HoverCard pins cardMode: single + viewport with room below the trigger. +export const Open = () => ( +
+ + }>@jane-doe + +
+ Jane Doe + Senior Software Engineer · San Francisco + 3 published resumes · joined 2023 +
+
+
+
+); diff --git a/.design-sync/previews/Input.tsx b/.design-sync/previews/Input.tsx new file mode 100644 index 000000000..85f2bb4e4 --- /dev/null +++ b/.design-sync/previews/Input.tsx @@ -0,0 +1,39 @@ +import { Input } from "@reactive-resume/ui/components/input"; +import { Label } from "@reactive-resume/ui/components/label"; + +const field: React.CSSProperties = { display: "flex", flexDirection: "column", gap: 6, padding: 16, width: 320 }; + +export const Default = () => ( +
+ + +
+); + +export const Placeholder = () => ( +
+ + +
+); + +export const Email = () => ( +
+ + +
+); + +export const Invalid = () => ( +
+ + +
+); + +export const Disabled = () => ( +
+ + +
+); diff --git a/.design-sync/previews/InputGroup.tsx b/.design-sync/previews/InputGroup.tsx new file mode 100644 index 000000000..a6001c474 --- /dev/null +++ b/.design-sync/previews/InputGroup.tsx @@ -0,0 +1,54 @@ +import { CopyIcon, GlobeIcon, MagnifyingGlassIcon } from "@phosphor-icons/react"; +import { + InputGroup, + InputGroupAddon, + InputGroupButton, + InputGroupInput, + InputGroupText, + InputGroupTextarea, +} from "@reactive-resume/ui/components/input-group"; + +const wrap: React.CSSProperties = { display: "flex", flexDirection: "column", gap: 16, padding: 16, width: 380 }; + +export const Addons = () => ( +
+ + + + + + + + + + + rxresu.me/u/ + + + + + + + + + + + + +
+); + +export const WithTextarea = () => ( +
+ + + + 240 characters left + Generate with AI + + +
+); diff --git a/.design-sync/previews/Kbd.tsx b/.design-sync/previews/Kbd.tsx new file mode 100644 index 000000000..29baf66b7 --- /dev/null +++ b/.design-sync/previews/Kbd.tsx @@ -0,0 +1,67 @@ +import { Kbd, KbdGroup } from "@reactive-resume/ui/components/kbd"; + +const row: React.CSSProperties = { display: "flex", flexWrap: "wrap", alignItems: "center", gap: 12, padding: 20 }; +const listRow: React.CSSProperties = { + display: "flex", + alignItems: "center", + justifyContent: "space-between", + gap: 24, + fontSize: 13, + color: "var(--foreground)", +}; +const col: React.CSSProperties = { display: "flex", flexDirection: "column", gap: 10, padding: 20, minWidth: 260 }; + +export const Keys = () => ( +
+ + + + Esc + Enter + Tab +
+); + +export const Combinations = () => ( +
+ + + K + + + + S + + + + + P + +
+); + +export const ShortcutList = () => ( +
+
+ Command palette + + + K + +
+
+ Save resume + + + S + +
+
+ Undo + + + Z + +
+
+); diff --git a/.design-sync/previews/Label.tsx b/.design-sync/previews/Label.tsx new file mode 100644 index 000000000..87126f13f --- /dev/null +++ b/.design-sync/previews/Label.tsx @@ -0,0 +1,38 @@ +import { Input } from "@reactive-resume/ui/components/input"; +import { Label } from "@reactive-resume/ui/components/label"; +import { Switch } from "@reactive-resume/ui/components/switch"; + +const field: React.CSSProperties = { display: "flex", flexDirection: "column", gap: 6, padding: 16, width: 320 }; +const row: React.CSSProperties = { display: "flex", alignItems: "center", gap: 10, padding: 16, width: 320 }; + +export const WithInput = () => ( +
+ + +
+); + +export const Required = () => ( +
+ + +
+); + +export const WithSwitch = () => ( +
+ + +
+); + +export const Disabled = () => ( +
+ + +
+); diff --git a/.design-sync/previews/Marker.tsx b/.design-sync/previews/Marker.tsx new file mode 100644 index 000000000..5726be380 --- /dev/null +++ b/.design-sync/previews/Marker.tsx @@ -0,0 +1,38 @@ +import { CheckCircleIcon, SparkleIcon, WarningCircleIcon } from "@phosphor-icons/react"; +import { Marker, MarkerContent, MarkerIcon } from "@reactive-resume/ui/components/marker"; + +const wrap: React.CSSProperties = { display: "flex", flexDirection: "column", gap: 12, padding: 16, width: 360 }; + +export const Statuses = () => ( +
+ + + + + Tailoring your resume… + + + + + + Applied 4 edits to your resume + + + + + + Couldn't reach the AI provider + +
+); + +export const Dividers = () => ( +
+ + Today + + + Conversation history + +
+); diff --git a/.design-sync/previews/Message.tsx b/.design-sync/previews/Message.tsx new file mode 100644 index 000000000..83c0b9c5e --- /dev/null +++ b/.design-sync/previews/Message.tsx @@ -0,0 +1,64 @@ +import { SparkleIcon, UserIcon } from "@phosphor-icons/react"; +import { Bubble, BubbleContent } from "@reactive-resume/ui/components/bubble"; +import { + Message, + MessageAvatar, + MessageContent, + MessageFooter, + MessageGroup, + MessageHeader, +} from "@reactive-resume/ui/components/message"; + +const avatar: React.CSSProperties = { display: "flex", alignItems: "center", justifyContent: "center", padding: 8 }; + +export const Conversation = () => ( +
+ + + + + + + + + + Tailor my resume for a product manager role. + + + + + + + + + + + + + Done — I emphasized roadmap ownership and stakeholder communication in your summary. + + + + + +
+); + +export const WithMeta = () => ( +
+ + + + + + + + Reactive AI + + I found 4 weak bullets and rewrote them with stronger verbs and metrics. + + Just now · applied 4 edits + + +
+); diff --git a/.design-sync/previews/MessageScroller.tsx b/.design-sync/previews/MessageScroller.tsx new file mode 100644 index 000000000..0bf329391 --- /dev/null +++ b/.design-sync/previews/MessageScroller.tsx @@ -0,0 +1,56 @@ +import { SparkleIcon, UserIcon } from "@phosphor-icons/react"; +import { Bubble, BubbleContent } from "@reactive-resume/ui/components/bubble"; +import { Message, MessageAvatar, MessageContent } from "@reactive-resume/ui/components/message"; +import { + MessageScroller, + MessageScrollerButton, + MessageScrollerContent, + MessageScrollerItem, + MessageScrollerProvider, + MessageScrollerViewport, +} from "@reactive-resume/ui/components/message-scroller"; + +const avatar: React.CSSProperties = { display: "flex", alignItems: "center", justifyContent: "center", padding: 8 }; + +const turns = [ + { role: "user", text: "Can you review my resume for a senior engineering role?" }, + { role: "assistant", text: "Sure — I'll focus on scope, impact, and leadership signals. Reading it now." }, + { role: "user", text: "Great, keep the tone concise." }, + { + role: "assistant", + text: "I rewrote your summary and tightened three experience bullets with measurable outcomes.", + }, + { role: "user", text: "Perfect, publish the draft." }, + { role: "assistant", text: "Draft saved and published to your public resume. Anything else you'd like to refine?" }, +]; + +export const Thread = () => ( +
+ + + + + {turns.map((turn, index) => ( + + + + {turn.role === "user" ? : } + + + + {turn.text} + + + + + ))} + + + + + +
+); diff --git a/.design-sync/previews/Popover.tsx b/.design-sync/previews/Popover.tsx new file mode 100644 index 000000000..8a38f1ee1 --- /dev/null +++ b/.design-sync/previews/Popover.tsx @@ -0,0 +1,33 @@ +import { Button } from "@reactive-resume/ui/components/button"; +import { + Popover, + PopoverContent, + PopoverDescription, + PopoverHeader, + PopoverTitle, + PopoverTrigger, +} from "@reactive-resume/ui/components/popover"; + +// Anchored overlay — rendered open (defaultOpen), positioned below its trigger. +// cfg.overrides.Popover pins cardMode: single + viewport with room for the popup. +export const Open = () => ( +
+ + }>Share resume + + + Public link + Anyone with this link can view your published resume. + +
+ + +
+
+
+
+); diff --git a/.design-sync/previews/ResizableGroup.tsx b/.design-sync/previews/ResizableGroup.tsx new file mode 100644 index 000000000..ec81cedd7 --- /dev/null +++ b/.design-sync/previews/ResizableGroup.tsx @@ -0,0 +1,56 @@ +import { ResizableGroup, ResizablePanel, ResizableSeparator } from "@reactive-resume/ui/components/resizable"; + +const panelStyle: React.CSSProperties = { height: "100%", padding: 16, fontSize: 14, lineHeight: 1.6 }; +const label: React.CSSProperties = { + fontSize: 11, + fontWeight: 600, + textTransform: "uppercase", + letterSpacing: "0.05em", + color: "var(--muted-foreground)", + marginBottom: 8, +}; + +export const BuilderLayout = () => ( +
+ + +
+
Editor
+
Basics
+
Work Experience
+
Education
+
Skills
+
+
+ + +
+
Live Preview
+
Jordan Rivera
+
Senior Product Designer
+
+
+
+
+); + +export const VerticalSplit = () => ( +
+ + +
+
Summary
+
Eight years building design systems and shipping delightful product experiences.
+
+
+ + +
+
Contact
+
jordan.rivera@email.com
+
San Francisco, CA
+
+
+
+
+); diff --git a/.design-sync/previews/ScrollArea.tsx b/.design-sync/previews/ScrollArea.tsx new file mode 100644 index 000000000..b18f94c65 --- /dev/null +++ b/.design-sync/previews/ScrollArea.tsx @@ -0,0 +1,38 @@ +import { ScrollArea } from "@reactive-resume/ui/components/scroll-area"; + +const templates = [ + { name: "Azurill", tag: "Minimal" }, + { name: "Bronzor", tag: "Classic" }, + { name: "Chikorita", tag: "Modern" }, + { name: "Ditto", tag: "Compact" }, + { name: "Gengar", tag: "Bold" }, + { name: "Glalie", tag: "Elegant" }, + { name: "Kakuna", tag: "Timeless" }, + { name: "Leafish", tag: "Creative" }, + { name: "Nosepass", tag: "Formal" }, + { name: "Onyx", tag: "Technical" }, + { name: "Pikachu", tag: "Friendly" }, + { name: "Rhyhorn", tag: "Corporate" }, +]; + +const rowStyle: React.CSSProperties = { + display: "flex", + alignItems: "center", + justifyContent: "space-between", + padding: "10px 14px", + borderBottom: "1px solid var(--border)", + fontSize: 14, +}; + +export const TemplateList = () => ( + +
+ {templates.map((template) => ( +
+ {template.name} + {template.tag} +
+ ))} +
+
+); diff --git a/.design-sync/previews/Separator.tsx b/.design-sync/previews/Separator.tsx new file mode 100644 index 000000000..d36eeb61b --- /dev/null +++ b/.design-sync/previews/Separator.tsx @@ -0,0 +1,44 @@ +import { Separator } from "@reactive-resume/ui/components/separator"; + +const block: React.CSSProperties = { + display: "flex", + flexDirection: "column", + gap: 12, + padding: 20, + maxWidth: 360, + fontSize: 13, + color: "var(--foreground)", +}; +const inline: React.CSSProperties = { + display: "flex", + alignItems: "center", + gap: 12, + padding: 20, + fontSize: 13, + color: "var(--muted-foreground)", +}; + +export const Horizontal = () => ( +
+
+ Amruth Pillai + Senior Software Engineer +
+ + + Building resume tooling at Reactive Resume. Open-source enthusiast. + +
+); + +export const Vertical = () => ( +
+ Profile + + Experience + + Education + + Skills +
+); diff --git a/.design-sync/previews/Sheet.tsx b/.design-sync/previews/Sheet.tsx new file mode 100644 index 000000000..80f4da17a --- /dev/null +++ b/.design-sync/previews/Sheet.tsx @@ -0,0 +1,38 @@ +import { Button } from "@reactive-resume/ui/components/button"; +import { Label } from "@reactive-resume/ui/components/label"; +import { + Sheet, + SheetClose, + SheetContent, + SheetDescription, + SheetFooter, + SheetHeader, + SheetTitle, +} from "@reactive-resume/ui/components/sheet"; + +// Side drawer — rendered open (defaultOpen), anchored to the right edge. +// cfg.overrides.Sheet pins cardMode: single + viewport. +export const Open = () => ( + + + + Resume settings + Control how “Software Engineer” appears when shared publicly. + +
+
+ + rxresume.me/jane-doe +
+
+ + Anyone with the link can view +
+
+ + }>Cancel + }>Save changes + +
+
+); diff --git a/.design-sync/previews/Sidebar.tsx b/.design-sync/previews/Sidebar.tsx new file mode 100644 index 000000000..3a4d36ce8 --- /dev/null +++ b/.design-sync/previews/Sidebar.tsx @@ -0,0 +1,61 @@ +import { FileTextIcon, GearIcon, HouseIcon, PlusIcon } from "@phosphor-icons/react"; +import { + Sidebar, + SidebarContent, + SidebarFooter, + SidebarGroup, + SidebarGroupLabel, + SidebarHeader, + SidebarMenu, + SidebarMenuButton, + SidebarMenuItem, + SidebarProvider, +} from "@reactive-resume/ui/components/sidebar"; + +// SidebarProvider supplies context + --sidebar-width. `collapsible="none"` +// renders the sidebar inline (the default offcanvas variant is fixed-positioned +// and would escape the card). +export const Navigation = () => ( + +
+ + +
Reactive Resume
+
+ + + Workspace + + + + Dashboard + + + + + Resumes + + + + + New resume + + + + + + + + + + Settings + + + + +
+
+
+); diff --git a/.design-sync/previews/Skeleton.tsx b/.design-sync/previews/Skeleton.tsx new file mode 100644 index 000000000..de1d9153b --- /dev/null +++ b/.design-sync/previews/Skeleton.tsx @@ -0,0 +1,40 @@ +import { Skeleton } from "@reactive-resume/ui/components/skeleton"; + +const pad: React.CSSProperties = { padding: 20 }; + +export const TextLines = () => ( +
+ + + + +
+); + +export const ProfileHeader = () => ( +
+ +
+ + +
+
+); + +export const ResumeCard = () => ( +
+ + + +
+); diff --git a/.design-sync/previews/Slider.tsx b/.design-sync/previews/Slider.tsx new file mode 100644 index 000000000..c98d31153 --- /dev/null +++ b/.design-sync/previews/Slider.tsx @@ -0,0 +1,32 @@ +import { Label } from "@reactive-resume/ui/components/label"; +import { Slider } from "@reactive-resume/ui/components/slider"; + +const field: React.CSSProperties = { display: "flex", flexDirection: "column", gap: 10, padding: 16, width: 320 }; + +export const Single = () => ( +
+ + +
+); + +export const Range = () => ( +
+ + +
+); + +export const FontScale = () => ( +
+ + +
+); + +export const Disabled = () => ( +
+ + +
+); diff --git a/.design-sync/previews/Spinner.tsx b/.design-sync/previews/Spinner.tsx new file mode 100644 index 000000000..285e0efe1 --- /dev/null +++ b/.design-sync/previews/Spinner.tsx @@ -0,0 +1,34 @@ +import { Spinner } from "@reactive-resume/ui/components/spinner"; + +const row: React.CSSProperties = { display: "flex", alignItems: "center", gap: 20, padding: 24 }; + +export const Sizes = () => ( +
+ + + +
+); + +export const Colors = () => ( +
+ + +
+); + +export const LoadingRow = () => ( +
+ + Generating your PDF… +
+); diff --git a/.design-sync/previews/Switch.tsx b/.design-sync/previews/Switch.tsx new file mode 100644 index 000000000..ddb015190 --- /dev/null +++ b/.design-sync/previews/Switch.tsx @@ -0,0 +1,39 @@ +import { Label } from "@reactive-resume/ui/components/label"; +import { Switch } from "@reactive-resume/ui/components/switch"; + +const row: React.CSSProperties = { display: "flex", alignItems: "center", gap: 10, padding: 16, width: 300 }; +const stack: React.CSSProperties = { display: "flex", flexDirection: "column", gap: 16, padding: 16, width: 300 }; + +export const On = () => ( +
+ + +
+); + +export const Off = () => ( +
+ + +
+); + +export const Small = () => ( +
+ + +
+); + +export const Disabled = () => ( +
+
+ + +
+
+ + +
+
+); diff --git a/.design-sync/previews/Tabs.tsx b/.design-sync/previews/Tabs.tsx new file mode 100644 index 000000000..0e0fdaf14 --- /dev/null +++ b/.design-sync/previews/Tabs.tsx @@ -0,0 +1,56 @@ +import { BriefcaseIcon, GraduationCapIcon, SparkleIcon } from "@phosphor-icons/react"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@reactive-resume/ui/components/tabs"; + +const wrap: React.CSSProperties = { width: 460, padding: 16 }; +const panel: React.CSSProperties = { padding: "12px 4px", lineHeight: 1.6 }; + +export const ResumeSections = () => ( +
+ + + + Experience + + + Education + + + Skills + + + + Staff Engineer · Vercel +
Owned the edge runtime rollout serving 2B requests per day.
+
+ + M.S. Computer Science · Carnegie Mellon +
Focus on distributed systems and human-computer interaction.
+
+ + Core stack +
TypeScript, React, Go, PostgreSQL, and Kubernetes.
+
+
+
+); + +export const LineVariant = () => ( +
+ + + Preview + Share + Export + + + Your resume renders live as you edit each section. + + + Publish a public link at reactive-resume.app/u/your-name. + + + Download a print-ready PDF or DOCX in one click. + + +
+); diff --git a/.design-sync/previews/Textarea.tsx b/.design-sync/previews/Textarea.tsx new file mode 100644 index 000000000..717f90a26 --- /dev/null +++ b/.design-sync/previews/Textarea.tsx @@ -0,0 +1,36 @@ +import { Label } from "@reactive-resume/ui/components/label"; +import { Textarea } from "@reactive-resume/ui/components/textarea"; + +const field: React.CSSProperties = { display: "flex", flexDirection: "column", gap: 6, padding: 16, width: 360 }; + +export const Default = () => ( +
+ +