diff --git a/docs/src/app/new/(content)/components/accordion/demos/hero/css-modules/index.module.css b/docs/src/app/new/(content)/components/accordion/demos/hero/css-modules/index.module.css new file mode 100644 index 0000000000..10aef9b783 --- /dev/null +++ b/docs/src/app/new/(content)/components/accordion/demos/hero/css-modules/index.module.css @@ -0,0 +1,71 @@ +.Root { + box-sizing: border-box; + display: flex; + min-height: 12rem; + width: 24rem; + max-width: calc(100vw - 8rem); + flex-direction: column; + justify-content: center; +} + +.Item { + border-bottom: 1px solid var(--color-gray-200); +} + +.Header { + margin: 0; +} + +.Trigger { + box-sizing: border-box; + display: flex; + width: 100%; + align-items: baseline; + justify-content: space-between; + padding: 0.5rem 0; + font: inherit; + font-weight: 500; + font-size: 1rem; + line-height: 1.5rem; + letter-spacing: 0em; + background: none; + border: none; + outline: none; + cursor: pointer; + + &:focus-visible { + outline: 2px solid var(--color-blue); + } +} + +.TriggerIcon { + box-sizing: border-box; + width: 0.75rem; + height: 0.75rem; + margin-right: 0.5rem; + transition: transform 150ms ease-out; + + [data-panel-open] > & { + transform: rotate(45deg) scale(1.1); + } +} + +.Panel { + box-sizing: border-box; + height: var(--accordion-panel-height); + overflow: hidden; + color: var(--color-gray-600); + font-size: 0.9375rem; + line-height: 1.375rem; + letter-spacing: 0.001em; + transition: height 150ms ease-out; + + &[data-entering], + &[data-exiting] { + height: 0; + } +} + +.Content { + padding-bottom: 0.5rem; +} diff --git a/docs/src/app/new/(content)/components/accordion/demos/hero/css-modules/index.tsx b/docs/src/app/new/(content)/components/accordion/demos/hero/css-modules/index.tsx new file mode 100644 index 0000000000..4ed5cfaafd --- /dev/null +++ b/docs/src/app/new/(content)/components/accordion/demos/hero/css-modules/index.tsx @@ -0,0 +1,61 @@ +import * as React from 'react'; +import { Accordion } from '@base-ui-components/react/accordion'; +import styles from './index.module.css'; + +export default function ExampleAccordion() { + return ( + + + + + What is Base UI? + + + + +
+ Base UI is a library of high-quality, accessible, unstyled React + components for design systems and web apps. +
+
+
+ + + + + How do I get started? + + + + +
+ Head to the “Quick start” guide in the docs. If you’ve used unstyled + libraries before, you’ll feel right at home. +
+
+
+ + + + + Can I use it for my next project? + + + + +
+ Of course! Base UI is free and open source. +
+
+
+
+ ); +} + +function PlusIcon(props: React.ComponentProps<'svg'>) { + return ( + + + + ); +} diff --git a/docs/src/app/new/(content)/components/accordion/demos/hero/index.ts b/docs/src/app/new/(content)/components/accordion/demos/hero/index.ts new file mode 100644 index 0000000000..80097d6015 --- /dev/null +++ b/docs/src/app/new/(content)/components/accordion/demos/hero/index.ts @@ -0,0 +1,3 @@ +'use client'; +export { default as CssModules } from './css-modules'; +export { default as Tailwind } from './tailwind'; diff --git a/docs/src/app/new/(content)/components/accordion/demos/hero/tailwind/index.tsx b/docs/src/app/new/(content)/components/accordion/demos/hero/tailwind/index.tsx new file mode 100644 index 0000000000..f9d03b6dd1 --- /dev/null +++ b/docs/src/app/new/(content)/components/accordion/demos/hero/tailwind/index.tsx @@ -0,0 +1,58 @@ +import * as React from 'react'; +import { Accordion } from '@base-ui-components/react/accordion'; + +export default function ExampleAccordion() { + return ( + + + + + What is Base UI? + + + + +
+ Base UI is a library of high-quality, accessible, unstyled React + components for design systems and web apps. +
+
+
+ + + + + How do I get started? + + + + +
+ Head to the “Quick start” guide in the docs. If you’ve used unstyled + libraries before, you’ll feel right at home. +
+
+
+ + + + + Can I use it for my next project? + + + + +
Of course! Base UI is free and open source.
+
+
+
+ ); +} + +function PlusIcon(props: React.ComponentProps<'svg'>) { + return ( + + + + ); +} diff --git a/docs/src/app/new/(content)/components/accordion/page.mdx b/docs/src/app/new/(content)/components/accordion/page.mdx new file mode 100644 index 0000000000..aec5846767 --- /dev/null +++ b/docs/src/app/new/(content)/components/accordion/page.mdx @@ -0,0 +1,25 @@ +# Accordion + +A set of collapsible panels with headings. + + + + +## API reference + +Import the component and place its parts the following way: + +```jsx title="Anatomy" +import { Accordion } from '@base-ui-components/react/accordion'; + + + + + + + + +; +``` + + diff --git a/docs/src/app/new/(content)/components/alert-dialog/demos/hero/css-modules/index.module.css b/docs/src/app/new/(content)/components/alert-dialog/demos/hero/css-modules/index.module.css new file mode 100644 index 0000000000..91f4db5eb1 --- /dev/null +++ b/docs/src/app/new/(content)/components/alert-dialog/demos/hero/css-modules/index.module.css @@ -0,0 +1,93 @@ +.Button { + box-sizing: border-box; + display: flex; + padding: 0.5rem 0.875rem; + margin: 0; + border: none; + border-radius: 0.375rem; + background-color: var(--color-gray-50); + font: inherit; + font-weight: 500; + color: var(--color-gray-900); + outline: 1px solid var(--color-gray-200); + user-select: none; + + &[data-color='red'] { + color: var(--color-red); + } + + @media (hover: hover) { + &:hover { + background-color: var(--color-gray-100); + } + } + + &:focus-visible { + outline: 2px solid var(--color-blue); + } + + &:active { + background-color: var(--color-gray-100); + } +} + +.Backdrop { + position: fixed; + inset: 0; + background-color: black; + opacity: 0.2; + transition: opacity 150ms; + + @media (prefers-color-scheme: dark) { + opacity: 0.7; + } + + &[data-entering], + &[data-exiting] { + opacity: 0; + } +} + +.Popup { + box-sizing: border-box; + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + width: 24rem; + max-width: calc(100vw - 3rem); + margin-top: -2rem; + padding: 1.5rem; + border-radius: 0.5rem; + border: 1px solid var(--color-gray-300); + background-color: var(--color-gray-50); + color: var(--color-gray-950); + outline: 0; + transition: all 150ms; + + &[data-entering], + &[data-exiting] { + opacity: 0; + transform: translate(-50%, -50%) scale(0.9); + } +} + +.Title { + margin-top: -0.375rem; + margin-bottom: 0.25rem; + font-size: 1.125rem; + line-height: 1.75rem; + letter-spacing: -0.0025em; + font-weight: 500; +} + +.Description { + margin: 0 0 1.5rem; + color: var(--color-gray-600); +} + +.Actions { + display: flex; + justify-content: flex-end; + gap: 1rem; +} diff --git a/docs/src/app/new/(content)/components/alert-dialog/demos/hero/css-modules/index.tsx b/docs/src/app/new/(content)/components/alert-dialog/demos/hero/css-modules/index.tsx new file mode 100644 index 0000000000..67e7fca52f --- /dev/null +++ b/docs/src/app/new/(content)/components/alert-dialog/demos/hero/css-modules/index.tsx @@ -0,0 +1,28 @@ +import * as React from 'react'; +import { AlertDialog } from '@base-ui-components/react/alert-dialog'; +import styles from './index.module.css'; + +export default function ExampleAlertDialog() { + return ( + + + Discard draft + + + + + Discard draft? + + + You can't undo this action. + +
+ Cancel + + Discard + +
+
+
+ ); +} diff --git a/docs/src/app/new/(content)/components/alert-dialog/demos/hero/index.ts b/docs/src/app/new/(content)/components/alert-dialog/demos/hero/index.ts new file mode 100644 index 0000000000..80097d6015 --- /dev/null +++ b/docs/src/app/new/(content)/components/alert-dialog/demos/hero/index.ts @@ -0,0 +1,3 @@ +'use client'; +export { default as CssModules } from './css-modules'; +export { default as Tailwind } from './tailwind'; diff --git a/docs/src/app/new/(content)/components/alert-dialog/demos/hero/tailwind/index.tsx b/docs/src/app/new/(content)/components/alert-dialog/demos/hero/tailwind/index.tsx new file mode 100644 index 0000000000..46aa816b02 --- /dev/null +++ b/docs/src/app/new/(content)/components/alert-dialog/demos/hero/tailwind/index.tsx @@ -0,0 +1,29 @@ +import * as React from 'react'; +import { AlertDialog } from '@base-ui-components/react/alert-dialog'; + +export default function ExampleAlertDialog() { + return ( + + + Discard draft + + + + + Discard draft? + + + You can’t undo this action. + +
+ + Cancel + + + Discard + +
+
+
+ ); +} diff --git a/docs/src/app/new/(content)/components/alert-dialog/page.mdx b/docs/src/app/new/(content)/components/alert-dialog/page.mdx new file mode 100644 index 0000000000..87620deac8 --- /dev/null +++ b/docs/src/app/new/(content)/components/alert-dialog/page.mdx @@ -0,0 +1,26 @@ +# Alert Dialog + +A dialog that requires user response to proceed. + + + + +## API reference + +Import the component and place its parts the following way: + +```jsx title="Anatomy" +import { AlertDialog } from '@base-ui-components/react/alert-dialog'; + + + + + + + + + +; +``` + + diff --git a/docs/src/app/new/(content)/components/checkbox-group/demos/hero/css-modules/index.module.css b/docs/src/app/new/(content)/components/checkbox-group/demos/hero/css-modules/index.module.css new file mode 100644 index 0000000000..67dd06d4e1 --- /dev/null +++ b/docs/src/app/new/(content)/components/checkbox-group/demos/hero/css-modules/index.module.css @@ -0,0 +1,58 @@ +.Group { + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.Label { + font-weight: 500; +} + +.Item { + display: flex; + align-items: center; + gap: 0.5rem; +} + +.Checkbox { + box-sizing: border-box; + display: flex; + width: 1.25rem; + height: 1.25rem; + align-items: center; + justify-content: center; + border-radius: 0.25rem; + outline: 0; + padding: 0; + margin: 0; + border: none; + + &[data-checked] { + background-color: var(--color-gray-900); + } + + &[data-unchecked] { + border: 1px solid var(--color-gray-300); + background-color: transparent; + } + + &:focus-visible { + outline: 2px solid var(--color-blue); + outline-offset: 2px; + } +} + +.Indicator { + width: 0.75rem; + height: 0.75rem; + color: var(--color-gray-50); + + &[data-unchecked] { + display: none; + } +} + +.Icon { + width: 100%; + height: 100%; +} diff --git a/docs/src/app/new/(content)/components/checkbox-group/demos/hero/css-modules/index.tsx b/docs/src/app/new/(content)/components/checkbox-group/demos/hero/css-modules/index.tsx new file mode 100644 index 0000000000..7f3333e3d6 --- /dev/null +++ b/docs/src/app/new/(content)/components/checkbox-group/demos/hero/css-modules/index.tsx @@ -0,0 +1,57 @@ +import * as React from 'react'; +import { Checkbox } from '@base-ui-components/react/checkbox'; +import { CheckboxGroup } from '@base-ui-components/react/checkbox-group'; +import styles from './index.module.css'; + +export default function ExampleCheckboxGroup() { + return ( + +
+ Apples +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+
+ ); +} + +function CheckIcon(props: React.ComponentProps<'svg'>) { + return ( + + + + ); +} diff --git a/docs/src/app/new/(content)/components/checkbox-group/demos/hero/index.ts b/docs/src/app/new/(content)/components/checkbox-group/demos/hero/index.ts new file mode 100644 index 0000000000..80097d6015 --- /dev/null +++ b/docs/src/app/new/(content)/components/checkbox-group/demos/hero/index.ts @@ -0,0 +1,3 @@ +'use client'; +export { default as CssModules } from './css-modules'; +export { default as Tailwind } from './tailwind'; diff --git a/docs/src/app/new/(content)/components/checkbox-group/demos/hero/tailwind/index.tsx b/docs/src/app/new/(content)/components/checkbox-group/demos/hero/tailwind/index.tsx new file mode 100644 index 0000000000..15150b0658 --- /dev/null +++ b/docs/src/app/new/(content)/components/checkbox-group/demos/hero/tailwind/index.tsx @@ -0,0 +1,64 @@ +import * as React from 'react'; +import { Checkbox } from '@base-ui-components/react/checkbox'; +import { CheckboxGroup } from '@base-ui-components/react/checkbox-group'; + +export default function ExampleCheckboxGroup() { + return ( + +
+ Apples +
+ +
+ + + + + + +
+ +
+ + + + + + +
+ +
+ + + + + + +
+
+ ); +} + +function CheckIcon(props: React.ComponentProps<'svg'>) { + return ( + + + + ); +} diff --git a/docs/src/app/new/(content)/components/checkbox-group/page.mdx b/docs/src/app/new/(content)/components/checkbox-group/page.mdx new file mode 100644 index 0000000000..3c5b4e1097 --- /dev/null +++ b/docs/src/app/new/(content)/components/checkbox-group/page.mdx @@ -0,0 +1,21 @@ +# Checkbox Group + +A series of checkboxes with a shared state. + + + + +## API reference + +Checkbox Group is meant to be composed together with Checkbox. Import the components and place them together: + +```jsx title="Anatomy" +import { Checkbox } from '@base-ui-components/react/checkbox'; +import { CheckboxGroup } from '@base-ui-components/react/checkbox-group'; + + + +; +``` + + diff --git a/docs/src/app/new/(content)/components/checkbox/demos/hero/css-modules/index.module.css b/docs/src/app/new/(content)/components/checkbox/demos/hero/css-modules/index.module.css new file mode 100644 index 0000000000..337c01a41a --- /dev/null +++ b/docs/src/app/new/(content)/components/checkbox/demos/hero/css-modules/index.module.css @@ -0,0 +1,42 @@ +.Checkbox { + box-sizing: border-box; + display: flex; + width: 1.25rem; + height: 1.25rem; + align-items: center; + justify-content: center; + border-radius: 0.25rem; + outline: 0; + padding: 0; + margin: 0; + border: none; + + &[data-checked] { + background-color: var(--color-gray-900); + } + + &[data-unchecked] { + border: 1px solid var(--color-gray-300); + background-color: transparent; + } + + &:focus-visible { + outline: 2px solid var(--color-blue); + outline-offset: 2px; + } +} + +.Indicator { + width: 0.75rem; + height: 0.75rem; + color: var(--color-gray-50); + + &[data-unchecked] { + display: none; + } +} + +.Icon { + width: 100%; + height: 100%; +} diff --git a/docs/src/app/new/(content)/components/checkbox/demos/hero/css-modules/index.tsx b/docs/src/app/new/(content)/components/checkbox/demos/hero/css-modules/index.tsx new file mode 100644 index 0000000000..be6c7bc9dd --- /dev/null +++ b/docs/src/app/new/(content)/components/checkbox/demos/hero/css-modules/index.tsx @@ -0,0 +1,21 @@ +import * as React from 'react'; +import { Checkbox } from '@base-ui-components/react/checkbox'; +import styles from './index.module.css'; + +export default function ExampleCheckbox() { + return ( + + + + + + ); +} + +function CheckIcon(props: React.ComponentProps<'svg'>) { + return ( + + + + ); +} diff --git a/docs/src/app/new/(content)/components/checkbox/demos/hero/index.ts b/docs/src/app/new/(content)/components/checkbox/demos/hero/index.ts new file mode 100644 index 0000000000..80097d6015 --- /dev/null +++ b/docs/src/app/new/(content)/components/checkbox/demos/hero/index.ts @@ -0,0 +1,3 @@ +'use client'; +export { default as CssModules } from './css-modules'; +export { default as Tailwind } from './tailwind'; diff --git a/docs/src/app/new/(content)/components/checkbox/demos/hero/tailwind/index.tsx b/docs/src/app/new/(content)/components/checkbox/demos/hero/tailwind/index.tsx new file mode 100644 index 0000000000..e7aeca91f3 --- /dev/null +++ b/docs/src/app/new/(content)/components/checkbox/demos/hero/tailwind/index.tsx @@ -0,0 +1,23 @@ +import * as React from 'react'; +import { Checkbox } from '@base-ui-components/react/checkbox'; + +export default function ExampleCheckbox() { + return ( + + + + + + ); +} + +function CheckIcon(props: React.ComponentProps<'svg'>) { + return ( + + + + ); +} diff --git a/docs/src/app/new/(content)/components/checkbox/page.mdx b/docs/src/app/new/(content)/components/checkbox/page.mdx new file mode 100644 index 0000000000..3d367cb2f0 --- /dev/null +++ b/docs/src/app/new/(content)/components/checkbox/page.mdx @@ -0,0 +1,20 @@ +# Checkbox + +An easily stylable checkbox component. + + + + +## API reference + +Import the component and place its parts the following way: + +```jsx title="Anatomy" +import { Checkbox } from '@base-ui-components/react/checkbox'; + + + +; +``` + + diff --git a/docs/src/app/new/(content)/components/dialog/demos/hero/css-modules/index.module.css b/docs/src/app/new/(content)/components/dialog/demos/hero/css-modules/index.module.css index 138eb292f9..bad9b0459f 100644 --- a/docs/src/app/new/(content)/components/dialog/demos/hero/css-modules/index.module.css +++ b/docs/src/app/new/(content)/components/dialog/demos/hero/css-modules/index.module.css @@ -1,5 +1,4 @@ -.Trigger, -.Close { +.Button { box-sizing: border-box; display: flex; padding: 0.5rem 0.875rem; @@ -28,12 +27,7 @@ } } -.Close { - margin-left: auto; -} - .Backdrop { - box-sizing: border-box; position: fixed; inset: 0; background-color: black; @@ -56,8 +50,8 @@ top: 50%; left: 50%; transform: translate(-50%, -50%); - width: 320px; - max-width: calc(100vw - 48px); + width: 24rem; + max-width: calc(100vw - 3rem); margin-top: -2rem; padding: 1.5rem; border-radius: 0.5rem; @@ -75,7 +69,6 @@ } .Title { - box-sizing: border-box; margin-top: -0.375rem; margin-bottom: 0.25rem; font-size: 1.125rem; @@ -85,7 +78,12 @@ } .Description { - box-sizing: border-box; - margin: 0 0 1rem; + margin: 0 0 1.5rem; color: var(--color-gray-600); } + +.Actions { + display: flex; + justify-content: flex-end; + gap: 1rem; +} diff --git a/docs/src/app/new/(content)/components/dialog/demos/hero/css-modules/index.tsx b/docs/src/app/new/(content)/components/dialog/demos/hero/css-modules/index.tsx index 77351605bb..6f9fdce841 100644 --- a/docs/src/app/new/(content)/components/dialog/demos/hero/css-modules/index.tsx +++ b/docs/src/app/new/(content)/components/dialog/demos/hero/css-modules/index.tsx @@ -12,7 +12,9 @@ export default function ExampleDialog() { You are all caught up. Good job! - Close +
+ Close +
); diff --git a/docs/src/app/new/(content)/components/dialog/demos/hero/tailwind/index.tsx b/docs/src/app/new/(content)/components/dialog/demos/hero/tailwind/index.tsx index 0645d4f6f0..8912b5c348 100644 --- a/docs/src/app/new/(content)/components/dialog/demos/hero/tailwind/index.tsx +++ b/docs/src/app/new/(content)/components/dialog/demos/hero/tailwind/index.tsx @@ -8,16 +8,18 @@ export default function ExampleDialog() { View notifications - + Your notifications - + You are all caught up. Good job! - - Close - +
+ + Close + +
); diff --git a/docs/src/app/new/(content)/components/dialog/page.mdx b/docs/src/app/new/(content)/components/dialog/page.mdx index 96656ca9ab..7c770744d9 100644 --- a/docs/src/app/new/(content)/components/dialog/page.mdx +++ b/docs/src/app/new/(content)/components/dialog/page.mdx @@ -1,6 +1,7 @@ # Dialog A popup that opens on top of the entire page. + diff --git a/docs/src/mdx-components.tsx b/docs/src/mdx-components.tsx index b360b8f493..075d76c342 100644 --- a/docs/src/mdx-components.tsx +++ b/docs/src/mdx-components.tsx @@ -65,13 +65,14 @@ export const mdxComponents: MDXComponents = { QuickNav, AttributesTable: (props) => , CssVariablesTable: (props) => , + Meta: (props: React.ComponentProps<'meta'>) => { + if (props.name === 'description' && String(props.content).length > 170) { + throw new Error('Meta description shouldn’t be longer than 170 chars'); + } + return ; + }, PropsTable: (props) => , - Subtitle: (props) => ( - -

- - - ), + Subtitle: (props) =>

, }; export const inlineMdxComponents: MDXComponents = { diff --git a/docs/src/nav.ts b/docs/src/nav.ts index 4aa91f8321..7e815feae9 100644 --- a/docs/src/nav.ts +++ b/docs/src/nav.ts @@ -35,15 +35,15 @@ export const nav = [ label: 'Composition', href: '/new/handbook/composition', }, - { - label: 'Migrating from Radix', - href: '/new/handbook/migrating-from-radix', - }, ], }, { label: 'Components', links: [ + { + label: 'Accordion', + href: '/new/components/accordion', + }, { label: 'Alert Dialog', href: '/new/components/alert-dialog', @@ -54,7 +54,7 @@ export const nav = [ }, { label: 'Checkbox Group', - href: '/new/components/checkbox group', + href: '/new/components/checkbox-group', }, { label: 'Collapsible',