diff --git a/packages/ui/report.api.md b/packages/ui/report.api.md index f33d5a750f..cb92b605d4 100644 --- a/packages/ui/report.api.md +++ b/packages/ui/report.api.md @@ -2355,40 +2355,72 @@ export interface TableSelection { export const TabList: (props: TabListProps) => JSX_2.Element; // @public -export interface TabListProps extends Omit, 'items'> {} +export type TabListOwnProps = { + className?: string; + children?: TabListProps_2['children']; +}; + +// @public +export interface TabListProps + extends TabListOwnProps, + Omit, 'items' | keyof TabListOwnProps> {} // @public export type TabMatchStrategy = 'exact' | 'prefix'; +// @public +export type TabOwnProps = { + className?: string; + matchStrategy?: TabMatchStrategy; + href?: TabProps_2['href']; + id?: TabProps_2['id']; +}; + // @public export const TabPanel: (props: TabPanelProps) => JSX_2.Element; // @public -export interface TabPanelProps extends TabPanelProps_2 {} +export type TabPanelOwnProps = { + className?: string; +}; // @public -export interface TabProps extends TabProps_2 { - matchStrategy?: 'exact' | 'prefix'; -} +export interface TabPanelProps + extends TabPanelOwnProps, + Omit {} + +// @public +export interface TabProps + extends TabOwnProps, + Omit {} // @public export const Tabs: (props: TabsProps) => JSX_2.Element | null; // @public export const TabsDefinition: { + readonly styles: { + readonly [key: string]: string; + }; readonly classNames: { - readonly tabs: 'bui-Tabs'; - readonly tabList: 'bui-TabList'; - readonly tabListWrapper: 'bui-TabListWrapper'; - readonly tab: 'bui-Tab'; - readonly tabActive: 'bui-TabActive'; - readonly tabHovered: 'bui-TabHovered'; - readonly panel: 'bui-TabPanel'; + readonly root: 'bui-Tabs'; + }; + readonly propDefs: { + readonly className: {}; + readonly children: {}; }; }; // @public -export interface TabsProps extends TabsProps_2 {} +export type TabsOwnProps = { + className?: string; + children?: TabsProps_2['children']; +}; + +// @public +export interface TabsProps + extends TabsOwnProps, + Omit {} // @public export const Tag: ForwardRefExoticComponent< diff --git a/packages/ui/src/components/Tabs/Tabs.tsx b/packages/ui/src/components/Tabs/Tabs.tsx index 11d77a6a5f..cf6263b9a4 100644 --- a/packages/ui/src/components/Tabs/Tabs.tsx +++ b/packages/ui/src/components/Tabs/Tabs.tsx @@ -43,14 +43,17 @@ import { TabPanel as AriaTabPanel, TabProps as AriaTabProps, } from 'react-aria-components'; -import { useStyles } from '../../hooks/useStyles'; -import { TabsDefinition } from './definition'; +import { useDefinition } from '../../hooks/useDefinition'; +import { + TabsDefinition, + TabListDefinition, + TabDefinition, + TabPanelDefinition, +} from './definition'; import { isInternalLink, createRoutingRegistration, } from '../InternalLinkProvider'; -import styles from './Tabs.module.css'; -import clsx from 'clsx'; const { RoutingProvider, useRoutingRegistrationEffect } = createRoutingRegistration(); @@ -105,8 +108,8 @@ const isTabActive = ( * @public */ export const Tabs = (props: TabsProps) => { - const { classNames, cleanedProps } = useStyles(TabsDefinition, props); - const { className, children, ...rest } = cleanedProps; + const { ownProps, restProps } = useDefinition(TabsDefinition, props); + const { classes, children } = ownProps; const tabsRef = useRef(null); const tabRefs = useRef>(new Map()); const [hoveredKey, setHoveredKey] = useState(null); @@ -210,15 +213,11 @@ export const Tabs = (props: TabsProps) => { {children as ReactNode} @@ -234,8 +233,8 @@ export const Tabs = (props: TabsProps) => { * @public */ export const TabList = (props: TabListProps) => { - const { classNames, cleanedProps } = useStyles(TabsDefinition, props); - const { className, children, ...rest } = cleanedProps; + const { ownProps, restProps } = useDefinition(TabListDefinition, props); + const { classes, children } = ownProps; const { setHoveredKey, tabRefs, tabsRef, hoveredKey, prevHoveredKey } = useTabsContext(); @@ -255,17 +254,11 @@ export const TabList = (props: TabListProps) => { }); return ( -
+
{enhancedChildren} @@ -330,9 +323,8 @@ function RoutedTabEffects({ * @public */ export const Tab = (props: TabProps) => { - const { classNames, cleanedProps } = useStyles(TabsDefinition, props); - const { className, href, children, id, matchStrategy, ...rest } = - cleanedProps; + const { ownProps, restProps } = useDefinition(TabDefinition, props); + const { classes, matchStrategy, href, id } = ownProps; const { setTabRef } = useTabsContext(); return ( @@ -346,13 +338,11 @@ export const Tab = (props: TabProps) => { )} setTabRef(id as string, el as HTMLDivElement)} href={href} - {...rest} - > - {children} - + {...restProps} + /> ); }; @@ -363,15 +353,7 @@ export const Tab = (props: TabProps) => { * @public */ export const TabPanel = (props: TabPanelProps) => { - const { classNames, cleanedProps } = useStyles(TabsDefinition, props); - const { className, children, ...rest } = cleanedProps; + const { ownProps, restProps } = useDefinition(TabPanelDefinition, props); - return ( - - {children} - - ); + return ; }; diff --git a/packages/ui/src/components/Tabs/TabsIndicators.tsx b/packages/ui/src/components/Tabs/TabsIndicators.tsx index 2aa4f72508..82826ac640 100644 --- a/packages/ui/src/components/Tabs/TabsIndicators.tsx +++ b/packages/ui/src/components/Tabs/TabsIndicators.tsx @@ -15,12 +15,10 @@ */ import { TabListStateContext } from 'react-aria-components'; -import { useStyles } from '../../hooks/useStyles'; -import { TabsDefinition } from './definition'; +import { useDefinition } from '../../hooks/useDefinition'; +import { TabsIndicatorsDefinition } from './definition'; import { useContext, useEffect, useCallback, useRef } from 'react'; import type { TabsIndicatorsProps } from './types'; -import styles from './Tabs.module.css'; -import clsx from 'clsx'; /** * A component that renders the indicators for the toolbar. @@ -28,8 +26,8 @@ import clsx from 'clsx'; * @internal */ export const TabsIndicators = (props: TabsIndicatorsProps) => { - const { tabRefs, tabsRef, hoveredKey, prevHoveredKey } = props; - const { classNames } = useStyles(TabsDefinition); + const { ownProps } = useDefinition(TabsIndicatorsDefinition, props); + const { classes, tabRefs, tabsRef, hoveredKey, prevHoveredKey } = ownProps; const state = useContext(TabListStateContext); const prevSelectedKey = useRef(null); @@ -187,12 +185,8 @@ export const TabsIndicators = (props: TabsIndicatorsProps) => { return ( <> -
-
+
+
); }; diff --git a/packages/ui/src/components/Tabs/definition.ts b/packages/ui/src/components/Tabs/definition.ts index 10e9247372..f938c8b3f8 100644 --- a/packages/ui/src/components/Tabs/definition.ts +++ b/packages/ui/src/components/Tabs/definition.ts @@ -14,20 +14,81 @@ * limitations under the License. */ -import type { ComponentDefinition } from '../../types'; +import { defineComponent } from '../../hooks/useDefinition'; +import type { + TabsOwnProps, + TabListOwnProps, + TabOwnProps, + TabPanelOwnProps, + TabsIndicatorsOwnProps, +} from './types'; +import styles from './Tabs.module.css'; /** * Component definition for Tabs * @public */ -export const TabsDefinition = { +export const TabsDefinition = defineComponent()({ + styles, classNames: { - tabs: 'bui-Tabs', - tabList: 'bui-TabList', - tabListWrapper: 'bui-TabListWrapper', - tab: 'bui-Tab', - tabActive: 'bui-TabActive', - tabHovered: 'bui-TabHovered', - panel: 'bui-TabPanel', + root: 'bui-Tabs', }, -} as const satisfies ComponentDefinition; + propDefs: { + className: {}, + children: {}, + }, +}); + +/** @internal */ +export const TabListDefinition = defineComponent()({ + styles, + classNames: { + root: 'bui-TabListWrapper', + tabList: 'bui-TabList', + }, + propDefs: { + className: {}, + children: {}, + }, +}); + +/** @internal */ +export const TabDefinition = defineComponent()({ + styles, + classNames: { + root: 'bui-Tab', + }, + propDefs: { + className: {}, + matchStrategy: {}, + href: {}, + id: {}, + }, +}); + +/** @internal */ +export const TabPanelDefinition = defineComponent()({ + styles, + classNames: { + root: 'bui-TabPanel', + }, + propDefs: { + className: {}, + }, +}); + +/** @internal */ +export const TabsIndicatorsDefinition = + defineComponent()({ + styles, + classNames: { + root: 'bui-TabActive', + hovered: 'bui-TabHovered', + }, + propDefs: { + tabRefs: {}, + tabsRef: {}, + hoveredKey: {}, + prevHoveredKey: {}, + }, + }); diff --git a/packages/ui/src/components/Tabs/index.ts b/packages/ui/src/components/Tabs/index.ts index 009d515294..b6dc0ce9f8 100644 --- a/packages/ui/src/components/Tabs/index.ts +++ b/packages/ui/src/components/Tabs/index.ts @@ -17,9 +17,13 @@ export { Tabs, TabList, Tab, TabPanel } from './Tabs'; export type { TabsProps, + TabsOwnProps, TabListProps, + TabListOwnProps, TabPanelProps, + TabPanelOwnProps, TabProps, + TabOwnProps, TabMatchStrategy, } from './types'; export { TabsDefinition } from './definition'; diff --git a/packages/ui/src/components/Tabs/types.ts b/packages/ui/src/components/Tabs/types.ts index 05d080441b..09f7e2e944 100644 --- a/packages/ui/src/components/Tabs/types.ts +++ b/packages/ui/src/components/Tabs/types.ts @@ -29,33 +29,69 @@ import { MutableRefObject } from 'react'; */ export type TabMatchStrategy = 'exact' | 'prefix'; +/** + * Own props for the Tabs component. + * + * @public + */ +export type TabsOwnProps = { + className?: string; + children?: AriaTabsProps['children']; +}; + /** * Props for the Tabs component. * * @public */ -export interface TabsProps extends AriaTabsProps {} +export interface TabsProps + extends TabsOwnProps, + Omit {} + +/** + * Own props for the TabList component. + * + * @public + */ +export type TabListOwnProps = { + className?: string; + children?: AriaTabListProps['children']; +}; /** * Props for the TabList component. * * @public */ -export interface TabListProps extends Omit, 'items'> {} +export interface TabListProps + extends TabListOwnProps, + Omit, 'items' | keyof TabListOwnProps> {} + +/** + * Own props for the Tab component. + * + * @public + */ +export type TabOwnProps = { + className?: string; + /** + * Strategy for matching the current route to determine if this tab should be active. + * - 'exact': Tab href must exactly match the current pathname (default) + * - 'prefix': Tab is active if current pathname starts with tab href + */ + matchStrategy?: TabMatchStrategy; + href?: AriaTabProps['href']; + id?: AriaTabProps['id']; +}; /** * Props for the Tab component. * * @public */ -export interface TabProps extends AriaTabProps { - /** - * Strategy for matching the current route to determine if this tab should be active. - * - 'exact': Tab href must exactly match the current pathname (default) - * - 'prefix': Tab is active if current pathname starts with tab href - */ - matchStrategy?: 'exact' | 'prefix'; -} +export interface TabProps + extends TabOwnProps, + Omit {} /** Context for sharing refs between Tabs and TabList * @@ -70,21 +106,39 @@ export interface TabsContextValue { setTabRef: (key: string, element: HTMLDivElement | null) => void; } +/** + * Own props for the TabPanel component. + * + * @public + */ +export type TabPanelOwnProps = { + className?: string; +}; + /** * Props for the TabPanel component. * * @public */ -export interface TabPanelProps extends AriaTabPanelProps {} +export interface TabPanelProps + extends TabPanelOwnProps, + Omit {} + +/** + * Own props for the TabsIndicators component. + * + * @internal + */ +export type TabsIndicatorsOwnProps = { + tabRefs: MutableRefObject>; + tabsRef: MutableRefObject; + hoveredKey: string | null; + prevHoveredKey: MutableRefObject; +}; /** * Props for the TabsIndicators component. * * @internal */ -export interface TabsIndicatorsProps { - tabRefs: MutableRefObject>; - tabsRef: MutableRefObject; - hoveredKey: string | null; - prevHoveredKey: MutableRefObject; -} +export interface TabsIndicatorsProps extends TabsIndicatorsOwnProps {}