[WIP] feat(playground): build own chat interface
This PR adds Playground, a place where user can intuitively build their own assistant-ui interface, just like tweakcn.
Feature:
- [ ] a page where we can intuitively build own interface
- [ ] cli tool that can directly pull code to local, like
npx shadcn@latest add "xxxxx" - [ ] theme option
- [ ] custom combined available components
[!IMPORTANT] Introduces a new Playground feature for building custom chat interfaces, along with numerous new UI components and dependencies.
- Playground Feature:
- Adds
PlaygroundPageinpage.tsxto allow users to customize chat interfaces.- Integrates
Builder,DocsRuntimeProvider, andBuilderCodeOutputcomponents.- UI Components:
- Introduces new UI components like
Accordion,AlertDialog,Badge,Breadcrumb,ButtonGroup,Calendar,Card,Carousel,Chart,Checkbox,Command,ContextMenu,Dialog,Drawer,DropdownMenu,Empty,Field,Form,HoverCard,InputGroup,InputOTP,Item,Kbd,Label,Menubar,NavigationMenu,Pagination,Popover,Progress,RadioGroup,ScrollArea,Select,Sidebar,Slider,Sonner,Spinner,Switch,Table,Tabs,Textarea,ToggleGroup,Toggle.- Utilizes Radix UI components and Lucide icons extensively.
- Dependencies:
- Adds new dependencies:
@radix-ui/react-*,lucide-react,class-variance-authority,input-otp,sonner,vaul.This description was created by
for 858ae7b248752c1ada2804e930cc069b05520308. You can customize this summary. It will automatically update as commits are pushed.
⚠️ No Changeset found
Latest commit: 9f0d546ffde5b967fcb9f75b29a906566ba156d2
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
Claude finished @okisdev's task —— View job
Code Review Complete
This PR introduces a Playground feature that allows users to customize their assistant-ui chat interface and generate code. This is a significant addition with ~6,700 lines added across 55 files.
Summary of Changes
The PR adds:
- New
/playgroundroute with interactive builder interface - 4 core builder components (builder.tsx, builder-controls.tsx, builder-preview.tsx, builder-code-output.tsx)
- Configuration system with presets (Default, ChatGPT, Claude, Perplexity, Minimal)
- Code generation for customized thread components
- 40+ new shadcn/ui components
- Significant refactoring of existing UI components (badge, button, card, select, dropdown-menu, etc.)
- 30+ new dependencies
Critical Issues
1. Missing Changeset
The changeset-bot correctly identified that this PR needs a changeset. While this only affects the @assistant-ui/docs package (which is private), you should still add a changeset to track this change.
Action: Run pnpm changeset and add an entry for @assistant-ui/docs with a patch bump.
2. Playground Not in Navigation
The playground page exists at /playground, but there's no link to it in the main navigation (apps/docs/lib/layout.shared.tsx). Users won't be able to discover this feature unless they know the URL.
Recommendation: Add a navigation link:
{
text: "Playground",
url: "/playground",
icon: <LayoutTemplateIcon />, // or another appropriate icon
},
Add this in the links array in layout.shared.tsx, probably after "Examples" and before "Dashboard".
3. No Metadata for Playground Page
The playground page (apps/docs/app/(home)/playground/page.tsx) lacks SEO metadata. This is important for a public-facing feature page.
Recommendation: Add metadata export:
export const metadata = {
title: "Playground - assistant-ui",
description: "Customize your assistant-ui chat interface and generate code to use in your project.",
};
4. Inline Styles with User-Controlled Colors
In builder-controls.tsx:253 and builder-preview.tsx:201,214, accent colors are applied via inline styles using user input. While the color values are constrained to predefined options, this pattern could be problematic if extended in the future.
Current code:
style={{ backgroundColor: color.value }}
Recommendation: Consider using CSS custom properties throughout instead of inline styles, or add explicit validation/sanitization for color values if you plan to allow custom colors in the future.
5. Performance: No Memoization in Builder Components
The builder components re-render frequently (on every config change), but there's no use of useMemo, useCallback, or React.memo. This could lead to performance issues, especially in:
-
BuilderCodeOutput- regenerates code on every render -
BuilderPreview- re-renders entire preview on every config change - Icon imports generation in
generateIconImports()
Recommendation:
- Memoize
generateComponentCode()andgenerateCliCommand()usinguseMemo - Consider memoizing the preview components
- Use
useCallbackfor event handlers passed as props
Code Quality Issues
6. Generated Code Has Hardcoded Import Paths
The code generator (builder-code-output.tsx) generates imports with hardcoded paths like:
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
These paths may not work in all user projects, especially if they don't use the @/ alias or have different directory structures.
Recommendation: Add a note in the CLI instructions about adjusting import paths, or consider making import path generation configurable.
7. Incomplete CSS Custom Property Usage
In builder-code-output.tsx:137, the generated code uses a type assertion to work around CSS custom properties:
["--thread-max-width" as string]: "${styles.maxWidth}",
This is a TypeScript workaround that shouldn't be in generated user code.
Recommendation: Use proper typing or generate the style attribute differently:
style={{ ["--thread-max-width"]: styles.maxWidth } as React.CSSProperties}
8. Deep Nested JSON Comparison for Preset Detection
In presets.ts:152, the code uses JSON.stringify() for deep equality:
return PRESETS.find(
(preset) => JSON.stringify(preset.config) === JSON.stringify(config),
);
This is inefficient and fragile (property order matters). This function appears unused in the codebase.
Recommendation: Either remove this function if unused, or implement proper deep equality comparison if needed.
9. Theme Handling Inconsistency
In builder-preview.tsx:48-64, the theme is hardcoded:
const themeClass = styles.theme === "dark" ? "dark" : "";
This doesn't respect the "system" theme option from the config. Users selecting "system" theme will see light mode in the preview.
Recommendation: Implement proper system theme detection or clarify that preview only shows explicit light/dark.
10. Missing Error Handling in Clipboard API
In builder-code-output.tsx:20-24, clipboard operations have no error handling:
const handleCopy = async (text: string, tab: string) => {
await navigator.clipboard.writeText(text);
setCopiedTab(tab);
setTimeout(() => setCopiedTab(null), 2000);
};
The clipboard API can fail (permissions, browser support, etc.).
Recommendation: Add try-catch with user feedback:
const handleCopy = async (text: string, tab: string) => {
try {
await navigator.clipboard.writeText(text);
setCopiedTab(tab);
setTimeout(() => setCopiedTab(null), 2000);
} catch (error) {
// Show error toast or fallback to document.execCommand
}
};
UI Component Refactoring Concerns
11. Breaking Changes to Shared UI Components
Multiple shared UI components have been significantly refactored:
-
badge.tsx: Complete rewrite, changed from<div>to<span>, addedasChildprop -
button.tsx: Removedshadow-xsfrom some variants, added new icon sizes -
card.tsx: Complete restructure with newCardActioncomponent, changed spacing -
select.tsx: Switched from@radix-ui/react-iconstolucide-reacticons -
dropdown-menu.tsx: Major refactor with data-slot attributes
These changes affect shared components used throughout the docs site, not just the playground. While they appear intentional, they could introduce visual regressions elsewhere.
Recommendation:
- Test these components across the entire docs site
- Consider if all these changes are necessary for the playground feature
- Document any intentional breaking changes
12. Added 30+ New Dependencies
The PR adds many new Radix UI primitives and other dependencies that were previously not used:
-
@radix-ui/react-accordion,alert-dialog,aspect-ratio,checkbox,context-menu, etc. -
embla-carousel-react,vaul,sonner,input-otp,react-day-picker,recharts,cmdk
Many of these dependencies appear to be added for new UI components that aren't actually used in the playground feature (e.g., accordion, alert-dialog, calendar, chart, carousel, drawer, form, table).
Recommendation: Review if all these dependencies are necessary. Consider splitting this into two PRs:
- Playground feature with only required dependencies
- Additional shadcn/ui components as a separate update
Minor Issues & Suggestions
-
Accessibility: The color picker buttons in
builder-controls.tsx:244-257only havetitleattributes. Consider adding properaria-labelfor screen readers. -
Code duplication: The border radius mapping appears in both
builder-preview.tsx:40-46andbuilder-code-output.tsx:408-417. Extract to shared constant. -
Magic numbers: The timeout values (e.g.,
setTimeout(() => setCopiedTab(null), 2000)) should be constants. -
Type safety: In
builder-code-output.tsx:56-58, the icon imports could be typed more strictly to ensure all required icons are included. -
Unused layout config: The
layoutfield inBuilderConfigonly has one working option ("default"). The other options (sidebar, modal, fullscreen) are shown in the UI but don't affect the preview or generated code. -
Missing loading states: When switching presets or updating configs, there are no loading indicators.
-
No persistence: User configurations are lost on page refresh. Consider adding localStorage persistence.
-
Generated code formatting: The code output could benefit from proper formatting with consistent indentation (currently uses template literals with manual spacing).
Security Considerations
✅ No security issues found
- No usage of
dangerouslySetInnerHTML,eval(), orinnerHTML - User input is properly constrained to predefined options
- No XSS vectors identified
- File system operations are safe (read-only operations during code generation)
Good Practices Observed
- Clean TypeScript usage with proper type definitions
- "use client" directives correctly placed for client components
- Consistent naming conventions
- Good component composition and separation of concerns
- Code generation approach is sound and produces usable output
Recommendations Summary
Must Fix:
- Add changeset for tracking
- Add playground to navigation
- Add metadata to playground page
- Fix system theme handling or document limitation
Should Fix: 5. Add performance optimizations (memoization) 6. Add error handling for clipboard operations 7. Review and reduce unnecessary dependencies 8. Document UI component breaking changes
Nice to Have: 9. Add localStorage persistence for user configs 10. Improve generated code formatting 11. Implement or remove unused layout options 12. Extract shared constants
Testing Recommendations
Before merging, please verify:
- [ ] Playground is accessible via navigation
- [ ] All presets work correctly
- [ ] Code generation produces valid, working code
- [ ] Copy buttons work across different browsers
- [ ] Theme switching works (or document limitations)
- [ ] No visual regressions on other pages from UI component changes
- [ ] Mobile responsiveness of playground interface
@okisdev is attempting to deploy a commit to the assistant-ui Team on Vercel.
A member of the Team first needs to authorize it.