Files
pbakaus_impeccable/site/components/LiveUiGallery.astro
T
Paul BakausandClaude Fable 5 7557935fdb Expand concept system: modes, ratings, re-roll, breadth strategy
Catalog: mode-aligned staging surfaces (persuade/operate/read/experience),
star ratings on approvals feeding challenger draw weights, family
retirements, authoring strategy and territory guide, rework and breadth
authoring rounds, composition mining from rejected worlds.

Seed: six challengers (two per tier), --reroll chains, --mode staging
filter, rating-weighted draws. New-work: Present/visualize/re-roll flow,
image-gen requirement, register-neutral vocabulary.

Pipeline: per-mode staging prompts with split frames, hero-from-board
reference generation, render-safety guards. Labs: ratings UI, unrated
filter, mode chips, composition approve-guard.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 22:10:10 -07:00

156 lines
6.4 KiB
Plaintext

---
import '../styles/live-ui-gallery.css';
import { LIVE_COMMANDS } from '../../skill/scripts/live/vocabulary.mjs';
import { LIVE_UI_SURFACES } from '../../skill/scripts/live/ui-core.mjs';
const STATE_GROUPS = [
{
key: 'global-chrome',
label: 'Global chrome',
summary: 'Session status, page-wide tools, and steering.',
states: [
['global-ready', 'Ready', 'global-bottom-bar'],
['global-disconnected', 'Agent disconnected', 'global-bottom-bar'],
['global-foreground', 'Codex CLI fallback', 'global-bottom-bar'],
['global-tools', 'Detect + DESIGN.md', 'global-bottom-bar'],
['steer-expanded', 'Steer composing', 'global-bottom-bar'],
['steer-processing', 'Steer processing', 'global-bottom-bar'],
],
},
{
key: 'selection',
label: 'Selection',
summary: 'Target, annotate, and insert before generation.',
states: [
['configure-replace', 'Configure selection', 'element-selection-chrome'],
['action-picker', 'Action picker', 'action-picker'],
['configure-listening', 'Voice input', 'element-selection-chrome'],
['configure-locked', 'Apply locked', 'element-selection-chrome'],
['annotation', 'Annotations', 'annotation-chrome'],
['insert-placeholder', 'Insert placeholder', 'insert-mode-chrome'],
],
},
{
key: 'generation-review',
label: 'Generation + review',
summary: 'Progressive arrival, tuning, application, and confirmation.',
states: [
['generating', 'Generating', 'generating-row'],
['generation-recovery', 'Recovery', 'generating-row'],
['cycling-progressive', 'Variant 1 arrived', 'variant-cycling-row'],
['cycling-second', 'Variant 2 arrived', 'variant-cycling-row'],
['tune-open', 'Tune panel', 'variant-params-panel'],
['applying', 'Applying variant', 'saving-confirmed-rows'],
['confirmed', 'Variant applied', 'saving-confirmed-rows'],
],
},
{
key: 'copy-support',
label: 'Copy + support',
summary: 'Inline copy edits, design context, and recovery feedback.',
states: [
['edit-copy', 'Edit copy', 'edit-chrome'],
['copy-pending', 'Copy edits pending', 'pending-copy-edit-dock'],
['copy-applying', 'Copy edits applying', 'pending-copy-edit-dock'],
['copy-attention', 'Apply needs attention', 'pending-copy-edit-dock'],
['design-panel', 'DESIGN.md panel', 'design-system-panel'],
['toast-error', 'Error toast', 'toasts-and-errors'],
],
},
];
// Keep the catalog honest as Live grows. CSS isolation is a structural mount
// contract rather than a visible state; every other surface must own at least
// one snapshot here or the site build fails with the missing surface name.
const STRUCTURAL_SURFACES = new Set(['css-isolation-boundary']);
const coveredSurfaces = new Set(
STATE_GROUPS.flatMap((group) => group.states.map(([, , surface]) => surface)),
);
const visualSurfaces = LIVE_UI_SURFACES.filter((surface) => !STRUCTURAL_SURFACES.has(surface.key));
const uncoveredSurfaces = visualSurfaces.filter((surface) => !coveredSurfaces.has(surface.key));
if (uncoveredSurfaces.length > 0) {
throw new Error(`Live UI lab is missing snapshots for: ${uncoveredSurfaces.map((surface) => surface.key).join(', ')}`);
}
const statePayload = STATE_GROUPS.flatMap((group) =>
group.states.map(([key, label, surface]) => ({
key,
label,
surface,
groupKey: group.key,
group: group.label,
groupSummary: group.summary,
})),
);
const groupPayload = STATE_GROUPS.map((group) => ({
key: group.key,
label: group.label,
summary: group.summary,
states: statePayload.filter((state) => state.groupKey === group.key),
}));
const commandPayload = JSON.stringify(LIVE_COMMANDS).replace(/</g, '\\u003c');
const groupsJson = JSON.stringify(groupPayload).replace(/</g, '\\u003c');
---
<!--
Dev-only state harness for Impeccable Live. The chrome mirrors:
- skill/scripts/live-browser.js (standalone browser UI and exact wording)
- skill/scripts/live/ui-core.mjs (surface/state inventory)
- skill/scripts/live/vocabulary.mjs (canonical command labels and SVGs)
Production Live deliberately uses the same dark Neo Kinpaku chrome on light
and dark host pages (barPaletteForTheme, live-browser.js). The host control
therefore changes the canvas behind every state, not the product chrome.
-->
<section class="live-ui-gallery" data-live-ui-gallery data-dev-only="true" aria-label="Live UI state inspector">
<aside class="live-ui-gallery__sidebar">
<header class="live-ui-gallery__sidebar-head">
<span>State catalog</span>
<strong>{statePayload.length} snapshots</strong>
<small>{visualSurfaces.length} visible surfaces</small>
</header>
<nav class="live-ui-gallery__group-nav" aria-label="Live UI workflow groups" aria-keyshortcuts="ArrowUp ArrowDown Home End">
{STATE_GROUPS.map((group, index) => (
<button type="button" data-gallery-group={group.key} aria-current={index === 0 ? 'true' : 'false'}>
<span>{String(index + 1).padStart(2, '0')}</span>
<span>
<strong>{group.label}</strong>
<small>{group.states.length} states</small>
</span>
</button>
))}
</nav>
<footer>
<span>Product rule</span>
<p>Live chrome stays dark. Host context changes around it.</p>
</footer>
</aside>
<div class="live-ui-gallery__workspace">
<header class="live-ui-gallery__toolbar">
<div class="live-ui-gallery__group-readout" aria-live="polite" aria-atomic="true">
<span data-gallery-group-index>Group 01</span>
<h2 data-gallery-group-label>Global chrome</h2>
<p data-gallery-group-summary>Session status, page-wide tools, and steering.</p>
</div>
<div class="live-ui-gallery__host-switch" role="group" aria-label="Preview host theme">
<span>Host</span>
<button type="button" data-gallery-host="light" aria-pressed="true">Light</button>
<button type="button" data-gallery-host="dark" aria-pressed="false">Dark</button>
</div>
</header>
<div class="live-ui-gallery__cluster" data-gallery-cluster role="list" aria-label="Global chrome states"></div>
</div>
<script is:inline type="application/json" data-live-gallery-groups set:html={groupsJson}></script>
<script is:inline type="application/json" data-live-gallery-vocabulary set:html={commandPayload}></script>
</section>
<script>
import '../scripts/live-ui-gallery.js';
</script>