Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(Tab,ButtonGroup): Add forwardRef to ButtonGroup and update styling for Tab #646

73 changes: 39 additions & 34 deletions src/components/ButtonGroup/ButtonGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { FC } from 'react';
import React, { FC, forwardRef } from 'react';
import classNames from 'classnames';

import { DEFAULTS, STYLE, CHILD_OF } from './ButtonGroup.constants';
Expand All @@ -7,43 +7,48 @@ import { Props } from './ButtonGroup.types';
import './ButtonGroup.style.scss';

export interface CompoundProps {
CHILD_PROPS: {
CHILD_PROPS?: {
[CHILD_OF.KEY]: typeof CHILD_OF.VALUE;
};
}

const ButtonGroup: FC<Props> & CompoundProps = (props: Props) => {
const {
children,
className,
id,
round,
spaced,
compressed,
separator,
style,
role,
orientation,
...rest
} = props;

return (
<div
className={classNames(STYLE.wrapper, className)}
data-round={round || DEFAULTS.ROUND}
data-spaced={spaced || DEFAULTS.SPACED}
data-compressed={compressed || DEFAULTS.COMPRESSED}
data-separator={separator || DEFAULTS.SEPARATOR}
data-orientation={orientation || DEFAULTS.ORIENTATION}
id={id}
style={style}
role={role}
{...rest}
>
{children}
</div>
);
};
const ButtonGroup: FC<Props> & CompoundProps = forwardRef<HTMLDivElement, Props>(
(props: Props, ref) => {
const {
children,
className,
id,
round,
spaced,
compressed,
separator,
style,
role,
orientation,
...rest
} = props;

return (
<div
ref={ref}
className={classNames(STYLE.wrapper, className)}
data-round={round || DEFAULTS.ROUND}
data-spaced={spaced || DEFAULTS.SPACED}
data-compressed={compressed || DEFAULTS.COMPRESSED}
data-separator={separator || DEFAULTS.SEPARATOR}
data-orientation={orientation || DEFAULTS.ORIENTATION}
id={id}
style={style}
role={role}
{...rest}
>
{children}
</div>
);
}
);

ButtonGroup.displayName = 'ButtonGroup';

export default ButtonGroup;

Expand Down
9 changes: 5 additions & 4 deletions src/components/Tab/Tab.style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

.md-text-wrapper,
.md-icon-wrapper {
color: var(--mds-color-theme-text-primary-normal);
color: var(--mds-color-theme-text-secondary-normal);
}
}

Expand Down Expand Up @@ -54,7 +54,8 @@

.md-text-wrapper,
.md-icon-wrapper {
color: var(--mds-color-theme-text-secondary-normal);
color: var(--mds-color-theme-text-primary-normal);
font-weight: 700;
}

&:hover {
Expand All @@ -67,7 +68,7 @@
}

&:active {
background-color: var(--mds-color-theme-button-secondary-pressed);
background-color: var(--mds-color-theme-button-secondary-active-pressed);

.md-text-wrapper,
.md-icon-wrapper {
Expand All @@ -82,7 +83,7 @@
}

&[data-disabled='true'] {
background-color: var(--mds-color-theme-button-secondary-normal);
background-color: var(--mds-color-theme-button-secondary-active-normal);

.md-text-wrapper,
.md-icon-wrapper {
Expand Down
4 changes: 3 additions & 1 deletion src/components/Tab/Tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ const Tab: FC<Props> = (props: Props) => {
data-disabled={disabled || DEFAULTS.DISABLED}
>
{typeof children === 'string' ? (
<PrimitiveConverter fontStyle="subheader-secondary">{children}</PrimitiveConverter>
<PrimitiveConverter tagName="span" fontStyle="subheader-secondary">
{children}
</PrimitiveConverter>
) : (
children
)}
Expand Down
12 changes: 11 additions & 1 deletion src/components/Tab/Tab.types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CSSProperties, ReactElement } from 'react';
import { AriaRole, CSSProperties, ReactElement } from 'react';
import { BadgeProps } from '../Badge';
import { IconProps } from '../Icon';
import { TextProps } from '../Text';
Expand Down Expand Up @@ -34,4 +34,14 @@ export interface Props extends AriaButtonProps {
* Determines whether the tab is disabled or not.
*/
disabled?: boolean;

/**
* Tabindex for accessibility
*/
tabIndex?: number;

/**
* WAI-ARIA role for accessibility
*/
role?: AriaRole;
}
6 changes: 4 additions & 2 deletions src/components/Tab/Tab.unit.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1096,16 +1096,18 @@ exports[`<Tab /> snapshot string children should match snapshot 1`] = `
>
<PrimitiveConverter
fontStyle="subheader-secondary"
tagName="span"
>
<Text
tagName="span"
type="subheader-secondary"
>
<h3
<span
className="md-text-wrapper"
data-type="subheader-secondary"
>
Example label
</h3>
</span>
</Text>
</PrimitiveConverter>
</button>
Expand Down
11 changes: 8 additions & 3 deletions src/utils/component-conversions.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { FC, isValidElement } from 'react';
import classNames from 'classnames';
import Text from '../components/Text';
import { FontStyle } from '../components/Text/Text.types';
import { AllowedTagNames, FontStyle } from '../components/Text/Text.types';

export interface PrimativeConverterProps {
/**
Expand All @@ -14,6 +14,11 @@ export interface PrimativeConverterProps {
*/
className?: string;

/**
* Allowed tag names to wrap the Text. Default depends on `fontStyle`
*/
tagName?: AllowedTagNames;

/**
* Style of the Text. Default: body-primary.
*/
Expand All @@ -28,7 +33,7 @@ export interface PrimativeConverterProps {
* @returns - FC of provided child if needed.
*/
const PrimitiveConverter: FC<PrimativeConverterProps> = (props: PrimativeConverterProps) => {
const { children, className, fontStyle = 'body-primary' } = props;
const { children, className, tagName, fontStyle = 'body-primary' } = props;
const isElement = isValidElement(children);

const addedProps: { className?: string } = {};
Expand All @@ -40,7 +45,7 @@ const PrimitiveConverter: FC<PrimativeConverterProps> = (props: PrimativeConvert
return isElement ? (
React.cloneElement(children, { ...addedProps })
) : (
<Text {...addedProps} type={fontStyle}>
<Text {...addedProps} tagName={tagName} type={fontStyle}>
{children}
</Text>
);
Expand Down
Loading