Improve BUI manifest
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
+2
-3
@@ -55,9 +55,8 @@ export default defineMain({
|
||||
name: getAbsolutePath('@storybook/react-vite'),
|
||||
options: {},
|
||||
},
|
||||
features: {
|
||||
experimentalComponentsManifest: true,
|
||||
experimentalCodeExamples: true, // optional
|
||||
typescript: {
|
||||
reactDocgen: 'react-docgen',
|
||||
},
|
||||
viteFinal: async (config, { configType }) => {
|
||||
// Add Node.js polyfills for browser compatibility
|
||||
|
||||
+8
-8
@@ -136,13 +136,13 @@
|
||||
"@octokit/rest": "^19.0.3",
|
||||
"@playwright/test": "^1.32.3",
|
||||
"@spotify/eslint-plugin": "^15.0.0",
|
||||
"@storybook/addon-a11y": "^10.3.0-alpha.1",
|
||||
"@storybook/addon-docs": "^10.3.0-alpha.1",
|
||||
"@storybook/addon-links": "^10.3.0-alpha.1",
|
||||
"@storybook/addon-mcp": "^0.3.0",
|
||||
"@storybook/addon-themes": "^10.3.0-alpha.1",
|
||||
"@storybook/addon-vitest": "^10.3.0-alpha.1",
|
||||
"@storybook/react-vite": "^10.3.0-alpha.1",
|
||||
"@storybook/addon-a11y": "^10.3.3",
|
||||
"@storybook/addon-docs": "^10.3.3",
|
||||
"@storybook/addon-links": "^10.3.3",
|
||||
"@storybook/addon-mcp": "^0.4.2",
|
||||
"@storybook/addon-themes": "^10.3.3",
|
||||
"@storybook/addon-vitest": "^10.3.3",
|
||||
"@storybook/react-vite": "^10.3.3",
|
||||
"@techdocs/cli": "workspace:*",
|
||||
"@types/cacheable-request": "^8.3.6",
|
||||
"@types/jest": "^30",
|
||||
@@ -173,7 +173,7 @@
|
||||
"shx": "^0.4.0",
|
||||
"sloc": "^0.3.1",
|
||||
"sort-package-json": "^3.0.0",
|
||||
"storybook": "^10.3.0-alpha.1",
|
||||
"storybook": "^10.3.3",
|
||||
"ts-morph": "^24.0.0",
|
||||
"typedoc": "^0.28.0",
|
||||
"typescript": "~5.7.0",
|
||||
|
||||
@@ -63,13 +63,13 @@
|
||||
"@types/react": "^18.0.0",
|
||||
"@types/react-dom": "^18.0.0",
|
||||
"@types/use-sync-external-store": "^0.0.6",
|
||||
"eslint-plugin-storybook": "^10.3.0-alpha.1",
|
||||
"eslint-plugin-storybook": "^10.3.3",
|
||||
"glob": "^11.0.1",
|
||||
"globals": "^17.0.0",
|
||||
"react": "^18.0.2",
|
||||
"react-dom": "^18.0.2",
|
||||
"react-router-dom": "^6.30.2",
|
||||
"storybook": "^10.3.0-alpha.1"
|
||||
"storybook": "^10.3.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "^18.0.0",
|
||||
|
||||
@@ -38,7 +38,11 @@ import {
|
||||
} from './definition';
|
||||
import { Flex } from '../Flex';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A collapsible section that reveals or hides its content when the trigger is activated.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const Accordion = forwardRef(
|
||||
(props: AccordionProps, ref: Ref<React.ElementRef<typeof RADisclosure>>) => {
|
||||
const { ownProps, restProps, dataAttributes } = useDefinition(
|
||||
@@ -62,7 +66,11 @@ export const Accordion = forwardRef(
|
||||
|
||||
Accordion.displayName = 'Accordion';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* The clickable heading that toggles the visibility of an accordion panel.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const AccordionTrigger = forwardRef(
|
||||
(
|
||||
props: AccordionTriggerProps,
|
||||
@@ -100,7 +108,11 @@ export const AccordionTrigger = forwardRef(
|
||||
|
||||
AccordionTrigger.displayName = 'AccordionTrigger';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* The content area of an accordion that is revealed when the trigger is activated.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const AccordionPanel = forwardRef(
|
||||
(
|
||||
props: AccordionPanelProps,
|
||||
@@ -125,7 +137,11 @@ export const AccordionPanel = forwardRef(
|
||||
|
||||
AccordionPanel.displayName = 'AccordionPanel';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A container that groups multiple Accordion items, optionally allowing several panels to be expanded at once.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const AccordionGroup = forwardRef(
|
||||
(
|
||||
props: AccordionGroupProps,
|
||||
|
||||
@@ -19,7 +19,11 @@ import { AvatarProps } from './types';
|
||||
import { useDefinition } from '../../hooks/useDefinition';
|
||||
import { AvatarDefinition } from './definition';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Displays a user's profile image with an automatic fallback to their initials when the image fails to load.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const Avatar = forwardRef<HTMLDivElement, AvatarProps>((props, ref) => {
|
||||
const { ownProps, restProps, dataAttributes } = useDefinition(
|
||||
AvatarDefinition,
|
||||
|
||||
@@ -19,7 +19,11 @@ import { BoxProps } from './types';
|
||||
import { useDefinition } from '../../hooks/useDefinition';
|
||||
import { BoxDefinition } from './definition';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A general-purpose layout primitive that can render as any HTML element and supports spacing, sizing, and background props.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const Box = forwardRef<HTMLDivElement, BoxProps>((props, ref) => {
|
||||
const { ownProps, restProps, dataAttributes, utilityStyle } = useDefinition(
|
||||
BoxDefinition,
|
||||
|
||||
@@ -21,7 +21,11 @@ import type { ButtonIconProps } from './types';
|
||||
import { useDefinition } from '../../hooks/useDefinition';
|
||||
import { ButtonIconDefinition } from './definition';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* An icon-only button that supports a loading state and requires an accessible label.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const ButtonIcon = forwardRef(
|
||||
(props: ButtonIconProps, ref: Ref<HTMLButtonElement>) => {
|
||||
const { ownProps, restProps, dataAttributes } = useDefinition(
|
||||
|
||||
@@ -21,7 +21,11 @@ import { useDefinition } from '../../hooks/useDefinition';
|
||||
import { ButtonLinkDefinition } from './definition';
|
||||
import { getNodeText } from '../../analytics/getNodeText';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A button-styled anchor element for navigation, supporting optional start and end icon slots and analytics event tracking.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const ButtonLink = forwardRef(
|
||||
(props: ButtonLinkProps, ref: Ref<HTMLAnchorElement>) => {
|
||||
const { ownProps, restProps, dataAttributes, analytics } = useDefinition(
|
||||
|
||||
@@ -21,7 +21,11 @@ import { useDefinition } from '../../hooks/useDefinition';
|
||||
import { CheckboxDefinition } from './definition';
|
||||
import { RiCheckLine, RiSubtractLine } from '@remixicon/react';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A form checkbox input with support for indeterminate state and accessible labeling.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const Checkbox = forwardRef<HTMLLabelElement, CheckboxProps>(
|
||||
(props, ref) => {
|
||||
const { ownProps, restProps, dataAttributes } = useDefinition(
|
||||
|
||||
@@ -19,7 +19,11 @@ import type { ContainerProps } from './types';
|
||||
import { useDefinition } from '../../hooks/useDefinition';
|
||||
import { ContainerDefinition } from './definition';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A centered layout wrapper that constrains content to a maximum width and provides consistent page-level padding.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const Container = forwardRef<HTMLDivElement, ContainerProps>(
|
||||
(props, ref) => {
|
||||
const { ownProps, restProps, utilityStyle } = useDefinition(
|
||||
|
||||
@@ -41,12 +41,20 @@ import { Box } from '../Box';
|
||||
import { BgReset } from '../../hooks/useBg';
|
||||
import { Flex } from '../Flex';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A wrapper that connects a trigger element to a Dialog, controlling its open and close state.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const DialogTrigger = (props: DialogTriggerProps) => {
|
||||
return <RADialogTrigger {...props} />;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A modal overlay that presents content requiring user interaction or acknowledgment, dismissible by clicking outside or pressing Escape.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const Dialog = forwardRef<React.ElementRef<typeof Modal>, DialogProps>(
|
||||
(props, ref) => {
|
||||
const { ownProps, restProps } = useDefinition(DialogDefinition, props, {
|
||||
@@ -89,7 +97,11 @@ export const Dialog = forwardRef<React.ElementRef<typeof Modal>, DialogProps>(
|
||||
|
||||
Dialog.displayName = 'Dialog';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* The header section of a Dialog, containing the title and a close button.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const DialogHeader = forwardRef<
|
||||
React.ElementRef<'div'>,
|
||||
DialogHeaderProps
|
||||
@@ -110,7 +122,11 @@ export const DialogHeader = forwardRef<
|
||||
});
|
||||
DialogHeader.displayName = 'DialogHeader';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* The main scrollable content area of a Dialog.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const DialogBody = forwardRef<React.ElementRef<'div'>, DialogBodyProps>(
|
||||
(props, ref) => {
|
||||
const { ownProps, restProps } = useDefinition(DialogBodyDefinition, props);
|
||||
@@ -126,7 +142,11 @@ export const DialogBody = forwardRef<React.ElementRef<'div'>, DialogBodyProps>(
|
||||
|
||||
DialogBody.displayName = 'DialogBody';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* The footer section of a Dialog, typically used to place action buttons.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const DialogFooter = forwardRef<
|
||||
React.ElementRef<'div'>,
|
||||
DialogFooterProps
|
||||
|
||||
@@ -20,7 +20,11 @@ import type { FieldErrorProps } from './types';
|
||||
import { useDefinition } from '../../hooks/useDefinition';
|
||||
import { FieldErrorDefinition } from './definition';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Displays a validation error message associated with a form field.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const FieldError = forwardRef<HTMLDivElement, FieldErrorProps>(
|
||||
(props: FieldErrorProps, ref) => {
|
||||
const { ownProps, restProps } = useDefinition(FieldErrorDefinition, props);
|
||||
|
||||
@@ -19,7 +19,11 @@ import type { FieldLabelProps } from './types';
|
||||
import { useDefinition } from '../../hooks/useDefinition';
|
||||
import { FieldLabelDefinition } from './definition';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* Renders a label for a form field with optional secondary label and description text.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const FieldLabel = forwardRef<HTMLDivElement, FieldLabelProps>(
|
||||
(props: FieldLabelProps, ref) => {
|
||||
const { ownProps, restProps } = useDefinition(FieldLabelDefinition, props);
|
||||
|
||||
@@ -19,7 +19,11 @@ import type { FlexProps } from './types';
|
||||
import { useDefinition } from '../../hooks/useDefinition';
|
||||
import { FlexDefinition } from './definition';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A flexbox layout container with props for controlling gap, alignment, justification, and direction.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const Flex = forwardRef<HTMLDivElement, FlexProps>((props, ref) => {
|
||||
const { ownProps, dataAttributes, utilityStyle, restProps } = useDefinition(
|
||||
FlexDefinition,
|
||||
|
||||
@@ -61,7 +61,11 @@ const LinkInternal = forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => {
|
||||
|
||||
LinkInternal.displayName = 'LinkInternal';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A styled anchor element that supports analytics event tracking on click.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const Link = forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => {
|
||||
return <LinkInternal {...props} ref={ref} />;
|
||||
});
|
||||
|
||||
@@ -76,7 +76,11 @@ const MenuEmptyState = () => {
|
||||
return <div className={ownProps.classes.root}>No results found.</div>;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A wrapper that connects a trigger element to a dropdown menu, controlling its open and close state.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const MenuTrigger = (props: MenuTriggerProps) => {
|
||||
return <RAMenuTrigger {...props} />;
|
||||
};
|
||||
|
||||
@@ -28,7 +28,11 @@ import { useDefinition } from '../../hooks/useDefinition';
|
||||
import { PasswordFieldDefinition } from './definition';
|
||||
import { RiEyeLine, RiEyeOffLine } from '@remixicon/react';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A text input for password entry with a toggleable visibility button, integrated label, and inline error display.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const PasswordField = forwardRef<HTMLDivElement, PasswordFieldProps>(
|
||||
(props, ref) => {
|
||||
const { ownProps, restProps, dataAttributes } = useDefinition(
|
||||
|
||||
@@ -26,7 +26,11 @@ import { RadioGroupDefinition, RadioDefinition } from './definition';
|
||||
|
||||
import type { RadioGroupProps, RadioProps } from './types';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A group of radio buttons for selecting a single option from a set, with an integrated label, description, and error display.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const RadioGroup = forwardRef<HTMLDivElement, RadioGroupProps>(
|
||||
(props, ref) => {
|
||||
const { ownProps, restProps } = useDefinition(RadioGroupDefinition, props);
|
||||
@@ -70,7 +74,11 @@ export const RadioGroup = forwardRef<HTMLDivElement, RadioGroupProps>(
|
||||
|
||||
RadioGroup.displayName = 'RadioGroup';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A single radio button for use within a RadioGroup.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const Radio = forwardRef<HTMLLabelElement, RadioProps>((props, ref) => {
|
||||
const { ownProps, restProps } = useDefinition(RadioDefinition, props);
|
||||
|
||||
|
||||
@@ -47,7 +47,11 @@ const SearchAutocompleteEmptyState = () => {
|
||||
return <div className={ownProps.classes.emptyState}>No results found.</div>;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A search input that shows a dropdown list of suggestions as the user types, with loading and empty states.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export function SearchAutocomplete(props: SearchAutocompleteProps) {
|
||||
const { ownProps, dataAttributes } = useDefinition(
|
||||
SearchAutocompleteDefinition,
|
||||
@@ -184,7 +188,11 @@ export function SearchAutocomplete(props: SearchAutocompleteProps) {
|
||||
);
|
||||
}
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* An individual option item within a SearchAutocomplete dropdown.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export function SearchAutocompleteItem(props: SearchAutocompleteItemProps) {
|
||||
const { ownProps, restProps } = useDefinition(
|
||||
SearchAutocompleteItemDefinition,
|
||||
|
||||
@@ -28,7 +28,11 @@ import { SearchFieldDefinition } from './definition';
|
||||
|
||||
import type { SearchFieldProps } from './types';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A text input optimized for search queries, with a built-in clear button, optional icon, and support for a collapsible mode.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const SearchField = forwardRef<HTMLDivElement, SearchFieldProps>(
|
||||
(props, ref) => {
|
||||
const { ownProps, restProps, dataAttributes } = useDefinition(
|
||||
|
||||
@@ -26,7 +26,11 @@ import { FieldError } from '../FieldError';
|
||||
import { SelectTrigger } from './SelectTrigger';
|
||||
import { SelectContent } from './SelectContent';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A dropdown picker for selecting one or multiple options from a list, with optional search filtering and inline error display.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const Select = forwardRef<
|
||||
HTMLDivElement,
|
||||
SelectProps<'single' | 'multiple'>
|
||||
|
||||
@@ -18,7 +18,11 @@ import type { SkeletonProps } from './types';
|
||||
import { useDefinition } from '../../hooks/useDefinition';
|
||||
import { SkeletonDefinition } from './definition';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A placeholder shape displayed while content is loading, matching the size and layout of the content it replaces.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const Skeleton = (props: SkeletonProps) => {
|
||||
const { ownProps, restProps, dataAttributes } = useDefinition(
|
||||
SkeletonDefinition,
|
||||
|
||||
@@ -115,7 +115,11 @@ function SliderImpl<T extends number | number[]>(
|
||||
);
|
||||
}
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A draggable input for selecting a numeric value or range within a defined interval, with an integrated label and value output.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const Slider = forwardRef(SliderImpl) as (<T extends number | number[]>(
|
||||
props: SliderProps<T> & { ref?: React.ForwardedRef<HTMLDivElement> },
|
||||
) => JSX.Element) & { displayName: string };
|
||||
|
||||
@@ -20,7 +20,11 @@ import type { SwitchProps } from './types';
|
||||
import { useDefinition } from '../../hooks/useDefinition';
|
||||
import { SwitchDefinition } from './definition';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A toggle control for switching between on and off states, with an optional visible label.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const Switch = forwardRef<HTMLLabelElement, SwitchProps>(
|
||||
(props, ref) => {
|
||||
const { ownProps, restProps } = useDefinition(SwitchDefinition, props);
|
||||
|
||||
@@ -19,7 +19,12 @@ import type { CellProps } from '../types';
|
||||
import { useDefinition } from '../../../hooks/useDefinition';
|
||||
import { CellDefinition } from '../definition';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A low-level table cell primitive for building custom cell content.
|
||||
* For standard use cases, prefer `CellText` or `CellProfile`.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
const Cell = (props: CellProps) => {
|
||||
const { ownProps, restProps } = useDefinition(CellDefinition, props);
|
||||
|
||||
|
||||
@@ -22,7 +22,11 @@ import { useDefinition } from '../../../hooks/useDefinition';
|
||||
import { CellProfileDefinition } from '../definition';
|
||||
import { Cell as ReactAriaCell } from 'react-aria-components';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A table cell that renders an avatar image alongside a name, with an optional description and link.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const CellProfile = (props: CellProfileProps) => {
|
||||
const { ownProps, restProps } = useDefinition(CellProfileDefinition, props);
|
||||
const { classes, src, name, href, description, color } = ownProps;
|
||||
|
||||
@@ -21,7 +21,11 @@ import type { CellTextProps } from '../types';
|
||||
import { useDefinition } from '../../../hooks/useDefinition';
|
||||
import { CellTextDefinition } from '../definition';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A table cell that renders a primary text title with an optional secondary description, leading icon, and link.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
const CellText = (props: CellTextProps) => {
|
||||
const { ownProps, restProps } = useDefinition(CellTextDefinition, props);
|
||||
const { classes, title, description, color, leadingIcon, href } = ownProps;
|
||||
|
||||
@@ -20,7 +20,11 @@ import { ColumnDefinition } from '../definition';
|
||||
import { ColumnProps } from '../types';
|
||||
import { RiArrowUpLine } from '@remixicon/react';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A table column header cell with an optional sort toggle and support for resizable widths.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const Column = (props: ColumnProps) => {
|
||||
const { ownProps, restProps } = useDefinition(ColumnDefinition, props);
|
||||
const { classes, children } = ownProps;
|
||||
|
||||
@@ -28,7 +28,11 @@ import { isExternalLink } from '../../../utils/linkUtils';
|
||||
import clsx from 'clsx';
|
||||
import { Flex } from '../../Flex';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A table row that can optionally act as a navigation link or trigger an action when clicked, with analytics tracking.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export function Row<T extends object>(props: RowProps<T>) {
|
||||
const { ownProps, restProps, dataAttributes, analytics } = useDefinition(
|
||||
RowDefinition,
|
||||
|
||||
@@ -98,7 +98,12 @@ function useLiveRegionLabel(
|
||||
return liveRegionLabel;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A full-featured data table with built-in pagination, sorting, row selection, loading and error states, and optional virtualization.
|
||||
* Pair with `useTable` to manage data fetching and state, or pass `data` and `pagination` directly for manual control.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export function Table<T extends TableItem>({
|
||||
columnConfig,
|
||||
data,
|
||||
|
||||
@@ -19,7 +19,11 @@ import { useDefinition } from '../../../hooks/useDefinition';
|
||||
import { TableBodyDefinition } from '../definition';
|
||||
import type { TableBodyProps } from '../types';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* The body section of a table that renders data rows from the provided items collection.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const TableBody = <T extends object>(props: TableBodyProps<T>) => {
|
||||
const { ownProps, restProps } = useDefinition(TableBodyDefinition, props);
|
||||
|
||||
|
||||
@@ -26,7 +26,11 @@ import { TableHeaderDefinition } from '../definition';
|
||||
import type { TableHeaderProps } from '../types';
|
||||
import { Flex } from '../../Flex';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* The header row of a table, rendering column labels and an optional select-all checkbox for toggle selection mode.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const TableHeader = <T extends object>(props: TableHeaderProps<T>) => {
|
||||
let { selectionBehavior, selectionMode } = useTableOptions();
|
||||
|
||||
|
||||
@@ -19,7 +19,12 @@ import { TableDefinition } from '../definition';
|
||||
import { Table as ReactAriaTable } from 'react-aria-components';
|
||||
import { TableRootProps } from '../types';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* The low-level table root element for building custom table layouts from atomic components.
|
||||
* For most use cases, prefer the `Table` convenience wrapper.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const TableRoot = (props: TableRootProps) => {
|
||||
const { ownProps, restProps, dataAttributes } = useDefinition(
|
||||
TableDefinition,
|
||||
|
||||
@@ -121,7 +121,12 @@ function useTableProps<T extends TableItem>(
|
||||
);
|
||||
}
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A hook that manages table data fetching, pagination, sorting, search, and filtering.
|
||||
* Supports three modes: `complete` for client-side data, `offset` for server-side offset pagination, and `cursor` for server-side cursor pagination.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export function useTable<T extends TableItem, TFilter = unknown>(
|
||||
options: UseTableCompleteOptions<T, TFilter>,
|
||||
): UseTableResult<T, TFilter>;
|
||||
|
||||
@@ -1,202 +0,0 @@
|
||||
/* eslint-disable no-restricted-syntax */
|
||||
/*
|
||||
* Copyright 2025 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { useState } from 'react';
|
||||
import type { Meta, StoryObj } from '@storybook/react-vite';
|
||||
import { Table, CellText, CellProfile, useTable, type ColumnConfig } from '..';
|
||||
import { Flex } from '../../Flex';
|
||||
import { Text } from '../../Text';
|
||||
import { RadioGroup, Radio } from '../../RadioGroup';
|
||||
import { data as data4 } from './mocked-data4';
|
||||
import { selectionData, selectionColumns, tableStoriesMeta } from './utils';
|
||||
|
||||
const meta = {
|
||||
title: 'Backstage UI/Table/docs',
|
||||
...tableStoriesMeta,
|
||||
} satisfies Meta;
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof meta>;
|
||||
type Data4Item = (typeof data4)[0];
|
||||
|
||||
export const TableRockBand: Story = {
|
||||
render: () => {
|
||||
const columns: ColumnConfig<Data4Item>[] = [
|
||||
{
|
||||
id: 'name',
|
||||
label: 'Band name',
|
||||
isRowHeader: true,
|
||||
defaultWidth: '4fr',
|
||||
cell: item => (
|
||||
<CellProfile name={item.name} src={item.image} href={item.website} />
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 'genre',
|
||||
label: 'Genre',
|
||||
defaultWidth: '4fr',
|
||||
cell: item => <CellText title={item.genre} />,
|
||||
},
|
||||
{
|
||||
id: 'yearFormed',
|
||||
label: 'Year formed',
|
||||
defaultWidth: '1fr',
|
||||
cell: item => <CellText title={item.yearFormed.toString()} />,
|
||||
},
|
||||
{
|
||||
id: 'albums',
|
||||
label: 'Albums',
|
||||
defaultWidth: '1fr',
|
||||
cell: item => <CellText title={item.albums.toString()} />,
|
||||
},
|
||||
];
|
||||
|
||||
const { tableProps } = useTable({
|
||||
mode: 'complete',
|
||||
getData: () => data4,
|
||||
paginationOptions: { pageSize: 5 },
|
||||
});
|
||||
|
||||
return <Table columnConfig={columns} {...tableProps} />;
|
||||
},
|
||||
};
|
||||
|
||||
export const SelectionToggleWithActions: Story = {
|
||||
render: () => {
|
||||
const [selected, setSelected] = useState<Set<string | number> | 'all'>(
|
||||
new Set(),
|
||||
);
|
||||
|
||||
const { tableProps } = useTable({
|
||||
mode: 'complete',
|
||||
getData: () => selectionData,
|
||||
paginationOptions: { pageSize: 10 },
|
||||
});
|
||||
|
||||
return (
|
||||
<Table
|
||||
{...tableProps}
|
||||
columnConfig={selectionColumns}
|
||||
selection={{
|
||||
mode: 'multiple',
|
||||
behavior: 'toggle',
|
||||
selected,
|
||||
onSelectionChange: setSelected,
|
||||
}}
|
||||
rowConfig={{ onClick: item => alert(`Clicked: ${item.name}`) }}
|
||||
/>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export const SelectionModePlayground: Story = {
|
||||
render: () => {
|
||||
const [selectionMode, setSelectionMode] = useState<'single' | 'multiple'>(
|
||||
'multiple',
|
||||
);
|
||||
const [selected, setSelected] = useState<Set<string | number> | 'all'>(
|
||||
new Set(),
|
||||
);
|
||||
|
||||
const { tableProps } = useTable({
|
||||
mode: 'complete',
|
||||
getData: () => selectionData,
|
||||
paginationOptions: { pageSize: 10 },
|
||||
});
|
||||
|
||||
return (
|
||||
<Flex direction="column" gap="8">
|
||||
<Table
|
||||
{...tableProps}
|
||||
columnConfig={selectionColumns}
|
||||
selection={{
|
||||
mode: selectionMode,
|
||||
behavior: 'toggle',
|
||||
selected,
|
||||
onSelectionChange: setSelected,
|
||||
}}
|
||||
/>
|
||||
<div>
|
||||
<Text as="h4" style={{ marginBottom: 'var(--bui-space-2)' }}>
|
||||
Selection mode:
|
||||
</Text>
|
||||
<RadioGroup
|
||||
aria-label="Selection mode"
|
||||
orientation="horizontal"
|
||||
value={selectionMode}
|
||||
onChange={value => {
|
||||
setSelectionMode(value as 'single' | 'multiple');
|
||||
setSelected(new Set());
|
||||
}}
|
||||
>
|
||||
<Radio value="single">single</Radio>
|
||||
<Radio value="multiple">multiple</Radio>
|
||||
</RadioGroup>
|
||||
</div>
|
||||
</Flex>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export const SelectionBehaviorPlayground: Story = {
|
||||
render: () => {
|
||||
const [selectionBehavior, setSelectionBehavior] = useState<
|
||||
'toggle' | 'replace'
|
||||
>('toggle');
|
||||
const [selected, setSelected] = useState<Set<string | number> | 'all'>(
|
||||
new Set(),
|
||||
);
|
||||
|
||||
const { tableProps } = useTable({
|
||||
mode: 'complete',
|
||||
getData: () => selectionData,
|
||||
paginationOptions: { pageSize: 10 },
|
||||
});
|
||||
|
||||
return (
|
||||
<Flex direction="column" gap="8">
|
||||
<Table
|
||||
{...tableProps}
|
||||
columnConfig={selectionColumns}
|
||||
selection={{
|
||||
mode: 'multiple',
|
||||
behavior: selectionBehavior,
|
||||
selected,
|
||||
onSelectionChange: setSelected,
|
||||
}}
|
||||
/>
|
||||
<div>
|
||||
<Text as="h4" style={{ marginBottom: 'var(--bui-space-2)' }}>
|
||||
Selection behavior:
|
||||
</Text>
|
||||
<RadioGroup
|
||||
aria-label="Selection behavior"
|
||||
orientation="horizontal"
|
||||
value={selectionBehavior}
|
||||
onChange={value => {
|
||||
setSelectionBehavior(value as 'toggle' | 'replace');
|
||||
setSelected(new Set());
|
||||
}}
|
||||
>
|
||||
<Radio value="toggle">toggle</Radio>
|
||||
<Radio value="replace">replace</Radio>
|
||||
</RadioGroup>
|
||||
</div>
|
||||
</Flex>
|
||||
);
|
||||
},
|
||||
};
|
||||
@@ -47,7 +47,11 @@ function TextComponent<T extends ElementType = 'span'>(
|
||||
|
||||
TextComponent.displayName = 'Text';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A typographic primitive that renders text with design system variants, weights, and colors, and can render as any HTML element.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const Text = forwardRef(TextComponent) as {
|
||||
<T extends ElementType = 'p'>(
|
||||
props: TextProps<T> & { ref?: React.ComponentPropsWithRef<T>['ref'] },
|
||||
|
||||
@@ -22,7 +22,11 @@ import type { TextFieldProps } from './types';
|
||||
import { useDefinition } from '../../hooks/useDefinition';
|
||||
import { TextFieldDefinition } from './definition';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A single-line text input with an integrated label, optional icon, and inline error display.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const TextField = forwardRef<HTMLDivElement, TextFieldProps>(
|
||||
(props, ref) => {
|
||||
const { ownProps, restProps, dataAttributes } = useDefinition(
|
||||
|
||||
@@ -20,7 +20,11 @@ import type { ToggleButtonProps } from './types';
|
||||
import { useDefinition } from '../../hooks/useDefinition';
|
||||
import { ToggleButtonDefinition } from './definition';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A button that maintains a pressed or unpressed state, with optional start and end icon slots.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const ToggleButton = forwardRef(
|
||||
(props: ToggleButtonProps, ref: Ref<HTMLButtonElement>) => {
|
||||
const { ownProps, restProps, dataAttributes } = useDefinition(
|
||||
|
||||
@@ -20,7 +20,11 @@ import type { ToggleButtonGroupProps } from './types';
|
||||
import { useDefinition } from '../../hooks/useDefinition';
|
||||
import { ToggleButtonGroupDefinition } from './definition';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A container that groups ToggleButton items and manages their collective selection state.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const ToggleButtonGroup = forwardRef(
|
||||
(props: ToggleButtonGroupProps, ref: Ref<HTMLDivElement>) => {
|
||||
const { ownProps, restProps } = useDefinition(
|
||||
|
||||
@@ -28,14 +28,22 @@ import { TooltipDefinition } from './definition';
|
||||
import { Box } from '../Box';
|
||||
import { BgReset } from '../../hooks/useBg';
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A wrapper that connects a trigger element to a Tooltip, controlling its show and hide behavior with a configurable delay.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const TooltipTrigger = (props: TooltipTriggerComponentProps) => {
|
||||
const { delay = 600 } = props;
|
||||
|
||||
return <AriaTooltipTrigger delay={delay} {...props} />;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
/**
|
||||
* A floating label that provides contextual information about an element when it receives hover or focus.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export const Tooltip = forwardRef<HTMLDivElement, TooltipProps>(
|
||||
(props, ref) => {
|
||||
const { ownProps, restProps } = useDefinition(TooltipDefinition, props);
|
||||
|
||||
@@ -20,6 +20,7 @@ import { Text } from '../components/Text';
|
||||
|
||||
const meta = preview.meta({
|
||||
title: 'Backstage UI/Colors',
|
||||
tags: ['!manifest'],
|
||||
});
|
||||
|
||||
export const Default = meta.story({
|
||||
|
||||
@@ -7946,7 +7946,7 @@ __metadata:
|
||||
"@types/react-dom": "npm:^18.0.0"
|
||||
"@types/use-sync-external-store": "npm:^0.0.6"
|
||||
clsx: "npm:^2.1.1"
|
||||
eslint-plugin-storybook: "npm:^10.3.0-alpha.1"
|
||||
eslint-plugin-storybook: "npm:^10.3.3"
|
||||
glob: "npm:^11.0.1"
|
||||
globals: "npm:^17.0.0"
|
||||
react: "npm:^18.0.2"
|
||||
@@ -7955,7 +7955,7 @@ __metadata:
|
||||
react-dom: "npm:^18.0.2"
|
||||
react-router-dom: "npm:^6.30.2"
|
||||
react-stately: "npm:^3.45.0"
|
||||
storybook: "npm:^10.3.0-alpha.1"
|
||||
storybook: "npm:^10.3.3"
|
||||
use-sync-external-store: "npm:^1.4.0"
|
||||
peerDependencies:
|
||||
"@types/react": ^18.0.0
|
||||
@@ -19267,7 +19267,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-a11y@npm:^10.3.0-alpha.1":
|
||||
"@storybook/addon-a11y@npm:^10.3.3":
|
||||
version: 10.3.3
|
||||
resolution: "@storybook/addon-a11y@npm:10.3.3"
|
||||
dependencies:
|
||||
@@ -19279,7 +19279,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-docs@npm:^10.3.0-alpha.1":
|
||||
"@storybook/addon-docs@npm:^10.3.3":
|
||||
version: 10.3.3
|
||||
resolution: "@storybook/addon-docs@npm:10.3.3"
|
||||
dependencies:
|
||||
@@ -19296,7 +19296,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-links@npm:^10.3.0-alpha.1":
|
||||
"@storybook/addon-links@npm:^10.3.3":
|
||||
version: 10.3.3
|
||||
resolution: "@storybook/addon-links@npm:10.3.3"
|
||||
dependencies:
|
||||
@@ -19311,11 +19311,11 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-mcp@npm:^0.3.0":
|
||||
version: 0.3.4
|
||||
resolution: "@storybook/addon-mcp@npm:0.3.4"
|
||||
"@storybook/addon-mcp@npm:^0.4.2":
|
||||
version: 0.4.2
|
||||
resolution: "@storybook/addon-mcp@npm:0.4.2"
|
||||
dependencies:
|
||||
"@storybook/mcp": "npm:0.5.1"
|
||||
"@storybook/mcp": "npm:0.6.1"
|
||||
"@tmcp/adapter-valibot": "npm:^0.1.4"
|
||||
"@tmcp/transport-http": "npm:^0.8.0"
|
||||
picoquery: "npm:^2.5.0"
|
||||
@@ -19327,11 +19327,11 @@ __metadata:
|
||||
peerDependenciesMeta:
|
||||
"@storybook/addon-vitest":
|
||||
optional: true
|
||||
checksum: 10/0fb377d8ee96055703cfee48c4a47d25367a090b4e343a0d5db15341137463ae01f167725e7087bc20fe072b474a798a6488452a3afce1b27c47049e65e56177
|
||||
checksum: 10/42408a05ec7e9a7bfd5f168e7047b32a67d3a8cfcfaf68e74ddd820c9e188af006883e69173c4514f7845e29ebc58f6412be3c0ccab396590b3da4d1f3866bc6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-themes@npm:^10.3.0-alpha.1":
|
||||
"@storybook/addon-themes@npm:^10.3.3":
|
||||
version: 10.3.3
|
||||
resolution: "@storybook/addon-themes@npm:10.3.3"
|
||||
dependencies:
|
||||
@@ -19342,7 +19342,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/addon-vitest@npm:^10.3.0-alpha.1":
|
||||
"@storybook/addon-vitest@npm:^10.3.3":
|
||||
version: 10.3.3
|
||||
resolution: "@storybook/addon-vitest@npm:10.3.3"
|
||||
dependencies:
|
||||
@@ -19421,15 +19421,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/mcp@npm:0.5.1":
|
||||
version: 0.5.1
|
||||
resolution: "@storybook/mcp@npm:0.5.1"
|
||||
"@storybook/mcp@npm:0.6.1":
|
||||
version: 0.6.1
|
||||
resolution: "@storybook/mcp@npm:0.6.1"
|
||||
dependencies:
|
||||
"@tmcp/adapter-valibot": "npm:^0.1.4"
|
||||
"@tmcp/transport-http": "npm:^0.8.0"
|
||||
tmcp: "npm:^1.16.0"
|
||||
valibot: "npm:1.2.0"
|
||||
checksum: 10/a5924be156db45ac86ee57c325878ee1a46cf3bf9523fc9f231d8f491e3a77f92d74801d138a4af6256cebcd74c8aa5985d0c9fded4fcbdbd4708ccdcc70ee31
|
||||
checksum: 10/0f61c6a3866197ee894eda99642896d83dbbcc946dce089b8b5f099b6de3ec5ec4ec0fc40e0a36fd9e5ef9ff0d3241a49e371aaf5d9ef75ef4f50fd46b5787f8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -19444,7 +19444,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@storybook/react-vite@npm:^10.3.0-alpha.1":
|
||||
"@storybook/react-vite@npm:^10.3.3":
|
||||
version: 10.3.3
|
||||
resolution: "@storybook/react-vite@npm:10.3.3"
|
||||
dependencies:
|
||||
@@ -30157,7 +30157,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"eslint-plugin-storybook@npm:^10.3.0-alpha.1":
|
||||
"eslint-plugin-storybook@npm:^10.3.3":
|
||||
version: 10.3.3
|
||||
resolution: "eslint-plugin-storybook@npm:10.3.3"
|
||||
dependencies:
|
||||
@@ -45112,13 +45112,13 @@ __metadata:
|
||||
"@octokit/rest": "npm:^19.0.3"
|
||||
"@playwright/test": "npm:^1.32.3"
|
||||
"@spotify/eslint-plugin": "npm:^15.0.0"
|
||||
"@storybook/addon-a11y": "npm:^10.3.0-alpha.1"
|
||||
"@storybook/addon-docs": "npm:^10.3.0-alpha.1"
|
||||
"@storybook/addon-links": "npm:^10.3.0-alpha.1"
|
||||
"@storybook/addon-mcp": "npm:^0.3.0"
|
||||
"@storybook/addon-themes": "npm:^10.3.0-alpha.1"
|
||||
"@storybook/addon-vitest": "npm:^10.3.0-alpha.1"
|
||||
"@storybook/react-vite": "npm:^10.3.0-alpha.1"
|
||||
"@storybook/addon-a11y": "npm:^10.3.3"
|
||||
"@storybook/addon-docs": "npm:^10.3.3"
|
||||
"@storybook/addon-links": "npm:^10.3.3"
|
||||
"@storybook/addon-mcp": "npm:^0.4.2"
|
||||
"@storybook/addon-themes": "npm:^10.3.3"
|
||||
"@storybook/addon-vitest": "npm:^10.3.3"
|
||||
"@storybook/react-vite": "npm:^10.3.3"
|
||||
"@techdocs/cli": "workspace:*"
|
||||
"@types/cacheable-request": "npm:^8.3.6"
|
||||
"@types/global-agent": "npm:^2.1.3"
|
||||
@@ -45151,7 +45151,7 @@ __metadata:
|
||||
shx: "npm:^0.4.0"
|
||||
sloc: "npm:^0.3.1"
|
||||
sort-package-json: "npm:^3.0.0"
|
||||
storybook: "npm:^10.3.0-alpha.1"
|
||||
storybook: "npm:^10.3.3"
|
||||
ts-morph: "npm:^24.0.0"
|
||||
typedoc: "npm:^0.28.0"
|
||||
typescript: "npm:~5.7.0"
|
||||
@@ -46617,7 +46617,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"storybook@npm:^10.3.0-alpha.1":
|
||||
"storybook@npm:^10.3.3":
|
||||
version: 10.3.3
|
||||
resolution: "storybook@npm:10.3.3"
|
||||
dependencies:
|
||||
|
||||
Reference in New Issue
Block a user