Skip to content
Open
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
2 changes: 1 addition & 1 deletion packages/dev/s2-docs/pages/react-aria/Button.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const tags = ['btn'];
props={['variant', 'isPending', 'isDisabled']}
initialProps={{children: 'Press me'}}
type="tailwind"
files={["starters/tailwind/src/Button.tsx", "starters/tailwind/src/index.css"]} />
files={["starters/tailwind/src/Button.tsx"]} />
{/* <VisualExample
component={MacroButton}
docs={docs.exports.Button}
Expand Down
2 changes: 1 addition & 1 deletion packages/dev/s2-docs/pages/react-aria/Calendar.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const tags = ['date'];
links={vanillaDocs.links}
props={['isDisabled']}
type="tailwind"
files={["starters/tailwind/src/Calendar.tsx", "starters/tailwind/src/index.css"]} />
files={["starters/tailwind/src/Calendar.tsx"]} />
</ExampleSwitcher>

## Value
Expand Down
2 changes: 1 addition & 1 deletion packages/dev/s2-docs/pages/react-aria/Checkbox.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const tags = ['input'];
props={['children', 'isIndeterminate', 'isDisabled']}
initialProps={{children: 'Remember me'}}
type="tailwind"
files={["starters/tailwind/src/Checkbox.tsx", "starters/tailwind/src/index.css"]} />
files={["starters/tailwind/src/Checkbox.tsx"]} />
</ExampleSwitcher>

## Selection
Expand Down
2 changes: 1 addition & 1 deletion packages/dev/s2-docs/pages/react-aria/ColorArea.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const tags = [];
props={['colorSpace', 'xChannel', 'yChannel', 'isDisabled']}
initialProps={{defaultValue: 'hsl(0, 100%, 50%)'}}
type="tailwind"
files={["starters/tailwind/src/ColorArea.tsx", "starters/tailwind/src/ColorThumb.tsx", "starters/tailwind/src/index.css"]} />
files={["starters/tailwind/src/ColorArea.tsx", "starters/tailwind/src/ColorThumb.tsx"]} />
</ExampleSwitcher>

## Value
Expand Down
2 changes: 1 addition & 1 deletion packages/dev/s2-docs/pages/react-aria/ColorField.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const tags = ['input'];
props={['label', 'colorSpace', 'channel', 'description', 'isDisabled']}
initialProps={{label: 'Color', defaultValue: '#ff0000', placeholder: 'Enter a color'}}
type="tailwind"
files={["starters/tailwind/src/ColorField.tsx", "starters/tailwind/src/index.css"]} />
files={["starters/tailwind/src/ColorField.tsx"]} />
</ExampleSwitcher>

## Value
Expand Down
2 changes: 1 addition & 1 deletion packages/dev/s2-docs/pages/react-aria/ColorPicker.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const tags = ['input'];
props={['label']}
initialProps={{label: 'Fill', defaultValue: '#5100FF'}}
type="tailwind"
files={["starters/tailwind/src/ColorPicker.tsx", "starters/tailwind/src/index.css"]} />
files={["starters/tailwind/src/ColorPicker.tsx"]} />
</ExampleSwitcher>

## Value
Expand Down
2 changes: 1 addition & 1 deletion packages/dev/s2-docs/pages/react-aria/ColorSlider.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const tags = ['input'];
props={['label', 'colorSpace', 'channel', 'orientation', 'isDisabled']}
initialProps={{channel: 'hue', defaultValue: 'hsl(0, 100%, 50%)'}}
type="tailwind"
files={["starters/tailwind/src/ColorSlider.tsx", "starters/tailwind/src/ColorThumb.tsx", "starters/tailwind/src/index.css"]} />
files={["starters/tailwind/src/ColorSlider.tsx", "starters/tailwind/src/ColorThumb.tsx"]} />
</ExampleSwitcher>

## Value
Expand Down
2 changes: 1 addition & 1 deletion packages/dev/s2-docs/pages/react-aria/ColorSwatch.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const tags = [];
props={[]}
initialProps={{color: '#f00'}}
type="tailwind"
files={["starters/tailwind/src/ColorSwatch.tsx", "starters/tailwind/src/index.css"]} />
files={["starters/tailwind/src/ColorSwatch.tsx"]} />
</ExampleSwitcher>

## Accessibility
Expand Down
2 changes: 1 addition & 1 deletion packages/dev/s2-docs/pages/react-aria/ColorWheel.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const tags = ['input'];
links={docs.links}
props={['isDisabled']}
type="tailwind"
files={["starters/tailwind/src/ColorWheel.tsx", "starters/tailwind/src/ColorThumb.tsx", "starters/tailwind/src/index.css"]} />
files={["starters/tailwind/src/ColorWheel.tsx", "starters/tailwind/src/ColorThumb.tsx"]} />
</ExampleSwitcher>

## Value
Expand Down
2 changes: 1 addition & 1 deletion packages/dev/s2-docs/pages/react-aria/DateField.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const tags = ['calendar', 'input'];
props={['label', 'granularity', 'isDisabled']}
initialProps={{label: 'Date'}}
type="tailwind"
files={["starters/tailwind/src/DateField.tsx", "starters/tailwind/src/index.css"]} />
files={["starters/tailwind/src/DateField.tsx"]} />
</ExampleSwitcher>

## Value
Expand Down
2 changes: 1 addition & 1 deletion packages/dev/s2-docs/pages/react-aria/Link.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const tags = ['anchor', 'hyperlink', 'href'];
props={['children', 'variant', 'isDisabled']}
initialProps={{children: 'The missing link', href: 'https://www.imdb.com/title/tt6348138/', target: '_blank'}}
type="tailwind"
files={["starters/tailwind/src/Link.tsx", "starters/tailwind/src/index.css"]} />
files={["starters/tailwind/src/Link.tsx"]} />
</ExampleSwitcher>

## Events
Expand Down
2 changes: 1 addition & 1 deletion packages/dev/s2-docs/pages/react-aria/RangeCalendar.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const tags = ['calendar'];
links={vanillaDocs.links}
props={['isDisabled']}
type="tailwind"
files={["starters/tailwind/src/RangeCalendar.tsx", "starters/tailwind/src/index.css"]} />
files={["starters/tailwind/src/RangeCalendar.tsx"]} />
</ExampleSwitcher>

## Value
Expand Down
2 changes: 1 addition & 1 deletion packages/dev/s2-docs/pages/react-aria/SearchField.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const tags = ['input'];
props={['label', 'description', 'isDisabled']}
initialProps={{label: 'Search', placeholder: 'Search documents'}}
type="tailwind"
files={["starters/tailwind/src/SearchField.tsx", "starters/tailwind/src/index.css"]} />
files={["starters/tailwind/src/SearchField.tsx"]} />
</ExampleSwitcher>

## Value
Expand Down
2 changes: 1 addition & 1 deletion packages/dev/s2-docs/pages/react-aria/Switch.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const tags = ['toggle', 'input'];
props={['children', 'isDisabled']}
initialProps={{children: 'Low power mode'}}
type="tailwind"
files={["starters/tailwind/src/Switch.tsx", "starters/tailwind/src/index.css"]} />
files={["starters/tailwind/src/Switch.tsx"]} />
</ExampleSwitcher>

## Selection
Expand Down
2 changes: 1 addition & 1 deletion packages/dev/s2-docs/pages/react-aria/TextField.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const tags = ['input'];
props={['label', 'description', 'isReadOnly', 'isDisabled']}
initialProps={{label: 'Name', placeholder: 'Enter your full name'}}
type="tailwind"
files={["starters/tailwind/src/TextField.tsx", "starters/tailwind/src/index.css"]} />
files={["starters/tailwind/src/TextField.tsx"]} />
</ExampleSwitcher>

## Value
Expand Down
2 changes: 1 addition & 1 deletion packages/dev/s2-docs/pages/react-aria/TimeField.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const tags = ['date', 'input'];
props={['label', 'granularity', 'isDisabled']}
initialProps={{label: 'Time'}}
type="tailwind"
files={["starters/tailwind/src/TimeField.tsx", "starters/tailwind/src/index.css"]} />
files={["starters/tailwind/src/TimeField.tsx"]} />
</ExampleSwitcher>

## Value
Expand Down
2 changes: 1 addition & 1 deletion packages/dev/s2-docs/pages/react-aria/ToggleButton.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const tags = ['button', 'btn'];
props={['isDisabled']}
initialProps={{children: 'Pin'}}
type="tailwind"
files={["starters/tailwind/src/ToggleButton.tsx", "starters/tailwind/src/index.css"]} />
files={["starters/tailwind/src/ToggleButton.tsx"]} />
</ExampleSwitcher>

## Selection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const tags = ['toggle', 'btn'];
</ToggleButtonGroup>
```

```tsx render docs={docs.exports.ToggleButtonGroup} links={docs.links} props={['selectionMode', 'orientation', 'isDisabled']} initialProps={{'aria-label': 'Text style'}} type="tailwind" files={["starters/tailwind/src/ToggleButtonGroup.tsx", "starters/tailwind/src/index.css"]}
```tsx render docs={docs.exports.ToggleButtonGroup} links={docs.links} props={['selectionMode', 'orientation', 'isDisabled']} initialProps={{'aria-label': 'Text style'}} type="tailwind" files={["starters/tailwind/src/ToggleButtonGroup.tsx"]}
"use client";
import {ToggleButtonGroup} from 'tailwind-starter/ToggleButtonGroup';
import {ToggleButton} from 'tailwind-starter/ToggleButton';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const description = 'With autocomplete, virtualized scrolling, and keyboa

<PageDescription>An emoji picker with autocomplete, virtualized scrolling, and arrow key navigation.</PageDescription>

```tsx render dir="react-aria/examples" files={['packages/dev/s2-docs/pages/react-aria/examples/EmojiPicker.css']} type="vanilla" expanded includeAllImports
```tsx render dir="react-aria/examples" files={['packages/dev/s2-docs/pages/react-aria/examples/EmojiPicker.css']} type="vanilla" expanded
"use client";
import {Autocomplete, GridLayout, ListBox, ListBoxItem, Select, SelectValue, Size, useFilter, Virtualizer} from 'react-aria-components';
import {Button} from 'vanilla-starter/Button';
Expand Down
7 changes: 7 additions & 0 deletions packages/dev/s2-docs/src/Code.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {CodeProps} from './VisualExampleClient';
import {HastNode, HastTextNode, highlightHast, Language} from 'tree-sitter-highlight';
import React, {ReactNode} from 'react';
import {style, StyleString} from '@react-spectrum/s2/style' with {type: 'macro'};
import {TabLink} from './FileTabs';

const property = style({color: 'indigo-1000'});
const fn = style({color: 'red-1000'});
Expand Down Expand Up @@ -239,6 +240,12 @@ function renderHast(node: HastNode | HastTextNode, key: string, links?: Links, i
properties = {...properties, href: link};
}

// Link to imported files.
if (properties?.className === 'string' && typeof children === 'string' && /^['"]\.\//.test(children)) {
tagName = TabLink;
properties = {...properties, name: children.slice(3, -1)};
}

if (tagName === 'span' && !className) {
return children;
}
Expand Down
63 changes: 43 additions & 20 deletions packages/dev/s2-docs/src/CodeBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
// @ts-ignore
import assets from 'url:../pages/**/*.{png,jpg,svg}' with {env: 'react-client'};
import {cache, ReactNode} from 'react';
import {cache, ReactElement, ReactNode} from 'react';
import {Code, ICodeProps} from './Code';
import {CodePlatter, FileProvider, Pre} from './CodePlatter';
import {ExampleOutput} from './ExampleOutput';
import {ExpandableCode} from './ExpandableCode';
import {ExpandableCode, ExpandableCodeProvider} from './ExpandableCode';
import {FileTabs} from './FileTabs';
import {findPackageJSON} from 'module';
import fs from 'fs';
import {highlight, Language} from 'tree-sitter-highlight';
import path from 'path';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {Tab, TabList, TabPanel, Tabs} from '@react-spectrum/s2';
import {VisualExample, VisualExampleProps} from './VisualExample';

const example = style({
Expand Down Expand Up @@ -59,11 +59,10 @@ interface CodeBlockProps extends VisualExampleProps {
files?: string[],
expanded?: boolean,
hidden?: boolean,
includeAllImports?: boolean,
showCoachMark?: boolean
}

export function CodeBlock({render, children, dir, files, expanded, hidden, includeAllImports, ...props}: CodeBlockProps) {
export function CodeBlock({render, children, dir, files, expanded, hidden, ...props}: CodeBlockProps) {
if (hidden) {
return null;
}
Expand Down Expand Up @@ -116,7 +115,8 @@ export function CodeBlock({render, children, dir, files, expanded, hidden, inclu
<div>
{files ?
<Files
files={includeAllImports ? findAllFiles(files) : files}
files={files}
downloadFiles={downloadFiles.files}
maxLines={expanded ? Infinity : 6}
type={props.type}>
{content}
Expand Down Expand Up @@ -161,21 +161,44 @@ function TruncatedCode({children, maxLines = 6, ...props}: TruncatedCodeProps) {
);
}

export function Files({children, files, type, defaultSelected, maxLines}: {children?: ReactNode, files: string[], type?: 'vanilla' | 'tailwind' | 's2', defaultSelected?: string, maxLines?: number}) {
interface FilesProps {
children?: ReactNode,
files: string[],
downloadFiles?: {[name: string]: string},
type?: 'vanilla' | 'tailwind' | 's2',
defaultSelected?: string,
maxLines?: number
}

export function Files({children, files, downloadFiles, type, defaultSelected, maxLines}: FilesProps) {
let fileMap: {[name: string]: ReactElement} = {};
for (let file of files) {
fileMap[path.basename(file)] = <File filename={file} maxLines={maxLines} type={type} />;
}

let extraFiles: {[name: string]: ReactElement} = {};
if (downloadFiles) {
for (let name in downloadFiles) {
if (!files[name]) {
extraFiles[name] = (
<CodePlatter type={type}>
<TruncatedCode lang={path.extname(name).slice(1)} hideImports={false} maxLines={maxLines}>{downloadFiles[name]}</TruncatedCode>
</CodePlatter>
);
}
}
}

return (
<Tabs
key={files.join('|')}
aria-label="Files"
defaultSelectedKey={defaultSelected || (children ? 'example' : undefined)}
density="compact"
data-files>
<TabList styles={style({marginBottom: 20})}>
{children && <Tab id="example">Example</Tab>}
{files.map(file => <Tab key={file} id={file}>{path.basename(file)}</Tab>)}
</TabList>
{children && <TabPanel id="example" shouldForceMount data-example>{children}</TabPanel>}
{files.map(file => <TabPanel key={file} id={file}><File filename={file} maxLines={maxLines} type={type} /></TabPanel>)}
</Tabs>
<ExpandableCodeProvider>
<FileTabs
key={files.join('|')}
files={fileMap}
extraFiles={extraFiles}
defaultSelectedKey={defaultSelected || (children ? 'example' : undefined)}>
{children}
</FileTabs>
</ExpandableCodeProvider>
);
}

Expand Down
18 changes: 16 additions & 2 deletions packages/dev/s2-docs/src/ExpandableCode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import {ActionButton} from '@react-spectrum/s2';
import {flushSync} from 'react-dom';
import React, {CSSProperties, ReactNode, useRef, useState} from 'react';
import React, {createContext, CSSProperties, ReactNode, useContext, useRef, useState} from 'react';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};

const example = style({
Expand Down Expand Up @@ -46,8 +46,22 @@ const expandWrapper = style({
paddingY: 8
});

export function ExpandableCode({children, hasHighlightedLine}: {children: ReactNode, hasHighlightedLine?: boolean}) {
type ExpandableCodeContextValue = [boolean, (v: boolean) => void] | null;
const ExpandableCodeContext = createContext<ExpandableCodeContextValue>(null);

export function ExpandableCodeProvider({children}) {
let [isExpanded, setExpanded] = useState(false);
return (
<ExpandableCodeContext value={[isExpanded, setExpanded]}>
{children}
</ExpandableCodeContext>
);
}

export function ExpandableCode({children, hasHighlightedLine}: {children: ReactNode, hasHighlightedLine?: boolean}) {
let state = useState(false);
let ctx = useContext(ExpandableCodeContext);
let [isExpanded, setExpanded] = ctx || state;
let ref = useRef<HTMLDivElement | null>(null);
let mask: string | undefined;
let padding: string | undefined;
Expand Down
69 changes: 69 additions & 0 deletions packages/dev/s2-docs/src/FileTabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
'use client';

import {CodeLink} from './Link';
import {createContext, ReactElement, ReactNode, useContext, useState} from 'react';
import {Key, Tab, TabList, TabPanel, Tabs} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};

interface FileTabsProps {
children?: ReactNode,
files: {[name: string]: ReactElement},
extraFiles?: {[name: string]: ReactElement},
defaultSelectedKey?: Key
}

const FileTabsContext = createContext<((tab: Key) => void) | null>(null);

export function FileTabs({children, files, extraFiles, defaultSelectedKey}: FileTabsProps) {
let [tabs, setTabs] = useState(files);
let [selectedKey, setSelectedKey] = useState<Key>(defaultSelectedKey || Object.keys(files)[0]);
let onFileClick = (key: Key) => {
let file: Key | null = null;
for (let k of [key, key + '.tsx', key + '.ts', key + '.js']) {
if (k in files || (extraFiles && k in extraFiles)) {
file = k;
break;
}
}

if (file) {
setSelectedKey(file);
if (!tabs[file] && extraFiles?.[file]) {
setTabs({...tabs, [file]: extraFiles[file]});
}
}
};

return (
<FileTabsContext value={onFileClick}>
<Tabs
aria-label="Files"
selectedKey={selectedKey}
onSelectionChange={setSelectedKey}
density="compact"
data-files>
<TabList styles={style({marginBottom: 20})}>
{children && <Tab id="example">Example</Tab>}
{Object.keys(tabs).map(file => <Tab key={file} id={file}>{file}</Tab>)}
</TabList>
{children && <TabPanel id="example" shouldForceMount data-example>{children}</TabPanel>}
{Object.entries(tabs).map(([name, file]) => <TabPanel key={name} id={name}>{file}</TabPanel>)}
</Tabs>
</FileTabsContext>
);
}

export function TabLink({name, ...props}) {
let onFileClick = useContext(FileTabsContext);
if (!onFileClick) {
return <span {...props} />;
}

return (
<CodeLink
{...props}
onPress={() => {
onFileClick(name);
}} />
);
}
Loading