Migrate PluginHeader component from useStyles to useDefinition

Signed-off-by: Johan Persson <johanopersson@gmail.com>
This commit is contained in:
Johan Persson
2026-02-26 10:53:29 +01:00
parent 437ae1943d
commit a393ed3f17
7 changed files with 108 additions and 102 deletions
+16 -7
View File
@@ -1743,20 +1743,26 @@ export const PluginHeader: (props: PluginHeaderProps) => JSX_2.Element;
// @public
export const PluginHeaderDefinition: {
readonly styles: {
readonly [key: string]: string;
};
readonly classNames: {
readonly root: 'bui-PluginHeader';
readonly toolbar: 'bui-PluginHeaderToolbar';
readonly toolbarWrapper: 'bui-PluginHeaderToolbarWrapper';
readonly toolbarContent: 'bui-PluginHeaderToolbarContent';
readonly toolbarControls: 'bui-PluginHeaderToolbarControls';
readonly toolbarIcon: 'bui-PluginHeaderToolbarIcon';
readonly toolbarName: 'bui-PluginHeaderToolbarName';
readonly tabsWrapper: 'bui-PluginHeaderTabsWrapper';
};
readonly propDefs: {
readonly icon: {};
readonly title: {};
readonly titleLink: {};
readonly customActions: {};
readonly tabs: {};
readonly onTabSelectionChange: {};
readonly className: {};
};
};
// @public
export interface PluginHeaderProps {
export interface PluginHeaderOwnProps {
// (undocumented)
className?: string;
// (undocumented)
@@ -1773,6 +1779,9 @@ export interface PluginHeaderProps {
titleLink?: string;
}
// @public
export interface PluginHeaderProps extends PluginHeaderOwnProps {}
// @public
export const Popover: ForwardRefExoticComponent<
PopoverProps & RefAttributes<HTMLDivElement>
@@ -17,13 +17,11 @@
import type { PluginHeaderProps } from './types';
import { PluginHeaderToolbar } from './PluginHeaderToolbar';
import { Tabs, TabList, Tab } from '../Tabs';
import { useStyles } from '../../hooks/useStyles';
import { useDefinition } from '../../hooks/useDefinition';
import { PluginHeaderDefinition } from './definition';
import { type NavigateOptions } from 'react-router-dom';
import { useRef } from 'react';
import { useIsomorphicLayoutEffect } from '../../hooks/useIsomorphicLayoutEffect';
import styles from './PluginHeader.module.css';
import clsx from 'clsx';
declare module 'react-aria-components' {
interface RouterConfig {
@@ -38,16 +36,16 @@ declare module 'react-aria-components' {
* @public
*/
export const PluginHeader = (props: PluginHeaderProps) => {
const { classNames, cleanedProps } = useStyles(PluginHeaderDefinition, props);
const { ownProps } = useDefinition(PluginHeaderDefinition, props);
const {
className,
classes,
tabs,
icon,
title,
titleLink,
customActions,
onTabSelectionChange,
} = cleanedProps;
} = ownProps;
const hasTabs = tabs && tabs.length > 0;
const headerRef = useRef<HTMLElement>(null);
@@ -85,10 +83,7 @@ export const PluginHeader = (props: PluginHeaderProps) => {
}, []);
return (
<header
ref={headerRef}
className={clsx(classNames.root, styles[classNames.root], className)}
>
<header ref={headerRef} className={classes.root}>
<PluginHeaderToolbar
icon={icon}
title={title}
@@ -97,12 +92,7 @@ export const PluginHeader = (props: PluginHeaderProps) => {
hasTabs={hasTabs}
/>
{tabs && (
<div
className={clsx(
classNames.tabsWrapper,
styles[classNames.tabsWrapper],
)}
>
<div className={classes.tabsWrapper}>
<Tabs onSelectionChange={onTabSelectionChange}>
<TabList>
{tabs?.map(tab => (
@@ -15,14 +15,12 @@
*/
import { Link } from 'react-aria-components';
import { useStyles } from '../../hooks/useStyles';
import { PluginHeaderDefinition } from './definition';
import { useDefinition } from '../../hooks/useDefinition';
import { PluginHeaderToolbarDefinition } from './definition';
import { useRef } from 'react';
import { RiShapesLine } from '@remixicon/react';
import type { PluginHeaderToolbarProps } from './types';
import { Text } from '../Text';
import styles from './PluginHeader.module.css';
import clsx from 'clsx';
/**
* A component that renders the toolbar section of a plugin header.
@@ -30,9 +28,8 @@ import clsx from 'clsx';
* @internal
*/
export const PluginHeaderToolbar = (props: PluginHeaderToolbarProps) => {
const { classNames, cleanedProps } = useStyles(PluginHeaderDefinition, props);
const { className, icon, title, titleLink, customActions, hasTabs } =
cleanedProps;
const { ownProps } = useDefinition(PluginHeaderToolbarDefinition, props);
const { classes, icon, title, titleLink, customActions, hasTabs } = ownProps;
// Refs for collision detection
const toolbarWrapperRef = useRef<HTMLDivElement>(null);
@@ -41,68 +38,26 @@ export const PluginHeaderToolbar = (props: PluginHeaderToolbarProps) => {
const titleContent = (
<>
<div
className={clsx(classNames.toolbarIcon, styles[classNames.toolbarIcon])}
>
{icon || <RiShapesLine />}
</div>
<div className={classes.icon}>{icon || <RiShapesLine />}</div>
<Text variant="body-medium">{title || 'Your plugin'}</Text>
</>
);
return (
<div
className={clsx(
classNames.toolbar,
styles[classNames.toolbar],
className,
)}
data-has-tabs={hasTabs}
>
<div
className={clsx(
classNames.toolbarWrapper,
styles[classNames.toolbarWrapper],
)}
ref={toolbarWrapperRef}
>
<div
className={clsx(
classNames.toolbarContent,
styles[classNames.toolbarContent],
)}
ref={toolbarContentRef}
>
<div className={classes.root} data-has-tabs={hasTabs}>
<div className={classes.wrapper} ref={toolbarWrapperRef}>
<div className={classes.content} ref={toolbarContentRef}>
<Text as="h1" variant="body-medium">
{titleLink ? (
<Link
className={clsx(
classNames.toolbarName,
styles[classNames.toolbarName],
)}
href={titleLink}
>
<Link className={classes.name} href={titleLink}>
{titleContent}
</Link>
) : (
<div
className={clsx(
classNames.toolbarName,
styles[classNames.toolbarName],
)}
>
{titleContent}
</div>
<div className={classes.name}>{titleContent}</div>
)}
</Text>
</div>
<div
className={clsx(
classNames.toolbarControls,
styles[classNames.toolbarControls],
)}
ref={toolbarControlsRef}
>
<div className={classes.controls} ref={toolbarControlsRef}>
{customActions}
</div>
</div>
@@ -14,21 +14,55 @@
* limitations under the License.
*/
import type { ComponentDefinition } from '../../types';
import { defineComponent } from '../../hooks/useDefinition';
import type {
PluginHeaderOwnProps,
PluginHeaderToolbarOwnProps,
} from './types';
import styles from './PluginHeader.module.css';
/**
* Component definition for PluginHeader
* @public
*/
export const PluginHeaderDefinition = {
export const PluginHeaderDefinition = defineComponent<PluginHeaderOwnProps>()({
styles,
classNames: {
root: 'bui-PluginHeader',
toolbar: 'bui-PluginHeaderToolbar',
toolbarWrapper: 'bui-PluginHeaderToolbarWrapper',
toolbarContent: 'bui-PluginHeaderToolbarContent',
toolbarControls: 'bui-PluginHeaderToolbarControls',
toolbarIcon: 'bui-PluginHeaderToolbarIcon',
toolbarName: 'bui-PluginHeaderToolbarName',
tabsWrapper: 'bui-PluginHeaderTabsWrapper',
},
} as const satisfies ComponentDefinition;
propDefs: {
icon: {},
title: {},
titleLink: {},
customActions: {},
tabs: {},
onTabSelectionChange: {},
className: {},
},
});
/**
* Component definition for PluginHeaderToolbar
* @internal
*/
export const PluginHeaderToolbarDefinition =
defineComponent<PluginHeaderToolbarOwnProps>()({
styles,
classNames: {
root: 'bui-PluginHeaderToolbar',
wrapper: 'bui-PluginHeaderToolbarWrapper',
content: 'bui-PluginHeaderToolbarContent',
controls: 'bui-PluginHeaderToolbarControls',
icon: 'bui-PluginHeaderToolbarIcon',
name: 'bui-PluginHeaderToolbarName',
},
propDefs: {
icon: {},
title: {},
titleLink: {},
customActions: {},
hasTabs: {},
className: {},
},
});
@@ -16,4 +16,8 @@
export { PluginHeader } from './PluginHeader';
export { PluginHeaderDefinition } from './definition';
export type { PluginHeaderProps, HeaderTab } from './types';
export type {
PluginHeaderOwnProps,
PluginHeaderProps,
HeaderTab,
} from './types';
@@ -18,11 +18,11 @@ import { TabsProps } from 'react-aria-components';
import { TabMatchStrategy } from '../Tabs';
/**
* Props for the {@link PluginHeader} component.
* Own props for the {@link PluginHeader} component.
*
* @public
*/
export interface PluginHeaderProps {
export interface PluginHeaderOwnProps {
icon?: React.ReactNode;
title?: string;
titleLink?: string;
@@ -32,6 +32,13 @@ export interface PluginHeaderProps {
className?: string;
}
/**
* Props for the {@link PluginHeader} component.
*
* @public
*/
export interface PluginHeaderProps extends PluginHeaderOwnProps {}
/**
* Represents a tab item in the header navigation.
*
@@ -49,16 +56,23 @@ export interface HeaderTab {
matchStrategy?: TabMatchStrategy;
}
/**
* Own props for the PluginHeaderToolbar component.
*
* @internal
*/
export interface PluginHeaderToolbarOwnProps {
icon?: PluginHeaderOwnProps['icon'];
title?: PluginHeaderOwnProps['title'];
titleLink?: PluginHeaderOwnProps['titleLink'];
customActions?: PluginHeaderOwnProps['customActions'];
hasTabs?: boolean;
className?: string;
}
/**
* Props for the PluginHeaderToolbar component.
*
* @internal
*/
export interface PluginHeaderToolbarProps {
icon?: PluginHeaderProps['icon'];
title?: PluginHeaderProps['title'];
titleLink?: PluginHeaderProps['titleLink'];
customActions?: PluginHeaderProps['customActions'];
hasTabs?: boolean;
className?: string;
}
export interface PluginHeaderToolbarProps extends PluginHeaderToolbarOwnProps {}