Skip to content

feat(demos): clearer welcome-suggestion copy + palette validate-on-read#705

Merged
blove merged 5 commits into
mainfrom
claude/demo-welcome-clarity
Jun 19, 2026
Merged

feat(demos): clearer welcome-suggestion copy + palette validate-on-read#705
blove merged 5 commits into
mainfrom
claude/demo-welcome-clarity

Conversation

@blove

@blove blove commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Two audit-polish items from the Phase-2 capability audit, landed together:

A. Welcome-suggestion discoverability (repo-wide copy pass). Every welcome suggestion across the demos now has a developer-inferrable, sentence-case title and a one-line description of what the prompt exercises. The description powers two surfaces from a single field:

  • Dropdown ("More prompts"): ChatSelectOption gains an optional description?; chat-select renders it as a multiline subtitle under each label.
  • Chips: chat-welcome-suggestion gains an optional description input, surfaced as a title + aria-description hover/focus tooltip (chips stay compact — no visible subtitle).

Copy was rewritten across 13 apps: examples/chat (17), examples/ag-ui (7), and 11 cockpit apps. Prompt value strings are unchanged everywhere (only labels improved + descriptions added), so no LLM behavior shifts.

B. Stale-localStorage hardening (palette validate-on-read). The two demo PalettePersistence services now validate each enum-like field (model / effort / genUiMode / theme / colorScheme / sidenavMode) against its current allowed value-set on read. A stale or renamed value falls back to the default (?? default) instead of loading an invalid selection on a fresh checkout. No versioning; minimal validate-on-read.

Changes

  • libs/chat: ChatSelectOption.description (multiline option) + chat-welcome-suggestion description tooltip + specs.
  • examples/chat, examples/ag-ui: rewritten titles/descriptions, [description] wired through featured chip + moreOptions dropdown; WelcomeSuggestion gains description.
  • 11 cockpit apps: improved labels + per-chip descriptions + [description] binding.
  • Palette services + specs: validate-on-read allowlists.
  • Regenerated chat api-docs.json.

Verification

  • nx run-many -t test lint build --projects=chat — green.
  • Both example apps + all 11 touched cockpit apps build — green.
  • Example unit specs: examples-chat 51/51 (incl. 20 palette + 7 welcome-suggestion), examples-ag-ui 22/22 (incl. 15 palette) — green.
  • e2e label/prompt audit: no changed value; the only chip-label assertions (examples/chat initial-render + lifecycle) updated to the new label; no cockpit e2e asserts on a welcome chip — confirmed via grep.

Plan: docs/superpowers/plans/2026-06-19-demo-welcome-clarity.md

🤖 Generated with Claude Code

blove and others added 5 commits June 18, 2026 22:12
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…at-welcome-suggestion (tooltip)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tiline dropdown)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… tooltips)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 19, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
threadplane Ignored Ignored Jun 19, 2026 6:05am

Request Review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Automated approval: this PR received an intelligent (AI) code review. See the review comments on this PR.

@github-actions

github-actions Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Claude encountered an error after 2m 58s —— View job


PR Review

  • Gather context
  • Read CLAUDE.md
  • Review diff and changed files
  • Post findings

Overall this is a clean, well-scoped PR. Tests are thorough (spec coverage for all new surfaces, palette allowlist validation, non-enum pass-through), e2e label assertions were correctly updated, and no prompt value strings changed. Two findings below.

Finding 1 — aria-description ARIA 1.3 browser support (lib component)

[attr.aria-description] in chat-welcome-suggestion.component.ts:16 is an ARIA 1.3 string attribute. Chromium and Safari support it well; Firefox support was still landing as of late 2025. Since this is a published @threadplane/chat library component, AT users on Firefox may silently lose the accessible description.

title already delivers the hover tooltip, so the only additional value from aria-description is screen-reader announcement. Options: document the browser limitation in the JSDoc, or use a universally-supported aria-describedby with a visually-hidden <span>. Neither is a hard blocker, but worth a conscious decision for a library.

Finding 2 — Dead !== undefined guard in ag-ui palette service (minor)

palette-persistence.service.ts:48 in examples/ag-ui:

const value = (raw[key] as PaletteState[K] | undefined) ?? null;
if (value !== null && value !== undefined) {   // ← `!== undefined` always true

The ?? null on the line above already converts undefinednull, so value is PaletteState[K] | null at this point and !== undefined is always true. The chat version of the same service doesn't have this redundancy. Inline suggestion posted.

No issues found in

  • ChatSelectOption.description optional extension — correct, no breaking change
  • ChatWelcomeSuggestionComponent.description input — optional, correct fallback || null pattern
  • Palette ALLOWED type structure — ag-ui correctly uses Record<PaletteKey, ...> (all 5 fields are enum-like); chat correctly uses Partial<Record<PaletteKey, ...>> with key in ALLOWED guard before the boolean drawerOpen field could be reached
  • value as string casts — safe given the guards
  • e2e label assertions updated for both changed chip labels; no cockpit e2e chips asserted
  • api-docs.json regeneration looks correct

@blove blove merged commit 42baccd into main Jun 19, 2026
7 of 8 checks passed
type="button"
class="chat-welcome-suggestion"
[attr.title]="description() || null"
[attr.aria-description]="description() || null"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

aria-description is an ARIA 1.3 attribute (direct string value, no referenced element). It has good Chromium/Safari support but Firefox support was still landing as of late 2025. Since this is a published library component, AT users on Firefox may not pick up the accessible description.

title alone already provides the hover tooltip; aria-description adds screen-reader announcement. If broad AT support matters here, the hardened alternative is a visually-hidden <span [id]> + aria-describedby, which has universal support. Worth documenting the browser limitation at minimum.

Fix this →

return (raw[key] as PaletteState[K] | undefined) ?? null;
const value = (raw[key] as PaletteState[K] | undefined) ?? null;

if (value !== null && value !== undefined) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

value !== undefined is dead code here. The line above sets value = ... ?? null, so undefined was already coerced to null before this guard runs. The === null check is sufficient.

Suggested change
if (value !== null && value !== undefined) {
if (value !== null) {

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