Skip to content
Draft
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
3 changes: 2 additions & 1 deletion test/performance/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
"private": true,
"description": "Performance benchmark workspace for Base UI",
"scripts": {
"benchmark": "vitest run"
"benchmark": "vitest run",
"debug": "vitest --browser.headless=false"
},
"dependencies": {
"@base-ui/react": "workspace:*",
Expand Down
5 changes: 3 additions & 2 deletions test/performance/tests/checkbox.bench.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ import * as React from 'react';
import { Checkbox } from '@base-ui/react/checkbox';
import { benchmark } from '@mui/internal-benchmark';
import { createRows, MountList } from './shared';
import styles from './styles/checkbox.module.css';

const checkboxRows = createRows(500, 'Checkbox');

function CheckboxMountList() {
return (
<MountList rows={checkboxRows}>
{(row) => (
<Checkbox.Root key={row.id} aria-label={row.label}>
<Checkbox.Indicator />
<Checkbox.Root key={row.id} aria-label={row.label} className={styles.Checkbox}>
<Checkbox.Indicator className={styles.Indicator} />
</Checkbox.Root>
)}
</MountList>
Expand Down
17 changes: 11 additions & 6 deletions test/performance/tests/dialog.bench.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as React from 'react';
import { Dialog } from '@base-ui/react/dialog';
import { benchmark } from '@mui/internal-benchmark';
import { createRows, MountList } from './shared';
import styles from './styles/dialog.module.css';

const dialogRows = createRows(300, 'Dialog');

Expand All @@ -10,13 +11,17 @@ function DialogMountList() {
<MountList rows={dialogRows}>
{(row) => (
<Dialog.Root key={row.id}>
<Dialog.Trigger aria-label={`Open ${row.label}`}>{row.label}</Dialog.Trigger>
<Dialog.Trigger aria-label={`Open ${row.label}`} className={styles.Button}>
{row.label}
</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Backdrop />
<Dialog.Popup>
<Dialog.Title>{row.label}</Dialog.Title>
<Dialog.Description>Dialog content</Dialog.Description>
<Dialog.Close>Close</Dialog.Close>
<Dialog.Backdrop className={styles.Backdrop} />
<Dialog.Popup className={styles.Popup}>
<Dialog.Title className={styles.Title}>{row.label}</Dialog.Title>
<Dialog.Description className={styles.Description}>Dialog content</Dialog.Description>
<div className={styles.Actions}>
<Dialog.Close className={styles.Button}>Close</Dialog.Close>
</div>
</Dialog.Popup>
</Dialog.Portal>
</Dialog.Root>
Expand Down
25 changes: 17 additions & 8 deletions test/performance/tests/menu.bench.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as React from 'react';
import { Menu } from '@base-ui/react/menu';
import { benchmark, ElementTiming } from '@mui/internal-benchmark';
import { createRows, MountList } from './shared';
import styles from './styles/menu.module.css';

const menuRows = createRows(300, 'Menu');
const menuItems = createRows(5, 'Menu item');
Expand All @@ -12,12 +13,16 @@ function MenuMountList() {
<MountList rows={menuRows}>
{(row) => (
<Menu.Root key={row.id}>
<Menu.Trigger aria-label={`Open ${row.label}`}>{row.label}</Menu.Trigger>
<Menu.Trigger aria-label={`Open ${row.label}`} className={styles.Button}>
{row.label}
</Menu.Trigger>
<Menu.Portal>
<Menu.Positioner sideOffset={8}>
<Menu.Popup>
<Menu.Positioner sideOffset={8} className={styles.Positioner}>
<Menu.Popup className={styles.Popup}>
{menuItems.map((item) => (
<Menu.Item key={item.id}>{item.label}</Menu.Item>
<Menu.Item key={item.id} className={styles.Item}>
{item.label}
</Menu.Item>
))}
</Menu.Popup>
</Menu.Positioner>
Expand All @@ -31,15 +36,19 @@ function MenuMountList() {
function LargeMenu() {
return (
<Menu.Root>
<Menu.Trigger aria-label="Open menu benchmark">Open menu</Menu.Trigger>
<Menu.Trigger aria-label="Open menu benchmark" className={styles.Button}>
Open menu
</Menu.Trigger>
<Menu.Portal>
<Menu.Positioner sideOffset={8} positionMethod="fixed">
<Menu.Popup>
<Menu.Positioner sideOffset={8} positionMethod="fixed" className={styles.Positioner}>
<Menu.Popup className={styles.Popup}>
<div data-benchmark="menu-open-content">
<ElementTiming name="menu-open" />
</div>
{largeMenuItems.map((item) => (
<Menu.Item key={item.id}>{item.label}</Menu.Item>
<Menu.Item key={item.id} className={styles.Item}>
{item.label}
</Menu.Item>
))}
</Menu.Popup>
</Menu.Positioner>
Expand Down
125 changes: 82 additions & 43 deletions test/performance/tests/mixed.bench.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ import { Tabs } from '@base-ui/react/tabs';
import { Tooltip } from '@base-ui/react/tooltip';
import { benchmark } from '@mui/internal-benchmark';
import { createRows } from './shared';
import checkboxStyles from './styles/checkbox.module.css';
import dialogStyles from './styles/dialog.module.css';
import menuStyles from './styles/menu.module.css';
import popoverStyles from './styles/popover.module.css';
import scrollAreaStyles from './styles/scroll-area.module.css';
import selectStyles from './styles/select.module.css';
import sliderStyles from './styles/slider.module.css';
import tabsStyles from './styles/tabs.module.css';
import tooltipStyles from './styles/tooltip.module.css';

const tooltipRows = createRows(200, 'Tooltip');
const checkboxRows = createRows(40, 'Checkbox');
Expand All @@ -29,12 +38,18 @@ function MixedSurface() {
<section>
{tooltipRows.map((row) => (
<Tooltip.Root key={`tooltip-${row.id}`}>
<Tooltip.Trigger delay={0} aria-label={`Open tooltip ${row.id}`}>
<Tooltip.Trigger
delay={0}
aria-label={`Open tooltip ${row.id}`}
className={tooltipStyles.Button}
>
{row.label}
</Tooltip.Trigger>
<Tooltip.Portal>
<Tooltip.Positioner sideOffset={8}>
<Tooltip.Popup>Tooltip for {row.label}</Tooltip.Popup>
<Tooltip.Popup className={tooltipStyles.Popup}>
Tooltip for {row.label}
</Tooltip.Popup>
</Tooltip.Positioner>
</Tooltip.Portal>
</Tooltip.Root>
Expand All @@ -44,12 +59,16 @@ function MixedSurface() {
<section>
{menuRows.map((row) => (
<Menu.Root key={`menu-${row.id}`}>
<Menu.Trigger aria-label={`Open menu ${row.id}`}>{row.label}</Menu.Trigger>
<Menu.Trigger aria-label={`Open menu ${row.id}`} className={menuStyles.Button}>
{row.label}
</Menu.Trigger>
<Menu.Portal>
<Menu.Positioner sideOffset={8}>
<Menu.Popup>
<Menu.Positioner sideOffset={8} className={menuStyles.Positioner}>
<Menu.Popup className={menuStyles.Popup}>
{listItems.map((item) => (
<Menu.Item key={item.id}>{item.label}</Menu.Item>
<Menu.Item key={item.id} className={menuStyles.Item}>
{item.label}
</Menu.Item>
))}
</Menu.Popup>
</Menu.Positioner>
Expand All @@ -59,12 +78,19 @@ function MixedSurface() {

{popoverRows.map((row) => (
<Popover.Root key={`popover-${row.id}`}>
<Popover.Trigger aria-label={`Open popover ${row.id}`}>{row.label}</Popover.Trigger>
<Popover.Trigger
aria-label={`Open popover ${row.id}`}
className={popoverStyles.IconButton}
>
{row.label}
</Popover.Trigger>
<Popover.Portal>
<Popover.Positioner sideOffset={8}>
<Popover.Popup>
<Popover.Title>{row.label}</Popover.Title>
<Popover.Description>Popover content</Popover.Description>
<Popover.Positioner sideOffset={8} className={popoverStyles.Positioner}>
<Popover.Popup className={popoverStyles.Popup}>
<Popover.Title className={popoverStyles.Title}>{row.label}</Popover.Title>
<Popover.Description className={popoverStyles.Description}>
Popover content
</Popover.Description>
</Popover.Popup>
</Popover.Positioner>
</Popover.Portal>
Expand All @@ -73,18 +99,20 @@ function MixedSurface() {

{selectRows.map((row) => (
<Select.Root key={`select-${row.id}`} items={listItems}>
<Select.Trigger aria-label={`Open select ${row.id}`}>
<Select.Value placeholder={row.label} />
<Select.Icon>v</Select.Icon>
<Select.Trigger aria-label={`Open select ${row.id}`} className={selectStyles.Select}>
<Select.Value placeholder={row.label} className={selectStyles.Value} />
<Select.Icon className={selectStyles.SelectIcon}>v</Select.Icon>
</Select.Trigger>
<Select.Portal>
<Select.Positioner sideOffset={8}>
<Select.Popup>
<Select.List>
<Select.Positioner sideOffset={8} className={selectStyles.Positioner}>
<Select.Popup className={selectStyles.Popup}>
<Select.List className={selectStyles.List}>
{listItems.map((item) => (
<Select.Item key={item.id} value={item.value}>
<Select.ItemIndicator />
<Select.ItemText>{item.label}</Select.ItemText>
<Select.Item key={item.id} value={item.value} className={selectStyles.Item}>
<Select.ItemIndicator className={selectStyles.ItemIndicator} />
<Select.ItemText className={selectStyles.ItemText}>
{item.label}
</Select.ItemText>
</Select.Item>
))}
</Select.List>
Expand All @@ -96,13 +124,19 @@ function MixedSurface() {

{dialogRows.map((row) => (
<Dialog.Root key={`dialog-${row.id}`}>
<Dialog.Trigger aria-label={`Open dialog ${row.id}`}>{row.label}</Dialog.Trigger>
<Dialog.Trigger aria-label={`Open dialog ${row.id}`} className={dialogStyles.Button}>
{row.label}
</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Backdrop />
<Dialog.Popup>
<Dialog.Title>{row.label}</Dialog.Title>
<Dialog.Description>Dialog content</Dialog.Description>
<Dialog.Close>Close</Dialog.Close>
<Dialog.Backdrop className={dialogStyles.Backdrop} />
<Dialog.Popup className={dialogStyles.Popup}>
<Dialog.Title className={dialogStyles.Title}>{row.label}</Dialog.Title>
<Dialog.Description className={dialogStyles.Description}>
Dialog content
</Dialog.Description>
<div className={dialogStyles.Actions}>
<Dialog.Close className={dialogStyles.Button}>Close</Dialog.Close>
</div>
</Dialog.Popup>
</Dialog.Portal>
</Dialog.Root>
Expand All @@ -111,17 +145,17 @@ function MixedSurface() {

<section>
{tabsRows.map((row) => (
<Tabs.Root key={`tabs-${row.id}`} defaultValue={tabValues[0]}>
<Tabs.List aria-label={row.label}>
<Tabs.Root key={`tabs-${row.id}`} defaultValue={tabValues[0]} className={tabsStyles.Tabs}>
<Tabs.List aria-label={row.label} className={tabsStyles.List}>
{tabValues.map((value) => (
<Tabs.Tab key={value} value={value}>
<Tabs.Tab key={value} value={value} className={tabsStyles.Tab}>
{value}
</Tabs.Tab>
))}
<Tabs.Indicator />
<Tabs.Indicator className={tabsStyles.Indicator} />
</Tabs.List>
{tabValues.map((value) => (
<Tabs.Panel key={value} value={value}>
<Tabs.Panel key={value} value={value} className={tabsStyles.Panel}>
{row.label} {value}
</Tabs.Panel>
))}
Expand All @@ -131,10 +165,10 @@ function MixedSurface() {
{sliderRows.map((row) => (
<Slider.Root key={`slider-${row.id}`} defaultValue={50}>
<Slider.Value />
<Slider.Control aria-label={row.label}>
<Slider.Track>
<Slider.Indicator />
<Slider.Thumb />
<Slider.Control aria-label={row.label} className={sliderStyles.Control}>
<Slider.Track className={sliderStyles.Track}>
<Slider.Indicator className={sliderStyles.Indicator} />
<Slider.Thumb className={sliderStyles.Thumb} />
</Slider.Track>
</Slider.Control>
</Slider.Root>
Expand All @@ -143,26 +177,31 @@ function MixedSurface() {
{scrollAreaRows.map((row) => (
<ScrollArea.Root
key={`scroll-area-${row.id}`}
className={scrollAreaStyles.ScrollArea}
style={{ width: 120, height: 120, overflow: 'hidden', position: 'relative' }}
>
<ScrollArea.Viewport>
<ScrollArea.Content>
<ScrollArea.Viewport className={scrollAreaStyles.Viewport}>
<ScrollArea.Content className={scrollAreaStyles.Content}>
<div style={{ width: 240, height: 240 }}>{row.label}</div>
</ScrollArea.Content>
</ScrollArea.Viewport>
<ScrollArea.Scrollbar>
<ScrollArea.Thumb />
<ScrollArea.Scrollbar className={scrollAreaStyles.Scrollbar}>
<ScrollArea.Thumb className={scrollAreaStyles.Thumb} />
</ScrollArea.Scrollbar>
<ScrollArea.Scrollbar orientation="horizontal">
<ScrollArea.Thumb />
<ScrollArea.Scrollbar orientation="horizontal" className={scrollAreaStyles.Scrollbar}>
<ScrollArea.Thumb className={scrollAreaStyles.Thumb} />
</ScrollArea.Scrollbar>
<ScrollArea.Corner />
</ScrollArea.Root>
))}

{checkboxRows.map((row) => (
<Checkbox.Root key={`checkbox-${row.id}`} aria-label={row.label}>
<Checkbox.Indicator />
<Checkbox.Root
key={`checkbox-${row.id}`}
aria-label={row.label}
className={checkboxStyles.Checkbox}
>
<Checkbox.Indicator className={checkboxStyles.Indicator} />
</Checkbox.Root>
))}
</section>
Expand Down
19 changes: 12 additions & 7 deletions test/performance/tests/popover.bench.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,25 @@ import * as React from 'react';
import { Popover } from '@base-ui/react/popover';
import { benchmark } from '@mui/internal-benchmark';
import { createRows, MountList } from './shared';
import styles from './styles/popover.module.css';

const popoverRows = createRows(300, 'Popover');
const popoverRows = createRows(150, 'Popover');

function PopoverMountList() {
return (
<MountList rows={popoverRows}>
{(row) => (
<Popover.Root key={row.id}>
<Popover.Trigger aria-label={`Open ${row.label}`}>{row.label}</Popover.Trigger>
<Popover.Trigger aria-label={`Open ${row.label}`} className={styles.IconButton}>
{row.label}
</Popover.Trigger>
<Popover.Portal>
<Popover.Positioner sideOffset={8}>
<Popover.Popup>
<Popover.Title>{row.label}</Popover.Title>
<Popover.Description>Popover content</Popover.Description>
<Popover.Positioner sideOffset={8} className={styles.Positioner}>
<Popover.Popup className={styles.Popup}>
<Popover.Title className={styles.Title}>{row.label}</Popover.Title>
<Popover.Description className={styles.Description}>
Popover content
</Popover.Description>
</Popover.Popup>
</Popover.Positioner>
</Popover.Portal>
Expand All @@ -25,4 +30,4 @@ function PopoverMountList() {
);
}

benchmark('Popover mount (300 instances)', () => <PopoverMountList />);
benchmark('Popover mount (150 instances)', () => <PopoverMountList />);
Loading
Loading