Portfolio/docs/superpowers/specs/2026-06-14-nychthemeron-library-refactor-design.md
Matthew L McPeak cb287c0e51
All checks were successful
ci / build (push) Successful in 30s
ci / publish (push) Successful in 18s
Inital Commit
2026-07-16 12:38:41 -04:00

112 lines
6 KiB
Markdown

# Refactor portfolio to use `@nychthemeron/library`
## Context
The portfolio currently ships a hand-rolled "Nychthemeron" design system:
local components in `src/components/ds/` (`NychButton`, `NychCard`,
`NychInputText`, `NychTextarea`, `NychMessage`, `NychTag`, `LaurelSpinner`,
`LaurelDivider`, `ImageSlot`) backed by ~1200 lines of token CSS in
`src/assets/styles/`.
`@nychthemeron/library` (now installed from the private registry at
`git.mcpeakdev.com`) is the extracted, PrimeVue-backed version of this same
design system: unstyled PrimeVue components (`Button`, `Card`, `InputText`,
`Textarea`, `Message`, `Tag`, `LoadingIcon`, plus others not yet used here)
wired up with the same `nych-*` passthrough classes, and ships the same
theme as CSS via `@nychthemeron/library/style` and `@nychthemeron/library/theme`.
Goal: replace the local duplicated implementation with the library, keeping
only what the library doesn't provide (`LaurelDivider`, `ImageSlot`, and the
580px static hero spinner).
## Styling / setup
- `src/main.ts`:
- Add `import '@nychthemeron/library/style'` and
`import '@nychthemeron/library/theme'`.
- Register PrimeVue: `app.use(PrimeVue)` (the library's components are
PrimeVue components under the hood).
- Keep the existing `import './assets/styles/styles.css'`, but trim its
`@import` manifest (see below) so it only covers portfolio-specific
CSS; the library CSS imports are added separately in `main.ts`.
- Delete `src/assets/styles/tokens/fonts.css`, `tokens/colors.css`,
`tokens/base.css` — fully superseded by `@nychthemeron/library/style`
(same theme CSS variables for both `hades`/`apollo` themes, font imports,
base reset, focus-ring, and the `nych-spin` keyframes).
- `src/assets/styles/tokens/components.css`: delete every section except
**LaurelDivider** (currently the last section, ~line 738 onward). Rename
the file to `tokens/laurel-divider.css` containing just that section.
Everything else (Button, Input/Textarea, Checkbox/Radio, ToggleSwitch,
Select, Card, Message, Tag, Dialog) is covered by
`@nychthemeron/library/theme`.
- Keep as-is: `tokens/spacing.css`, `tokens/typography.css`,
`portfolio.css`, brand SVGs in `src/assets/brand/`.
- Update `src/assets/styles/styles.css`'s `@import` manifest to drop the
removed files and add `tokens/laurel-divider.css` in place of
`tokens/components.css`.
## Component mapping
| Local component | Replacement | Notes |
|---|---|---|
| `NychTag` | `Tag` from `@nychthemeron/library` | `severity` / `rounded` props pass straight through |
| `NychMessage` | `Message` | `severity` / `closable` pass straight through |
| `NychInputText` | `InputText` | `v-model`, `placeholder`, `type`, `invalid` pass through; drop the local `size="normal"` prop (PrimeVue `size` only accepts `small`/`large`/default — `normal` maps to "don't pass `size`") |
| `NychTextarea` | `Textarea` | `v-model`, `rows`, `placeholder`, `invalid` — direct match |
| `NychButton` | `Button` | `severity`, `disabled`, `loading`, default + `icon` slots — direct match. The library's `Button` has a built-in loading spinner (laurel wreath), replacing the local `LaurelSpinner` usage inside `NychButton` |
| `NychCard` | `Card` | slot rename: local `image` slot → PrimeVue `header` slot; local default slot → PrimeVue `content` slot; `title`/`subtitle` props match |
| `LaurelSpinner` (small, used inside `NychButton`) | dropped — covered by `Button`'s built-in loader | |
| `LaurelSpinner` (Hero, 580px static, `:spinning="false"`) | kept as a local component, rewritten as a thin wrapper around `NychLoadingIcon` imported from `@nychthemeron/library/components`, with scoped CSS to set `width`/`height` and override/disable the `nych-spin` animation when `spinning` is false | per approved "wrap with CSS overrides" approach |
| `LaurelDivider`, `ImageSlot` | unchanged, no library equivalent | |
## Files affected
**Deleted:**
- `src/components/ds/NychTag.vue`
- `src/components/ds/NychMessage.vue`
- `src/components/ds/NychInputText.vue`
- `src/components/ds/NychTextarea.vue`
- `src/components/ds/NychButton.vue`
- `src/components/ds/NychCard.vue`
- `src/assets/styles/tokens/fonts.css`
- `src/assets/styles/tokens/colors.css`
- `src/assets/styles/tokens/base.css`
**Rewritten:**
- `src/components/ds/LaurelSpinner.vue` — becomes a thin wrapper around the
library's `NychLoadingIcon`, preserving its existing `size` / `color` /
`spinning` prop API so `HeroSection.vue` doesn't need to change its usage.
- `src/assets/styles/tokens/components.css``tokens/laurel-divider.css`
(LaurelDivider section only).
- `src/assets/styles/styles.css` (updated `@import` manifest).
- `src/main.ts` (add PrimeVue + library CSS imports, `app.use(PrimeVue)`).
**Updated imports/usages:**
- `src/components/portfolio/SkillsSection.vue``NychTag` from library.
- `src/components/portfolio/WorkSection.vue``NychCard`, `NychTag` from
library; update `NychCard` slot usage (`image` → `header`, default →
`content`).
- `src/components/portfolio/ContactSection.vue``NychInputText`,
`NychTextarea`, `NychButton`, `NychMessage` from library.
- `src/components/portfolio/HeroSection.vue``NychButton` from library;
`LaurelSpinner` continues to be imported from `./ds/LaurelSpinner.vue`
(rewritten).
## Verification
- `bun run build` and `bun run type-check` must pass.
- Visually verify via dev server (`bun run dev`):
- Hero section renders the large static laurel wreath at the same size.
- Skills/Work section tags render with correct severity colors.
- Work section cards render header image, title, content, footer tags.
- Contact form inputs/textarea/button/message render and behave
(loading spinner shows in button while "sending").
- Both `hades` and `apollo` themes (toggle `data-theme` on `<html>`) still
render correctly.
## Out of scope
- No changes to `LaurelDivider.vue` or `ImageSlot.vue` internals.
- No changes to other library components not currently used
(`Checkbox`, `Select`, `Dialog`, `ToggleSwitch`, `RadioButton`, etc.).
- No changes to the CI workflow or registry configuration.