assistant-ui icon indicating copy to clipboard operation
assistant-ui copied to clipboard

[WIP] feat(playground): build own chat interface

Open okisdev opened this issue 1 month ago • 3 comments

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 PlaygroundPage in page.tsx to allow users to customize chat interfaces.
    • Integrates Builder, DocsRuntimeProvider, and BuilderCodeOutput components.
  • 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 Ellipsis for 858ae7b248752c1ada2804e930cc069b05520308. You can customize this summary. It will automatically update as commits are pushed.

okisdev avatar Nov 25 '25 16:11 okisdev

⚠️ 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

changeset-bot[bot] avatar Nov 25 '25 16:11 changeset-bot[bot]

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 /playground route 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() and generateCliCommand() using useMemo
  • Consider memoizing the preview components
  • Use useCallback for 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>, added asChild prop
  • button.tsx: Removed shadow-xs from some variants, added new icon sizes
  • card.tsx: Complete restructure with new CardAction component, changed spacing
  • select.tsx: Switched from @radix-ui/react-icons to lucide-react icons
  • 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:

  1. Playground feature with only required dependencies
  2. Additional shadcn/ui components as a separate update

Minor Issues & Suggestions

  1. Accessibility: The color picker buttons in builder-controls.tsx:244-257 only have title attributes. Consider adding proper aria-label for screen readers.

  2. Code duplication: The border radius mapping appears in both builder-preview.tsx:40-46 and builder-code-output.tsx:408-417. Extract to shared constant.

  3. Magic numbers: The timeout values (e.g., setTimeout(() => setCopiedTab(null), 2000)) should be constants.

  4. Type safety: In builder-code-output.tsx:56-58, the icon imports could be typed more strictly to ensure all required icons are included.

  5. Unused layout config: The layout field in BuilderConfig only 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.

  6. Missing loading states: When switching presets or updating configs, there are no loading indicators.

  7. No persistence: User configurations are lost on page refresh. Consider adding localStorage persistence.

  8. 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(), or innerHTML
  • 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:

  1. Add changeset for tracking
  2. Add playground to navigation
  3. Add metadata to playground page
  4. 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

github-actions[bot] avatar Nov 25 '25 16:11 github-actions[bot]

@okisdev is attempting to deploy a commit to the assistant-ui Team on Vercel.

A member of the Team first needs to authorize it.

vercel[bot] avatar Nov 26 '25 14:11 vercel[bot]