Add Portfolio 2026 design spec
This commit is contained in:
@@ -0,0 +1,240 @@
|
||||
---
|
||||
name: Portfolio 2026 Theme Design
|
||||
description: Surface overhaul, conflict resolution, and template build-out for the ks-portfolio WordPress theme.
|
||||
created: 2026-08-16
|
||||
status: approved
|
||||
---
|
||||
|
||||
# Portfolio 2026 Theme — Design Spec
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
Rebuild the surface of `ks-portfolio` (WordPress theme at `wp-content/themes/ks-portfolio/`) to match the **Portfolio 2026** identity defined in `notes/DESIGN.md`, `notes/TOKENS.md`, and the three mockups (`home-screen.png`, `archive-screen.png`, `single-screen.png`). Resolve the documented conflicts in `notes/DESIGN.md` §12. Keep the SoloFrame Evo architecture and the installed `projects-portfolio` plugin as-is; build only the presentation layer.
|
||||
|
||||
## 2. Source hierarchy
|
||||
|
||||
When sources disagree, follow `notes/DESIGN.md` §1. In short:
|
||||
|
||||
1. `style.css` for current identity.
|
||||
2. `notes/Projects Plugin Design.md` for content model.
|
||||
3. `notes/Background Gradient.md` for atmospheric field.
|
||||
4. `theme.json`, `styles/`, ACF JSON, templates for implemented tokens.
|
||||
5. `README.md` and `docs/` for inherited architecture.
|
||||
|
||||
User decisions (locked at brainstorm time):
|
||||
|
||||
- **Projects source**: theme renders templates against the `projects` CPT provided by the installed `projects-portfolio` plugin. The theme does NOT re-register the CPT.
|
||||
- **Mockup content**: live `projects` CPT with empty-state fallbacks ("Nothing here yet..."). The mockups are layout references, not content sources.
|
||||
- **Test scope**: Chromium + axe only. Firefox / WebKit / mobile are out of scope.
|
||||
- **Pen-test**: static security audit (PHPCS + grep + manual review). No OWASP ZAP.
|
||||
|
||||
## 3. Identity & naming
|
||||
|
||||
- `style.css` keeps `Theme Name: Portfolio 2026`, `Text Domain: ks-portfolio`.
|
||||
- PHP namespace `SoloFrameEvo` → `KsPortfolio` across all PHP files (composer script + manual review).
|
||||
- Drop `screenshot.png` (Basic WP) at the end; replace with a Carbon-Blue-themed capture.
|
||||
|
||||
## 4. Visual system
|
||||
|
||||
### 4.1 Body surface
|
||||
|
||||
```css
|
||||
body {
|
||||
background-color: #100e0b; /* Carbon Blue page base */
|
||||
color: var(--color-on-surface); /* #e3e1e9 — ~14:1 on dark */
|
||||
}
|
||||
```
|
||||
|
||||
The existing rule `main#maincontent { background: var(--color-background); }` is removed. Sections paint directly on the dark body; there is no light block underneath content.
|
||||
|
||||
### 4.2 Carbon Blue atmospheric field
|
||||
|
||||
Implemented as a `views/partials/aura-bg.php` partial loaded on the home and project archive templates (per mockup: dark atmospheric field on hero surfaces, plain dark surface elsewhere).
|
||||
|
||||
- Layer 1: linear 138deg `#05070c → #0f172a → #172554 → #1e3a8a`. `mix-blend-mode: normal`. `transform: translateZ(0)`.
|
||||
- Layer 2: radial ellipse `45% 50% at 72% 40%`, `rgba(96,165,250,0.20)` → transparent 68%. `mix-blend-mode: screen`. `filter: blur(105px)` mobile, `151px` desktop.
|
||||
- Layer 3: inline SVG `feTurbulence baseFrequency="0.7" numOctaves="4" stitchTiles="stitch"`, `mix-blend-mode: overlay`, `opacity: 0.85`.
|
||||
- All three: `position: absolute; inset: 0;`, `pointer-events: none;`, `aria-hidden="true"`.
|
||||
- Parent container: `position: relative; overflow: hidden; min-height: 100vh;` with NO `background-color` (per the blend-mode architecture warning in `notes/Background Gradient.md`).
|
||||
- Content wrapper: `position: relative; z-index: 1`.
|
||||
|
||||
### 4.3 Tokens
|
||||
|
||||
Resolve the unresolved tokens from `notes/DESIGN.md` §12:
|
||||
|
||||
- Define `--font-headings: var(--font-sans)` in `styles/base/typography.css`.
|
||||
- Update `theme.json` `styles` block to reference the existing palette slugs (`theme-bg`, `theme-text`) — currently references `background` / `text` which don't exist.
|
||||
- Add Carbon-Blue editor palette entries in `theme.json`: `theme-surface` (#121318), `theme-on-surface` (#e3e1e9), `theme-outline` (#8f909d), `theme-outline-variant` (#444651), `theme-primary` (#b6c4ff), `theme-on-primary` (#05297a).
|
||||
- Add 100–900 mix tokens for `theme-primary` if not already present.
|
||||
- Remove legacy hex values (`#3857BC`, `#ddd`) from pagination CSS; replace with `var(--color-outline-variant)` / `var(--color-primary)`.
|
||||
|
||||
Keep the implemented light tokens in `styles/base/colors.css` for any block-editor surface that still wants light, but default new portfolio-facing CSS to the dark surface.
|
||||
|
||||
## 5. Template → mockup mapping
|
||||
|
||||
### 5.1 `front-page.php` — matches `notes/home-screen.png`
|
||||
|
||||
- Header: `WP_DEV_2026` logo, top nav (Plugins, Themes, Open Source, Documentation, Blog), `Download CV` button (right-aligned).
|
||||
- Hero on Carbon Blue: heading + intro + two CTAs (`Download CV`, `View Repositories`) pulled from ACF Homepage Hero fields. No hardcoded sample text.
|
||||
- "Recent Projects" section: queries `projects` CPT, max 3, rendered as 3-column grid on `lg`, single column on mobile.
|
||||
- Each card: type badge (Plugin / Theme / Pattern), title, excerpt, `Download` + `View Repo` links when both URLs exist (provider-agnostic labels).
|
||||
- Empty state when zero published projects: "Nothing here yet..." + "No published projects found." centered in the grid area.
|
||||
- Footer: copyright + GitHub / Privacy / License / Site Status links.
|
||||
|
||||
### 5.2 `archive-projects.php` (new) — matches `notes/archive-screen.png`
|
||||
|
||||
- Hero: `Project Archive` heading + intro from ACF option (or page-derived intro).
|
||||
- Grid: project cards 3-up on `lg`, 2-up on `md`, 1-up on mobile.
|
||||
- Each card: type label (PLUGIN / THEME FRAMEWORK / INTEGRATION, uppercase tracking-wide), title, excerpt, language pill + star count, `View Repo →` link.
|
||||
- Pagination via `the_posts_pagination` styled against dark surface.
|
||||
|
||||
### 5.3 `single-projects.php` (new) — matches `notes/single-screen.png`
|
||||
|
||||
- Hero: provider icon + type pill, project title + version suffix (from `projects_portfolio_get_latest_version()`), excerpt.
|
||||
- Primary `Download vX.Y.Z` button + secondary `View Repo` link.
|
||||
- Two-column body below: featured image / project content on the left; sidebar (Maintainer, Repository Details table, four stat cards) on the right.
|
||||
- Owner avatar: 40px square using `background-image` with explicit `width: 40px; height: 40px; background-size: 40px 40px;` (per `notes/Projects Plugin Design.md` §9 — host CSS quirk workaround).
|
||||
- Below columns: `Architecture & Implementation` (post body content), `Key Features` (list), `Installation` (code block) — all from WordPress content.
|
||||
|
||||
### 5.4 `taxonomy-project-type.php` (new)
|
||||
|
||||
- Same template as `archive-projects.php` with taxonomy-aware title: `<h1>{project-type label}</h1>` plus a back link to the full archive.
|
||||
|
||||
### 5.5 Other templates
|
||||
|
||||
- `index.php` (post archive), `search.php`, `single.php` (post), `page.php`, `404.php`: keep structure, recolor surfaces to dark, remove `picsum.photos` fallback URLs, ensure empty-state copy matches existing `Nothing here yet...` / `No published posts found.` / `Page Not Found` patterns.
|
||||
- Keep `Resources` CPT and `resource_type` taxonomy styling independent from `projects`.
|
||||
|
||||
## 6. Components
|
||||
|
||||
### 6.1 Buttons
|
||||
|
||||
Keep the existing token-driven button block (Primary / Secondary / White / Black × Default / Outline × Small / Medium / Large × Auto / Small / Wide / Full Width). The Primary button in the mockup maps to the existing default-styled Primary button (3px border, semibold 16px, 200ms transitions, focus outline offset, 99% active press).
|
||||
|
||||
### 6.2 Project card
|
||||
|
||||
New `views/components/project-card.php`:
|
||||
|
||||
- Border `1px solid var(--color-outline-variant)`.
|
||||
- Background `var(--color-surface-container)` (#1e1f25).
|
||||
- Radius `lg` (1rem).
|
||||
- Padding `1.5rem`.
|
||||
- Type badge top-left (small, uppercase, tracking-wide).
|
||||
- Provider icon top-right (decorative if visible text label is present).
|
||||
- Title (h3 if in archive, h2 on home), excerpt (line-clamp), action row at bottom with `Download` and `View Repo`.
|
||||
- Hover: subtle border tint to `var(--color-primary)`.
|
||||
- Focus-visible: 2px primary outline, 3px offset.
|
||||
|
||||
### 6.3 Stat card
|
||||
|
||||
New `views/components/project-stat-card.php`:
|
||||
|
||||
- Square surface with `var(--color-surface-container)`, radius `lg`, padding `1rem`.
|
||||
- Icon (decorative), large value, uppercase label below.
|
||||
|
||||
### 6.4 Navigation
|
||||
|
||||
Keep `views/components/nav-main.php`, `nav-aux.php`, `nav-main__toggle.php`. Recolor links to `var(--color-on-surface)`. Preserve skip link, dropdown behavior, focus visibility, mobile variants.
|
||||
|
||||
### 6.5 Header layout
|
||||
|
||||
Switch from `grid-cols-[83px_auto]` to a three-region responsive layout (logo | main nav | aux action button). The `Download CV` button is in the right region on `lg`, collapses into the mobile menu below.
|
||||
|
||||
## 7. Accessibility (WCAG 2.1 AA)
|
||||
|
||||
- Skip-to-main link: preserved (`#f6ff00` on black, yellow focus outline).
|
||||
- Body text contrast: `#e3e1e9` on `#100e0b` ≈ 14:1 — passes AA.
|
||||
- Primary buttons: `#b6c4ff` background with `#05297a` text ≈ 9:1 — passes AA.
|
||||
- All decorative layers `aria-hidden="true"` + `pointer-events: none`.
|
||||
- Heading order: each template has exactly one `<h1>`. Mockup headings map to page `<h1>`; lower-level headings step down in order.
|
||||
- Provider icons supplement text (GitHub, Gitea, Download, View Repo) — never replace them.
|
||||
- Keyboard: tab order header → hero → projects → footer; focus-visible on every interactive element.
|
||||
- `prefers-reduced-motion`: media-query guard around hover scale on cards / media.
|
||||
|
||||
## 8. Security
|
||||
|
||||
- All forms use `wp_nonce_field`; state-changing requests use `wp_verify_nonce`.
|
||||
- Dynamic output escaped with the right `esc_*` function for its context (`esc_html`, `esc_attr`, `esc_url`, `wp_kses_post`).
|
||||
- Post meta access via `get_post_meta( $id, $key, true )` with explicit defaults.
|
||||
- No `$_GET` / `$_POST` / `$_REQUEST` without `sanitize_*` + `wp_unslash`.
|
||||
- External URLs (Download / View Repo) use `esc_url` and add `rel="noopener noreferrer"` when `target="_blank"`.
|
||||
|
||||
## 9. Testing plan
|
||||
|
||||
### 9.1 Unit / static (composer)
|
||||
|
||||
- `composer run lint` (PHPCS with WordPress + WPCS ruleset) must pass clean across all theme PHP.
|
||||
- Fix any violations inline.
|
||||
|
||||
### 9.2 Static security audit
|
||||
|
||||
- PHPCS `WordPress.Security` ruleset (`NonceVerification`, `ValidatedSanitizedInput`, `EscapeOutput`).
|
||||
- Grep audit for `$_GET` / `$_POST` / `$_REQUEST` without `sanitize_*` / `wp_unslash` / `esc_*`.
|
||||
- Manual review of every new template for nonce, sanitize, escape coverage.
|
||||
- Severity-ranked written report (Critical / High / Medium / Low / Info) with `file:line` citations and remediation per finding.
|
||||
|
||||
### 9.3 Browser / functional (Playwright)
|
||||
|
||||
- `playwright.config.js`: chromium project only, base URL `http://portfolio.test` (matches `.env`).
|
||||
- New `tests/home.spec.js`: home renders Carbon Blue hero, project grid or empty state, no axe violations.
|
||||
- New `tests/archive.spec.js`: project archive grid renders, no axe violations.
|
||||
- New `tests/single.spec.js`: project detail hero + sidebar + Download button visible, no axe violations.
|
||||
- Keep existing `tests/site-a11y.spec.js` (homepage, blog index, 404).
|
||||
- axe tags: `wcag2a, wcag2aa, wcag21a, wcag21aa, wcag22a, wcag22aa`.
|
||||
- Full-page screenshots saved to `test-results/` per test.
|
||||
|
||||
## 10. File-level changes
|
||||
|
||||
### Modified
|
||||
|
||||
- `style.css` (already correct — verify)
|
||||
- `functions.php` (namespace swap, project helper include)
|
||||
- `header.php`, `footer.php` (namespace swap, dark surface)
|
||||
- `index.php`, `single.php`, `page.php`, `search.php`, `404.php`, `front-page.php` (namespace swap, dark surface, remove `picsum.photos`)
|
||||
- `lib/*.php` (11 files: `activation.php`, `class-acf.php`, `class-breadcrumbs.php`, `class-enqueue.php`, `class-menuitems.php`, `class-resources.php`, `extras.php`, `helpers.php`, `hooks.php`, `search-features.php`, `show-template.php` — namespace swap + dark surface tweaks)
|
||||
- `views/blocks/*/block.json` and any block PHP that uses a namespace (light touch — only what axe or the new templates require)
|
||||
- `views/forms/search.php` (light touch — escape review only, no behavior change)
|
||||
- `theme.json` (fix preset references, add dark palette)
|
||||
- `styles/base/colors.css` (add Carbon Blue tokens)
|
||||
- `styles/base/typography.css` (define `--font-headings`)
|
||||
- `styles/base/global.css` (dark body, remove light main rule)
|
||||
- `views/components/nav-*.php`, `views/partials/*.php` (namespace swap, dark overrides)
|
||||
|
||||
### New
|
||||
|
||||
- `archive-projects.php`
|
||||
- `single-projects.php`
|
||||
- `taxonomy-project-type.php`
|
||||
- `views/partials/aura-bg.php` (Carbon Blue layers + grain)
|
||||
- `views/components/project-card.php`
|
||||
- `views/components/project-stat-card.php`
|
||||
- `lib/class-projects.php` (thin wrapper around plugin helpers: `get_provider_label()`, `get_release_url()`, `get_repo_browse_url()`, `get_repo_data()`, `get_owner_data()`, `get_download_url()` with provider-agnostic fallbacks)
|
||||
- `tests/home.spec.js`
|
||||
- `tests/archive.spec.js`
|
||||
- `tests/single.spec.js`
|
||||
- `docs/superpowers/specs/2026-08-16-portfolio-2026-design.md` (this file)
|
||||
- `docs/superpowers/specs/2026-08-16-portfolio-2026-testing-report.md` (final report)
|
||||
|
||||
### Removed
|
||||
|
||||
- `screenshot.png` (Basic WP) — replaced at the end
|
||||
- `picsum.photos` fallback URLs in `index.php`, `search.php`
|
||||
- Legacy hex values in pagination CSS
|
||||
|
||||
## 11. Out of scope
|
||||
|
||||
- Migrating existing content (site has minimal published content — no destructive cleanup).
|
||||
- Changing `projects-portfolio` plugin behavior (we only consume its helpers).
|
||||
- Removing the `Resources` CPT (per notes: keep both, don't conflate).
|
||||
- Block-editor UI polish (follow-up).
|
||||
- Firefox / WebKit / mobile browser testing (out of scope per user choice).
|
||||
- OWASP ZAP scan (out of scope per user choice).
|
||||
|
||||
## 12. Definition of done
|
||||
|
||||
- `composer run lint` exits 0.
|
||||
- Playwright suite passes locally (Chromium, axe-core zero violations across all four specs).
|
||||
- Static security audit produced with no Critical or High findings (Medium+ requires remediation before sign-off).
|
||||
- All three mockups (home, archive, single project) reachable on `http://portfolio.test` and visually consistent with their reference screenshot.
|
||||
- `screenshot.png` replaced with a Carbon-Blue capture.
|
||||
- Final testing report committed to `docs/superpowers/specs/2026-08-16-portfolio-2026-testing-report.md`.
|
||||
Reference in New Issue
Block a user