From 4f93c46103df90f6967061355d0a3018c9e05c6e Mon Sep 17 00:00:00 2001 From: szalonna Date: Thu, 12 Dec 2024 12:30:28 +0100 Subject: [PATCH] feat(ui-tabs): extends the customization of Tab component Closes: CLX-276 Adds the possibility to disable built-in styling of a `Tab` to replace with a custom component through `renderTitle` - adds `customTab` flag to `Panel` to remove the default styling from the `Tab` - adds `alignTab` prop to `Panel` to allow to customzie the `Tabs`'s relative alignment in the container flexbox --- packages/ui-tabs/src/Tabs/Panel/index.tsx | 3 ++- packages/ui-tabs/src/Tabs/Panel/props.ts | 21 +++++++++++++++--- packages/ui-tabs/src/Tabs/Tab/index.tsx | 2 ++ packages/ui-tabs/src/Tabs/Tab/props.ts | 10 +++++++-- packages/ui-tabs/src/Tabs/Tab/styles.ts | 27 +++++++++++++---------- packages/ui-tabs/src/Tabs/index.tsx | 2 ++ 6 files changed, 47 insertions(+), 18 deletions(-) diff --git a/packages/ui-tabs/src/Tabs/Panel/index.tsx b/packages/ui-tabs/src/Tabs/Panel/index.tsx index ce5e4a9120..2f276edd02 100644 --- a/packages/ui-tabs/src/Tabs/Panel/index.tsx +++ b/packages/ui-tabs/src/Tabs/Panel/index.tsx @@ -56,7 +56,8 @@ class Panel extends Component { isSelected: false, padding: 'small', active: false, - unmountOnExit: true + unmountOnExit: true, + customTab: false } componentDidMount() { diff --git a/packages/ui-tabs/src/Tabs/Panel/props.ts b/packages/ui-tabs/src/Tabs/Panel/props.ts index c72d754ca8..e5a41f4279 100644 --- a/packages/ui-tabs/src/Tabs/Panel/props.ts +++ b/packages/ui-tabs/src/Tabs/Panel/props.ts @@ -35,6 +35,7 @@ import type { import type { OtherHTMLAttributes, PropValidators, + Renderable, TabsPanelTheme } from '@instructure/shared-types' @@ -43,7 +44,7 @@ type TabsPanelOwnProps = { * The content that will be rendered in the corresponding and will label * this `` for screen readers */ - renderTitle: React.ReactNode | (() => React.ReactNode) + renderTitle: Renderable children?: React.ReactNode variant?: 'default' | 'secondary' isSelected?: boolean @@ -67,6 +68,16 @@ type TabsPanelOwnProps = { * When set to false, the tabPanel only will be hidden, but not dismounted when not active */ unmountOnExit?: boolean + + /** + * When set to true, the tab will be rendered with minimal styling to enable a custom design + */ + customTab?: boolean + + /** + * Aligning the tab in the flex container + */ + alignTab?: string } type PropKeys = keyof TabsPanelOwnProps @@ -93,7 +104,9 @@ const propTypes: PropValidators = { textAlign: PropTypes.oneOf(['start', 'center', 'end']), elementRef: PropTypes.func, active: PropTypes.bool, - unmountOnExit: PropTypes.bool + unmountOnExit: PropTypes.bool, + customTab: PropTypes.bool, + alignTab: PropTypes.string } const allowedProps: AllowedPropKeys = [ @@ -110,7 +123,9 @@ const allowedProps: AllowedPropKeys = [ 'textAlign', 'elementRef', 'active', - 'unmountOnExit' + 'unmountOnExit', + 'customTab', + 'alignTab' ] export type { TabsPanelProps, TabsPanelStyle } diff --git a/packages/ui-tabs/src/Tabs/Tab/index.tsx b/packages/ui-tabs/src/Tabs/Tab/index.tsx index 4d498f3810..8371566334 100644 --- a/packages/ui-tabs/src/Tabs/Tab/index.tsx +++ b/packages/ui-tabs/src/Tabs/Tab/index.tsx @@ -96,6 +96,8 @@ class Tab extends Component { controls, children, styles, + customTab, + align, ...props } = this.props diff --git a/packages/ui-tabs/src/Tabs/Tab/props.ts b/packages/ui-tabs/src/Tabs/Tab/props.ts index db5a9dc091..70d4486c5d 100644 --- a/packages/ui-tabs/src/Tabs/Tab/props.ts +++ b/packages/ui-tabs/src/Tabs/Tab/props.ts @@ -50,6 +50,8 @@ type TabsTabOwnProps = { tabData: { index: number; id: string } ) => void children?: Renderable + customTab?: boolean + align?: string } type PropKeys = keyof TabsTabOwnProps @@ -71,7 +73,9 @@ const propTypes: PropValidators = { isSelected: PropTypes.bool, onClick: PropTypes.func, onKeyDown: PropTypes.func, - children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]) + children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]), + customTab: PropTypes.bool, + align: PropTypes.string } const allowedProps: AllowedPropKeys = [ @@ -83,7 +87,9 @@ const allowedProps: AllowedPropKeys = [ 'isSelected', 'onClick', 'onKeyDown', - 'children' + 'children', + 'customTab', + 'align' ] export type { TabsTabProps, TabsTabStyle } diff --git a/packages/ui-tabs/src/Tabs/Tab/styles.ts b/packages/ui-tabs/src/Tabs/Tab/styles.ts index 104280dcea..652f623bb7 100644 --- a/packages/ui-tabs/src/Tabs/Tab/styles.ts +++ b/packages/ui-tabs/src/Tabs/Tab/styles.ts @@ -49,7 +49,7 @@ const generateStyle = ( componentTheme: TabsTabTheme, props: TabsTabProps ): TabsTabStyle => { - const { variant, isSelected, isDisabled } = props + const { variant, isSelected, isDisabled, customTab, align } = props const variants = { default: { @@ -132,20 +132,23 @@ const generateStyle = ( return { tab: { label: 'tab', - fontFamily: componentTheme.fontFamily, - fontWeight: componentTheme.fontWeight, - lineHeight: componentTheme.lineHeight, - fontSize: componentTheme.fontSize, - cursor: 'pointer', - userSelect: 'none', - whiteSpace: 'nowrap', + ...(!customTab && { + fontFamily: componentTheme.fontFamily, + fontWeight: componentTheme.fontWeight, + lineHeight: componentTheme.lineHeight, + fontSize: componentTheme.fontSize, + cursor: 'pointer', + userSelect: 'none', + whiteSpace: 'nowrap', - ...((isSelected || isDisabled) && { cursor: 'default' }), - ...(isDisabled && { opacity: 0.5 }), + ...((isSelected || isDisabled) && { cursor: 'default' }), + ...(isDisabled && { opacity: 0.5 }), - ...focusRingStyles, + ...focusRingStyles, - ...variants[variant!] + ...variants[variant!] + }), + ...(align && { alignSelf: align }) } } } diff --git a/packages/ui-tabs/src/Tabs/index.tsx b/packages/ui-tabs/src/Tabs/index.tsx index fa4d69bce1..47f005ac05 100644 --- a/packages/ui-tabs/src/Tabs/index.tsx +++ b/packages/ui-tabs/src/Tabs/index.tsx @@ -352,6 +352,8 @@ class Tabs extends Component { isDisabled={panel.props.isDisabled} onClick={this.handleTabClick} onKeyDown={this.handleTabKeyDown} + customTab={panel.props.customTab} + align={panel.props.alignTab} > {panel.props.renderTitle}