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
6 changes: 4 additions & 2 deletions docs/6.x/docs/components/FAB/FAB.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@ import ExtendsLink from '@docs/components/ExtendsLink.tsx';
import ThemeColorsTable from '@docs/components/ThemeColorsTable.tsx';
import ScreenshotTabs from '@docs/components/ScreenshotTabs.tsx';
import ExtendedExample from '@docs/components/ExtendedExample.tsx';
import { FABVariantsExample, FABSizesExample } from '@docs/components/FABExample.tsx';

A floating action button represents the primary action on a screen.



<span />

<ScreenshotTabs screenshotData={{"all variants":"screenshots/fab-1.png","all sizes":"screenshots/fab-2.png","all modes":"screenshots/fab-4.png","with label":"screenshots/fab-3.png"}}/>

<FABVariantsExample />
<FABSizesExample />

## Usage
```js
Expand Down
3 changes: 3 additions & 0 deletions docs/6.x/docs/components/FAB/FABExtended.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import ExtendsLink from '@docs/components/ExtendsLink.tsx';
import ThemeColorsTable from '@docs/components/ThemeColorsTable.tsx';
import ScreenshotTabs from '@docs/components/ScreenshotTabs.tsx';
import ExtendedExample from '@docs/components/ExtendedExample.tsx';
import { FABExtendedExample } from '@docs/components/FABExample.tsx';

An extended floating action button represents the primary action on a screen
and shows a label next to the icon. Animates between expanded (icon + label)
Expand All @@ -16,6 +17,8 @@ and collapsed (icon only) states.

<span />

<FABExtendedExample />

## Usage
```js
import * as React from 'react';
Expand Down
7 changes: 5 additions & 2 deletions docs/6.x/docs/components/Switch/Switch.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@ import ExtendsLink from '@docs/components/ExtendsLink.tsx';
import ThemeColorsTable from '@docs/components/ThemeColorsTable.tsx';
import ScreenshotTabs from '@docs/components/ScreenshotTabs.tsx';
import ExtendedExample from '@docs/components/ExtendedExample.tsx';
import { SwitchStatesExample, SwitchDisabledExample, SwitchIconsExample } from '@docs/components/SwitchExample.tsx';

Material 3 toggle between two mutually exclusive states (on / off).



<span />

<ScreenshotTabs screenshotData={{"Android (enabled)":"screenshots/switch-enabled.android.png","Android (disabled)":"screenshots/switch-disabled.android.png","iOS (enabled)":"screenshots/switch-enabled.ios.png","iOS (disabled)":"screenshots/switch-disabled.ios.png"}}/>

<SwitchStatesExample />
<SwitchDisabledExample />
<SwitchIconsExample />

## Usage
```js
Expand Down
31 changes: 28 additions & 3 deletions docs/component-docs-plugin/generatePageMDX.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,27 @@ function generateThemeColors(
`;
}

type LiveExampleData = {
module: string;
exports: string[];
};

function generateLiveExamplesImport(liveExample: LiveExampleData | undefined) {
if (!liveExample) {
return '';
}

return `\nimport { ${liveExample.exports.join(', ')} } from '${liveExample.module}';`;
}

function generateLiveExamples(liveExample: LiveExampleData | undefined) {
if (!liveExample) {
return '';
}

return `\n\n${liveExample.exports.map((name) => `<${name} />`).join('\n')}`;
}

function generateScreenshots(screenshotData: string | undefined) {
if (!screenshotData) {
return `<span />`;
Expand Down Expand Up @@ -224,8 +245,12 @@ export default function generatePageMDX(doc: ComponentDoc, link: string) {
const summary = summaryMatch ? summaryMatch[1] : '';
const usage = description.replace(summary, '');

const liveExample = customFields.liveExamples[doc.title];
const themeColorsData = JSON.stringify(customFields.themeColors[doc.title]);
const screenshotData = JSON.stringify(customFields.screenshots[doc.title]);
// Live examples supersede screenshots, so a component never shows both.
const screenshotData = liveExample
? undefined
: JSON.stringify(customFields.screenshots[doc.title]);
const extendedExamplesData = JSON.stringify(
customFields.extendedExamples[doc.title]
);
Expand All @@ -241,11 +266,11 @@ import PropTable from '@docs/components/PropTable.tsx';
import ExtendsLink from '@docs/components/ExtendsLink.tsx';
import ThemeColorsTable from '@docs/components/ThemeColorsTable.tsx';
import ScreenshotTabs from '@docs/components/ScreenshotTabs.tsx';
import ExtendedExample from '@docs/components/ExtendedExample.tsx';
import ExtendedExample from '@docs/components/ExtendedExample.tsx';${generateLiveExamplesImport(liveExample)}

${summary}

${generateScreenshots(screenshotData)}
${generateScreenshots(screenshotData)}${generateLiveExamples(liveExample)}

${generateExtendedExamples(usage, extendedExamplesData)}

Expand Down
3 changes: 3 additions & 0 deletions docs/component-docs.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import path from 'node:path';
import { fileURLToPath } from 'node:url';

import { extendedExamples } from './src/data/extendedExamples.ts';
import { liveExamples, type LiveExample } from './src/data/liveExamples.ts';
import { screenshots } from './src/data/screenshots.ts';
import { themeColors } from './src/data/themeColors.ts';

Expand All @@ -19,6 +20,7 @@ type ComponentDocsConfig = {
themeColors: Record<string, unknown>;
screenshots: Record<string, unknown>;
extendedExamples: Record<string, unknown>;
liveExamples: Record<string, LiveExample>;
};
};

Expand Down Expand Up @@ -163,6 +165,7 @@ const componentDocsConfig: ComponentDocsConfig = {
themeColors,
screenshots,
extendedExamples,
liveExamples,
},
};

Expand Down
72 changes: 72 additions & 0 deletions docs/src/components/FABExample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import * as React from 'react';

import { FAB } from 'react-native-paper';

import InteractiveExample, { ExampleRow, Labelled } from './InteractiveExample';

/**
* Every role-color preset accepted by the `variant` prop, kept in the same
* order as the `Variant` union in `src/components/FAB/tokens.ts`.
*/
const VARIANTS = [
'primary',
'secondary',
'tertiary',
'tonalPrimary',
'tonalSecondary',
'tonalTertiary',
] as const;

/**
* Every spec size accepted by the `size` prop.
*/
const SIZES = ['default', 'medium', 'large'] as const;

export const FABVariantsExample = () => (
<InteractiveExample title="All variants — press for the ripple and state layer">
<ExampleRow>
{VARIANTS.map((variant) => (
<Labelled key={variant} label={variant}>
<FAB
icon="pencil"
variant={variant}
onPress={() => {}}
aria-label={`${variant} floating action button`}
/>
</Labelled>
))}
</ExampleRow>
</InteractiveExample>
);

export const FABSizesExample = () => (
<InteractiveExample title="All sizes — press for the ripple and state layer">
<ExampleRow>
{SIZES.map((size) => (
<Labelled key={size} label={size}>
<FAB
icon="pencil"
size={size}
onPress={() => {}}
aria-label={`${size} floating action button`}
/>
</Labelled>
))}
</ExampleRow>
</InteractiveExample>
);

export const FABExtendedExample = () => {
const [expanded, setExpanded] = React.useState(true);

return (
<InteractiveExample title="Extended — press to collapse and expand">
<FAB.Extended
icon="plus"
label="New message"
expanded={expanded}
onPress={() => setExpanded((value) => !value)}
/>
</InteractiveExample>
);
};
92 changes: 92 additions & 0 deletions docs/src/components/InteractiveExample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import * as React from 'react';
import { StyleSheet, View } from 'react-native';

import { BrowserOnly } from '@rspress/core/runtime';
import { DarkTheme, LightTheme, Provider, Text } from 'react-native-paper';

import { useColorMode } from './theme-common';

const styles = StyleSheet.create({
content: {
alignItems: 'flex-start',
},
row: {
flexDirection: 'row',
flexWrap: 'wrap',
alignItems: 'center',
gap: 24,
},
item: {
alignItems: 'center',
gap: 8,
},
itemLabel: {
fontSize: 12,
opacity: 0.7,
},
});

/**
* Row of demo variations, wrapping on narrow viewports.
*/
export const ExampleRow = ({ children }: React.PropsWithChildren) => (
<View style={styles.row}>{children}</View>
);

/**
* A single demo variation captioned with the prop value it illustrates.
*/
export const Labelled = ({
label,
children,
}: React.PropsWithChildren<{ label: string }>) => (
<View style={styles.item}>
{children}
<Text style={styles.itemLabel}>{label}</Text>
</View>
);

type InteractiveExampleProps = React.PropsWithChildren<{
/**
* Short caption rendered above the live preview, describing what the
* example demonstrates.
*/
title?: string;
}>;

/**
* Shared shell for live component demos embedded in the docs.
*
* Paper components depend on browser APIs through `react-native-web`, so the
* tree is only mounted on the client and a same-sized placeholder is rendered
* during SSR to avoid layout shift. The Paper theme is kept in sync with the
* active docs color mode so demos match the surrounding page.
*/
const Frame = ({ title, children }: InteractiveExampleProps) => {
const isDarkTheme = useColorMode().colorMode === 'dark';

return (
<Provider theme={isDarkTheme ? DarkTheme : LightTheme}>
<figure className="paper-interactive-example">
{title ? (
<figcaption className="paper-interactive-example__title">
{title}
</figcaption>
) : null}
<View style={styles.content}>{children}</View>
</figure>
</Provider>
);
};

const Placeholder = () => (
<div className="paper-interactive-example paper-interactive-example--loading" />
);

const InteractiveExample = (props: InteractiveExampleProps) => (
<BrowserOnly fallback={<Placeholder />}>
{() => <Frame {...props} />}
</BrowserOnly>
);

export default InteractiveExample;
66 changes: 66 additions & 0 deletions docs/src/components/SwitchExample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import * as React from 'react';

import { Switch } from 'react-native-paper';

import InteractiveExample, { ExampleRow, Labelled } from './InteractiveExample';

export const SwitchStatesExample = () => {
const [on, setOn] = React.useState(true);
const [off, setOff] = React.useState(false);

return (
<InteractiveExample title="Enabled — toggle to see the handle animate">
<ExampleRow>
<Labelled label="selected">
<Switch value={on} onValueChange={setOn} aria-label="Selected" />
</Labelled>
<Labelled label="unselected">
<Switch value={off} onValueChange={setOff} aria-label="Unselected" />
</Labelled>
</ExampleRow>
</InteractiveExample>
);
};

export const SwitchDisabledExample = () => (
<InteractiveExample title="Disabled — does not respond to input">
<ExampleRow>
<Labelled label="selected">
<Switch value disabled aria-label="Disabled and selected" />
</Labelled>
<Labelled label="unselected">
<Switch value={false} disabled aria-label="Disabled and unselected" />
</Labelled>
</ExampleRow>
</InteractiveExample>
);

export const SwitchIconsExample = () => {
const [on, setOn] = React.useState(true);
const [off, setOff] = React.useState(false);

return (
<InteractiveExample title="With icons in the handle — toggle to swap the icon">
<ExampleRow>
<Labelled label="selected">
<Switch
value={on}
onValueChange={setOn}
checkedIcon="check"
uncheckedIcon="close"
aria-label="Selected with icon"
/>
</Labelled>
<Labelled label="unselected">
<Switch
value={off}
onValueChange={setOff}
checkedIcon="check"
uncheckedIcon="close"
aria-label="Unselected with icon"
/>
</Labelled>
</ExampleRow>
</InteractiveExample>
);
};
23 changes: 23 additions & 0 deletions docs/src/css/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -1286,3 +1286,26 @@ html:not(.dark) .paper-version-selector-menu {
padding: 18px;
}
}

.paper-interactive-example {
margin: 16px 0 24px;
padding: 24px;
border: 1px solid var(--rp-c-divider, rgba(148, 163, 184, 0.24));
border-radius: 16px;
background: var(--rp-c-bg-soft, rgba(148, 163, 184, 0.06));
overflow-x: auto;
}

.paper-interactive-example__title {
margin-bottom: 16px;
color: var(--rp-c-text-2);
font-size: 13px;
font-weight: 600;
}

/* Nominal reserve so the page does not jump to zero height during SSR. Demos
vary in height, so this deliberately approximates a single row rather than
claiming to match any particular example. */
.paper-interactive-example--loading {
min-height: 96px;
}
Loading