Skip to content

Commit eec6c1a

Browse files
authored
docs: Improve shadcn registry (#9401)
* Fix some tailwind examples * Add registry items to install all components * Update getting started to add all components * fix dist dir
1 parent 0c7746a commit eec6c1a

File tree

13 files changed

+109
-62
lines changed

13 files changed

+109
-62
lines changed

packages/dev/s2-docs/pages/react-aria/CheckboxGroup.mdx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@ export const description = 'Allows a user to select multiple items from a list o
3131
</CheckboxGroup>
3232
```
3333

34-
```tsx render docs={vanillaDocs.exports.CheckboxGroup} links={vanillaDocs.links} props={['label', 'description', 'isDisabled']} initialProps={{label: 'Favorite sports'}} type="tailwind" files={["starters/tailwind/src/Checkbox.tsx"]}
34+
```tsx render docs={vanillaDocs.exports.CheckboxGroup} links={vanillaDocs.links} props={['label', 'description', 'isDisabled']} initialProps={{label: 'Favorite sports'}} type="tailwind" files={["starters/tailwind/src/CheckboxGroup.tsx"]}
3535
"use client";
36-
import {CheckboxGroup, Checkbox} from 'tailwind-starter/Checkbox';
36+
import {CheckboxGroup} from 'tailwind-starter/CheckboxGroup';
37+
import {Checkbox} from 'tailwind-starter/Checkbox';
3738

3839
<CheckboxGroup/* PROPS */>
3940
<Checkbox value="soccer">Soccer</Checkbox>

packages/dev/s2-docs/pages/react-aria/DisclosureGroup.mdx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@ export const description = 'A grouping of related disclosures, sometimes called
3131
</DisclosureGroup>
3232
```
3333

34-
```tsx render docs={vanillaDocs.exports.DisclosureGroup} links={vanillaDocs.links} props={['allowsMultipleExpanded', 'isDisabled']} type="tailwind" files={["starters/tailwind/src/Disclosure.tsx"]}
34+
```tsx render docs={vanillaDocs.exports.DisclosureGroup} links={vanillaDocs.links} props={['allowsMultipleExpanded', 'isDisabled']} type="tailwind" files={["starters/tailwind/src/DisclosureGroup.tsx"]}
3535
"use client";
36-
import {DisclosureGroup, Disclosure, DisclosureHeader, DisclosurePanel} from 'tailwind-starter/Disclosure';
36+
import {DisclosureGroup} from 'tailwind-starter/DisclosureGroup';
37+
import {Disclosure, DisclosureHeader, DisclosurePanel} from 'tailwind-starter/Disclosure';
3738

3839
<DisclosureGroup/* PROPS */>
3940
<Disclosure>

packages/dev/s2-docs/pages/react-aria/FileTrigger.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export const description = 'Allows a user to access the file system with any pre
1212

1313
<PageDescription>{docs.exports.FileTrigger.description}</PageDescription>
1414

15-
```tsx render docs={docs.exports.FileTrigger} links={docs.links} props={['acceptedFileTypes', 'allowsMultiple', 'acceptDirectory', 'defaultCamera']} initialProps={{acceptedFileTypes: ['image/*']}} type="vanilla"
15+
```tsx render docs={docs.exports.FileTrigger} links={docs.links} props={['acceptedFileTypes', 'allowsMultiple', 'acceptDirectory', 'defaultCamera']} initialProps={{acceptedFileTypes: ['image/*']}} type="vanilla" hideShadcn
1616
"use client";
1717
import {FileTrigger} from 'react-aria-components';
1818
import {Button} from 'vanilla-starter/Button';

packages/dev/s2-docs/pages/react-aria/getting-started.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ Install React Aria with your preferred package manager.
2828

2929
## Quick start
3030

31-
The documentation for each component includes vanilla CSS and [Tailwind](https://tailwindcss.com) examples. Copy and paste these into your project and make them your own. You can also download each example as a ZIP or open in StackBlitz.
31+
Copy and paste the CSS or [Tailwind](https://tailwindcss.com) examples into your project and make them your own. You can also download each example as a ZIP, open in StackBlitz, or install with [shadcn](https://ui.shadcn.com/docs/cli).
3232

3333
<ExampleSwitcher>
3434
```tsx render docs={docs.exports.Select} links={docs.links} props={[]} type="vanilla" files={["starters/docs/src/Select.tsx", "starters/docs/src/Select.css"]} showCoachMark
@@ -63,9 +63,9 @@ The documentation for each component includes vanilla CSS and [Tailwind](https:/
6363

6464
### shadcn CLI
6565

66-
Each example can also be installed with the [shadcn](https://ui.shadcn.com/docs/cli) CLI. This will add the component source code, styles, and all dependencies to your project automatically.
66+
Use the [shadcn](https://ui.shadcn.com/docs/cli) CLI to add the example code, styles, and dependencies to your project. Install individual components using the menu on each example, or add all components with the command below.
6767

68-
<ShadcnCommand type="vanilla" component="Select" />
68+
<ShadcnCommand />
6969

7070
### Storybook starter kits
7171

packages/dev/s2-docs/src/ShadcnCommand.tsx

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import Prompt from '@react-spectrum/s2/icons/Prompt';
77
import {RefObject} from 'react';
88
import {useLocalStorage} from './useLocalStorage';
99

10-
export function ShadcnCommand({type, component, preRef}: {type: 'vanilla' | 'tailwind', component: string, preRef?: RefObject<HTMLPreElement | null>}) {
10+
export function ShadcnCommand({type, component, preRef}: {type?: 'vanilla' | 'tailwind', component?: string, preRef?: RefObject<HTMLPreElement | null>}) {
1111
let [packageManager, setPackageManager] = useLocalStorage('packageManager', 'npm');
1212
let command = packageManager;
1313
if (packageManager === 'npm') {
@@ -20,10 +20,12 @@ export function ShadcnCommand({type, component, preRef}: {type: 'vanilla' | 'tai
2020
setPackageManager(String(value));
2121
};
2222

23-
let shadcnType = type === 'vanilla' ? 'css' : type;
23+
let [storedType, setStoredType] = useLocalStorage('style', type || 'Vanilla CSS');
24+
let shadcnType = type === 'vanilla' || storedType === 'Vanilla CSS' ? 'css' : 'tailwind';
25+
let componentName = component ? '-' + component.toLowerCase() : '';
2426
let specifier = process.env.DOCS_ENV === 'prod'
25-
? `@react-aria/${shadcnType}-${component.toLowerCase()}`
26-
: `${getBaseUrl('react-aria')}/registry/${shadcnType}-${component.toLowerCase()}.json`;
27+
? `@react-aria/${shadcnType}${componentName}`
28+
: `${getBaseUrl('react-aria')}/registry/${shadcnType}${componentName}.json`;
2729

2830
let cmd = `${command} shadcn@latest add ${specifier}`;
2931

@@ -37,11 +39,24 @@ export function ShadcnCommand({type, component, preRef}: {type: 'vanilla' | 'tai
3739
flexDirection: 'column',
3840
gap: 16
3941
})}>
40-
<SegmentedControl aria-label="Package manager" selectedKey={packageManager} onSelectionChange={onSelectionChange}>
41-
<SegmentedControlItem id="npm">npm</SegmentedControlItem>
42-
<SegmentedControlItem id="yarn">yarn</SegmentedControlItem>
43-
<SegmentedControlItem id="pnpm">pnpm</SegmentedControlItem>
44-
</SegmentedControl>
42+
<div
43+
className={style({
44+
display: 'flex',
45+
flexWrap: 'wrap',
46+
gap: 16
47+
})}>
48+
<SegmentedControl aria-label="Package manager" selectedKey={packageManager} onSelectionChange={onSelectionChange}>
49+
<SegmentedControlItem id="npm">npm</SegmentedControlItem>
50+
<SegmentedControlItem id="yarn">yarn</SegmentedControlItem>
51+
<SegmentedControlItem id="pnpm">pnpm</SegmentedControlItem>
52+
</SegmentedControl>
53+
{!type &&
54+
<SegmentedControl aria-label="Style" selectedKey={storedType} onSelectionChange={v => setStoredType(String(v))}>
55+
<SegmentedControlItem id="Vanilla CSS">Vanilla CSS</SegmentedControlItem>
56+
<SegmentedControlItem id="Tailwind">Tailwind</SegmentedControlItem>
57+
</SegmentedControl>
58+
}
59+
</div>
4560
<div
4661
className={style({
4762
display: 'flex',

packages/dev/s2-docs/src/VisualExample.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ export interface VisualExampleProps {
105105
align?: 'center' | 'start' | 'end',
106106
acceptOrientation?: boolean,
107107
propsObject?: string,
108-
showCoachMark?: boolean
108+
showCoachMark?: boolean,
109+
hideShadcn?: boolean
109110
}
110111

111112
export interface PropControl extends Omit<TProperty, 'description'> {
@@ -119,7 +120,7 @@ export interface PropControl extends Omit<TProperty, 'description'> {
119120
/**
120121
* Displays a component example with controls for changing the props.
121122
*/
122-
export function VisualExample({component, docs, links, importSource, props, initialProps, controlOptions, files, downloadFiles, code, wide, slots, align, acceptOrientation, type, propsObject, showCoachMark}: VisualExampleProps) {
123+
export function VisualExample({component, docs, links, importSource, props, initialProps, controlOptions, files, downloadFiles, code, wide, slots, align, acceptOrientation, type, propsObject, showCoachMark, hideShadcn}: VisualExampleProps) {
123124
let componentProps = docs.type === 'interface' ? docs : docs.props;
124125
if (componentProps?.type !== 'interface') {
125126
return null;
@@ -188,7 +189,7 @@ export function VisualExample({component, docs, links, importSource, props, init
188189
return (
189190
<VisualExampleClient component={component} name={docs.name} importSource={importSource} controls={controls} initialProps={initialProps} propsObject={propsObject}>
190191
<FileProvider value={downloadFiles}>
191-
<ShadcnProvider value={!type || type === 's2' || docs.type !== 'component' ? null : {type, component: docs.name}}>
192+
<ShadcnProvider value={!type || type === 's2' || docs.type !== 'component' || hideShadcn ? null : {type, component: docs.name}}>
192193
<div role="group" aria-label="Example" className={exampleStyle({layout: files || wide ? 'wide' : 'narrow'})}>
193194
<Output align={align} acceptOrientation={acceptOrientation} />
194195
{props.length > 0 && <div role="group" aria-label="Controls" className={controlsStyle}>

scripts/buildRegistry.mjs

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,15 @@ fs.rmSync(distDir, {recursive: true, force: true});
1313
fs.mkdirSync(distDir, {recursive: true});
1414

1515
let items = [];
16-
17-
for (let file of globSync('starters/tailwind/src/*.{ts,tsx}')) {
16+
let tailwind = {
17+
$schema: 'https://ui.shadcn.com/schema/registry-item.json',
18+
name: 'tailwind',
19+
type: 'registry:style',
20+
registryDependencies: []
21+
};
22+
items.push(tailwind);
23+
24+
for (let file of globSync('starters/tailwind/src/*.{ts,tsx}').sort()) {
1825
let name = path.basename(file, path.extname(file));
1926
let {dependencies, registryDependencies, content} = analyzeDeps(file, 'tailwind');
2027
let type = name === 'utils' ? 'registry:lib' : 'registry:ui';
@@ -45,9 +52,20 @@ for (let file of globSync('starters/tailwind/src/*.{ts,tsx}')) {
4552
}
4653

4754
items.push(item);
55+
tailwind.registryDependencies.push(`${publicUrl}/tailwind-${name.toLowerCase()}.json`);
4856
}
4957

50-
for (let file of globSync('starters/docs/src/*.{ts,tsx}')) {
58+
fs.writeFileSync(path.join(distDir, 'tailwind.json'), JSON.stringify(tailwind, null, 2) + '\n');
59+
60+
let css = {
61+
$schema: 'https://ui.shadcn.com/schema/registry-item.json',
62+
name: 'css',
63+
type: 'registry:style',
64+
registryDependencies: []
65+
};
66+
items.push(css);
67+
68+
for (let file of globSync('starters/docs/src/*.{ts,tsx}').sort()) {
5169
let name = path.basename(file, path.extname(file));
5270
let {dependencies, registryDependencies, content} = analyzeDeps(file, 'css');
5371
let type = name === 'utils' ? 'registry:lib' : 'registry:ui';
@@ -79,8 +97,10 @@ for (let file of globSync('starters/docs/src/*.{ts,tsx}')) {
7997
}
8098

8199
items.push(item);
100+
css.registryDependencies.push(`${publicUrl}/css-${name.toLowerCase()}.json`);
82101
}
83102

103+
fs.writeFileSync(path.join(distDir, 'css.json'), JSON.stringify(css, null, 2) + '\n');
84104
fs.writeFileSync(path.join(distDir, 'registry.json'), JSON.stringify({
85105
'$schema': 'https://ui.shadcn.com/schema/registry.json',
86106
name: 'react-aria',

starters/tailwind/src/Checkbox.tsx

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,9 @@
11
'use client';
22
import { Check, Minus } from 'lucide-react';
3-
import React, { ReactNode } from 'react';
4-
import { Checkbox as AriaCheckbox, CheckboxGroup as AriaCheckboxGroup, CheckboxGroupProps as AriaCheckboxGroupProps, CheckboxProps, ValidationResult, composeRenderProps } from 'react-aria-components';
3+
import React from 'react';
4+
import { Checkbox as AriaCheckbox, CheckboxProps, composeRenderProps } from 'react-aria-components';
55
import { tv } from 'tailwind-variants';
6-
import { Description, FieldError, Label } from './Field';
7-
import { composeTailwindRenderProps, focusRing } from './utils';
8-
9-
export interface CheckboxGroupProps extends Omit<AriaCheckboxGroupProps, 'children'> {
10-
label?: string,
11-
children?: ReactNode,
12-
description?: string;
13-
errorMessage?: string | ((validation: ValidationResult) => string);
14-
}
15-
16-
export function CheckboxGroup(props: CheckboxGroupProps) {
17-
return (
18-
<AriaCheckboxGroup {...props} className={composeTailwindRenderProps(props.className, 'flex flex-col gap-2 font-sans')}>
19-
<Label>{props.label}</Label>
20-
{props.children}
21-
{props.description && <Description>{props.description}</Description>}
22-
<FieldError>{props.errorMessage}</FieldError>
23-
</AriaCheckboxGroup>
24-
);
25-
}
6+
import { focusRing } from './utils';
267

278
const checkboxStyles = tv({
289
base: 'flex gap-2 items-center group font-sans text-sm transition relative [-webkit-tap-highlight-color:transparent]',
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
'use client';
2+
import React, { ReactNode } from 'react';
3+
import { CheckboxGroup as AriaCheckboxGroup, CheckboxGroupProps as AriaCheckboxGroupProps, ValidationResult } from 'react-aria-components';
4+
import { Description, FieldError, Label } from './Field';
5+
import { composeTailwindRenderProps } from './utils';
6+
7+
export interface CheckboxGroupProps extends Omit<AriaCheckboxGroupProps, 'children'> {
8+
label?: string,
9+
children?: ReactNode,
10+
description?: string,
11+
errorMessage?: string | ((validation: ValidationResult) => string)
12+
}
13+
14+
export function CheckboxGroup(props: CheckboxGroupProps) {
15+
return (
16+
<AriaCheckboxGroup {...props} className={composeTailwindRenderProps(props.className, 'flex flex-col gap-2 font-sans')}>
17+
<Label>{props.label}</Label>
18+
{props.children}
19+
{props.description && <Description>{props.description}</Description>}
20+
<FieldError>{props.errorMessage}</FieldError>
21+
</AriaCheckboxGroup>
22+
);
23+
}

starters/tailwind/src/Disclosure.tsx

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
import React, { useContext } from "react";
33
import {
44
Disclosure as AriaDisclosure,
5-
DisclosureGroup as AriaDisclosureGroup,
65
DisclosureProps as AriaDisclosureProps,
7-
DisclosureGroupProps as AriaDisclosureGroupProps,
86
DisclosurePanel as AriaDisclosurePanel,
97
DisclosurePanelProps as AriaDisclosurePanelProps,
108
composeRenderProps,
@@ -81,15 +79,3 @@ export function DisclosurePanel({ children, ...props }: DisclosurePanelProps) {
8179
</AriaDisclosurePanel>
8280
);
8381
}
84-
85-
export interface DisclosureGroupProps extends AriaDisclosureGroupProps {
86-
children: React.ReactNode;
87-
}
88-
89-
export function DisclosureGroup({ children, ...props }: DisclosureGroupProps) {
90-
return (
91-
<AriaDisclosureGroup {...props}>
92-
{children}
93-
</AriaDisclosureGroup>
94-
);
95-
}

0 commit comments

Comments
 (0)