Skip to content

feat(a2ui-playground): unify icon set and button system#2776

Merged
Huxpro merged 5 commits into
lynx-family:mainfrom
Huxpro:Huxpro/a2ui-ui-unify
Jun 3, 2026
Merged

feat(a2ui-playground): unify icon set and button system#2776
Huxpro merged 5 commits into
lynx-family:mainfrom
Huxpro:Huxpro/a2ui-ui-unify

Conversation

@Huxpro
Copy link
Copy Markdown
Collaborator

@Huxpro Huxpro commented Jun 3, 2026

Summary

Polishes the playground UI by collapsing fragmented icons and button styles into one cohesive system.

New primitives

  • src/components/Icon.tsx — Lucide-react barrel (same set Shadcn uses). Centralizes the icon vocabulary with consistent stroke weight and a paired ICON_SIZE scale.
  • src/components/Button.tsx + Button.css — pill-shaped Geist-aligned button with variant (primary/secondary/ghost/danger) × size (sm/md/lg) axes, plus iconBefore/iconAfter/iconOnly slots.

Icon sweep

  • Send Send, Back ChevronLeft, Reset/Restart RotateCcw, Play Play, Pause Pause, Clear X, Expand /Maximize2/Minimize2, theme /Sun/Moon, New Chat 💬MessageSquarePlus, status /Sparkles/Zap, See all ArrowRight.
  • MobileTabBar and PreviewPanel inline SVGs replaced with Pencil and Smartphone.

Button consolidation

  • Six per-page button styles collapsed into one system: toolbarBtn, chatSendBtn, detailBackButton, conversationNewButton, conversationIconButton, themeToggle, previewInfoBtn, previewExpandBtn → all use <Button>.
  • Net +502 / -444 lines (the additions are mostly the new primitives + their CSS; the deletions are the obsolete per-component styling).

Verified visually in light + dark, desktop + mobile, on the Create page, the Examples detail page, and the MobileTabBar.

Test plan

  • pnpm build passes
  • pnpm test passes (mountQueue tests)
  • Visual check at 1440×900 (light + dark): Create page, Examples detail page
  • Visual check at 390×800 (mobile): bottom MobileTabBar, Send button, New conversation chips
  • Reviewer: spot-check that no stray toolbarBtn / chatSendBtn / etc. selectors remain that I missed

Summary by CodeRabbit

  • New Features

    • Unified Button component with variants, sizes, icon-only and responsive icon-only modes.
    • Centralized icon set for consistent, scalable icons used across theme toggle, controls, and indicators.
  • Style

    • Replaced many native/inline buttons with the new Button across chat, preview, demos, mobile bar, and toolbars.
    • Improved visuals, interactions, accessibility (focus, aria labels), and tighter mobile/layout spacing.
  • Chores

    • Added an icon library dependency for the shared icon set.

Copilot AI review requested due to automatic review settings June 3, 2026 01:21
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Jun 3, 2026

⚠️ No Changeset found

Latest commit: c9b174e

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jun 3, 2026

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds lucide-react and a centralized Icon module, implements a forwardRef Button component with CSS, and replaces inline buttons, SVGs, and glyphs across the a2ui-playground with the new Button and Icon primitives.

Changes

Button Component System and Icon Consolidation

Layer / File(s) Summary
Icon module and lucide-react dependency
packages/genui/a2ui-playground/package.json, packages/genui/a2ui-playground/src/components/Icon.tsx
Adds lucide-react and creates Icon.tsx that re-exports a curated set of Lucide icons, exports IconProps, and ICON_SIZE constants.
Button component and CSS styling
packages/genui/a2ui-playground/src/components/Button.tsx, packages/genui/a2ui-playground/src/components/Button.css
Adds a forwardRef Button component with variants (primary,secondary,ghost,danger), sizes (sm,md,lg), iconBefore/iconAfter, iconOnly/responsiveIconOnly, fullWidth, and a .btn CSS system (sizes, interaction states, responsive icon-only, dark overrides, and Lucide svg alignment).
Theme toggle and section badge
packages/genui/a2ui-playground/src/App.tsx, packages/genui/a2ui-playground/src/styles.css
Replaces App's inline theme-toggle with Button variant="ghost" size="sm" iconOnly using Sun/Moon icons and adds a .sectionBadge utility; removes old .themeToggle rules.
Component-level button & icon migrations
packages/genui/a2ui-playground/src/components/*, packages/genui/a2ui-playground/src/components/PreviewPanel.tsx
InstantExamplesStrip uses Zap/ArrowRight; MobileTabBar uses Pencil/Smartphone; PreviewPanel and ConversationListPanel replace native buttons/SVGs with the shared Button and icon components.
AIChatPage CSS and JSX updates
packages/genui/a2ui-playground/src/pages/AIChatPage.tsx, packages/genui/a2ui-playground/src/pages/AIChatPage.css
Removes legacy chat button CSS selectors, replaces Send and status icons with Button and Lucide icons (Send, Sparkles, Zap), updates link/icon alignment/hover, and adds mobile compacting overrides.
DemosPage / OpenUIDemosPage and related styles
packages/genui/a2ui-playground/src/pages/DemosPage.tsx, packages/genui/a2ui-playground/src/pages/DemosPage.css, packages/genui/a2ui-playground/src/pages/OpenUIDemosPage.tsx, packages/genui/a2ui-playground/src/styles.css
Playback controls, sidebar back, restart, editor toolbar, and OpenUIDemos Render now use Button variants and icons; legacy toolbar/detail CSS removed; playback header/meta and idle hint styles updated; preview button CSS adjusted to use .btn primitive.

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • HuJean
  • Sherry-hue
  • PupilTong

Poem

🐰 I hop through code with nimble paws,
Swapping glyphs for icons without a pause.
Sun, Moon, Zap in tidy rows,
Buttons stitched where old markup goes.
A tiny rabbit tidies UI laws.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and accurately reflects the main changes: it unifies the icon set (lucide-react barrel in Icon.tsx) and the button system (new Button component and CSS). The subtitle is specific and clear about what was accomplished.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 3, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Polishes the a2ui-playground UI by consolidating icon usage and replacing multiple bespoke button styles with a single reusable <Button> primitive, improving consistency across pages/components.

Changes:

  • Added a centralized Lucide icon barrel (Icon.tsx) plus an ICON_SIZE scale.
  • Introduced a unified button component (Button.tsx + Button.css) with variant/size axes and icon slots.
  • Swept the playground UI to replace emoji/inline SVG icons and per-page button styles with the new primitives.

Reviewed changes

Copilot reviewed 15 out of 16 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
pnpm-lock.yaml Adds lockfile entries for the new lucide-react dependency.
packages/genui/a2ui-playground/package.json Adds lucide-react dependency to the playground package.
packages/genui/a2ui-playground/src/styles.css Removes legacy theme/preview button styling and aligns selectors with the new .btn primitive.
packages/genui/a2ui-playground/src/pages/OpenUIDemosPage.tsx Replaces toolbar render button with <Button> + Lucide icon.
packages/genui/a2ui-playground/src/pages/DemosPage.tsx Replaces playback/toolbar/back controls with <Button> + Lucide icons.
packages/genui/a2ui-playground/src/pages/DemosPage.css Removes legacy button styles in favor of the shared button primitive.
packages/genui/a2ui-playground/src/pages/AIChatPage.tsx Replaces chat send button + status icons and updates empty-state icon to JSX.
packages/genui/a2ui-playground/src/pages/AIChatPage.css Removes legacy chat/conversation button styles and updates icon-related styling.
packages/genui/a2ui-playground/src/components/PreviewPanel.tsx Replaces inline SVG and text glyph buttons with icon-only <Button> usage.
packages/genui/a2ui-playground/src/components/MobileTabBar.tsx Replaces inline SVG tab icons with Lucide icons and shared sizing.
packages/genui/a2ui-playground/src/components/InstantExamplesStrip.tsx Replaces emoji/arrow glyphs with Lucide icons and shared sizing.
packages/genui/a2ui-playground/src/components/Icon.tsx New Lucide icon barrel + shared icon size scale.
packages/genui/a2ui-playground/src/components/ConversationListPanel.tsx Replaces “New Chat” and row action buttons with <Button> + Lucide icons.
packages/genui/a2ui-playground/src/components/Button.tsx New button primitive component (variants/sizes, icon slots, fullWidth/iconOnly).
packages/genui/a2ui-playground/src/components/Button.css New shared styling for the button system (variants/sizes/focus/disabled).
packages/genui/a2ui-playground/src/App.tsx Replaces theme toggle glyph button with icon-only <Button>.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +70 to +79
<Button
variant='secondary'
size='lg'
fullWidth
iconBefore={MessageSquarePlus}
disabled={disabled}
onClick={onCreate}
>
<span className='conversationNewButtonIcon'>💬</span>
<span className='conversationNewButtonLabel'>+ New Chat</span>
</button>
New Chat
</Button>
Comment on lines +2111 to +2119
<Button
variant='primary'
size='lg'
iconBefore={Send}
disabled={isGenerating || inputValue.trim().length === 0}
onClick={handleSend}
>
<span className='chatSendIcon' aria-hidden='true'>↖</span>
{isGenerating ? 'Generating' : 'Send'}
</button>
</Button>
Comment on lines +639 to +647
<Button
variant='secondary'
size='md'
iconBefore={ChevronLeft}
onClick={handleBackToExamples}
aria-label='Back to Examples'
>
<span className='detailBackIcon'>←</span>
<span className='detailBackLabel'>Back to Examples</span>
</button>
Back to Examples
</Button>
Comment on lines +805 to +831
<Button
variant='ghost'
size='sm'
iconBefore={RotateCcw}
onClick={handleFillExample}
title='Reset'
title='Reset to example'
>
↻ Reset
</button>
<button
type='button'
className='toolbarBtn'
Reset
</Button>
<Button
variant='ghost'
size='sm'
iconBefore={X}
onClick={handleClear}
title='Clear'
title='Clear editor'
>
✕ Clear
</button>
<button
type='button'
className='toolbarBtn primary'
Clear
</Button>
<Button
variant='primary'
size='sm'
iconBefore={Play}
onClick={handleRender}
disabled={isPublishingPayload}
>
{isPublishingPayload ? 'Publishing...' : 'Render'}
</button>
{isPublishingPayload ? 'Publishing...' : 'Render'}
</Button>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (4)
packages/genui/a2ui-playground/src/components/Button.tsx (3)

56-66: ⚡ Quick win

Icon-only buttons need an accessible name.

In iconOnly mode the label is dropped, so without an aria-label the button has no accessible name for screen readers. It's currently only available via ...rest, so nothing prevents a consumer from omitting it. Consider documenting/enforcing aria-label for icon-only usage.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/genui/a2ui-playground/src/components/Button.tsx` around lines 56 -
66, When iconOnly is true the visible label (children) is removed so the button
needs an accessible name; update the Button component to require an accessible
name when iconOnly is set by checking props spread (rest) for aria-label or
aria-labelledby and failing fast in development: in the Button render (where
iconOnly, IconBefore, IconAfter, children are used) detect if iconOnly &&
!('aria-label' in props || 'aria-labelledby' in props) and emit a clear
developer error/warning (or throw in dev) and/or add a TypeScript/PropTypes
requirement so consumers must provide aria-label/aria-labelledby for icon-only
buttons. Ensure the check references iconOnly and the incoming props (rest) so
it prevents silent omission.

45-46: 💤 Low value

Simplify redundant iconSize lookup.

size is already constrained to 'sm' | 'md' | 'lg', so the nested ternary is equivalent to indexing directly.

♻️ Proposed change
-    const iconSize =
-      ICON_SIZE[size === 'lg' ? 'lg' : (size === 'sm' ? 'sm' : 'md')];
+    const iconSize = ICON_SIZE[size];
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/genui/a2ui-playground/src/components/Button.tsx` around lines 45 -
46, The iconSize lookup in Button.tsx is overly verbose — replace the nested
ternary expression with a direct index into ICON_SIZE using the existing size
variable (i.e. use ICON_SIZE[size]) to simplify the code; update the expression
that assigns iconSize (referencing ICON_SIZE and the size prop/variable) and, if
necessary for TS, ensure size is typed as 'sm' | 'md' | 'lg' or cast to the
correct key type so the index is type-safe.

17-18: ⚡ Quick win

Button.tsx: React namespace types are already used in-package; ComponentType import is optional

Other TSX files under packages/genui/a2ui-playground already reference React.* types without importing React (e.g., AIChatPage.tsx, Chip.tsx), and the package tsconfig.json has strict: true with types: ["react", "react-dom"], so React.* type namespaces are expected to work. Switching React.ComponentType to an imported ComponentType is still a reasonable consistency/clarity cleanup.

♻️ Proposed change
-import type { ButtonHTMLAttributes, ReactNode } from 'react';
+import type { ButtonHTMLAttributes, ComponentType, ReactNode } from 'react';
-  iconBefore?: React.ComponentType<{ size?: number; strokeWidth?: number }>;
-  iconAfter?: React.ComponentType<{ size?: number; strokeWidth?: number }>;
+  iconBefore?: ComponentType<{ size?: number; strokeWidth?: number }>;
+  iconAfter?: ComponentType<{ size?: number; strokeWidth?: number }>;
  • Double-check icon-only rendering has an accessible name (e.g., aria-label/aria-labelledby).
  • Confirm any icon sizing logic/conditional styling is simplified/consistent with the size union.
  • Ensure inline strokeWidth and CSS stroke-width don’t conflict for the same SVG.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/genui/a2ui-playground/src/components/Button.tsx` around lines 17 -
18, The Button.tsx props currently declare iconBefore and iconAfter as
ComponentType imports; change them to use the React namespace
(React.ComponentType<{ size?: number; strokeWidth?: number }>) or import
ComponentType consistently across the package to match other files, then ensure
when rendering icon-only buttons the element always has an accessible name (add
aria-label or aria-labelledby when no children), validate the size prop union
usage in the render to simplify/normalize sizing logic against the declared size
union, and ensure you do not apply conflicting strokeWidth via both inline prop
and CSS (harmonize to a single source of truth for SVG stroke width).
packages/genui/a2ui-playground/src/components/Icon.tsx (1)

9-52: ⚡ Quick win

Collapse the duplicated import/export into a single re-export.

The icon names are listed twice, so adding/removing an icon requires editing both blocks and risks divergence. A direct re-export keeps tree-shaking and a single source of truth.

♻️ Proposed refactor
-import {
-  ArrowRight,
-  ArrowUpRight,
-  ChevronLeft,
-  Copy,
-  Maximize2,
-  MessageSquarePlus,
-  Minimize2,
-  Moon,
-  Pause,
-  Pencil,
-  Play,
-  RotateCcw,
-  Send,
-  Smartphone,
-  Sparkles,
-  Sun,
-  Trash2,
-  X,
-  Zap,
-} from 'lucide-react';
-import type { LucideProps } from 'lucide-react';
-
-export {
-  ArrowRight,
-  ArrowUpRight,
-  ChevronLeft,
-  Copy,
-  Maximize2,
-  MessageSquarePlus,
-  Minimize2,
-  Moon,
-  Pause,
-  Pencil,
-  Play,
-  RotateCcw,
-  Send,
-  Smartphone,
-  Sparkles,
-  Sun,
-  Trash2,
-  X,
-  Zap,
-};
+export {
+  ArrowRight,
+  ArrowUpRight,
+  ChevronLeft,
+  Copy,
+  Maximize2,
+  MessageSquarePlus,
+  Minimize2,
+  Moon,
+  Pause,
+  Pencil,
+  Play,
+  RotateCcw,
+  Send,
+  Smartphone,
+  Sparkles,
+  Sun,
+  Trash2,
+  X,
+  Zap,
+} from 'lucide-react';
+import type { LucideProps } from 'lucide-react';
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/genui/a2ui-playground/src/components/Icon.tsx` around lines 9 - 52,
Remove the duplicated import+export block by replacing the two-step pattern with
a single re-export: export the listed icon symbols (ArrowRight, ArrowUpRight,
ChevronLeft, Copy, Maximize2, MessageSquarePlus, Minimize2, Moon, Pause, Pencil,
Play, RotateCcw, Send, Smartphone, Sparkles, Sun, Trash2, X, Zap) directly from
'lucide-react' and re-export the LucideProps type (export type { LucideProps }
from 'lucide-react'); this keeps a single source of truth and preserves
tree-shaking while eliminating the need to edit icons in two places.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/genui/a2ui-playground/src/components/Button.css`:
- Around line 199-206: The comment and rules are inconsistent: the base rule
.btn svg sets stroke-width: 2 and .btn-lg svg sets 1.9 but the comment claims
"down to 1.8 on the larger sizes" and is placed on the base rule; update the
comment to reflect the actual values and move it to the .btn-lg svg block (or
change the numeric values to match the comment if 1.8 was intended).
Specifically, either change the explanatory text to mention nudging from 2 to
1.9 and attach it to .btn-lg svg, or adjust .btn svg / .btn-lg svg stroke-widths
so the comment accurately describes them.

---

Nitpick comments:
In `@packages/genui/a2ui-playground/src/components/Button.tsx`:
- Around line 56-66: When iconOnly is true the visible label (children) is
removed so the button needs an accessible name; update the Button component to
require an accessible name when iconOnly is set by checking props spread (rest)
for aria-label or aria-labelledby and failing fast in development: in the Button
render (where iconOnly, IconBefore, IconAfter, children are used) detect if
iconOnly && !('aria-label' in props || 'aria-labelledby' in props) and emit a
clear developer error/warning (or throw in dev) and/or add a
TypeScript/PropTypes requirement so consumers must provide
aria-label/aria-labelledby for icon-only buttons. Ensure the check references
iconOnly and the incoming props (rest) so it prevents silent omission.
- Around line 45-46: The iconSize lookup in Button.tsx is overly verbose —
replace the nested ternary expression with a direct index into ICON_SIZE using
the existing size variable (i.e. use ICON_SIZE[size]) to simplify the code;
update the expression that assigns iconSize (referencing ICON_SIZE and the size
prop/variable) and, if necessary for TS, ensure size is typed as 'sm' | 'md' |
'lg' or cast to the correct key type so the index is type-safe.
- Around line 17-18: The Button.tsx props currently declare iconBefore and
iconAfter as ComponentType imports; change them to use the React namespace
(React.ComponentType<{ size?: number; strokeWidth?: number }>) or import
ComponentType consistently across the package to match other files, then ensure
when rendering icon-only buttons the element always has an accessible name (add
aria-label or aria-labelledby when no children), validate the size prop union
usage in the render to simplify/normalize sizing logic against the declared size
union, and ensure you do not apply conflicting strokeWidth via both inline prop
and CSS (harmonize to a single source of truth for SVG stroke width).

In `@packages/genui/a2ui-playground/src/components/Icon.tsx`:
- Around line 9-52: Remove the duplicated import+export block by replacing the
two-step pattern with a single re-export: export the listed icon symbols
(ArrowRight, ArrowUpRight, ChevronLeft, Copy, Maximize2, MessageSquarePlus,
Minimize2, Moon, Pause, Pencil, Play, RotateCcw, Send, Smartphone, Sparkles,
Sun, Trash2, X, Zap) directly from 'lucide-react' and re-export the LucideProps
type (export type { LucideProps } from 'lucide-react'); this keeps a single
source of truth and preserves tree-shaking while eliminating the need to edit
icons in two places.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3adfc6d6-b0be-4fd9-9940-f9be16791549

📥 Commits

Reviewing files that changed from the base of the PR and between c368e85 and f6fdf3d.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (15)
  • packages/genui/a2ui-playground/package.json
  • packages/genui/a2ui-playground/src/App.tsx
  • packages/genui/a2ui-playground/src/components/Button.css
  • packages/genui/a2ui-playground/src/components/Button.tsx
  • packages/genui/a2ui-playground/src/components/ConversationListPanel.tsx
  • packages/genui/a2ui-playground/src/components/Icon.tsx
  • packages/genui/a2ui-playground/src/components/InstantExamplesStrip.tsx
  • packages/genui/a2ui-playground/src/components/MobileTabBar.tsx
  • packages/genui/a2ui-playground/src/components/PreviewPanel.tsx
  • packages/genui/a2ui-playground/src/pages/AIChatPage.css
  • packages/genui/a2ui-playground/src/pages/AIChatPage.tsx
  • packages/genui/a2ui-playground/src/pages/DemosPage.css
  • packages/genui/a2ui-playground/src/pages/DemosPage.tsx
  • packages/genui/a2ui-playground/src/pages/OpenUIDemosPage.tsx
  • packages/genui/a2ui-playground/src/styles.css

Comment on lines +199 to +206
/* Lucide strokes look heaviest at their baseline weight; nudging stroke
down to 1.8 on the larger sizes keeps icons from outweighing the label. */
stroke-width: 2;
}

.btn-lg svg {
stroke-width: 1.9;
}
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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Comment doesn't match the code.

The comment states the stroke is nudged "down to 1.8 on the larger sizes," but .btn svg is set to 2 and the large-size override (.btn-lg svg) is 1.9. Also, the explanatory comment lives on the base .btn svg rule rather than the .btn-lg svg rule it describes. Align the comment with the actual values/location.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/genui/a2ui-playground/src/components/Button.css` around lines 199 -
206, The comment and rules are inconsistent: the base rule .btn svg sets
stroke-width: 2 and .btn-lg svg sets 1.9 but the comment claims "down to 1.8 on
the larger sizes" and is placed on the base rule; update the comment to reflect
the actual values and move it to the .btn-lg svg block (or change the numeric
values to match the comment if 1.8 was intended). Specifically, either change
the explanatory text to mention nudging from 2 to 1.9 and attach it to .btn-lg
svg, or adjust .btn svg / .btn-lg svg stroke-widths so the comment accurately
describes them.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Jun 3, 2026

Merging this PR will not alter performance

✅ 83 untouched benchmarks
⏩ 26 skipped benchmarks1


Comparing Huxpro:Huxpro/a2ui-ui-unify (c9b174e) with main (a3e4607)

Open in CodSpeed

Footnotes

  1. 26 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/genui/a2ui-playground/src/pages/DemosPage.css (1)

1098-1105: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Mobile toolbar compaction rules currently target removed .toolbarBtn classes.

At Line 1098 and Line 1103, these selectors no longer match the migrated shared <Button> controls, so the ≤720px compaction can silently stop applying and the toolbar may wrap/crowd again on phones.

Suggested selector update
-  .codePanelToolbar .toolbarBtn {
+  .codePanelToolbar .btn {
     height: 26px;
     padding: 0 8px;
     font-size: 11px;
   }
-  .codePanelToolbar .toolbarBtn.primary {
+  .codePanelToolbar .btn.btn-primary {
     padding: 0 10px;
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/genui/a2ui-playground/src/pages/DemosPage.css` around lines 1098 -
1105, The media-query compaction rules currently target the removed selectors
".codePanelToolbar .toolbarBtn" and ".codePanelToolbar .toolbarBtn.primary", so
update those selectors to match the migrated shared Button component (and native
button elements) used in the toolbar; for example replace occurrences of
".codePanelToolbar .toolbarBtn" with selectors that target the shared Button
class and elements such as ".codePanelToolbar .Button" and ".codePanelToolbar
button", and update the primary variant selector proportionally (e.g.
".codePanelToolbar .Button.primary" or ".codePanelToolbar button.primary") so
the ≤720px compaction still applies to the toolbar controls.
🧹 Nitpick comments (1)
packages/genui/a2ui-playground/src/pages/DemosPage.css (1)

1049-1056: ⚡ Quick win

Legacy back-button selectors are now dead CSS after Button migration.

Line 1049 and Line 1052 target .detailBackLabel / .detailBackButton, but the sidebar back control now renders through shared <Button> (with responsiveIconOnly), so these hooks are stale and misleading.

Cleanup option
-  .detailBackLabel {
-    display: none;
-  }
-  .detailBackButton {
-    min-height: 32px;
-    padding: 6px 10px;
-    box-shadow: none;
-  }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/genui/a2ui-playground/src/pages/DemosPage.css` around lines 1049 -
1056, Remove the dead CSS selectors .detailBackLabel and .detailBackButton from
DemosPage.css since the sidebar back control now uses the shared Button
component with the responsiveIconOnly prop; search for .detailBackLabel and
.detailBackButton in the file and delete those rule blocks (or consolidate any
remaining needed styling onto the shared Button styles/variants instead) to
avoid stale, misleading hooks.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@packages/genui/a2ui-playground/src/pages/DemosPage.css`:
- Around line 1098-1105: The media-query compaction rules currently target the
removed selectors ".codePanelToolbar .toolbarBtn" and ".codePanelToolbar
.toolbarBtn.primary", so update those selectors to match the migrated shared
Button component (and native button elements) used in the toolbar; for example
replace occurrences of ".codePanelToolbar .toolbarBtn" with selectors that
target the shared Button class and elements such as ".codePanelToolbar .Button"
and ".codePanelToolbar button", and update the primary variant selector
proportionally (e.g. ".codePanelToolbar .Button.primary" or ".codePanelToolbar
button.primary") so the ≤720px compaction still applies to the toolbar controls.

---

Nitpick comments:
In `@packages/genui/a2ui-playground/src/pages/DemosPage.css`:
- Around line 1049-1056: Remove the dead CSS selectors .detailBackLabel and
.detailBackButton from DemosPage.css since the sidebar back control now uses the
shared Button component with the responsiveIconOnly prop; search for
.detailBackLabel and .detailBackButton in the file and delete those rule blocks
(or consolidate any remaining needed styling onto the shared Button
styles/variants instead) to avoid stale, misleading hooks.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3dcbe706-c0df-4e61-b03b-ef7e02fffee4

📥 Commits

Reviewing files that changed from the base of the PR and between f6fdf3d and 0afd39a.

📒 Files selected for processing (5)
  • packages/genui/a2ui-playground/src/components/Button.css
  • packages/genui/a2ui-playground/src/components/Button.tsx
  • packages/genui/a2ui-playground/src/components/ConversationListPanel.tsx
  • packages/genui/a2ui-playground/src/pages/DemosPage.css
  • packages/genui/a2ui-playground/src/pages/DemosPage.tsx
🚧 Files skipped from review as they are similar to previous changes (4)
  • packages/genui/a2ui-playground/src/components/ConversationListPanel.tsx
  • packages/genui/a2ui-playground/src/components/Button.tsx
  • packages/genui/a2ui-playground/src/pages/DemosPage.tsx
  • packages/genui/a2ui-playground/src/components/Button.css

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/genui/a2ui-playground/src/pages/AIChatPage.css`:
- Around line 1466-1469: The horizontal gutter for .promptSuggestionsRail was
reduced to 14px but the element that controls snapping still uses
scroll-padding-left: 24px, causing snap alignment issues on mobile; update the
scroll-padding-left value (wherever it is set for the suggestions rail/scroll
container) to 14px to match .promptSuggestionsRail so snap positions align, or
set an explicit scroll-padding-inline/start property on .promptSuggestionsRail
to 14px to ensure consistent snapping.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0b410842-66fc-4d3a-8efc-44e48ee7fc3e

📥 Commits

Reviewing files that changed from the base of the PR and between 0afd39a and bccc914.

📒 Files selected for processing (1)
  • packages/genui/a2ui-playground/src/pages/AIChatPage.css

Comment on lines +1466 to +1469
.promptSuggestionsRail {
padding: 2px 14px 4px;
margin: 0 -14px;
}
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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix snap offset mismatch in the mobile suggestions rail.

You reduced .promptSuggestionsRail horizontal gutter to 14px, but scroll-padding-left still inherits 24px, so snap alignment is off on mobile.

Suggested fix
  .promptSuggestionsRail {
    padding: 2px 14px 4px;
    margin: 0 -14px;
+   scroll-padding-left: 14px;
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.promptSuggestionsRail {
padding: 2px 14px 4px;
margin: 0 -14px;
}
.promptSuggestionsRail {
padding: 2px 14px 4px;
margin: 0 -14px;
scroll-padding-left: 14px;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/genui/a2ui-playground/src/pages/AIChatPage.css` around lines 1466 -
1469, The horizontal gutter for .promptSuggestionsRail was reduced to 14px but
the element that controls snapping still uses scroll-padding-left: 24px, causing
snap alignment issues on mobile; update the scroll-padding-left value (wherever
it is set for the suggestions rail/scroll container) to 14px to match
.promptSuggestionsRail so snap positions align, or set an explicit
scroll-padding-inline/start property on .promptSuggestionsRail to 14px to ensure
consistent snapping.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/genui/a2ui-playground/src/pages/DemosPage.css (1)

1069-1076: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Mobile toolbar compaction selector is stale after Button migration.

Line 1069 still targets .toolbarBtn, but toolbar controls now use .btn classes from the shared Button primitive, so these mobile compact rules never apply.

Suggested fix
-  .codePanelToolbar .toolbarBtn {
+  .codePanelToolbar .btn.btn-sm {
     height: 26px;
     padding: 0 8px;
     font-size: 11px;
   }
-  .codePanelToolbar .toolbarBtn.primary {
+  .codePanelToolbar .btn.btn-primary.btn-sm {
     padding: 0 10px;
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/genui/a2ui-playground/src/pages/DemosPage.css` around lines 1069 -
1076, Styles targeting the deprecated .toolbarBtn selector in .codePanelToolbar
no longer apply after the Button migration; update the selectors to target the
new Button class (e.g., change occurrences of .codePanelToolbar .toolbarBtn and
.codePanelToolbar .toolbarBtn.primary to .codePanelToolbar .btn and
.codePanelToolbar .btn.primary) and preserve the intended mobile compaction
values (height, padding, font-size) so the toolbar uses the compact layout for
mobile. Ensure any specific overrides for the "primary" variant (previously
.toolbarBtn.primary) are applied to .btn.primary as well and keep specificity
consistent with the shared Button primitive.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@packages/genui/a2ui-playground/src/pages/DemosPage.css`:
- Around line 1069-1076: Styles targeting the deprecated .toolbarBtn selector in
.codePanelToolbar no longer apply after the Button migration; update the
selectors to target the new Button class (e.g., change occurrences of
.codePanelToolbar .toolbarBtn and .codePanelToolbar .toolbarBtn.primary to
.codePanelToolbar .btn and .codePanelToolbar .btn.primary) and preserve the
intended mobile compaction values (height, padding, font-size) so the toolbar
uses the compact layout for mobile. Ensure any specific overrides for the
"primary" variant (previously .toolbarBtn.primary) are applied to .btn.primary
as well and keep specificity consistent with the shared Button primitive.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 170398d0-ce4d-42b8-ac95-46c3c4cff63a

📥 Commits

Reviewing files that changed from the base of the PR and between bccc914 and d3d0605.

📒 Files selected for processing (3)
  • packages/genui/a2ui-playground/src/pages/DemosPage.css
  • packages/genui/a2ui-playground/src/pages/DemosPage.tsx
  • packages/genui/a2ui-playground/src/styles.css

Huxpro added 5 commits June 3, 2026 00:12
Adds Lucide-based icon barrel (`src/components/Icon.tsx`) and a unified
`<Button>` primitive (`src/components/Button.tsx`) with variant
(primary/secondary/ghost/danger) and size (sm/md/lg) axes, then sweeps
the existing UI to use them.

Replaces ad-hoc glyphs (↖ Send, ← Back, ↻ Reset, ⏸/▶ Play, ✕ Clear,
⤢/✕ Expand, ☀/☾ theme, 💬/⚡/✨ status) and inline SVGs (MobileTabBar
Pencil + Smartphone, PreviewPanel Phone) with consistent Lucide icons.

Collapses six previous button styles — toolbarBtn, chatSendBtn,
detailBackButton, conversationNewButton, conversationIconButton,
themeToggle, previewInfoBtn, previewExpandBtn — into one pill-shaped
Geist-aligned system. Net -275 LOC.
…polish Playback header

- Add `responsiveIconOnly` to <Button>: hides the label and squares the
  hit-target at ≤720px (compound selectors override fullWidth). Apply to
  New Chat (ConversationListPanel) and Back to Examples (DemosPage) so
  the leftmost button stops eating horizontal space on phones.
- Replace the chunky "LLM stream" badge with a refined inline meta
  ("Playback · LLM STREAM") that reads as one visual unit with the title.
- Swap the unicode ▶ in the idle hint for a Lucide Play icon; trim copy
  to "Replay payload chunk by chunk" (Play button right next to it makes
  "Press · to" redundant). Hide the hint below 720px.
The instant-example cards and chat composer were eating the entire mobile
viewport, leaving no scrollable area for chat bubbles after the first
exchange. Inside the existing ≤720px media query:

- Instant tiles: 244→180px wide, preview height 220→150px
- Suggestion chips: 28→26px tall, slimmer padding
- Composer: drop min-height 132→0, textarea min-height 66→38px
- Send button shrinks to size-sm in mobile composer
- Tighter padding/gap across `.chatInputArea` and `.promptSuggestionsRail`

Result: ~180px of vertical space recovered between the AI welcome bubble
and the suggestion strip — the conversation now actually has room to land.
… JSON)

Both "LLM stream" and "JSON" labels now use a single `.sectionBadge`
utility — bordered chip, visible at every viewport. Drops the prior
`display: none` that was hiding the JSON chip on mobile, so the type
indicator stays informative at every width.

The pulsing "playing" state dot for the LLM stream remains untouched.
…k header

The playback button morphed between primary (Play, Resume) and ghost
(Pause), so the toolbar's visual weight shifted whenever state changed.
Pause is the main action while playing — same emphasis as Resume while
paused — so it should share the primary variant.
@Huxpro Huxpro force-pushed the Huxpro/a2ui-ui-unify branch from 36132dc to c9b174e Compare June 3, 2026 07:13
@Huxpro Huxpro merged commit 4f34061 into lynx-family:main Jun 3, 2026
18 checks passed
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