Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/app/docs/docsNavigationSections.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ export const docsNavigationSections = [
{
title:"Large Lists & Virtualization",
path:"/docs/guides/large-lists-and-virtualization"
},
{
title:"Framework Usage",
path:"/docs/guides/framework-usage"
}
]
},
Expand Down
2 changes: 2 additions & 0 deletions docs/app/docs/first-steps/usage/content.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Usage

For framework-specific setup (Vite, Next.js App Router, Remix), see [Framework usage](/docs/guides/framework-usage).

## Importing components
Integrating Rad UI into your project is straightforward. Whether you're looking for a headless library with full flexibility or a quick way to prototype with a default theme, Rad UI has you covered. Here’s how you can get started.

Expand Down
173 changes: 173 additions & 0 deletions docs/app/docs/guides/framework-usage/content.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# Framework usage

Minimal setup patterns for using Rad UI in **Vite**, **Next.js App Router**, and **Remix**.

For SSR pitfalls, see [Troubleshooting](/docs/guides/troubleshooting).

## Shared setup

Install the package:

```bash
npm install @radui/ui
```

Import components from per-component entrypoints:

```tsx
import Button from '@radui/ui/Button'
import Theme from '@radui/ui/Theme'
```

Optional default theme styles:

```tsx
import '@radui/ui/themes/default.css'
```

Wrap interactive UI with `Theme` when you use Rad UI's tokenized styles or generated `classNamespace` classes.

## Vite + React

Vite works with Rad UI out of the box. No special SSR configuration is required for a client-rendered SPA.

```tsx
// src/main.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import '@radui/ui/themes/default.css'

ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App />
</React.StrictMode>
)
```

```tsx
// src/App.tsx
import Theme from '@radui/ui/Theme'
import Button from '@radui/ui/Button'

export default function App() {
return (
<Theme appearance="light" accentColor="indigo">
<Button>Get started</Button>
</Theme>
)
}
```
Comment on lines +39 to +60

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="docs/app/docs/guides/framework-usage/content.mdx"
test -f "$FILE" || { echo "Missing $FILE"; exit 1; }

echo "== file: $FILE =="
sed -n '1,220p' "$FILE" | nl -ba | sed -n '1,220p'

echo
echo "== occurrences of `@radui/ui/themes/default.css` in $FILE =="
rg -n "`@radui/ui/themes/default`\.css" "$FILE" || true

echo
echo "== occurrences of classNamespace in $FILE =="
rg -n "classNamespace" "$FILE" || true

echo
echo "== occurrences of <Theme " in $FILE =="
rg -n "<Theme\b" "$FILE" || true

echo
echo "== show relevant Theme snippets blocks (around 39-60, 71-111, 123-159) =="
python3 - <<'PY'
import itertools,sys
path="docs/app/docs/guides/framework-usage/content.mdx"
ranges=[(30,75),(65,120),(115,175)]
for a,b in ranges:
    print(f"\n--- {path}:{a}-{b} ---")
    with open(path,'r',encoding='utf-8') as f:
        for i,line in enumerate(f, start=1):
            if a<=i<=b:
                print(f"{i:4d}: {line.rstrip()}")
PY

echo
echo "== locate any other files referencing classNamespace for rad-ui theme =="
rg -n "classNamespace=\"rad-ui\"|classNamespace" docs/app/docs -S || true

echo
echo "== locate Theme component docs/usage in repo (if present) =="
rg -n "function App\(" docs/app/docs -S || true

Repository: rad-ui/ui

Length of output: 175


🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="docs/app/docs/guides/framework-usage/content.mdx"
test -f "$FILE" || { echo "Missing $FILE"; exit 1; }

echo "== file: $FILE =="
python3 - <<PY
path="$FILE"
with open(path,'r',encoding='utf-8') as f:
    for i,line in enumerate(f, start=1):
        if i<=220:
            print(f"{i:4d}: {line.rstrip()}")
PY

echo
echo "== occurrences of `@radui/ui/themes/default.css` in $FILE =="
rg -n "`@radui/ui/themes/default`\.css" "$FILE" || true

echo
echo "== occurrences of classNamespace in $FILE =="
rg -n "classNamespace" "$FILE" || true

echo
echo "== occurrences of <Theme\\b in $FILE =="
rg -n "<Theme\\b" "$FILE" || true

echo
echo "== show relevant Theme snippets blocks (around 39-60, 71-111, 123-159) =="
python3 - <<'PY'
path="docs/app/docs/guides/framework-usage/content.mdx"
ranges=[(35,70),(70,120),(120,170)]
with open(path,'r',encoding='utf-8') as f:
    lines=list(f)
for a,b in ranges:
    print(f"\n--- {path}:{a}-{b} ---")
    for i in range(a-1,b):
        if 0<=i<len(lines):
            print(f"{i+1:4d}: {lines[i].rstrip()}")
PY

echo
echo "== locate any other files referencing classNamespace for rad-ui theme =="
rg -n "classNamespace=\"rad-ui\"|classNamespace" docs/app/docs -S || true

echo
echo "== check for rad-ui Theme component usage examples =="
rg -n "<Theme\\b" docs/app/docs -S || true

Repository: rad-ui/ui

Length of output: 12558


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Show classNamespace guidance in first-steps usage
FILE="docs/app/docs/first-steps/usage/content.mdx"
test -f "$FILE" || { echo "Missing $FILE"; exit 1; }

python3 - <<'PY'
path="docs/app/docs/first-steps/usage/content.mdx"
start=40
end=140
with open(path,'r',encoding='utf-8') as f:
    lines=f.readlines()
for i in range(start-1,end):
    if i < len(lines):
        print(f"{i+1:4d}: {lines[i].rstrip()}")
PY

echo "== grep for 'default Rad UI CSS' and 'generated class names' phrases =="
rg -n "default Rad UI CSS|generated class names|class names|match the selectors" docs/app/docs/first-steps/usage/content.mdx -S || true

echo
echo "== Theme docs example_1.tsx =="
FILE2="docs/app/docs/components/theme/docs/example_1.tsx"
test -f "$FILE2" && cat -n "$FILE2" | sed -n '1,120p' || true

echo
echo "== Theme component docs usage in theme anatomy etc (small) =="
FILE3="docs/app/docs/components/theme/docs/anatomy.tsx"
test -f "$FILE3" && cat -n "$FILE3" | sed -n '1,120p' || true

Repository: rad-ui/ui

Length of output: 5113


Add classNamespace="rad-ui" to each Theme wrapper used with @radui/ui/themes/default.css.

In docs/app/docs/guides/framework-usage/content.mdx (Vite, Next.js App Router, and Remix), the examples import/link @radui/ui/themes/default.css, but the <Theme> components omit classNamespace. The Theme docs state that the default theme stylesheet expects generated namespaced classes (e.g. rad-ui-*), and Theme does not add them by default—so the rendered components won’t match the CSS selectors as described. Add classNamespace="rad-ui" to the <Theme> in each snippet (Vite App.tsx, Next providers.tsx, Remix route component).

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

In `@docs/app/docs/guides/framework-usage/content.mdx` around lines 39 - 60, The
Theme wrappers shown alongside the import of '`@radui/ui/themes/default.css`' are
missing the classNamespace prop so the CSS selectors (rad-ui-*) won't match;
update each Theme usage (e.g., the Theme component in the Vite App.tsx example,
the Theme in Next providers.tsx, and the Theme in the Remix route component) to
include classNamespace="rad-ui" (e.g., <Theme classNamespace="rad-ui"
appearance="light" accentColor="indigo">) so generated class names align with
the provided stylesheet.


**Notes**

- Prefer per-component imports for tree-shaking.
- Add your own global styles or Tailwind preset alongside the optional Rad UI theme CSS.

## Next.js App Router

Rad UI components are client-side interaction primitives. Place them in a **Client Component** file.

```tsx
// app/providers.tsx
'use client'

import Theme from '@radui/ui/Theme'

export function Providers({ children }: { children: React.ReactNode }) {
return (
<Theme appearance="system" accentColor="gray">
{children}
</Theme>
)
}
```

```tsx
// app/layout.tsx
import { Providers } from './providers'
import '@radui/ui/themes/default.css'

export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
<Providers>{children}</Providers>
</body>
</html>
)
}
```

```tsx
// app/page.tsx
'use client'

import Button from '@radui/ui/Button'

export default function HomePage() {
return <Button>Save</Button>
}
```

**Notes**

- Import Rad UI only from files marked with `'use client'` when they use state, effects, or event handlers.
- Keep server components free of interactive Rad UI imports unless they only re-export static markup wrappers you control.
- The docs app in this repository is a Next.js App Router consumer and is built in CI for compatibility smoke coverage.

## Remix

Remix can SSR Rad UI markup, but interactive behavior still hydrates on the client.

```tsx
// app/root.tsx
import type { LinksFunction } from '@remix-run/node'
import { Links, Meta, Outlet, Scripts, ScrollRestoration } from '@remix-run/react'
import themeStyles from '@radui/ui/themes/default.css?url'

export const links: LinksFunction = () => [{ rel: 'stylesheet', href: themeStyles }]

export default function App() {
return (
<html lang="en">
<head>
<Meta />
<Links />
</head>
<body>
<Outlet />
<ScrollRestoration />
<Scripts />
</body>
</html>
)
}
```

```tsx
// app/routes/_index.tsx
import Theme from '@radui/ui/Theme'
import Button from '@radui/ui/Button'

export default function Index() {
return (
<Theme appearance="light">
<Button>Continue</Button>
</Theme>
)
}
```

**Notes**

- Load theme CSS through Remix `links` so styles are present on the first server render.
- Avoid reading browser-only APIs during the initial render path.

## Choosing a pattern

| Framework | Rad UI entry | Theme CSS | Client boundary |
| --- | --- | --- | --- |
| Vite SPA | `main.tsx` | import in entry | not required for SPA |
| Next.js App Router | `providers.tsx` + route components | `layout.tsx` | `'use client'` for interactive components |
| Remix | `root.tsx` + routes | `links` export | route components hydrate automatically |
7 changes: 7 additions & 0 deletions docs/app/docs/guides/framework-usage/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { createDocsPage } from '@/components/docsPage/createDocsPage'
import metadata from './seo'
import Content from './content.mdx'

export { metadata }

export default createDocsPage(Content)
8 changes: 8 additions & 0 deletions docs/app/docs/guides/framework-usage/seo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import generateSeoMetadata from '@/utils/seo/generateSeoMetadata'

const frameworkUsageGuideMetadata = generateSeoMetadata({
title: 'Framework usage | Rad UI',
description: 'Minimal Rad UI setup examples for Vite, Next.js App Router, and Remix.'
})

export default frameworkUsageGuideMetadata
Loading