Skip to content

Commit

Permalink
feat: button: adds counter badge support to all buttons (#187)
Browse files Browse the repository at this point in the history
* feat: button: adds counter badge support to all buttons

* chore: button: address counter pr feedback
  • Loading branch information
dkilgore-eightfold authored Jun 15, 2022
1 parent 16d26fa commit 45eaec1
Show file tree
Hide file tree
Showing 11 changed files with 298 additions and 22 deletions.
182 changes: 179 additions & 3 deletions src/__snapshots__/storybook.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -766,6 +766,60 @@ exports[`Storyshots Badge Badge Disruptive 1`] = `
</span>
`;

exports[`Storyshots Button Counter 1`] = `
<button
aria-disabled={false}
aria-label="Primary Button"
className="my-btn-class button buttonPrimary iconLeft"
data-test-id="my-btn-test-id"
defaultChecked={false}
disabled={false}
id="myButton"
style={Object {}}
type="button"
>
<span>
<span
aria-hidden={true}
className="icon my-btn-icon iconWrapper"
data-test-id="myButtonIconTestId"
id="myButtonIcon"
role="presentation"
>
<svg
role="presentation"
style={
Object {
"height": "20px",
"width": "20px",
}
}
viewBox="0 0 24 24"
>
<path
d="M12,21.35L10.55,20.03C5.4,15.36 2,12.27 2,8.5C2,5.41 4.42,3 7.5,3C9.24,3 10.91,3.81 12,5.08C13.09,3.81 14.76,3 16.5,3C19.58,3 22,5.41 22,8.5C22,12.27 18.6,15.36 13.45,20.03L12,21.35Z"
style={
Object {
"fill": "currentColor",
}
}
/>
</svg>
</span>
<span
className=""
>
Primary Button
<span
className="badge header6 counter"
>
8
</span>
</span>
</span>
</button>
`;

exports[`Storyshots Button Default 1`] = `
<button
aria-disabled={false}
Expand Down Expand Up @@ -1023,6 +1077,72 @@ Array [
]
`;

exports[`Storyshots Button Split With Counter 1`] = `
Array [
<button
aria-disabled={false}
aria-label="Split Button"
className="my-btn-class button buttonPrimary splitLeft"
data-test-id="my-btn-test-id"
defaultChecked={false}
disabled={false}
id="myButton"
style={Object {}}
type="button"
>
<span
className=""
>
Split Button
<span
className="badge header6 counter"
>
8
</span>
</span>
</button>,
<button
aria-checked={false}
aria-disabled={false}
aria-pressed={false}
className="my-btn-class button buttonPrimary undefined splitButton splitRight"
defaultChecked={false}
disabled={false}
type="button"
>
<span
aria-hidden={false}
className="icon iconWrapper"
role="presentation"
>
<svg
role="presentation"
style={
Object {
"height": "20px",
"width": "20px",
}
}
viewBox="0 0 24 24"
>
<path
d="M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z"
style={
Object {
"fill": "currentColor",
}
}
/>
</svg>
</span>
<span
aria-hidden="true"
className="splitDivider splitDividerPrimary"
/>
</button>,
]
`;

exports[`Storyshots Button Toggle 1`] = `
<button
aria-checked={false}
Expand Down Expand Up @@ -1074,6 +1194,62 @@ exports[`Storyshots Button Toggle 1`] = `
</button>
`;

exports[`Storyshots Button Toggle With Counter 1`] = `
<button
aria-checked={false}
aria-disabled={false}
aria-label="Toggle Button"
aria-pressed={false}
className="my-btn-class button buttonPrimary iconRight"
data-test-id="my-btn-test-id"
defaultChecked={false}
disabled={false}
id="myButton"
style={Object {}}
type="button"
>
<span>
<span
aria-hidden={true}
className="icon my-btn-icon iconWrapper"
data-test-id="myButtonIconTestId"
id="myButtonIcon"
role="presentation"
>
<svg
role="presentation"
style={
Object {
"height": "20px",
"width": "20px",
}
}
viewBox="0 0 24 24"
>
<path
d="M7.41,8.58L12,13.17L16.59,8.58L18,10L12,16L6,10L7.41,8.58Z"
style={
Object {
"fill": "currentColor",
}
}
/>
</svg>
</span>
<span
className=""
>
Toggle Button
<span
className="badge header6 counter"
>
8
</span>
</span>
</span>
</button>
`;

exports[`Storyshots Button Two State Button 1`] = `
<button
aria-checked={false}
Expand Down Expand Up @@ -4766,7 +4942,7 @@ exports[`Storyshots Icon Basic 1`] = `
role="presentation"
>
<svg
aria-labelledby="icon_labelledby_34 icon_describedby_34"
aria-labelledby="icon_labelledby_37 icon_describedby_37"
style={
Object {
"height": "20px",
Expand All @@ -4776,12 +4952,12 @@ exports[`Storyshots Icon Basic 1`] = `
viewBox="0 0 24 24"
>
<title
id="icon_labelledby_34"
id="icon_labelledby_37"
>
My icon title.
</title>
<desc
id="icon_describedby_34"
id="icon_describedby_37"
>
My icon description.
</desc>
Expand Down
21 changes: 18 additions & 3 deletions src/components/Button/BaseButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
SplitButton,
} from './';
import { Icon, IconSize } from '../Icon';
import { Badge } from '../Badge';
import { Breakpoints, useMatchMedia } from '../../hooks/useMatchMedia';
import { mergeClasses } from '../../shared/utilities';

Expand All @@ -25,6 +26,7 @@ export const BaseButton: FC<InternalButtonProps> = React.forwardRef(
buttonWidth = ButtonWidth.fitContent,
checked = false,
classNames,
counter,
disabled = false,
disruptive = false,
dropShadow = false,
Expand Down Expand Up @@ -52,6 +54,7 @@ export const BaseButton: FC<InternalButtonProps> = React.forwardRef(
const smallScreenActive: boolean = useMatchMedia(Breakpoints.Small);
const xSmallScreenActive: boolean = useMatchMedia(Breakpoints.XSmall);

const counterExists: boolean = !!counter;
const iconExists: boolean = !!iconProps;
const textExists: boolean = !!text;

Expand Down Expand Up @@ -120,6 +123,11 @@ export const BaseButton: FC<InternalButtonProps> = React.forwardRef(
{ [styles.buttonText3]: size === ButtonSize.Small },
]);

const badgeClassNames: string = mergeClasses([
styles.counter,
buttonTextClassNames,
]);

const getButtonIconSize = (): IconSize => {
let iconSize: IconSize;
if (size === ButtonSize.Flex && largeScreenActive) {
Expand Down Expand Up @@ -149,12 +157,15 @@ export const BaseButton: FC<InternalButtonProps> = React.forwardRef(
/>
);

const getButtonText = (
const getButtonContent = (
buttonTextClassNames: string,
text: string
): JSX.Element => (
<span className={buttonTextClassNames}>
{text ? text : 'Button'}
{counterExists && (
<Badge classNames={badgeClassNames}>{counter}</Badge>
)}
</span>
);

Expand All @@ -176,13 +187,17 @@ export const BaseButton: FC<InternalButtonProps> = React.forwardRef(
type={htmlType}
>
{iconExists && !textExists && getButtonIcon()}
{counterExists && !textExists && (
<Badge classNames={badgeClassNames}>{counter}</Badge>
)}
{iconExists && textExists && (
<span>
{getButtonIcon()}
{getButtonText(buttonTextClassNames, text)}
{getButtonContent(buttonTextClassNames, text)}
</span>
)}
{!iconExists && getButtonText(buttonTextClassNames, text)}
{!iconExists &&
getButtonContent(buttonTextClassNames, text)}
</button>
{split && (
<SplitButton
Expand Down
41 changes: 41 additions & 0 deletions src/components/Button/Button.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ const Primary_Button_Story: ComponentStory<typeof PrimaryButton> = (args) => (
);

export const Primary = Primary_Button_Story.bind({});
export const Counter = Primary_Button_Story.bind({});

const Secondary_Button_Story: ComponentStory<typeof SecondaryButton> = (
args
Expand All @@ -190,12 +191,14 @@ const Toggle_Button_Story: ComponentStory<typeof PrimaryButton> = (args) => (
);

export const Toggle = Toggle_Button_Story.bind({});
export const Toggle_With_Counter = Toggle_Button_Story.bind({});

const Split_Button_Story: ComponentStory<typeof PrimaryButton> = (args) => (
<PrimaryButton {...args} />
);

export const Split = Split_Button_Story.bind({});
export const Split_With_Counter = Split_Button_Story.bind({});

const buttonArgs: Object = {
alignIcon: ButtonIconAlign.Left,
Expand Down Expand Up @@ -238,6 +241,13 @@ Primary.args = {
text: 'Primary Button',
};

Counter.args = {
...buttonArgs,
ariaLabel: 'Primary Button',
counter: '8',
text: 'Primary Button',
};

Secondary.args = {
...buttonArgs,
ariaLabel: 'Secondary Button',
Expand Down Expand Up @@ -276,6 +286,27 @@ Toggle.args = {
toggle: true,
};

Toggle_With_Counter.args = {
...buttonArgs,
alignIcon: ButtonIconAlign.Right,
ariaLabel: 'Toggle Button',
checked: false,
counter: '8',
iconProps: {
path: IconName.mdiChevronDown,
ariaHidden: true,
classNames: 'my-btn-icon',
id: 'myButtonIcon',
role: 'presentation',
rotate: 0,
spin: false,
vertical: false,
'data-test-id': 'myButtonIconTestId',
},
text: 'Toggle Button',
toggle: true,
};

Split.args = {
...buttonArgs,
ariaLabel: 'Split Button',
Expand All @@ -284,3 +315,13 @@ Split.args = {
splitButtonChecked: false,
text: 'Split Button',
};

Split_With_Counter.args = {
...buttonArgs,
ariaLabel: 'Split Button',
counter: '8',
iconProps: null,
split: true,
splitButtonChecked: false,
text: 'Split Button',
};
8 changes: 4 additions & 4 deletions src/components/Button/Button.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,6 @@ export interface TwoStateButtonProps
| 'splitButtonChecked'
| 'splitButtonProps'
> {
/**
* The button counter number.
*/
counter?: number;
/**
* The button icon 1 props.
*/
Expand Down Expand Up @@ -118,6 +114,10 @@ export interface ButtonProps extends NativeButtonProps {
* The button class names.
*/
classNames?: string;
/**
* The button counter string.
*/
counter?: string;
/**
* The button disabled state.
* @default false
Expand Down
Loading

0 comments on commit 45eaec1

Please sign in to comment.