From 18fcf0f766857a7249cc0daac3c1609610edd158 Mon Sep 17 00:00:00 2001 From: shadcn Date: Fri, 26 Jun 2026 21:19:31 +0400 Subject: [PATCH] feat: @shadcn/react (#11022) * feat(@shadcn/react): add message-scroller package Add the @shadcn/react headless primitives package with MessageScroller scroll anchoring, streaming follow, history prepend, and jump-to-message behavior. Includes geometry helpers, use-render utility, and unit, browser, and perf tests. * feat(registry): add chat components Add MessageScroller, Message, Bubble, Attachment, and Marker registry sources for base and radix, style variants, preview-03 chat blocks, and registry index wiring. * feat(v4): integrate chat components into docs site Wire chat components into the v4 app with docs routes, example preview pages, message part renderers, markdown support, registry build updates, and supporting lib utilities. * feat(examples): add chat component demos Add base and radix example demos for MessageScroller, Message, Bubble, Attachment, Marker, scroll-fade, and shimmer. * docs: add chat component documentation Add component and utility docs for the chat component set, update docs navigation, and add the June 2026 chat components changelog entry. * chore: regenerate registry JSON output Rebuild public registry artifacts for all style variants with the new chat components. * chore(release): add @shadcn/react publish and CI pipeline Add Changesets prerelease workflow, browser test job, RELEASING docs, and monorepo wiring for publishing @shadcn/react independently from the shadcn CLI. * docs: fix display of component preview on mobile * fix * fix * docs: add message scroller docs * style: format * fix --- .changeset/moody-files-open.md | 5 + .changeset/plenty-cats-allow.md | 5 + .github/collect-prerelease-info.js | 35 + .github/version-script-prerelease.js | 37 - .github/workflows/browser-tests.yml | 56 + .github/workflows/code-check.yml | 4 +- .github/workflows/prerelease-comment.yml | 88 +- .github/workflows/release.yml | 88 +- .github/workflows/test.yml | 36 + .gitignore | 7 + .vscode/settings.json | 3 +- RELEASING.md | 59 + apps/v4/.gitignore | 1 + .../(root)/cards/contribution-history.tsx | 6 +- apps/v4/app/(app)/(root)/cards/index.tsx | 13 +- .../v4/app/(app)/(root)/cards/ui-elements.tsx | 2 +- .../create/components/create-devtools.tsx | 72 + .../(app)/create/components/customizer.tsx | 22 +- .../app/(app)/create/components/preview.tsx | 2 + apps/v4/app/(app)/create/lib/devtools.ts | 10 + apps/v4/app/(app)/docs/[[...slug]]/page.tsx | 2 +- .../(create)/preview/[base]/[name]/page.tsx | 1 + apps/v4/app/globals.css | 2 + apps/v4/app/legacy-themes.css | 71 + apps/v4/components/announcement.tsx | 4 +- apps/v4/components/components-list.tsx | 62 +- apps/v4/components/docs-base-switcher.tsx | 4 +- apps/v4/components/docs-sidebar.tsx | 13 +- apps/v4/components/docs-toc.tsx | 2 +- apps/v4/components/markdown.tsx | 28 + apps/v4/components/message-animated.tsx | 148 + apps/v4/components/message-parts.tsx | 645 ++++ .../changelog/2026-06-chat-components.mdx | 103 + .../docs/components/base/attachment.mdx | 304 ++ .../content/docs/components/base/bubble.mdx | 300 ++ .../content/docs/components/base/marker.mdx | 273 ++ .../docs/components/base/message-scroller.mdx | 586 ++++ .../content/docs/components/base/message.mdx | 248 ++ .../v4/content/docs/components/base/meta.json | 5 + apps/v4/content/docs/components/index.mdx | 6 + .../docs/components/radix/attachment.mdx | 302 ++ .../content/docs/components/radix/bubble.mdx | 304 ++ .../content/docs/components/radix/marker.mdx | 277 ++ .../components/radix/message-scroller.mdx | 586 ++++ .../content/docs/components/radix/message.mdx | 248 ++ .../content/docs/components/radix/meta.json | 5 + apps/v4/content/docs/meta.json | 2 + apps/v4/content/docs/react/index.mdx | 28 + .../content/docs/react/message-scroller.mdx | 277 ++ apps/v4/content/docs/react/meta.json | 4 + apps/v4/content/docs/utils/meta.json | 4 + apps/v4/content/docs/utils/scroll-fade.mdx | 176 ++ apps/v4/content/docs/utils/shimmer.mdx | 167 + apps/v4/examples/__components__.tsx | 1071 +++++++ apps/v4/examples/__index__.tsx | 476 +++ apps/v4/examples/base/attachment-demo.tsx | 82 + apps/v4/examples/base/attachment-group.tsx | 71 + apps/v4/examples/base/attachment-image.tsx | 69 + apps/v4/examples/base/attachment-sizes.tsx | 42 + apps/v4/examples/base/attachment-states.tsx | 101 + apps/v4/examples/base/attachment-trigger.tsx | 60 + apps/v4/examples/base/bubble-alignment.tsx | 18 + apps/v4/examples/base/bubble-collapsible.tsx | 59 + apps/v4/examples/base/bubble-demo.tsx | 48 + apps/v4/examples/base/bubble-group-demo.tsx | 36 + apps/v4/examples/base/bubble-link-button.tsx | 54 + apps/v4/examples/base/bubble-markdown.tsx | 24 + apps/v4/examples/base/bubble-popover.tsx | 55 + apps/v4/examples/base/bubble-reactions.tsx | 70 + apps/v4/examples/base/bubble-tooltip.tsx | 34 + apps/v4/examples/base/bubble-variants.tsx | 52 + apps/v4/examples/base/markdown-demo.tsx | 43 + apps/v4/examples/base/marker-border.tsx | 28 + apps/v4/examples/base/marker-demo.tsx | 32 + apps/v4/examples/base/marker-icon.tsx | 28 + apps/v4/examples/base/marker-link-button.tsx | 33 + apps/v4/examples/base/marker-separator.tsx | 17 + apps/v4/examples/base/marker-shimmer.tsx | 14 + apps/v4/examples/base/marker-status.tsx | 21 + apps/v4/examples/base/marker-variants.tsx | 17 + apps/v4/examples/base/message-actions.tsx | 64 + apps/v4/examples/base/message-attachment.tsx | 76 + apps/v4/examples/base/message-avatar.tsx | 71 + apps/v4/examples/base/message-demo.tsx | 93 + apps/v4/examples/base/message-group.tsx | 44 + .../examples/base/message-header-footer.tsx | 36 + apps/v4/examples/base/message-markdown.tsx | 35 + .../base/message-scroller-anchoring.tsx | 194 ++ .../base/message-scroller-animation.tsx | 182 ++ .../base/message-scroller-commands.tsx | 165 + .../examples/base/message-scroller-demo.tsx | 244 ++ .../base/message-scroller-group-chat.tsx | 235 ++ .../base/message-scroller-load-history.tsx | 171 + .../message-scroller-opening-position.tsx | 190 ++ .../message-scroller-previous-context.tsx | 257 ++ .../base/message-scroller-scrollable.tsx | 103 + .../examples/base/message-scroller-state.tsx | 101 + .../base/message-scroller-streaming.tsx | 245 ++ .../base/message-scroller-visibility.tsx | 185 ++ apps/v4/examples/base/scroll-fade-demo.tsx | 18 + apps/v4/examples/base/scroll-fade-edge.tsx | 93 + .../examples/base/scroll-fade-horizontal.tsx | 33 + apps/v4/examples/base/scroll-fade-none.tsx | 38 + .../v4/examples/base/scroll-fade-overflow.tsx | 18 + apps/v4/examples/base/scroll-fade-rtl.tsx | 78 + apps/v4/examples/base/scroll-fade-size.tsx | 38 + apps/v4/examples/base/shimmer-angle.tsx | 14 + apps/v4/examples/base/shimmer-color.tsx | 12 + apps/v4/examples/base/shimmer-demo.tsx | 7 + apps/v4/examples/base/shimmer-duration.tsx | 16 + apps/v4/examples/base/shimmer-marker.tsx | 18 + apps/v4/examples/base/shimmer-none.tsx | 8 + apps/v4/examples/base/shimmer-once.tsx | 27 + apps/v4/examples/base/shimmer-rtl.tsx | 18 + apps/v4/examples/base/shimmer-spread.tsx | 14 + apps/v4/examples/radix/attachment-demo.tsx | 82 + apps/v4/examples/radix/attachment-group.tsx | 71 + apps/v4/examples/radix/attachment-image.tsx | 67 + apps/v4/examples/radix/attachment-sizes.tsx | 42 + apps/v4/examples/radix/attachment-states.tsx | 101 + apps/v4/examples/radix/attachment-trigger.tsx | 58 + apps/v4/examples/radix/bubble-alignment.tsx | 18 + apps/v4/examples/radix/bubble-collapsible.tsx | 57 + apps/v4/examples/radix/bubble-demo.tsx | 48 + apps/v4/examples/radix/bubble-group-demo.tsx | 36 + apps/v4/examples/radix/bubble-link-button.tsx | 46 + apps/v4/examples/radix/bubble-markdown.tsx | 24 + apps/v4/examples/radix/bubble-popover.tsx | 53 + apps/v4/examples/radix/bubble-reactions.tsx | 70 + apps/v4/examples/radix/bubble-tooltip.tsx | 36 + apps/v4/examples/radix/bubble-variants.tsx | 52 + apps/v4/examples/radix/markdown-demo.tsx | 43 + apps/v4/examples/radix/marker-border.tsx | 32 + apps/v4/examples/radix/marker-demo.tsx | 36 + apps/v4/examples/radix/marker-icon.tsx | 32 + apps/v4/examples/radix/marker-link-button.tsx | 37 + apps/v4/examples/radix/marker-separator.tsx | 17 + apps/v4/examples/radix/marker-shimmer.tsx | 14 + apps/v4/examples/radix/marker-status.tsx | 25 + apps/v4/examples/radix/marker-variants.tsx | 17 + apps/v4/examples/radix/message-actions.tsx | 64 + apps/v4/examples/radix/message-attachment.tsx | 76 + apps/v4/examples/radix/message-avatar.tsx | 71 + apps/v4/examples/radix/message-demo.tsx | 93 + apps/v4/examples/radix/message-group.tsx | 44 + .../examples/radix/message-header-footer.tsx | 36 + apps/v4/examples/radix/message-markdown.tsx | 35 + .../radix/message-scroller-anchoring.tsx | 193 ++ .../radix/message-scroller-animation.tsx | 182 ++ .../radix/message-scroller-commands.tsx | 165 + .../examples/radix/message-scroller-demo.tsx | 240 ++ .../radix/message-scroller-group-chat.tsx | 233 ++ .../radix/message-scroller-load-history.tsx | 169 + .../message-scroller-opening-position.tsx | 190 ++ .../message-scroller-previous-context.tsx | 249 ++ .../radix/message-scroller-scrollable.tsx | 103 + .../radix/message-scroller-streaming.tsx | 241 ++ .../radix/message-scroller-visibility.tsx | 183 ++ apps/v4/examples/radix/scroll-fade-demo.tsx | 18 + apps/v4/examples/radix/scroll-fade-edge.tsx | 93 + .../examples/radix/scroll-fade-horizontal.tsx | 33 + apps/v4/examples/radix/scroll-fade-none.tsx | 38 + .../examples/radix/scroll-fade-overflow.tsx | 18 + apps/v4/examples/radix/scroll-fade-rtl.tsx | 78 + apps/v4/examples/radix/scroll-fade-size.tsx | 38 + apps/v4/examples/radix/shimmer-angle.tsx | 14 + apps/v4/examples/radix/shimmer-color.tsx | 12 + apps/v4/examples/radix/shimmer-demo.tsx | 7 + apps/v4/examples/radix/shimmer-duration.tsx | 16 + apps/v4/examples/radix/shimmer-marker.tsx | 22 + apps/v4/examples/radix/shimmer-none.tsx | 8 + apps/v4/examples/radix/shimmer-once.tsx | 27 + apps/v4/examples/radix/shimmer-rtl.tsx | 18 + apps/v4/examples/radix/shimmer-spread.tsx | 14 + apps/v4/hooks/use-delayed-status.ts | 19 + apps/v4/lib/ai.test.ts | 1092 +++++++ apps/v4/lib/ai.ts | 1703 ++++++++++ apps/v4/lib/docs.ts | 17 +- apps/v4/lib/llm.ts | 44 +- apps/v4/lib/message-animations.ts | 137 + apps/v4/mdx-components.tsx | 19 +- apps/v4/package.json | 20 +- apps/v4/public/avatars/06.png | Bin 0 -> 4930 bytes apps/v4/public/avatars/07.png | Bin 0 -> 5721 bytes apps/v4/public/avatars/08.png | Bin 0 -> 5840 bytes apps/v4/public/avatars/09.png | Bin 0 -> 6060 bytes apps/v4/public/avatars/10.png | Bin 0 -> 5823 bytes apps/v4/public/r/index.json | 53 + .../styles/base-luma/attachment-example.json | 16 + .../public/r/styles/base-luma/attachment.json | 15 + .../r/styles/base-luma/bubble-example.json | 19 + apps/v4/public/r/styles/base-luma/bubble.json | 12 + .../r/styles/base-luma/marker-example.json | 21 + apps/v4/public/r/styles/base-luma/marker.json | 12 + .../r/styles/base-luma/message-example.json | 19 + .../base-luma/message-scroller-example.json | 25 + .../r/styles/base-luma/message-scroller.json | 18 + .../v4/public/r/styles/base-luma/message.json | 12 + .../public/r/styles/base-luma/preview-03.json | 2 +- .../public/r/styles/base-luma/registry.json | 143 + .../styles/base-lyra/attachment-example.json | 16 + .../public/r/styles/base-lyra/attachment.json | 15 + .../r/styles/base-lyra/bubble-example.json | 19 + apps/v4/public/r/styles/base-lyra/bubble.json | 12 + .../r/styles/base-lyra/marker-example.json | 21 + apps/v4/public/r/styles/base-lyra/marker.json | 12 + .../r/styles/base-lyra/message-example.json | 19 + .../base-lyra/message-scroller-example.json | 25 + .../r/styles/base-lyra/message-scroller.json | 18 + .../v4/public/r/styles/base-lyra/message.json | 12 + .../public/r/styles/base-lyra/preview-03.json | 2 +- .../public/r/styles/base-lyra/registry.json | 143 + .../styles/base-maia/attachment-example.json | 16 + .../public/r/styles/base-maia/attachment.json | 15 + .../r/styles/base-maia/bubble-example.json | 19 + apps/v4/public/r/styles/base-maia/bubble.json | 12 + .../r/styles/base-maia/marker-example.json | 21 + apps/v4/public/r/styles/base-maia/marker.json | 12 + .../r/styles/base-maia/message-example.json | 19 + .../base-maia/message-scroller-example.json | 25 + .../r/styles/base-maia/message-scroller.json | 18 + .../v4/public/r/styles/base-maia/message.json | 12 + .../public/r/styles/base-maia/preview-03.json | 2 +- .../public/r/styles/base-maia/registry.json | 143 + .../styles/base-mira/attachment-example.json | 16 + .../public/r/styles/base-mira/attachment.json | 15 + .../r/styles/base-mira/bubble-example.json | 19 + apps/v4/public/r/styles/base-mira/bubble.json | 12 + .../r/styles/base-mira/marker-example.json | 21 + apps/v4/public/r/styles/base-mira/marker.json | 12 + .../r/styles/base-mira/message-example.json | 19 + .../base-mira/message-scroller-example.json | 25 + .../r/styles/base-mira/message-scroller.json | 18 + .../v4/public/r/styles/base-mira/message.json | 12 + .../public/r/styles/base-mira/preview-03.json | 2 +- .../public/r/styles/base-mira/registry.json | 143 + .../styles/base-nova/attachment-example.json | 16 + .../public/r/styles/base-nova/attachment.json | 15 + .../r/styles/base-nova/bubble-example.json | 19 + apps/v4/public/r/styles/base-nova/bubble.json | 12 + .../r/styles/base-nova/marker-example.json | 21 + apps/v4/public/r/styles/base-nova/marker.json | 12 + .../r/styles/base-nova/message-example.json | 19 + .../base-nova/message-scroller-example.json | 25 + .../r/styles/base-nova/message-scroller.json | 18 + .../v4/public/r/styles/base-nova/message.json | 12 + .../public/r/styles/base-nova/preview-03.json | 2 +- .../public/r/styles/base-nova/registry.json | 143 + .../styles/base-rhea/attachment-example.json | 16 + .../public/r/styles/base-rhea/attachment.json | 15 + .../r/styles/base-rhea/bubble-example.json | 19 + apps/v4/public/r/styles/base-rhea/bubble.json | 12 + .../r/styles/base-rhea/marker-example.json | 21 + apps/v4/public/r/styles/base-rhea/marker.json | 12 + .../r/styles/base-rhea/message-example.json | 19 + .../base-rhea/message-scroller-example.json | 25 + .../r/styles/base-rhea/message-scroller.json | 18 + .../v4/public/r/styles/base-rhea/message.json | 12 + .../public/r/styles/base-rhea/preview-03.json | 2 +- .../public/r/styles/base-rhea/registry.json | 143 + .../styles/base-sera/attachment-example.json | 16 + .../public/r/styles/base-sera/attachment.json | 15 + .../r/styles/base-sera/bubble-example.json | 19 + apps/v4/public/r/styles/base-sera/bubble.json | 12 + .../r/styles/base-sera/marker-example.json | 21 + apps/v4/public/r/styles/base-sera/marker.json | 12 + .../r/styles/base-sera/message-example.json | 19 + .../base-sera/message-scroller-example.json | 25 + .../r/styles/base-sera/message-scroller.json | 18 + .../v4/public/r/styles/base-sera/message.json | 12 + .../public/r/styles/base-sera/preview-03.json | 2 +- .../public/r/styles/base-sera/registry.json | 143 + .../styles/base-vega/attachment-example.json | 16 + .../public/r/styles/base-vega/attachment.json | 15 + .../r/styles/base-vega/bubble-example.json | 19 + apps/v4/public/r/styles/base-vega/bubble.json | 12 + .../r/styles/base-vega/marker-example.json | 21 + apps/v4/public/r/styles/base-vega/marker.json | 12 + .../r/styles/base-vega/message-example.json | 19 + .../base-vega/message-scroller-example.json | 25 + .../r/styles/base-vega/message-scroller.json | 18 + .../v4/public/r/styles/base-vega/message.json | 12 + .../public/r/styles/base-vega/preview-03.json | 2 +- .../public/r/styles/base-vega/registry.json | 143 + .../styles/radix-luma/attachment-example.json | 16 + .../r/styles/radix-luma/attachment.json | 15 + .../r/styles/radix-luma/bubble-example.json | 19 + .../v4/public/r/styles/radix-luma/bubble.json | 12 + .../r/styles/radix-luma/item-example.json | 3 +- .../r/styles/radix-luma/marker-example.json | 21 + .../v4/public/r/styles/radix-luma/marker.json | 12 + .../r/styles/radix-luma/message-example.json | 19 + .../radix-luma/message-scroller-example.json | 25 + .../r/styles/radix-luma/message-scroller.json | 18 + .../public/r/styles/radix-luma/message.json | 12 + .../r/styles/radix-luma/preview-03.json | 2 +- .../public/r/styles/radix-luma/registry.json | 145 +- .../styles/radix-lyra/attachment-example.json | 16 + .../r/styles/radix-lyra/attachment.json | 15 + .../r/styles/radix-lyra/bubble-example.json | 19 + .../v4/public/r/styles/radix-lyra/bubble.json | 12 + .../r/styles/radix-lyra/item-example.json | 3 +- .../r/styles/radix-lyra/marker-example.json | 21 + .../v4/public/r/styles/radix-lyra/marker.json | 12 + .../r/styles/radix-lyra/message-example.json | 19 + .../radix-lyra/message-scroller-example.json | 25 + .../r/styles/radix-lyra/message-scroller.json | 18 + .../public/r/styles/radix-lyra/message.json | 12 + .../r/styles/radix-lyra/preview-03.json | 2 +- .../public/r/styles/radix-lyra/registry.json | 145 +- .../styles/radix-maia/attachment-example.json | 16 + .../r/styles/radix-maia/attachment.json | 15 + .../r/styles/radix-maia/bubble-example.json | 19 + .../v4/public/r/styles/radix-maia/bubble.json | 12 + .../r/styles/radix-maia/item-example.json | 3 +- .../r/styles/radix-maia/marker-example.json | 21 + .../v4/public/r/styles/radix-maia/marker.json | 12 + .../r/styles/radix-maia/message-example.json | 19 + .../radix-maia/message-scroller-example.json | 25 + .../r/styles/radix-maia/message-scroller.json | 18 + .../public/r/styles/radix-maia/message.json | 12 + .../r/styles/radix-maia/preview-03.json | 2 +- .../public/r/styles/radix-maia/registry.json | 145 +- .../styles/radix-mira/attachment-example.json | 16 + .../r/styles/radix-mira/attachment.json | 15 + .../r/styles/radix-mira/bubble-example.json | 19 + .../v4/public/r/styles/radix-mira/bubble.json | 12 + .../r/styles/radix-mira/item-example.json | 3 +- .../r/styles/radix-mira/marker-example.json | 21 + .../v4/public/r/styles/radix-mira/marker.json | 12 + .../r/styles/radix-mira/message-example.json | 19 + .../radix-mira/message-scroller-example.json | 25 + .../r/styles/radix-mira/message-scroller.json | 18 + .../public/r/styles/radix-mira/message.json | 12 + .../r/styles/radix-mira/preview-03.json | 2 +- .../public/r/styles/radix-mira/registry.json | 145 +- .../styles/radix-nova/attachment-example.json | 16 + .../r/styles/radix-nova/attachment.json | 15 + .../r/styles/radix-nova/bubble-example.json | 19 + .../v4/public/r/styles/radix-nova/bubble.json | 12 + .../r/styles/radix-nova/item-example.json | 3 +- .../r/styles/radix-nova/marker-example.json | 21 + .../v4/public/r/styles/radix-nova/marker.json | 12 + .../r/styles/radix-nova/message-example.json | 19 + .../radix-nova/message-scroller-example.json | 25 + .../r/styles/radix-nova/message-scroller.json | 18 + .../public/r/styles/radix-nova/message.json | 12 + .../r/styles/radix-nova/preview-03.json | 2 +- .../public/r/styles/radix-nova/registry.json | 145 +- .../styles/radix-rhea/attachment-example.json | 16 + .../r/styles/radix-rhea/attachment.json | 15 + .../r/styles/radix-rhea/bubble-example.json | 19 + .../v4/public/r/styles/radix-rhea/bubble.json | 12 + .../r/styles/radix-rhea/item-example.json | 3 +- .../r/styles/radix-rhea/marker-example.json | 21 + .../v4/public/r/styles/radix-rhea/marker.json | 12 + .../r/styles/radix-rhea/message-example.json | 19 + .../radix-rhea/message-scroller-example.json | 25 + .../r/styles/radix-rhea/message-scroller.json | 18 + .../public/r/styles/radix-rhea/message.json | 12 + .../r/styles/radix-rhea/preview-03.json | 2 +- .../public/r/styles/radix-rhea/registry.json | 145 +- .../styles/radix-sera/attachment-example.json | 16 + .../r/styles/radix-sera/attachment.json | 15 + .../r/styles/radix-sera/bubble-example.json | 19 + .../v4/public/r/styles/radix-sera/bubble.json | 12 + .../r/styles/radix-sera/item-example.json | 3 +- .../r/styles/radix-sera/marker-example.json | 21 + .../v4/public/r/styles/radix-sera/marker.json | 12 + .../r/styles/radix-sera/message-example.json | 19 + .../radix-sera/message-scroller-example.json | 25 + .../r/styles/radix-sera/message-scroller.json | 18 + .../public/r/styles/radix-sera/message.json | 12 + .../r/styles/radix-sera/preview-03.json | 2 +- .../public/r/styles/radix-sera/registry.json | 145 +- .../styles/radix-vega/attachment-example.json | 16 + .../r/styles/radix-vega/attachment.json | 15 + .../r/styles/radix-vega/bubble-example.json | 19 + .../v4/public/r/styles/radix-vega/bubble.json | 12 + .../r/styles/radix-vega/item-example.json | 3 +- .../r/styles/radix-vega/marker-example.json | 21 + .../v4/public/r/styles/radix-vega/marker.json | 12 + .../r/styles/radix-vega/message-example.json | 19 + .../radix-vega/message-scroller-example.json | 25 + .../r/styles/radix-vega/message-scroller.json | 18 + .../public/r/styles/radix-vega/message.json | 12 + .../r/styles/radix-vega/preview-03.json | 2 +- .../public/r/styles/radix-vega/registry.json | 145 +- apps/v4/registry/__blocks__.json | 59 +- apps/v4/registry/__components__.tsx | 720 +++++ apps/v4/registry/__index__.tsx | 1280 ++++++++ apps/v4/registry/bases/__components__.tsx | 208 ++ apps/v4/registry/bases/__index__.tsx | 390 ++- .../registry/bases/base/blocks/_registry.ts | 12 + .../bases/base/blocks/preview-03/index.tsx | 3 + .../registry/bases/base/examples/_registry.ts | 78 + .../base/examples/attachment-example.tsx | 1638 ++++++++++ .../bases/base/examples/bubble-example.tsx | 520 ++++ .../bases/base/examples/marker-example.tsx | 330 ++ .../bases/base/examples/message-example.tsx | 945 ++++++ .../examples/message-scroller-example.tsx | 252 ++ apps/v4/registry/bases/base/ui/_registry.ts | 53 + apps/v4/registry/bases/base/ui/attachment.tsx | 211 ++ apps/v4/registry/bases/base/ui/bubble.tsx | 121 + apps/v4/registry/bases/base/ui/marker.tsx | 64 + .../bases/base/ui/message-scroller.tsx | 139 + apps/v4/registry/bases/base/ui/message.tsx | 92 + .../registry/bases/radix/blocks/_registry.ts | 12 + .../blocks/preview-03/cards/files-chat.tsx | 194 ++ .../blocks/preview-03/cards/group-chat.tsx | 481 +++ .../preview-03/cards/reasoning-chat.tsx | 240 ++ .../blocks/preview-03/cards/simple-chat.tsx | 166 + .../blocks/preview-03/cards/sources-chat.tsx | 187 ++ .../blocks/preview-03/cards/tool-chat.tsx | 212 ++ .../preview-03/components/part-file.tsx | 130 + .../preview-03/components/part-reasoning.tsx | 67 + .../preview-03/components/part-source.tsx | 101 + .../preview-03/components/part-text.tsx | 49 + .../preview-03/components/part-tool.tsx | 123 + .../preview-03/components/prompt-input.tsx | 227 ++ .../bases/radix/blocks/preview-03/index.tsx | 34 + .../bases/radix/examples/_registry.ts | 80 +- .../radix/examples/attachment-example.tsx | 1614 ++++++++++ .../bases/radix/examples/bubble-example.tsx | 517 +++ .../bases/radix/examples/item-example.tsx | 70 + .../bases/radix/examples/marker-example.tsx | 330 ++ .../bases/radix/examples/message-example.tsx | 945 ++++++ .../examples/message-scroller-example.tsx | 252 ++ apps/v4/registry/bases/radix/ui/_registry.ts | 53 + .../v4/registry/bases/radix/ui/attachment.tsx | 208 ++ apps/v4/registry/bases/radix/ui/bubble.tsx | 118 + apps/v4/registry/bases/radix/ui/marker.tsx | 62 + .../bases/radix/ui/message-scroller.tsx | 139 + apps/v4/registry/bases/radix/ui/message.tsx | 92 + apps/v4/registry/icons/__hugeicons__.ts | 15 + apps/v4/registry/icons/__lucide__.ts | 14 + apps/v4/registry/icons/__phosphor__.ts | 11 + apps/v4/registry/icons/__remixicon__.ts | 12 + apps/v4/registry/icons/__tabler__.ts | 10 + apps/v4/registry/styles/style-luma.css | 169 + apps/v4/registry/styles/style-lyra.css | 169 + apps/v4/registry/styles/style-maia.css | 169 + apps/v4/registry/styles/style-mira.css | 169 + apps/v4/registry/styles/style-nova.css | 169 + apps/v4/registry/styles/style-rhea.css | 169 + apps/v4/registry/styles/style-sera.css | 169 + apps/v4/registry/styles/style-vega.css | 169 + apps/v4/scripts/build-registry.mts | 100 +- apps/v4/styles/README.md | 1 + apps/v4/styles/base-luma/ui/attachment.tsx | 209 ++ apps/v4/styles/base-luma/ui/bubble.tsx | 128 + apps/v4/styles/base-luma/ui/marker.tsx | 71 + .../styles/base-luma/ui/message-scroller.tsx | 130 + apps/v4/styles/base-luma/ui/message.tsx | 92 + apps/v4/styles/base-lyra/ui/attachment.tsx | 209 ++ apps/v4/styles/base-lyra/ui/bubble.tsx | 128 + apps/v4/styles/base-lyra/ui/marker.tsx | 71 + .../styles/base-lyra/ui/message-scroller.tsx | 130 + apps/v4/styles/base-lyra/ui/message.tsx | 92 + apps/v4/styles/base-maia/ui/attachment.tsx | 209 ++ apps/v4/styles/base-maia/ui/bubble.tsx | 128 + apps/v4/styles/base-maia/ui/marker.tsx | 71 + .../styles/base-maia/ui/message-scroller.tsx | 130 + apps/v4/styles/base-maia/ui/message.tsx | 92 + apps/v4/styles/base-mira/ui/attachment.tsx | 209 ++ apps/v4/styles/base-mira/ui/bubble.tsx | 128 + apps/v4/styles/base-mira/ui/marker.tsx | 71 + .../styles/base-mira/ui/message-scroller.tsx | 130 + apps/v4/styles/base-mira/ui/message.tsx | 92 + .../v4/styles/base-nova/ui-rtl/attachment.tsx | 209 ++ apps/v4/styles/base-nova/ui-rtl/bubble.tsx | 128 + apps/v4/styles/base-nova/ui-rtl/marker.tsx | 71 + .../base-nova/ui-rtl/message-scroller.tsx | 130 + apps/v4/styles/base-nova/ui-rtl/message.tsx | 92 + apps/v4/styles/base-nova/ui/attachment.tsx | 209 ++ apps/v4/styles/base-nova/ui/bubble.tsx | 128 + apps/v4/styles/base-nova/ui/marker.tsx | 71 + .../styles/base-nova/ui/message-scroller.tsx | 130 + apps/v4/styles/base-nova/ui/message.tsx | 92 + apps/v4/styles/base-rhea/ui/attachment.tsx | 209 ++ apps/v4/styles/base-rhea/ui/bubble.tsx | 128 + apps/v4/styles/base-rhea/ui/marker.tsx | 71 + .../styles/base-rhea/ui/message-scroller.tsx | 130 + apps/v4/styles/base-rhea/ui/message.tsx | 92 + apps/v4/styles/base-sera/ui/attachment.tsx | 209 ++ apps/v4/styles/base-sera/ui/bubble.tsx | 128 + apps/v4/styles/base-sera/ui/marker.tsx | 71 + .../styles/base-sera/ui/message-scroller.tsx | 130 + apps/v4/styles/base-sera/ui/message.tsx | 92 + apps/v4/styles/base-vega/ui/attachment.tsx | 209 ++ apps/v4/styles/base-vega/ui/bubble.tsx | 128 + apps/v4/styles/base-vega/ui/marker.tsx | 71 + .../styles/base-vega/ui/message-scroller.tsx | 130 + apps/v4/styles/base-vega/ui/message.tsx | 92 + apps/v4/styles/radix-luma/ui/attachment.tsx | 206 ++ apps/v4/styles/radix-luma/ui/bubble.tsx | 125 + apps/v4/styles/radix-luma/ui/marker.tsx | 69 + .../styles/radix-luma/ui/message-scroller.tsx | 130 + apps/v4/styles/radix-luma/ui/message.tsx | 92 + apps/v4/styles/radix-lyra/ui/attachment.tsx | 206 ++ apps/v4/styles/radix-lyra/ui/bubble.tsx | 125 + apps/v4/styles/radix-lyra/ui/marker.tsx | 69 + .../styles/radix-lyra/ui/message-scroller.tsx | 130 + apps/v4/styles/radix-lyra/ui/message.tsx | 92 + apps/v4/styles/radix-maia/ui/attachment.tsx | 206 ++ apps/v4/styles/radix-maia/ui/bubble.tsx | 125 + apps/v4/styles/radix-maia/ui/marker.tsx | 69 + .../styles/radix-maia/ui/message-scroller.tsx | 130 + apps/v4/styles/radix-maia/ui/message.tsx | 92 + apps/v4/styles/radix-mira/ui/attachment.tsx | 206 ++ apps/v4/styles/radix-mira/ui/bubble.tsx | 125 + apps/v4/styles/radix-mira/ui/marker.tsx | 69 + .../styles/radix-mira/ui/message-scroller.tsx | 130 + apps/v4/styles/radix-mira/ui/message.tsx | 92 + .../styles/radix-nova/ui-rtl/attachment.tsx | 206 ++ apps/v4/styles/radix-nova/ui-rtl/bubble.tsx | 125 + apps/v4/styles/radix-nova/ui-rtl/marker.tsx | 69 + .../radix-nova/ui-rtl/message-scroller.tsx | 130 + apps/v4/styles/radix-nova/ui-rtl/message.tsx | 92 + apps/v4/styles/radix-nova/ui/attachment.tsx | 206 ++ apps/v4/styles/radix-nova/ui/bubble.tsx | 125 + apps/v4/styles/radix-nova/ui/marker.tsx | 69 + .../styles/radix-nova/ui/message-scroller.tsx | 130 + apps/v4/styles/radix-nova/ui/message.tsx | 92 + apps/v4/styles/radix-rhea/ui/attachment.tsx | 206 ++ apps/v4/styles/radix-rhea/ui/bubble.tsx | 125 + apps/v4/styles/radix-rhea/ui/marker.tsx | 69 + .../styles/radix-rhea/ui/message-scroller.tsx | 130 + apps/v4/styles/radix-rhea/ui/message.tsx | 92 + apps/v4/styles/radix-sera/ui/attachment.tsx | 206 ++ apps/v4/styles/radix-sera/ui/bubble.tsx | 125 + apps/v4/styles/radix-sera/ui/marker.tsx | 69 + .../styles/radix-sera/ui/message-scroller.tsx | 130 + apps/v4/styles/radix-sera/ui/message.tsx | 92 + apps/v4/styles/radix-vega/ui/attachment.tsx | 206 ++ apps/v4/styles/radix-vega/ui/bubble.tsx | 125 + apps/v4/styles/radix-vega/ui/marker.tsx | 69 + .../styles/radix-vega/ui/message-scroller.tsx | 130 + apps/v4/styles/radix-vega/ui/message.tsx | 92 + package.json | 1 + packages/react/.gitignore | 2 + packages/react/README.md | 21 + packages/react/package.json | 74 + .../react/src/message-scroller/PERFORMANCE.md | 176 ++ packages/react/src/message-scroller/README.md | 73 + .../react/src/message-scroller/components.tsx | 407 +++ .../src/message-scroller/geometry.test.ts | 451 +++ .../react/src/message-scroller/geometry.ts | 387 +++ packages/react/src/message-scroller/index.ts | 31 + .../message-scroller.browser.test.tsx | 698 +++++ .../message-scroller.perf.browser.test.tsx | 841 +++++ .../message-scroller.test.tsx | 1701 ++++++++++ packages/react/src/message-scroller/stores.ts | 97 + packages/react/src/message-scroller/types.ts | 239 ++ .../use-message-scroller-commands.ts | 326 ++ .../use-message-scroller-controller.ts | 713 +++++ .../use-message-scroller-refs.ts | 167 + packages/react/src/message-scroller/utils.ts | 11 + packages/react/src/use-render/README.md | 16 + packages/react/src/use-render/index.ts | 208 ++ packages/react/tsconfig.json | 11 + packages/react/tsup.config.ts | 43 + packages/react/vitest.browser.config.ts | 25 + packages/react/vitest.browser.setup.ts | 4 + packages/react/vitest.config.ts | 19 + packages/shadcn/package.json | 11 +- packages/shadcn/src/tailwind.css | 534 ++++ packages/shadcn/tsup.config.ts | 9 +- pnpm-lock.yaml | 2761 +++++++++++------ 569 files changed, 59332 insertions(+), 1163 deletions(-) create mode 100644 .changeset/moody-files-open.md create mode 100644 .changeset/plenty-cats-allow.md create mode 100644 .github/collect-prerelease-info.js delete mode 100644 .github/version-script-prerelease.js create mode 100644 .github/workflows/browser-tests.yml create mode 100644 RELEASING.md create mode 100644 apps/v4/app/(app)/create/components/create-devtools.tsx create mode 100644 apps/v4/app/(app)/create/lib/devtools.ts create mode 100644 apps/v4/components/markdown.tsx create mode 100644 apps/v4/components/message-animated.tsx create mode 100644 apps/v4/components/message-parts.tsx create mode 100644 apps/v4/content/docs/changelog/2026-06-chat-components.mdx create mode 100644 apps/v4/content/docs/components/base/attachment.mdx create mode 100644 apps/v4/content/docs/components/base/bubble.mdx create mode 100644 apps/v4/content/docs/components/base/marker.mdx create mode 100644 apps/v4/content/docs/components/base/message-scroller.mdx create mode 100644 apps/v4/content/docs/components/base/message.mdx create mode 100644 apps/v4/content/docs/components/radix/attachment.mdx create mode 100644 apps/v4/content/docs/components/radix/bubble.mdx create mode 100644 apps/v4/content/docs/components/radix/marker.mdx create mode 100644 apps/v4/content/docs/components/radix/message-scroller.mdx create mode 100644 apps/v4/content/docs/components/radix/message.mdx create mode 100644 apps/v4/content/docs/react/index.mdx create mode 100644 apps/v4/content/docs/react/message-scroller.mdx create mode 100644 apps/v4/content/docs/react/meta.json create mode 100644 apps/v4/content/docs/utils/meta.json create mode 100644 apps/v4/content/docs/utils/scroll-fade.mdx create mode 100644 apps/v4/content/docs/utils/shimmer.mdx create mode 100644 apps/v4/examples/base/attachment-demo.tsx create mode 100644 apps/v4/examples/base/attachment-group.tsx create mode 100644 apps/v4/examples/base/attachment-image.tsx create mode 100644 apps/v4/examples/base/attachment-sizes.tsx create mode 100644 apps/v4/examples/base/attachment-states.tsx create mode 100644 apps/v4/examples/base/attachment-trigger.tsx create mode 100644 apps/v4/examples/base/bubble-alignment.tsx create mode 100644 apps/v4/examples/base/bubble-collapsible.tsx create mode 100644 apps/v4/examples/base/bubble-demo.tsx create mode 100644 apps/v4/examples/base/bubble-group-demo.tsx create mode 100644 apps/v4/examples/base/bubble-link-button.tsx create mode 100644 apps/v4/examples/base/bubble-markdown.tsx create mode 100644 apps/v4/examples/base/bubble-popover.tsx create mode 100644 apps/v4/examples/base/bubble-reactions.tsx create mode 100644 apps/v4/examples/base/bubble-tooltip.tsx create mode 100644 apps/v4/examples/base/bubble-variants.tsx create mode 100644 apps/v4/examples/base/markdown-demo.tsx create mode 100644 apps/v4/examples/base/marker-border.tsx create mode 100644 apps/v4/examples/base/marker-demo.tsx create mode 100644 apps/v4/examples/base/marker-icon.tsx create mode 100644 apps/v4/examples/base/marker-link-button.tsx create mode 100644 apps/v4/examples/base/marker-separator.tsx create mode 100644 apps/v4/examples/base/marker-shimmer.tsx create mode 100644 apps/v4/examples/base/marker-status.tsx create mode 100644 apps/v4/examples/base/marker-variants.tsx create mode 100644 apps/v4/examples/base/message-actions.tsx create mode 100644 apps/v4/examples/base/message-attachment.tsx create mode 100644 apps/v4/examples/base/message-avatar.tsx create mode 100644 apps/v4/examples/base/message-demo.tsx create mode 100644 apps/v4/examples/base/message-group.tsx create mode 100644 apps/v4/examples/base/message-header-footer.tsx create mode 100644 apps/v4/examples/base/message-markdown.tsx create mode 100644 apps/v4/examples/base/message-scroller-anchoring.tsx create mode 100644 apps/v4/examples/base/message-scroller-animation.tsx create mode 100644 apps/v4/examples/base/message-scroller-commands.tsx create mode 100644 apps/v4/examples/base/message-scroller-demo.tsx create mode 100644 apps/v4/examples/base/message-scroller-group-chat.tsx create mode 100644 apps/v4/examples/base/message-scroller-load-history.tsx create mode 100644 apps/v4/examples/base/message-scroller-opening-position.tsx create mode 100644 apps/v4/examples/base/message-scroller-previous-context.tsx create mode 100644 apps/v4/examples/base/message-scroller-scrollable.tsx create mode 100644 apps/v4/examples/base/message-scroller-state.tsx create mode 100644 apps/v4/examples/base/message-scroller-streaming.tsx create mode 100644 apps/v4/examples/base/message-scroller-visibility.tsx create mode 100644 apps/v4/examples/base/scroll-fade-demo.tsx create mode 100644 apps/v4/examples/base/scroll-fade-edge.tsx create mode 100644 apps/v4/examples/base/scroll-fade-horizontal.tsx create mode 100644 apps/v4/examples/base/scroll-fade-none.tsx create mode 100644 apps/v4/examples/base/scroll-fade-overflow.tsx create mode 100644 apps/v4/examples/base/scroll-fade-rtl.tsx create mode 100644 apps/v4/examples/base/scroll-fade-size.tsx create mode 100644 apps/v4/examples/base/shimmer-angle.tsx create mode 100644 apps/v4/examples/base/shimmer-color.tsx create mode 100644 apps/v4/examples/base/shimmer-demo.tsx create mode 100644 apps/v4/examples/base/shimmer-duration.tsx create mode 100644 apps/v4/examples/base/shimmer-marker.tsx create mode 100644 apps/v4/examples/base/shimmer-none.tsx create mode 100644 apps/v4/examples/base/shimmer-once.tsx create mode 100644 apps/v4/examples/base/shimmer-rtl.tsx create mode 100644 apps/v4/examples/base/shimmer-spread.tsx create mode 100644 apps/v4/examples/radix/attachment-demo.tsx create mode 100644 apps/v4/examples/radix/attachment-group.tsx create mode 100644 apps/v4/examples/radix/attachment-image.tsx create mode 100644 apps/v4/examples/radix/attachment-sizes.tsx create mode 100644 apps/v4/examples/radix/attachment-states.tsx create mode 100644 apps/v4/examples/radix/attachment-trigger.tsx create mode 100644 apps/v4/examples/radix/bubble-alignment.tsx create mode 100644 apps/v4/examples/radix/bubble-collapsible.tsx create mode 100644 apps/v4/examples/radix/bubble-demo.tsx create mode 100644 apps/v4/examples/radix/bubble-group-demo.tsx create mode 100644 apps/v4/examples/radix/bubble-link-button.tsx create mode 100644 apps/v4/examples/radix/bubble-markdown.tsx create mode 100644 apps/v4/examples/radix/bubble-popover.tsx create mode 100644 apps/v4/examples/radix/bubble-reactions.tsx create mode 100644 apps/v4/examples/radix/bubble-tooltip.tsx create mode 100644 apps/v4/examples/radix/bubble-variants.tsx create mode 100644 apps/v4/examples/radix/markdown-demo.tsx create mode 100644 apps/v4/examples/radix/marker-border.tsx create mode 100644 apps/v4/examples/radix/marker-demo.tsx create mode 100644 apps/v4/examples/radix/marker-icon.tsx create mode 100644 apps/v4/examples/radix/marker-link-button.tsx create mode 100644 apps/v4/examples/radix/marker-separator.tsx create mode 100644 apps/v4/examples/radix/marker-shimmer.tsx create mode 100644 apps/v4/examples/radix/marker-status.tsx create mode 100644 apps/v4/examples/radix/marker-variants.tsx create mode 100644 apps/v4/examples/radix/message-actions.tsx create mode 100644 apps/v4/examples/radix/message-attachment.tsx create mode 100644 apps/v4/examples/radix/message-avatar.tsx create mode 100644 apps/v4/examples/radix/message-demo.tsx create mode 100644 apps/v4/examples/radix/message-group.tsx create mode 100644 apps/v4/examples/radix/message-header-footer.tsx create mode 100644 apps/v4/examples/radix/message-markdown.tsx create mode 100644 apps/v4/examples/radix/message-scroller-anchoring.tsx create mode 100644 apps/v4/examples/radix/message-scroller-animation.tsx create mode 100644 apps/v4/examples/radix/message-scroller-commands.tsx create mode 100644 apps/v4/examples/radix/message-scroller-demo.tsx create mode 100644 apps/v4/examples/radix/message-scroller-group-chat.tsx create mode 100644 apps/v4/examples/radix/message-scroller-load-history.tsx create mode 100644 apps/v4/examples/radix/message-scroller-opening-position.tsx create mode 100644 apps/v4/examples/radix/message-scroller-previous-context.tsx create mode 100644 apps/v4/examples/radix/message-scroller-scrollable.tsx create mode 100644 apps/v4/examples/radix/message-scroller-streaming.tsx create mode 100644 apps/v4/examples/radix/message-scroller-visibility.tsx create mode 100644 apps/v4/examples/radix/scroll-fade-demo.tsx create mode 100644 apps/v4/examples/radix/scroll-fade-edge.tsx create mode 100644 apps/v4/examples/radix/scroll-fade-horizontal.tsx create mode 100644 apps/v4/examples/radix/scroll-fade-none.tsx create mode 100644 apps/v4/examples/radix/scroll-fade-overflow.tsx create mode 100644 apps/v4/examples/radix/scroll-fade-rtl.tsx create mode 100644 apps/v4/examples/radix/scroll-fade-size.tsx create mode 100644 apps/v4/examples/radix/shimmer-angle.tsx create mode 100644 apps/v4/examples/radix/shimmer-color.tsx create mode 100644 apps/v4/examples/radix/shimmer-demo.tsx create mode 100644 apps/v4/examples/radix/shimmer-duration.tsx create mode 100644 apps/v4/examples/radix/shimmer-marker.tsx create mode 100644 apps/v4/examples/radix/shimmer-none.tsx create mode 100644 apps/v4/examples/radix/shimmer-once.tsx create mode 100644 apps/v4/examples/radix/shimmer-rtl.tsx create mode 100644 apps/v4/examples/radix/shimmer-spread.tsx create mode 100644 apps/v4/hooks/use-delayed-status.ts create mode 100644 apps/v4/lib/ai.test.ts create mode 100644 apps/v4/lib/ai.ts create mode 100644 apps/v4/lib/message-animations.ts create mode 100644 apps/v4/public/avatars/06.png create mode 100644 apps/v4/public/avatars/07.png create mode 100644 apps/v4/public/avatars/08.png create mode 100644 apps/v4/public/avatars/09.png create mode 100644 apps/v4/public/avatars/10.png create mode 100644 apps/v4/public/r/styles/base-luma/attachment-example.json create mode 100644 apps/v4/public/r/styles/base-luma/attachment.json create mode 100644 apps/v4/public/r/styles/base-luma/bubble-example.json create mode 100644 apps/v4/public/r/styles/base-luma/bubble.json create mode 100644 apps/v4/public/r/styles/base-luma/marker-example.json create mode 100644 apps/v4/public/r/styles/base-luma/marker.json create mode 100644 apps/v4/public/r/styles/base-luma/message-example.json create mode 100644 apps/v4/public/r/styles/base-luma/message-scroller-example.json create mode 100644 apps/v4/public/r/styles/base-luma/message-scroller.json create mode 100644 apps/v4/public/r/styles/base-luma/message.json create mode 100644 apps/v4/public/r/styles/base-lyra/attachment-example.json create mode 100644 apps/v4/public/r/styles/base-lyra/attachment.json create mode 100644 apps/v4/public/r/styles/base-lyra/bubble-example.json create mode 100644 apps/v4/public/r/styles/base-lyra/bubble.json create mode 100644 apps/v4/public/r/styles/base-lyra/marker-example.json create mode 100644 apps/v4/public/r/styles/base-lyra/marker.json create mode 100644 apps/v4/public/r/styles/base-lyra/message-example.json create mode 100644 apps/v4/public/r/styles/base-lyra/message-scroller-example.json create mode 100644 apps/v4/public/r/styles/base-lyra/message-scroller.json create mode 100644 apps/v4/public/r/styles/base-lyra/message.json create mode 100644 apps/v4/public/r/styles/base-maia/attachment-example.json create mode 100644 apps/v4/public/r/styles/base-maia/attachment.json create mode 100644 apps/v4/public/r/styles/base-maia/bubble-example.json create mode 100644 apps/v4/public/r/styles/base-maia/bubble.json create mode 100644 apps/v4/public/r/styles/base-maia/marker-example.json create mode 100644 apps/v4/public/r/styles/base-maia/marker.json create mode 100644 apps/v4/public/r/styles/base-maia/message-example.json create mode 100644 apps/v4/public/r/styles/base-maia/message-scroller-example.json create mode 100644 apps/v4/public/r/styles/base-maia/message-scroller.json create mode 100644 apps/v4/public/r/styles/base-maia/message.json create mode 100644 apps/v4/public/r/styles/base-mira/attachment-example.json create mode 100644 apps/v4/public/r/styles/base-mira/attachment.json create mode 100644 apps/v4/public/r/styles/base-mira/bubble-example.json create mode 100644 apps/v4/public/r/styles/base-mira/bubble.json create mode 100644 apps/v4/public/r/styles/base-mira/marker-example.json create mode 100644 apps/v4/public/r/styles/base-mira/marker.json create mode 100644 apps/v4/public/r/styles/base-mira/message-example.json create mode 100644 apps/v4/public/r/styles/base-mira/message-scroller-example.json create mode 100644 apps/v4/public/r/styles/base-mira/message-scroller.json create mode 100644 apps/v4/public/r/styles/base-mira/message.json create mode 100644 apps/v4/public/r/styles/base-nova/attachment-example.json create mode 100644 apps/v4/public/r/styles/base-nova/attachment.json create mode 100644 apps/v4/public/r/styles/base-nova/bubble-example.json create mode 100644 apps/v4/public/r/styles/base-nova/bubble.json create mode 100644 apps/v4/public/r/styles/base-nova/marker-example.json create mode 100644 apps/v4/public/r/styles/base-nova/marker.json create mode 100644 apps/v4/public/r/styles/base-nova/message-example.json create mode 100644 apps/v4/public/r/styles/base-nova/message-scroller-example.json create mode 100644 apps/v4/public/r/styles/base-nova/message-scroller.json create mode 100644 apps/v4/public/r/styles/base-nova/message.json create mode 100644 apps/v4/public/r/styles/base-rhea/attachment-example.json create mode 100644 apps/v4/public/r/styles/base-rhea/attachment.json create mode 100644 apps/v4/public/r/styles/base-rhea/bubble-example.json create mode 100644 apps/v4/public/r/styles/base-rhea/bubble.json create mode 100644 apps/v4/public/r/styles/base-rhea/marker-example.json create mode 100644 apps/v4/public/r/styles/base-rhea/marker.json create mode 100644 apps/v4/public/r/styles/base-rhea/message-example.json create mode 100644 apps/v4/public/r/styles/base-rhea/message-scroller-example.json create mode 100644 apps/v4/public/r/styles/base-rhea/message-scroller.json create mode 100644 apps/v4/public/r/styles/base-rhea/message.json create mode 100644 apps/v4/public/r/styles/base-sera/attachment-example.json create mode 100644 apps/v4/public/r/styles/base-sera/attachment.json create mode 100644 apps/v4/public/r/styles/base-sera/bubble-example.json create mode 100644 apps/v4/public/r/styles/base-sera/bubble.json create mode 100644 apps/v4/public/r/styles/base-sera/marker-example.json create mode 100644 apps/v4/public/r/styles/base-sera/marker.json create mode 100644 apps/v4/public/r/styles/base-sera/message-example.json create mode 100644 apps/v4/public/r/styles/base-sera/message-scroller-example.json create mode 100644 apps/v4/public/r/styles/base-sera/message-scroller.json create mode 100644 apps/v4/public/r/styles/base-sera/message.json create mode 100644 apps/v4/public/r/styles/base-vega/attachment-example.json create mode 100644 apps/v4/public/r/styles/base-vega/attachment.json create mode 100644 apps/v4/public/r/styles/base-vega/bubble-example.json create mode 100644 apps/v4/public/r/styles/base-vega/bubble.json create mode 100644 apps/v4/public/r/styles/base-vega/marker-example.json create mode 100644 apps/v4/public/r/styles/base-vega/marker.json create mode 100644 apps/v4/public/r/styles/base-vega/message-example.json create mode 100644 apps/v4/public/r/styles/base-vega/message-scroller-example.json create mode 100644 apps/v4/public/r/styles/base-vega/message-scroller.json create mode 100644 apps/v4/public/r/styles/base-vega/message.json create mode 100644 apps/v4/public/r/styles/radix-luma/attachment-example.json create mode 100644 apps/v4/public/r/styles/radix-luma/attachment.json create mode 100644 apps/v4/public/r/styles/radix-luma/bubble-example.json create mode 100644 apps/v4/public/r/styles/radix-luma/bubble.json create mode 100644 apps/v4/public/r/styles/radix-luma/marker-example.json create mode 100644 apps/v4/public/r/styles/radix-luma/marker.json create mode 100644 apps/v4/public/r/styles/radix-luma/message-example.json create mode 100644 apps/v4/public/r/styles/radix-luma/message-scroller-example.json create mode 100644 apps/v4/public/r/styles/radix-luma/message-scroller.json create mode 100644 apps/v4/public/r/styles/radix-luma/message.json create mode 100644 apps/v4/public/r/styles/radix-lyra/attachment-example.json create mode 100644 apps/v4/public/r/styles/radix-lyra/attachment.json create mode 100644 apps/v4/public/r/styles/radix-lyra/bubble-example.json create mode 100644 apps/v4/public/r/styles/radix-lyra/bubble.json create mode 100644 apps/v4/public/r/styles/radix-lyra/marker-example.json create mode 100644 apps/v4/public/r/styles/radix-lyra/marker.json create mode 100644 apps/v4/public/r/styles/radix-lyra/message-example.json create mode 100644 apps/v4/public/r/styles/radix-lyra/message-scroller-example.json create mode 100644 apps/v4/public/r/styles/radix-lyra/message-scroller.json create mode 100644 apps/v4/public/r/styles/radix-lyra/message.json create mode 100644 apps/v4/public/r/styles/radix-maia/attachment-example.json create mode 100644 apps/v4/public/r/styles/radix-maia/attachment.json create mode 100644 apps/v4/public/r/styles/radix-maia/bubble-example.json create mode 100644 apps/v4/public/r/styles/radix-maia/bubble.json create mode 100644 apps/v4/public/r/styles/radix-maia/marker-example.json create mode 100644 apps/v4/public/r/styles/radix-maia/marker.json create mode 100644 apps/v4/public/r/styles/radix-maia/message-example.json create mode 100644 apps/v4/public/r/styles/radix-maia/message-scroller-example.json create mode 100644 apps/v4/public/r/styles/radix-maia/message-scroller.json create mode 100644 apps/v4/public/r/styles/radix-maia/message.json create mode 100644 apps/v4/public/r/styles/radix-mira/attachment-example.json create mode 100644 apps/v4/public/r/styles/radix-mira/attachment.json create mode 100644 apps/v4/public/r/styles/radix-mira/bubble-example.json create mode 100644 apps/v4/public/r/styles/radix-mira/bubble.json create mode 100644 apps/v4/public/r/styles/radix-mira/marker-example.json create mode 100644 apps/v4/public/r/styles/radix-mira/marker.json create mode 100644 apps/v4/public/r/styles/radix-mira/message-example.json create mode 100644 apps/v4/public/r/styles/radix-mira/message-scroller-example.json create mode 100644 apps/v4/public/r/styles/radix-mira/message-scroller.json create mode 100644 apps/v4/public/r/styles/radix-mira/message.json create mode 100644 apps/v4/public/r/styles/radix-nova/attachment-example.json create mode 100644 apps/v4/public/r/styles/radix-nova/attachment.json create mode 100644 apps/v4/public/r/styles/radix-nova/bubble-example.json create mode 100644 apps/v4/public/r/styles/radix-nova/bubble.json create mode 100644 apps/v4/public/r/styles/radix-nova/marker-example.json create mode 100644 apps/v4/public/r/styles/radix-nova/marker.json create mode 100644 apps/v4/public/r/styles/radix-nova/message-example.json create mode 100644 apps/v4/public/r/styles/radix-nova/message-scroller-example.json create mode 100644 apps/v4/public/r/styles/radix-nova/message-scroller.json create mode 100644 apps/v4/public/r/styles/radix-nova/message.json create mode 100644 apps/v4/public/r/styles/radix-rhea/attachment-example.json create mode 100644 apps/v4/public/r/styles/radix-rhea/attachment.json create mode 100644 apps/v4/public/r/styles/radix-rhea/bubble-example.json create mode 100644 apps/v4/public/r/styles/radix-rhea/bubble.json create mode 100644 apps/v4/public/r/styles/radix-rhea/marker-example.json create mode 100644 apps/v4/public/r/styles/radix-rhea/marker.json create mode 100644 apps/v4/public/r/styles/radix-rhea/message-example.json create mode 100644 apps/v4/public/r/styles/radix-rhea/message-scroller-example.json create mode 100644 apps/v4/public/r/styles/radix-rhea/message-scroller.json create mode 100644 apps/v4/public/r/styles/radix-rhea/message.json create mode 100644 apps/v4/public/r/styles/radix-sera/attachment-example.json create mode 100644 apps/v4/public/r/styles/radix-sera/attachment.json create mode 100644 apps/v4/public/r/styles/radix-sera/bubble-example.json create mode 100644 apps/v4/public/r/styles/radix-sera/bubble.json create mode 100644 apps/v4/public/r/styles/radix-sera/marker-example.json create mode 100644 apps/v4/public/r/styles/radix-sera/marker.json create mode 100644 apps/v4/public/r/styles/radix-sera/message-example.json create mode 100644 apps/v4/public/r/styles/radix-sera/message-scroller-example.json create mode 100644 apps/v4/public/r/styles/radix-sera/message-scroller.json create mode 100644 apps/v4/public/r/styles/radix-sera/message.json create mode 100644 apps/v4/public/r/styles/radix-vega/attachment-example.json create mode 100644 apps/v4/public/r/styles/radix-vega/attachment.json create mode 100644 apps/v4/public/r/styles/radix-vega/bubble-example.json create mode 100644 apps/v4/public/r/styles/radix-vega/bubble.json create mode 100644 apps/v4/public/r/styles/radix-vega/marker-example.json create mode 100644 apps/v4/public/r/styles/radix-vega/marker.json create mode 100644 apps/v4/public/r/styles/radix-vega/message-example.json create mode 100644 apps/v4/public/r/styles/radix-vega/message-scroller-example.json create mode 100644 apps/v4/public/r/styles/radix-vega/message-scroller.json create mode 100644 apps/v4/public/r/styles/radix-vega/message.json create mode 100644 apps/v4/registry/bases/base/blocks/preview-03/index.tsx create mode 100644 apps/v4/registry/bases/base/examples/attachment-example.tsx create mode 100644 apps/v4/registry/bases/base/examples/bubble-example.tsx create mode 100644 apps/v4/registry/bases/base/examples/marker-example.tsx create mode 100644 apps/v4/registry/bases/base/examples/message-example.tsx create mode 100644 apps/v4/registry/bases/base/examples/message-scroller-example.tsx create mode 100644 apps/v4/registry/bases/base/ui/attachment.tsx create mode 100644 apps/v4/registry/bases/base/ui/bubble.tsx create mode 100644 apps/v4/registry/bases/base/ui/marker.tsx create mode 100644 apps/v4/registry/bases/base/ui/message-scroller.tsx create mode 100644 apps/v4/registry/bases/base/ui/message.tsx create mode 100644 apps/v4/registry/bases/radix/blocks/preview-03/cards/files-chat.tsx create mode 100644 apps/v4/registry/bases/radix/blocks/preview-03/cards/group-chat.tsx create mode 100644 apps/v4/registry/bases/radix/blocks/preview-03/cards/reasoning-chat.tsx create mode 100644 apps/v4/registry/bases/radix/blocks/preview-03/cards/simple-chat.tsx create mode 100644 apps/v4/registry/bases/radix/blocks/preview-03/cards/sources-chat.tsx create mode 100644 apps/v4/registry/bases/radix/blocks/preview-03/cards/tool-chat.tsx create mode 100644 apps/v4/registry/bases/radix/blocks/preview-03/components/part-file.tsx create mode 100644 apps/v4/registry/bases/radix/blocks/preview-03/components/part-reasoning.tsx create mode 100644 apps/v4/registry/bases/radix/blocks/preview-03/components/part-source.tsx create mode 100644 apps/v4/registry/bases/radix/blocks/preview-03/components/part-text.tsx create mode 100644 apps/v4/registry/bases/radix/blocks/preview-03/components/part-tool.tsx create mode 100644 apps/v4/registry/bases/radix/blocks/preview-03/components/prompt-input.tsx create mode 100644 apps/v4/registry/bases/radix/blocks/preview-03/index.tsx create mode 100644 apps/v4/registry/bases/radix/examples/attachment-example.tsx create mode 100644 apps/v4/registry/bases/radix/examples/bubble-example.tsx create mode 100644 apps/v4/registry/bases/radix/examples/marker-example.tsx create mode 100644 apps/v4/registry/bases/radix/examples/message-example.tsx create mode 100644 apps/v4/registry/bases/radix/examples/message-scroller-example.tsx create mode 100644 apps/v4/registry/bases/radix/ui/attachment.tsx create mode 100644 apps/v4/registry/bases/radix/ui/bubble.tsx create mode 100644 apps/v4/registry/bases/radix/ui/marker.tsx create mode 100644 apps/v4/registry/bases/radix/ui/message-scroller.tsx create mode 100644 apps/v4/registry/bases/radix/ui/message.tsx create mode 100644 apps/v4/styles/README.md create mode 100644 apps/v4/styles/base-luma/ui/attachment.tsx create mode 100644 apps/v4/styles/base-luma/ui/bubble.tsx create mode 100644 apps/v4/styles/base-luma/ui/marker.tsx create mode 100644 apps/v4/styles/base-luma/ui/message-scroller.tsx create mode 100644 apps/v4/styles/base-luma/ui/message.tsx create mode 100644 apps/v4/styles/base-lyra/ui/attachment.tsx create mode 100644 apps/v4/styles/base-lyra/ui/bubble.tsx create mode 100644 apps/v4/styles/base-lyra/ui/marker.tsx create mode 100644 apps/v4/styles/base-lyra/ui/message-scroller.tsx create mode 100644 apps/v4/styles/base-lyra/ui/message.tsx create mode 100644 apps/v4/styles/base-maia/ui/attachment.tsx create mode 100644 apps/v4/styles/base-maia/ui/bubble.tsx create mode 100644 apps/v4/styles/base-maia/ui/marker.tsx create mode 100644 apps/v4/styles/base-maia/ui/message-scroller.tsx create mode 100644 apps/v4/styles/base-maia/ui/message.tsx create mode 100644 apps/v4/styles/base-mira/ui/attachment.tsx create mode 100644 apps/v4/styles/base-mira/ui/bubble.tsx create mode 100644 apps/v4/styles/base-mira/ui/marker.tsx create mode 100644 apps/v4/styles/base-mira/ui/message-scroller.tsx create mode 100644 apps/v4/styles/base-mira/ui/message.tsx create mode 100644 apps/v4/styles/base-nova/ui-rtl/attachment.tsx create mode 100644 apps/v4/styles/base-nova/ui-rtl/bubble.tsx create mode 100644 apps/v4/styles/base-nova/ui-rtl/marker.tsx create mode 100644 apps/v4/styles/base-nova/ui-rtl/message-scroller.tsx create mode 100644 apps/v4/styles/base-nova/ui-rtl/message.tsx create mode 100644 apps/v4/styles/base-nova/ui/attachment.tsx create mode 100644 apps/v4/styles/base-nova/ui/bubble.tsx create mode 100644 apps/v4/styles/base-nova/ui/marker.tsx create mode 100644 apps/v4/styles/base-nova/ui/message-scroller.tsx create mode 100644 apps/v4/styles/base-nova/ui/message.tsx create mode 100644 apps/v4/styles/base-rhea/ui/attachment.tsx create mode 100644 apps/v4/styles/base-rhea/ui/bubble.tsx create mode 100644 apps/v4/styles/base-rhea/ui/marker.tsx create mode 100644 apps/v4/styles/base-rhea/ui/message-scroller.tsx create mode 100644 apps/v4/styles/base-rhea/ui/message.tsx create mode 100644 apps/v4/styles/base-sera/ui/attachment.tsx create mode 100644 apps/v4/styles/base-sera/ui/bubble.tsx create mode 100644 apps/v4/styles/base-sera/ui/marker.tsx create mode 100644 apps/v4/styles/base-sera/ui/message-scroller.tsx create mode 100644 apps/v4/styles/base-sera/ui/message.tsx create mode 100644 apps/v4/styles/base-vega/ui/attachment.tsx create mode 100644 apps/v4/styles/base-vega/ui/bubble.tsx create mode 100644 apps/v4/styles/base-vega/ui/marker.tsx create mode 100644 apps/v4/styles/base-vega/ui/message-scroller.tsx create mode 100644 apps/v4/styles/base-vega/ui/message.tsx create mode 100644 apps/v4/styles/radix-luma/ui/attachment.tsx create mode 100644 apps/v4/styles/radix-luma/ui/bubble.tsx create mode 100644 apps/v4/styles/radix-luma/ui/marker.tsx create mode 100644 apps/v4/styles/radix-luma/ui/message-scroller.tsx create mode 100644 apps/v4/styles/radix-luma/ui/message.tsx create mode 100644 apps/v4/styles/radix-lyra/ui/attachment.tsx create mode 100644 apps/v4/styles/radix-lyra/ui/bubble.tsx create mode 100644 apps/v4/styles/radix-lyra/ui/marker.tsx create mode 100644 apps/v4/styles/radix-lyra/ui/message-scroller.tsx create mode 100644 apps/v4/styles/radix-lyra/ui/message.tsx create mode 100644 apps/v4/styles/radix-maia/ui/attachment.tsx create mode 100644 apps/v4/styles/radix-maia/ui/bubble.tsx create mode 100644 apps/v4/styles/radix-maia/ui/marker.tsx create mode 100644 apps/v4/styles/radix-maia/ui/message-scroller.tsx create mode 100644 apps/v4/styles/radix-maia/ui/message.tsx create mode 100644 apps/v4/styles/radix-mira/ui/attachment.tsx create mode 100644 apps/v4/styles/radix-mira/ui/bubble.tsx create mode 100644 apps/v4/styles/radix-mira/ui/marker.tsx create mode 100644 apps/v4/styles/radix-mira/ui/message-scroller.tsx create mode 100644 apps/v4/styles/radix-mira/ui/message.tsx create mode 100644 apps/v4/styles/radix-nova/ui-rtl/attachment.tsx create mode 100644 apps/v4/styles/radix-nova/ui-rtl/bubble.tsx create mode 100644 apps/v4/styles/radix-nova/ui-rtl/marker.tsx create mode 100644 apps/v4/styles/radix-nova/ui-rtl/message-scroller.tsx create mode 100644 apps/v4/styles/radix-nova/ui-rtl/message.tsx create mode 100644 apps/v4/styles/radix-nova/ui/attachment.tsx create mode 100644 apps/v4/styles/radix-nova/ui/bubble.tsx create mode 100644 apps/v4/styles/radix-nova/ui/marker.tsx create mode 100644 apps/v4/styles/radix-nova/ui/message-scroller.tsx create mode 100644 apps/v4/styles/radix-nova/ui/message.tsx create mode 100644 apps/v4/styles/radix-rhea/ui/attachment.tsx create mode 100644 apps/v4/styles/radix-rhea/ui/bubble.tsx create mode 100644 apps/v4/styles/radix-rhea/ui/marker.tsx create mode 100644 apps/v4/styles/radix-rhea/ui/message-scroller.tsx create mode 100644 apps/v4/styles/radix-rhea/ui/message.tsx create mode 100644 apps/v4/styles/radix-sera/ui/attachment.tsx create mode 100644 apps/v4/styles/radix-sera/ui/bubble.tsx create mode 100644 apps/v4/styles/radix-sera/ui/marker.tsx create mode 100644 apps/v4/styles/radix-sera/ui/message-scroller.tsx create mode 100644 apps/v4/styles/radix-sera/ui/message.tsx create mode 100644 apps/v4/styles/radix-vega/ui/attachment.tsx create mode 100644 apps/v4/styles/radix-vega/ui/bubble.tsx create mode 100644 apps/v4/styles/radix-vega/ui/marker.tsx create mode 100644 apps/v4/styles/radix-vega/ui/message-scroller.tsx create mode 100644 apps/v4/styles/radix-vega/ui/message.tsx create mode 100644 packages/react/.gitignore create mode 100644 packages/react/README.md create mode 100644 packages/react/package.json create mode 100644 packages/react/src/message-scroller/PERFORMANCE.md create mode 100644 packages/react/src/message-scroller/README.md create mode 100644 packages/react/src/message-scroller/components.tsx create mode 100644 packages/react/src/message-scroller/geometry.test.ts create mode 100644 packages/react/src/message-scroller/geometry.ts create mode 100644 packages/react/src/message-scroller/index.ts create mode 100644 packages/react/src/message-scroller/message-scroller.browser.test.tsx create mode 100644 packages/react/src/message-scroller/message-scroller.perf.browser.test.tsx create mode 100644 packages/react/src/message-scroller/message-scroller.test.tsx create mode 100644 packages/react/src/message-scroller/stores.ts create mode 100644 packages/react/src/message-scroller/types.ts create mode 100644 packages/react/src/message-scroller/use-message-scroller-commands.ts create mode 100644 packages/react/src/message-scroller/use-message-scroller-controller.ts create mode 100644 packages/react/src/message-scroller/use-message-scroller-refs.ts create mode 100644 packages/react/src/message-scroller/utils.ts create mode 100644 packages/react/src/use-render/README.md create mode 100644 packages/react/src/use-render/index.ts create mode 100644 packages/react/tsconfig.json create mode 100644 packages/react/tsup.config.ts create mode 100644 packages/react/vitest.browser.config.ts create mode 100644 packages/react/vitest.browser.setup.ts create mode 100644 packages/react/vitest.config.ts diff --git a/.changeset/moody-files-open.md b/.changeset/moody-files-open.md new file mode 100644 index 0000000000..9970c60656 --- /dev/null +++ b/.changeset/moody-files-open.md @@ -0,0 +1,5 @@ +--- +"shadcn": minor +--- + +add scroll-fade and shimmer utilities diff --git a/.changeset/plenty-cats-allow.md b/.changeset/plenty-cats-allow.md new file mode 100644 index 0000000000..91bf8c53cd --- /dev/null +++ b/.changeset/plenty-cats-allow.md @@ -0,0 +1,5 @@ +--- +"@shadcn/react": minor +--- + +initial release of @shadcn/react diff --git a/.github/collect-prerelease-info.js b/.github/collect-prerelease-info.js new file mode 100644 index 0000000000..1635213c45 --- /dev/null +++ b/.github/collect-prerelease-info.js @@ -0,0 +1,35 @@ +// Collect the packages that a snapshot prerelease just published, so the +// prerelease comment workflow can render an install line per package. +import { existsSync, readFileSync, readdirSync, writeFileSync } from "node:fs" +import { join } from "node:path" + +const [, , prNumber, channel] = process.argv + +const packagesDir = join(process.cwd(), "packages") +const published = [] + +for (const dir of readdirSync(packagesDir)) { + const pkgPath = join(packagesDir, dir, "package.json") + if (!existsSync(pkgPath)) { + continue + } + + const pkg = JSON.parse(readFileSync(pkgPath, "utf8")) + + // Snapshot versions are stamped `0.0.0--`, so the channel + // marker is how we tell which packages this run actually versioned. + if ( + !pkg.private && + typeof pkg.version === "string" && + pkg.version.includes(`-${channel}`) + ) { + published.push({ name: pkg.name, version: pkg.version }) + } +} + +writeFileSync( + "prerelease-info.json", + JSON.stringify({ pr: prNumber, channel, packages: published }, null, 2) +) + +console.log(`Collected ${published.length} prerelease package(s).`) diff --git a/.github/version-script-prerelease.js b/.github/version-script-prerelease.js deleted file mode 100644 index 3a2dff9b28..0000000000 --- a/.github/version-script-prerelease.js +++ /dev/null @@ -1,37 +0,0 @@ -import fs from "fs" - -const pkgJsonPath = "packages/shadcn/package.json" -const channel = process.argv[2] -const headSha = process.argv[3] - -if (!["beta", "rc"].includes(channel)) { - console.error( - `Expected prerelease channel to be "beta" or "rc", got "${channel}".` - ) - process.exit(1) -} - -if (!headSha) { - console.error("Expected pull request head SHA.") - process.exit(1) -} - -try { - const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, "utf8")) - const shortSha = headSha.trim().slice(0, 7) - const baseVersion = channel === "beta" ? "0.0.0" : pkg.version - - if (channel === "rc" && baseVersion.includes("-")) { - console.error( - `Expected a stable planned version for rc, got "${baseVersion}".` - ) - process.exit(1) - } - - pkg.version = `${baseVersion}-${channel}.${shortSha}` - fs.writeFileSync(pkgJsonPath, JSON.stringify(pkg, null, "\t") + "\n") - console.log(`Prepared shadcn@${pkg.version}`) -} catch (error) { - console.error(error) - process.exit(1) -} diff --git a/.github/workflows/browser-tests.yml b/.github/workflows/browser-tests.yml new file mode 100644 index 0000000000..bf576a1063 --- /dev/null +++ b/.github/workflows/browser-tests.yml @@ -0,0 +1,56 @@ +name: Browser tests + +on: + pull_request: + branches: ["*"] + paths: + - "packages/react/**" + - ".github/workflows/browser-tests.yml" + +jobs: + browser: + runs-on: ubuntu-latest + name: pnpm test:browser + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Install Node.js + uses: actions/setup-node@v3 + with: + node-version: 20 + + - uses: pnpm/action-setup@v4 + name: Install pnpm + id: pnpm-install + with: + version: 10.33.4 + run_install: false + + - name: Get pnpm store directory + id: pnpm-cache + run: | + echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT + - uses: actions/cache@v3 + name: Setup pnpm cache + with: + path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + - name: Install dependencies + run: pnpm install + + - name: Cache Playwright browsers + uses: actions/cache@v3 + with: + path: ~/.cache/ms-playwright + key: ${{ runner.os }}-playwright-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-playwright- + + - name: Install Playwright Chromium + run: pnpm --filter=@shadcn/react exec playwright install --with-deps chromium + + - run: pnpm --filter=@shadcn/react test:browser diff --git a/.github/workflows/code-check.yml b/.github/workflows/code-check.yml index 10f522772c..7c502f2477 100644 --- a/.github/workflows/code-check.yml +++ b/.github/workflows/code-check.yml @@ -78,7 +78,7 @@ jobs: run: pnpm install - name: Build packages - run: pnpm --filter=shadcn build + run: pnpm build:packages - run: pnpm format:check @@ -117,6 +117,6 @@ jobs: run: pnpm install - name: Build packages - run: pnpm --filter=shadcn build + run: pnpm build:packages - run: pnpm typecheck diff --git a/.github/workflows/prerelease-comment.yml b/.github/workflows/prerelease-comment.yml index 701d1af8d0..b029d481b0 100644 --- a/.github/workflows/prerelease-comment.yml +++ b/.github/workflows/prerelease-comment.yml @@ -16,50 +16,64 @@ jobs: runs-on: ubuntu-latest name: Write comment to the PR steps: - - name: "Comment on PR" + # Stable pushes and no-changeset runs upload no artifact, so a missing + # download is expected — gate the rest of the job on it succeeding. + - name: Download prerelease info + id: download + continue-on-error: true + uses: actions/download-artifact@v4 + with: + name: prerelease-info + run-id: ${{ github.event.workflow_run.id }} + github-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Build comment + id: info + if: steps.download.outcome == 'success' uses: actions/github-script@v7 with: - github-token: ${{ secrets.GITHUB_TOKEN }} script: | - const allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({ - owner: context.repo.owner, - repo: context.repo.repo, - run_id: context.payload.workflow_run.id, - }); + const fs = require("fs"); + const info = JSON.parse(fs.readFileSync("prerelease-info.json", "utf8")); - for (const artifact of allArtifacts.data.artifacts) { - // Extract the PR number and package version from the artifact name - const match = /^npm-package-shadcn@(.*?)-pr-(\d+)/.exec(artifact.name); - - if (match) { - const version = match[1]; - const channel = version.includes("-rc.") ? "rc" : "beta"; - require("fs").appendFileSync( - process.env.GITHUB_ENV, - `\nPRERELEASE_PACKAGE_VERSION=${version}` + - `\nPRERELEASE_CHANNEL=${channel}` + - `\nPRERELEASE_LABEL=release: ${channel}` + - `\nWORKFLOW_RUN_PR=${match[2]}` + - `\nWORKFLOW_RUN_ID=${context.payload.workflow_run.id}` - ); - break; - } + if (!info.packages || info.packages.length === 0) { + core.info("No prerelease packages to comment."); + return; } - - name: "Comment on PR with Link" + const installs = info.packages + .map((p) => `pnpm dlx ${p.name}@${p.version}`) + .join("\n"); + const links = info.packages + .map( + (p) => + `- [${p.name}@${p.version}](https://www.npmjs.com/package/${p.name}/v/${p.version})` + ) + .join("\n"); + + const body = [ + `A new ${info.channel} prerelease is available for testing:`, + "", + "```sh", + installs, + "```", + "", + links, + ].join("\n"); + + core.setOutput("pr", info.pr); + core.setOutput("channel", info.channel); + core.setOutput("body", body); + + - name: Comment on PR + if: steps.info.outputs.body uses: marocchino/sticky-pull-request-comment@v2 with: - number: ${{ env.WORKFLOW_RUN_PR }} - message: | - A new ${{ env.PRERELEASE_CHANNEL }} prerelease is available for testing: + number: ${{ steps.info.outputs.pr }} + message: ${{ steps.info.outputs.body }} - ```sh - pnpm dlx shadcn@${{ env.PRERELEASE_PACKAGE_VERSION }} - ``` - - View on npm: https://www.npmjs.com/package/shadcn/v/${{ env.PRERELEASE_PACKAGE_VERSION }} - - - name: "Remove the prerelease label once published" + - name: Remove the prerelease label once published + if: steps.info.outputs.pr uses: actions/github-script@v7 with: github-token: ${{ secrets.GITHUB_TOKEN }} @@ -68,8 +82,8 @@ jobs: await github.rest.issues.removeLabel({ owner: context.repo.owner, repo: context.repo.repo, - issue_number: '${{ env.WORKFLOW_RUN_PR }}', - name: '${{ env.PRERELEASE_LABEL }}', + issue_number: Number("${{ steps.info.outputs.pr }}"), + name: `release: ${{ steps.info.outputs.channel }}`, }); } catch (error) { if (error.status !== 404) { diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bf42298067..de2488d863 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -46,21 +46,8 @@ jobs: ); } - const selected = selectedLabels[0]; - const pullRequest = context.payload.pull_request; - - if ( - selected.channel === "rc" && - (pullRequest.head.ref !== "changeset-release/main" || - pullRequest.title !== "chore(release): version packages") - ) { - throw new Error( - "The release: rc label can only be used on the Changesets version PR from changeset-release/main." - ); - } - - core.setOutput("channel", selected.channel); - core.setOutput("label", selected.name); + core.setOutput("channel", selectedLabels[0].channel); + core.setOutput("label", selectedLabels[0].name); - name: Checkout Repo uses: actions/checkout@v4 @@ -86,37 +73,49 @@ jobs: - name: Install NPM Dependencies run: pnpm install - - name: Modify package.json version - run: node .github/version-script-prerelease.js ${{ steps.prerelease.outputs.channel }} ${{ github.event.pull_request.head.sha }} - - - name: get-npm-version - id: package-version - uses: martinbeentjes/npm-get-version-action@main - with: - path: packages/shadcn - - - name: Check package version on NPM - id: package-exists + # A snapshot prerelease needs changesets to compute versions. The + # Changesets version PR consumes them, so a label on that PR is a no-op. + - name: Check for changesets + id: changesets run: | - if npm view "shadcn@${{ steps.package-version.outputs.current-version }}" version >/dev/null 2>&1; then - echo "exists=true" >> "$GITHUB_OUTPUT" - else - echo "exists=false" >> "$GITHUB_OUTPUT" - fi + shopt -s nullglob + present=false + for file in .changeset/*.md; do + if [ "$(basename "$file")" != "README.md" ]; then + present=true + break + fi + done + echo "present=$present" >> "$GITHUB_OUTPUT" - - name: Publish Prerelease to NPM - if: ${{ steps.package-exists.outputs.exists == 'false' }} - run: pnpm pub:${{ steps.prerelease.outputs.channel }} + - name: No changesets to prerelease + if: steps.changesets.outputs.present == 'false' + run: echo "::notice::No changesets found on this branch; nothing to prerelease." - - name: Build packaged artifact - if: ${{ steps.package-exists.outputs.exists == 'true' }} - run: pnpm shadcn:build + # Snapshot versions are stamped per run (timestamped), so each publish is + # unique and can never collide with a real release on the latest tag. + - name: Version snapshot + if: steps.changesets.outputs.present == 'true' + run: pnpm exec changeset version --snapshot ${{ steps.prerelease.outputs.channel }} - - name: Upload packaged artifact + - name: Build packages + if: steps.changesets.outputs.present == 'true' + run: pnpm build:packages + + - name: Publish snapshot to NPM + if: steps.changesets.outputs.present == 'true' + run: pnpm exec changeset publish --tag ${{ steps.prerelease.outputs.channel }} --no-git-tag + + - name: Collect prerelease info + if: steps.changesets.outputs.present == 'true' + run: node .github/collect-prerelease-info.js "${{ github.event.number }}" "${{ steps.prerelease.outputs.channel }}" + + - name: Upload prerelease info + if: steps.changesets.outputs.present == 'true' uses: actions/upload-artifact@v4 with: - name: npm-package-shadcn@${{ steps.package-version.outputs.current-version }}-pr-${{ github.event.number }} # encode the PR number into the artifact name - path: packages/shadcn/dist/index.js + name: prerelease-info + path: prerelease-info.json release: if: ${{ github.event_name == 'push' && github.repository_owner == 'shadcn-ui' }} @@ -151,11 +150,10 @@ jobs: - name: Install NPM Dependencies run: pnpm install - # - name: Check for errors - # run: pnpm check - - - name: Build the package - run: pnpm shadcn:build + # Builds every publishable package under packages/* (shadcn, @shadcn/react), + # never apps/v4, so each dist is fresh before changeset publish. + - name: Build the packages + run: pnpm build:packages - name: Import GPG key uses: crazy-max/ghaction-import-gpg@v6 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 382aff4822..3fc475eb9a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -46,3 +46,39 @@ jobs: run: pnpm install - run: pnpm test + + react: + runs-on: ubuntu-latest + name: pnpm test (@shadcn/react) + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Install Node.js + uses: actions/setup-node@v3 + with: + node-version: 22 + + - uses: pnpm/action-setup@v4 + name: Install pnpm + id: pnpm-install + with: + version: 10.33.4 + run_install: false + + - name: Get pnpm store directory + id: pnpm-cache + run: | + echo "pnpm_cache_dir=$(pnpm store path)" >> $GITHUB_OUTPUT + - uses: actions/cache@v3 + name: Setup pnpm cache + with: + path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} + key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} + restore-keys: | + ${{ runner.os }}-pnpm-store- + - name: Install dependencies + run: pnpm install + + - run: pnpm --filter=@shadcn/react test diff --git a/.gitignore b/.gitignore index 8e9abde081..b74fbde78d 100644 --- a/.gitignore +++ b/.gitignore @@ -45,4 +45,11 @@ tsconfig.tsbuildinfo .playwright-mcp .playwright-cli shadcn-workspace + +# vitest browser mode writes these only on test failure. +__screenshots__ .codex-artifacts +.tmp* + +CONTEXT.md +docs/adr diff --git a/.vscode/settings.json b/.vscode/settings.json index d72f5636fc..0cea827432 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -15,6 +15,7 @@ "search.exclude": { "apps/v4/registry/radix-*": true, "apps/v4/public/r/*": true, - "packages/shadcn/test/fixtures/*": true + "packages/shadcn/test/fixtures/*": true, + "apps/v4/styles/*": true } } diff --git a/RELEASING.md b/RELEASING.md new file mode 100644 index 0000000000..14947c9a89 --- /dev/null +++ b/RELEASING.md @@ -0,0 +1,59 @@ +# Releasing + +This monorepo publishes two packages independently with [Changesets](https://github.com/changesets/changesets): + +- **`shadcn`** — the CLI and tooling. +- **`@shadcn/react`** — headless React primitives. + +They version on their own lines. A change to one never bumps the other unless a changeset says so. + +## 1. Add a changeset + +Every change that should publish needs a changeset. Run: + +```sh +pnpm changeset +``` + +Select the affected package(s) and bump level. One PR can carry separate changesets for `shadcn` and `@shadcn/react` at different levels. A PR with no changeset publishes nothing. + +## 2. Stable release + +Stable releases are automated by `.github/workflows/release.yml` (the `release` job, on push to `main`): + +1. Merged changesets accumulate on `main`. +2. The Changesets action opens/updates a **"Version Packages"** PR that bumps versions and writes changelogs. +3. Merging that PR triggers `changeset publish`, which builds all packages (`pnpm build:packages`) and publishes any whose version is ahead of npm — each to the `latest` tag. + +`pnpm build:packages` (`turbo run build --filter=./packages/*`) builds `shadcn` and `@shadcn/react` but never `apps/v4`. + +## 3. Prereleases (per-PR snapshots) + +Add the **`release: beta`** or **`release: rc`** label to a PR. The `prerelease` job in `release.yml`: + +1. Verifies the branch has changesets (a label on the version PR is a no-op, since it consumed them). +2. Runs `changeset version --snapshot ` — stamps a unique `0.0.0--` on each changeset'd package. +3. Builds and runs `changeset publish --tag --no-git-tag`. +4. Uploads the published package list; `prerelease-comment.yml` posts a `pnpm dlx` install line per package and removes the label. + +The label selects the **dist-tag/channel**; the **changesets on the branch** select which packages publish. Snapshots are timestamped, so they never touch `latest` and never collide. + +```sh +# Install a snapshot from the PR comment, e.g.: +pnpm dlx @shadcn/react@0.0.0-beta-20260624120000 +``` + +## 4. Prerelease trains (sustained `-beta.N` / `-rc.N`) + +For a baking release line (e.g. `1.0.0-rc.0`, `-rc.1`, …) rather than throwaway snapshots, use Changesets pre mode: + +```sh +pnpm changeset pre enter rc # writes .changeset/pre.json +# ...normal changeset + Version PR cycle now produces -rc.N versions on the rc tag... +pnpm changeset pre exit # back to stable; next Version PR ships X.Y.Z on latest +``` + +## Notes + +- `pnpm-workspace.yaml` sets `minimumReleaseAge: 2880` (48h), so freshly published stable/beta versions take time to resolve in normal installs. Use `pnpm dlx @` to test immediately. +- Publishing uses npm OIDC/provenance (`id-token: write` + `npm@latest`); no `NPM_TOKEN` secret is needed. diff --git a/apps/v4/.gitignore b/apps/v4/.gitignore index db9ea2f256..a6d58dfea0 100644 --- a/apps/v4/.gitignore +++ b/apps/v4/.gitignore @@ -46,3 +46,4 @@ next-env.d.ts .contentlayer .content-collections .source +.devtools diff --git a/apps/v4/app/(app)/(root)/cards/contribution-history.tsx b/apps/v4/app/(app)/(root)/cards/contribution-history.tsx index 33a9eba8d3..63107debcf 100644 --- a/apps/v4/app/(app)/(root)/cards/contribution-history.tsx +++ b/apps/v4/app/(app)/(root)/cards/contribution-history.tsx @@ -17,7 +17,6 @@ const chartData = [ { month: "Feb", amount: 900 }, { month: "Mar", amount: 1300 }, { month: "Apr", amount: 750 }, - { month: "May", amount: 1400 }, ] export function ContributionHistory() { @@ -35,13 +34,14 @@ export function ContributionHistory() { role="img" aria-label="Last 6 months of contribution activity" > - {chartData.map((item) => ( + {chartData.map((item, index) => (
diff --git a/apps/v4/app/(app)/(root)/cards/index.tsx b/apps/v4/app/(app)/(root)/cards/index.tsx index 063f736a09..939f6207a6 100644 --- a/apps/v4/app/(app)/(root)/cards/index.tsx +++ b/apps/v4/app/(app)/(root)/cards/index.tsx @@ -1,3 +1,5 @@ +import { MessageScrollerDemo } from "@/examples/radix/message-scroller-demo" + import { AccountAccess } from "./account-access" import { AnalyticsCard } from "./analytics-card" import { ClaimableBalance } from "./claimable-balance" @@ -79,7 +81,7 @@ export function CardsDemo() { return (
@@ -93,17 +95,20 @@ export function CardsDemo() {
-
+
- +
+ +
+ {/* */}
-
+
diff --git a/apps/v4/app/(app)/(root)/cards/ui-elements.tsx b/apps/v4/app/(app)/(root)/cards/ui-elements.tsx index df6225eb05..a82a502072 100644 --- a/apps/v4/app/(app)/(root)/cards/ui-elements.tsx +++ b/apps/v4/app/(app)/(root)/cards/ui-elements.tsx @@ -117,7 +117,7 @@ export function UIElements() { Dialog - + Allow accessory to connect? diff --git a/apps/v4/app/(app)/create/components/create-devtools.tsx b/apps/v4/app/(app)/create/components/create-devtools.tsx new file mode 100644 index 0000000000..1cb68aa89b --- /dev/null +++ b/apps/v4/app/(app)/create/components/create-devtools.tsx @@ -0,0 +1,72 @@ +"use client" + +import * as React from "react" + +import { BASES } from "@/registry/config" +import { Button } from "@/registry/new-york-v4/ui/button" +import { getDocsPathForItem } from "@/app/(app)/create/lib/devtools" +import { + serializeDesignSystemSearchParams, + useDesignSystemSearchParams, +} from "@/app/(app)/create/lib/search-params" + +export function CreateDevtools() { + const [params, setParams] = useDesignSystemSearchParams() + + const previewUrl = React.useMemo( + () => + serializeDesignSystemSearchParams( + `/preview/${params.base}/${params.item}`, + params + ), + [params] + ) + + const docsUrl = React.useMemo( + () => getDocsPathForItem(params.base, params.item), + [params.base, params.item] + ) + + if (process.env.NODE_ENV === "production") { + return null + } + + return ( +
+ {BASES.map((base) => ( + + ))} +
+ + + ) +} diff --git a/apps/v4/app/(app)/create/components/customizer.tsx b/apps/v4/app/(app)/create/components/customizer.tsx index 1030bd0468..f6749e4c60 100644 --- a/apps/v4/app/(app)/create/components/customizer.tsx +++ b/apps/v4/app/(app)/create/components/customizer.tsx @@ -6,6 +6,7 @@ import { type RegistryItem } from "shadcn/schema" import { useIsMobile } from "@/hooks/use-mobile" import { getThemesForBaseColor, STYLES } from "@/registry/config" +import { Button } from "@/styles/base-nova/ui/button" import { Card, CardContent, @@ -32,11 +33,22 @@ import { ThemePicker } from "@/app/(app)/create/components/theme-picker" import { FONT_HEADING_OPTIONS, FONTS } from "@/app/(app)/create/lib/fonts" import { useDesignSystemSearchParams } from "@/app/(app)/create/lib/search-params" -// Only visible when user clicks "Create Project". -const ProjectForm = dynamic(() => - import("@/app/(app)/create/components/project-form").then( - (m) => m.ProjectForm - ) +// Only visible when user clicks "Create Project". Rendered client-only to +// avoid a useId hydration mismatch on the Base UI dialog trigger. The loading +// placeholder mirrors the trigger button exactly so there is no layout shift. +const ProjectForm = dynamic( + () => + import("@/app/(app)/create/components/project-form").then( + (m) => m.ProjectForm + ), + { + ssr: false, + loading: () => ( + + ), + } ) export function Customizer({ diff --git a/apps/v4/app/(app)/create/components/preview.tsx b/apps/v4/app/(app)/create/components/preview.tsx index f2ad78c611..073bd7b5f0 100644 --- a/apps/v4/app/(app)/create/components/preview.tsx +++ b/apps/v4/app/(app)/create/components/preview.tsx @@ -3,6 +3,7 @@ import * as React from "react" import { CMD_K_FORWARD_TYPE } from "@/app/(app)/create/components/action-menu" +import { CreateDevtools } from "@/app/(app)/create/components/create-devtools" import { REDO_FORWARD_TYPE, UNDO_FORWARD_TYPE, @@ -160,6 +161,7 @@ export function Preview() { title="Preview" />
+
) diff --git a/apps/v4/app/(app)/create/lib/devtools.ts b/apps/v4/app/(app)/create/lib/devtools.ts new file mode 100644 index 0000000000..be85bd15a5 --- /dev/null +++ b/apps/v4/app/(app)/create/lib/devtools.ts @@ -0,0 +1,10 @@ +import { type BaseName } from "@/registry/config" + +export function getDocsPathForItem(base: BaseName, item: string) { + if (item.endsWith("-example")) { + const component = item.slice(0, -"-example".length) + return `/docs/components/${base}/${component}` + } + + return "/docs/components" +} diff --git a/apps/v4/app/(app)/docs/[[...slug]]/page.tsx b/apps/v4/app/(app)/docs/[[...slug]]/page.tsx index 8c8165aa7b..bc17d0e3f7 100644 --- a/apps/v4/app/(app)/docs/[[...slug]]/page.tsx +++ b/apps/v4/app/(app)/docs/[[...slug]]/page.tsx @@ -185,7 +185,7 @@ export default async function Page(props: {
{doc.toc?.length ? ( -
+
) : null} diff --git a/apps/v4/app/(create)/preview/[base]/[name]/page.tsx b/apps/v4/app/(create)/preview/[base]/[name]/page.tsx index e5a795ff59..716f80df9a 100644 --- a/apps/v4/app/(create)/preview/[base]/[name]/page.tsx +++ b/apps/v4/app/(create)/preview/[base]/[name]/page.tsx @@ -16,6 +16,7 @@ import { RandomizeScript } from "@/app/(app)/create/components/random-button" import { getBaseComponent, getBaseItem } from "@/app/(app)/create/lib/api" import "@/app/style-registry.css" +import "streamdown/styles.css" export const revalidate = false export const dynamic = "force-static" diff --git a/apps/v4/app/globals.css b/apps/v4/app/globals.css index 980953ca96..78f40c70b1 100644 --- a/apps/v4/app/globals.css +++ b/apps/v4/app/globals.css @@ -3,6 +3,8 @@ @import "shadcn/tailwind.css"; @import "./legacy-themes.css"; +@source "../node_modules/streamdown/dist/*.js"; + @custom-variant style-vega (&:where(.style-vega *)); @custom-variant style-nova (&:where(.style-nova *)); @custom-variant style-lyra (&:where(.style-lyra *)); diff --git a/apps/v4/app/legacy-themes.css b/apps/v4/app/legacy-themes.css index a6596bf178..4e450a7911 100644 --- a/apps/v4/app/legacy-themes.css +++ b/apps/v4/app/legacy-themes.css @@ -563,3 +563,74 @@ --sidebar-ring: oklch(0.556 0 0); } } + +.theme-blue { + --background: oklch(1 0 0); + --foreground: oklch(0.145 0 0); + --card: oklch(1 0 0); + --card-foreground: oklch(0.145 0 0); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.145 0 0); + --primary: oklch(0.488 0.243 264.376); + --primary-foreground: oklch(0.97 0.014 254.604); + --secondary: oklch(0.967 0.001 286.375); + --secondary-foreground: oklch(0.21 0.006 285.885); + --muted: oklch(0.97 0 0); + --muted-foreground: oklch(0.556 0 0); + --accent: oklch(0.97 0 0); + --accent-foreground: oklch(0.205 0 0); + --destructive: oklch(0.577 0.245 27.325); + --border: oklch(0.922 0 0); + --input: oklch(0.922 0 0); + --ring: oklch(0.708 0 0); + --chart-1: oklch(0.809 0.105 251.813); + --chart-2: oklch(0.623 0.214 259.815); + --chart-3: oklch(0.546 0.245 262.881); + --chart-4: oklch(0.488 0.243 264.376); + --chart-5: oklch(0.424 0.199 265.638); + --radius: 0.625rem; + --sidebar: oklch(0.985 0 0); + --sidebar-foreground: oklch(0.145 0 0); + --sidebar-primary: oklch(0.546 0.245 262.881); + --sidebar-primary-foreground: oklch(0.97 0.014 254.604); + --sidebar-accent: oklch(0.97 0 0); + --sidebar-accent-foreground: oklch(0.205 0 0); + --sidebar-border: oklch(0.922 0 0); + --sidebar-ring: oklch(0.708 0 0); + --selection: oklch(0.93 0.03 256); + --selection-foreground: oklch(0.145 0 0); + + @variant dark { + --background: oklch(0.145 0 0); + --foreground: oklch(0.985 0 0); + --card: oklch(0.205 0 0); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.205 0 0); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.424 0.199 265.638); + --primary-foreground: oklch(0.97 0.014 254.604); + --secondary: oklch(0.274 0.006 286.033); + --secondary-foreground: oklch(0.985 0 0); + --muted: oklch(0.269 0 0); + --muted-foreground: oklch(0.708 0 0); + --accent: oklch(0.269 0 0); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.704 0.191 22.216); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 15%); + --ring: oklch(0.556 0 0); + --chart-1: oklch(0.809 0.105 251.813); + --chart-2: oklch(0.623 0.214 259.815); + --chart-3: oklch(0.546 0.245 262.881); + --chart-4: oklch(0.488 0.243 264.376); + --chart-5: oklch(0.424 0.199 265.638); + --sidebar: oklch(0.205 0 0); + --sidebar-foreground: oklch(0.985 0 0); + --sidebar-primary: oklch(0.623 0.214 259.815); + --sidebar-primary-foreground: oklch(0.97 0.014 254.604); + --sidebar-accent: oklch(0.269 0 0); + --sidebar-accent-foreground: oklch(0.985 0 0); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.556 0 0); + } +} diff --git a/apps/v4/components/announcement.tsx b/apps/v4/components/announcement.tsx index dec4ed7efb..de967c4754 100644 --- a/apps/v4/components/announcement.tsx +++ b/apps/v4/components/announcement.tsx @@ -6,8 +6,8 @@ import { Badge } from "@/registry/new-york-v4/ui/badge" export function Announcement() { return ( - - Introducing GitHub Registries + + Components for Chat Interfaces ) diff --git a/apps/v4/components/components-list.tsx b/apps/v4/components/components-list.tsx index 9f81236f08..18a196be7b 100644 --- a/apps/v4/components/components-list.tsx +++ b/apps/v4/components/components-list.tsx @@ -1,33 +1,65 @@ import Link from "next/link" import { PAGES_NEW } from "@/lib/docs" -import { getPagesFromFolder, type PageTreeFolder } from "@/lib/page-tree" +import { + getPagesFromFolder, + type PageTreeFolder, + type PageTreePage, +} from "@/lib/page-tree" + +function ComponentLink({ + component, + showNewIndicator, +}: { + component: PageTreePage + showNewIndicator: boolean +}) { + const isNew = showNewIndicator && PAGES_NEW.includes(component.url) + + return ( + + {component.name} + {isNew && ( + <> + New +