Skip to content

feat(theme-center): style limits, phase label and alias caps, bullet/tick icon picker - #215

Merged
nathanialhenniges merged 2 commits into
mainfrom
feat/style-limits-icon-picker
Oct 26, 2026
Merged

nathanialhenniges merged 2 commits into
mainfrom
feat/style-limits-icon-picker

Conversation

@nathanialhenniges

Copy link
Copy Markdown
Member

Builds on #214 (branched from fix/overlay-task-wrap; until #214 merges this diff includes its commits — will rebase onto main once it lands).

What

  • One shared, zod-free limit per field (@dirework/api/style-limits, plus MAX_PLACEHOLDER_REPEATS in chat-text and ALIAS_MAX_LENGTH in chat-commands), read by the save schemas (boundedLengthSchema, phaseLabelSchema, overlayIconSchema, chatMessageSchema, normalizeAliases) and by the editors.
  • Style ranges for every length in TIMER_STYLE_FIELDS / TASK_STYLE_FIELDS (negatives rejected; rem/em = 16px; %/vw/vh only where they make sense, e.g. timer size 120–1200px / 10–100% / 10–100vw/vh). Ring width & gap 0–40, scroll speed 1–200, loop gap 0–300. Inline error names the range, ArrowUp/Down stop at the bounds, Save is blocked (existing updateStylesInput.safeParse).
  • Phase labels: 16 graphemes (Intl.Segmenter) and 48 bytes; counter from 13. The "Starting" default "Gathering the Pack" (18) becomes "Pack Gathering": the column default is frozen (PHASE_LABEL_COLUMN_DEFAULTS) and upgrades on read, same as bot replies.
  • Aliases: key and target 25 chars (no !), too-long issue, inputs cap at 26, counter.
  • Bot replies: max 4 uses of one placeholder; the field says so, and the chip stops at 4.
  • Bullet/tick icon picker: 14 ids (dot, circle, check, check-circle, square-check, star, sparkles, arrow-right, chevron-right, paw-print, heart, flame, zap, none), drawn with named lucide-react imports (components/overlay-icon.tsx; dot is a hand-drawn disc). Stored in the existing *_char columns, no migration. Config keys renamed checkbox.tickChar → tickIcon, bullet.char → icon (the old key from a web worker that is mid-deploy is stripped, not rejected). Picker is a radiogroup with roving tabindex via nextGridIndex.
  • Clamp on read, never migrate: clampTimerStyles / clampTaskStyles (nearest bound, or the default when a unit is no longer accepted), toOverlayIcon (✔ → check, • → dot, else default), clampPhaseLabel, limitPlaceholderRepeats, and aliases re-run through normalizeAliases in buildBotConfig (which also canonicalizes legacy !-prefixed records).

Cost

No new requests, polls, writes, or bindings. The overlay poll's read path does a few string checks more. Bundle budget: api 541 KiB, web 2112 KiB gzip (budget 2560).

Tests

  • api: style-limits.test.ts, clamp-on-read.test.ts (clamped reads pass updateStylesInput / updateBotSettingsInput), schema cases in validation-primitives, alias length cases; db defaults test for the frozen phase labels.
  • web: every preset inside every limit and unchanged by clamping, style-sections ↔ limits mapping, stepLength bounds, lengthFieldError agrees with the schema, phaseLabelBudget agrees with the schema.
  • e2e: new 42-style-limits (icon picker changes the overlay bullet; out-of-range length shows its range and blocks Save; long phase label is counted and blocks Save). Ran 00, 40, 42, 80, 90 locally on ports 3980/3981: all pass.
  • lint, check-types, test, test:coverage, build:worker, bundle-budget pass.

Not done

  • The optional contrast warning (< 3:1) was left out; it needs a small contrast helper and UI, more than "low effort".

@nathanialhenniges

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-26T18:27:19.446895Z 0c3c4f4 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3f8904a93c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/api/src/style-limits.ts Resolved
@nathanialhenniges

Copy link
Copy Markdown
Member Author

@codex review

@nathanialhenniges
nathanialhenniges force-pushed the feat/style-limits-icon-picker branch from 3f8904a to e5a271c Compare October 26, 2026 18:06
@nathanialhenniges

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep it up!

Reviewed commit: 53b266626f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

…ases, pick bullet and tick icons

One zod-free constant per limit (@dirework/api/style-limits, chat-text,
chat-commands) feeds both the save schemas and the editors: every Theme
Center length has a px range (plus %/vw/vh where it makes sense, never
negative), ring width/gap and scroll take integer ranges, phase labels
hold 16 graphemes / 48 bytes, aliases 25 characters, and a reply template
repeats one placeholder at most 4 times. Fields show the range inline,
arrow keys stop at its ends, counters appear from 80%, and Save blocks.

The free-text bullet and tick glyphs become a lucide icon picker; the id
is stored in the existing columns. Nothing is migrated: the build helpers
clamp old values on read (old glyphs map to their icon), so a whole-group
save of a loaded theme always passes. The Starting label default becomes
Pack Gathering (the frozen 18-character column default upgrades on read).
…s range

lengthIssue returned "range" at the first out-of-range part, so a stored
shorthand like "80px 10%" (accepted by the old allowlist) reached the
part-by-part clamp with a unit the field no longer takes, and the read
threw. Format and unit are now checked for every part first; a value with
any unreadable part falls back to the default, and every clamped read
passes the save schema (shorthand, mixed-unit, negative and 3/4-part cases).
@nathanialhenniges

Copy link
Copy Markdown
Member Author

@codex review

@nathanialhenniges
nathanialhenniges force-pushed the feat/style-limits-icon-picker branch from 53b2666 to 0c3c4f4 Compare October 26, 2026 18:25
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Hooray!

Reviewed commit: 0c3c4f4b55

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@nathanialhenniges
nathanialhenniges merged commit 44f7517 into main Oct 26, 2026
6 checks passed
@nathanialhenniges
nathanialhenniges deleted the feat/style-limits-icon-picker branch October 30, 2026 10:03
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.

1 participant