Skip to content

Add custom section title color and corner radius theme options#125

Merged
vincentmakes merged 6 commits into
mainfrom
claude/custom-section-title-colors-TEKRS
Apr 19, 2026
Merged

Add custom section title color and corner radius theme options#125
vincentmakes merged 6 commits into
mainfrom
claude/custom-section-title-colors-TEKRS

Conversation

@vincentmakes

Copy link
Copy Markdown
Owner

Description

This PR adds two new theme customization options to the theme picker:

  1. Custom section title color: Users can now toggle a color picker to set a custom color for all section headings (About, Experience, Skills, etc.), independent of the primary accent color. A preset swatch palette of 12 carefully chosen dark/neutral colors is provided for quick selection.

  2. Custom section corner radius: Users can toggle a slider (0–32px, integer steps, default 16px) to customize the border-radius of all section boxes. The header radius scales proportionally (1.5×) to maintain visual consistency. When disabled, sections fall back to the pre-1.41 --radius-lg value, ensuring backward compatibility.

Both options:

  • Are stored in the per-dataset data.theme blob alongside existing theme fields
  • Follow the same PUT /api/theme propagation rules (applyToAll flag, language sibling inheritance)
  • Are restored on dataset load
  • Are applied via new CSS variables (--section-title-color, --section-radius, --header-radius)
  • Are honored in print styles

The color picker machinery has been refactored to use a WHEEL_IDS lookup table, eliminating repetitive conditional logic and making it trivial to add new color wheels in the future.

Type of Change

  • New feature (non-breaking change that adds functionality)

Checklist

Required for all code changes

  • I have tested my changes locally (npm test passes)
  • Version has been bumped in all 3 files (package.json, package-lock.json, version.json) — bumped to 1.41.0
  • CHANGELOG.md has been updated with a new entry under the correct version

If adding or changing user-visible strings

  • No hardcoded English — all strings use data-i18n in HTML
  • New i18n keys added to en.json and all 7 other locale files (de, fr, nl, es, it, pt, zh)
  • User-provided content (hex colors) is validated server-side and client-side

Test Coverage

  • Added 12 new backend tests covering:
    • Invalid sectionTitleColor and sectionRadius validation
    • Persistence with applyToAll=true (bulk apply to all datasets)
    • Per-dataset updates with applyToAll=false
    • Language sibling propagation
    • Clearing values (set to null)
    • Out-of-range and non-integer radius rejection
  • Existing theme tests continue to pass
  • Frontend color picker and slider interactions tested via manual QA

https://claude.ai/code/session_01FWoGdrKqwcp3FjSo9ep57Q

claude added 6 commits April 19, 2026 16:55
The theme picker now exposes a "Custom section title color" toggle. When
enabled it reveals a dedicated color wheel (brightness slider, hex input,
and 12 preset swatches including black, navy, dark blue, midnight, slate,
charcoal, etc.) so section headings can be styled independently of the
primary accent. When the toggle is off, `--section-title-color` is
unset and section titles continue to fall back to `var(--primary)` —
existing themes are visually unchanged.

The new field threads through the existing theme pipeline: it is stored in
the per-dataset `data.theme` blob, propagates via `PUT /api/theme`
(applyToAll or language-siblings), is restored by the dataset load
handler, and is applied in both the admin preview and the public
read-only CV page. Keys added to all 8 locales.

https://claude.ai/code/session_01FWoGdrKqwcp3FjSo9ep57Q
The theme picker gains a "Custom section corner radius" toggle that
reveals a 0–32px slider (integer steps, default 16px). The chosen value
drives the new `--section-radius` CSS variable that both built-in and
custom section boxes now honor via `border-radius: var(--section-radius,
var(--radius-lg))` — so when the toggle is off the sections keep their
pre-1.41 look.

The field threads through the same pipeline as the other theme options:
stored in `settings` and the per-dataset `data.theme` blob, validated in
`PUT /api/theme` (integer in bounds), propagated via the shared
`themeBlob` (applyToAll or language-siblings), restored on dataset load,
and applied identically on the admin preview and the public read-only
page. Print styles honor the custom radius too. Keys added to all 8
locales; 5 new backend tests cover validation, bulk propagation,
language-sibling propagation, and null-clear.

https://claude.ai/code/session_01FWoGdrKqwcp3FjSo9ep57Q
Two small theme refinements:

- The top `.header` card now scales in proportion to the "Custom section
  corner radius" slider (1.5× — matches the pre-1.41 24px:16px ratio).
  New `--header-radius` CSS variable is derived client-side from the
  existing persisted `sectionRadius` field; `.header` falls back to
  `--radius-xl` so themes without a custom radius are unchanged.

- `--accent` now tracks the user's chosen `gradientEnd` when a custom
  gradient is active, preserving the default-theme invariant that accent
  equals the gradient end. Elements that echo the gradient end (the
  item-card highlight-pulse border, print-mode timeline branch strokes)
  stay in sync with the rest of the theme. When no custom gradient is
  set, accent keeps auto-deriving from primary as before.

Client-only change — no new persisted fields, no API surface change, no
new i18n strings. Mirrored across admin.js and public-readonly for
parity on the admin preview and the public read-only CV page. Full test
suite still passes (199/199).

https://claude.ai/code/session_01FWoGdrKqwcp3FjSo9ep57Q
1.41.1 made --accent follow the user's gradientEnd. The same invariant
holds for --primary-dark: in the default theme its formula matches the
auto --header-gradient-start, and it drives every item title in the CV
(.item-title for Experience job titles, .cert-name for Certifications,
.custom-item-title and .custom-bullet-title for custom sections).

Currently those titles stay primary-derived even when a custom gradient
is set, leaving the CV's body text disconnected from the chosen palette.
This change rebinds --primary-dark = gradientStart whenever a custom
gradient is active, mirrored across admin.js and public-readonly. When
the custom gradient toggle is off, both --primary-dark and --accent
revert to their auto-derivation.

Client-only — no server, API, or i18n change. 199/199 tests still pass.

https://claude.ai/code/session_01FWoGdrKqwcp3FjSo9ep57Q
Per request: stop bumping the patch version. Roll the header-radius
scaling and the custom-gradient text-color fix (previously 1.41.1 +
1.41.2) into a single 1.41.0 entry. Code is unchanged; only the
version files and CHANGELOG are touched.

https://claude.ai/code/session_01FWoGdrKqwcp3FjSo9ep57Q
Two related theme refinements (still under 1.41.0):

- Admin toolbar (.toolbar at admin.css:6) and its mobile-menu drawer
  (admin.css:2280) now paint with linear-gradient(135deg,
  --header-gradient-start, --header-gradient-end) instead of the literal
  --primary-dark / --dark variables. In the default theme these resolve
  to the same colors so the toolbar looks identical. When a custom
  gradient is set, the toolbar follows the user's start → end the same
  way the CV header does, instead of mixing a custom start with the
  default primary-derived dark end.

- --primary-dark now follows gradientEnd (not gradientStart) when a
  custom gradient is active. The gradient end is typically the darker
  of the two endpoints in user-picked gradients (Ocean Deep, Midnight,
  Forest, Aurora, etc.), so item titles stay legible body text in the
  chosen palette. --accent likewise follows gradientEnd. Both revert to
  primary-derived auto values when the custom gradient toggle is off.

199/199 tests still pass. No version bump per request.

https://claude.ai/code/session_01FWoGdrKqwcp3FjSo9ep57Q
@vincentmakes vincentmakes merged commit 2c3ccc2 into main Apr 19, 2026
3 checks passed
@vincentmakes vincentmakes deleted the claude/custom-section-title-colors-TEKRS branch April 19, 2026 18:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants