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

feat(component): add ButtonGroup component #556

Merged
merged 4 commits into from
Jul 7, 2021

Conversation

golcinho
Copy link
Contributor

@golcinho golcinho commented Jul 5, 2021

What?

Add the ButtonGroup component.

Examples

Screenshot 2021-07-05 at 14 29 15

Screenshot 2021-07-05 at 14 29 23

Screenshot 2021-07-05 at 14 29 43

Screenshot 2021-07-05 at 14 30 03

Screenshot 2021-07-05 at 14 30 20

Docs

Screenshot 2021-07-05 at 14 23 34

Screenshot 2021-07-05 at 14 23 46

Testing/Proof

Unit tests.

ping @chanceaclark @jorgemoya

@golcinho golcinho requested review from a team as code owners July 5, 2021 11:31

const renderedDropdown = useMemo(
() => (
<StyledFlexItem data-testid="button-group-dropdown" isVisible={isMenuVisible} ref={dropdownRef} role="listitem">
Copy link
Contributor Author

@golcinho golcinho Jul 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

About data-testid, these are the only reliable way we could think of for targeting them and setting the offsetWidths so that we could test the collapsing functionality (jsdom does not actually render things, so all elements have an offsetWidth of 0 in the testing environment)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that was the same issue we ran into with the PillsTabs.

🍹 I'm :gucci: with this, but could we align it with a similar name to the PillsTabs one? Definitely a nitpick:

Suggested change
<StyledFlexItem data-testid="button-group-dropdown" isVisible={isMenuVisible} ref={dropdownRef} role="listitem">
<StyledFlexItem data-testid="buttongroup-dropdown-toggle" isVisible={isMenuVisible} ref={dropdownRef} role="listitem">

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your comment! Sure, I agree with you!

Done ✅

Comment on lines +25 to +27
&:focus {
z-index: 1;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use z-index: 1 for correct displaying of box-shadow (pls see the example below). I decide to not use the value from theme cause it will be not semantic for my case and I think creating a new one will be redundant.

Without z-index
Screenshot 2021-04-22 at 10 29 58

With z-index
Screenshot 2021-04-22 at 10 29 46

Comment on lines +107 to +109
[...actionsState]
.reverse()
.sort(({ isVisible }) => (isVisible ? -1 : 1))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I'm sorting elements that visible elements will be first in the row. I do this for the correct working of pseudo-class :first-of-type which controls border-radius for the left side of the first element.

it's the possible case when the first element will be hidden under ellispsis when this element will have actionType="destructive".

Comment on lines +12 to +15
export interface ButtonGroupAction extends Omit<ButtonProps, 'children' | 'iconOnly' | 'iconRight' | 'iconLeft'> {
text: string;
icon?: React.ReactElement;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initially, Button has 'iconOnly' | 'iconRight' | 'iconLeft' properties but, according to the guidelines I can show the icon only when action will be hidden under ellipsis. So, I decide to exclude 'iconOnly' | 'iconRight' | 'iconLeft' and just add the icon property.

border-top-left-radius: ${({ theme }) => theme.borderRadius.normal};
}

&:nth-last-of-type(-n + 2) ${StyledButton} {
Copy link
Contributor Author

@golcinho golcinho Jul 5, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use &:nth-last-of-type(-n + 2) instead of :last-of-type according to case when dropdown is visible and when some of actions has actionType="destructive" and all action are fit... so, it sets border-radius to dropdown toggle and the last element of action. And it's the impossible case when last action and dropdown toggle will have border-radius at the same time case I have sorting (pls see comment above)

Copy link
Contributor

@chanceaclark chanceaclark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few comments but looks really good!

Comment on lines 21 to 26
const excludeIconProps = <T extends any>({
iconOnly,
iconRight,
iconLeft,
...actionProps
}: T): Pick<T, Exclude<keyof T, 'iconOnly' | 'iconRight' | 'iconLeft'>> => actionProps;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not complicate this with generics:

Suggested change
const excludeIconProps = <T extends any>({
iconOnly,
iconRight,
iconLeft,
...actionProps
}: T): Pick<T, Exclude<keyof T, 'iconOnly' | 'iconRight' | 'iconLeft'>> => actionProps;
const excludeIconProps = ({
iconOnly,
iconRight,
iconLeft,
...actionProps
}: ButtonProps & { text: string }): ButtonGroupAction => actionProps;

I don't really like the & { text: string } part 😅 , but I guess it's okay since it's an internal implementation 🤷

Copy link
Contributor Author

@golcinho golcinho Jul 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! I lil bit changed your suggestion from { text: string } to Pick<ButtonGroupAction, 'text'>, something like single source of truth for the text prop 😅


const renderedDropdown = useMemo(
() => (
<StyledFlexItem data-testid="button-group-dropdown" isVisible={isMenuVisible} ref={dropdownRef} role="listitem">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that was the same issue we ran into with the PillsTabs.

🍹 I'm :gucci: with this, but could we align it with a similar name to the PillsTabs one? Definitely a nitpick:

Suggested change
<StyledFlexItem data-testid="button-group-dropdown" isVisible={isMenuVisible} ref={dropdownRef} role="listitem">
<StyledFlexItem data-testid="buttongroup-dropdown-toggle" isVisible={isMenuVisible} ref={dropdownRef} role="listitem">

actions.map((action) => ({ isVisible: true, action: excludeIconProps(action), ref: createRef<HTMLDivElement>() })),
);

const changeActionsVisibility = useCallback(() => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🍹 nitpick, but could we align this to a similar name to the PillsTabs one?

Suggested change
const changeActionsVisibility = useCallback(() => {
const hideOverflowedActions = useCallback(() => {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, thank you, done ✅

Copy link
Contributor

@chanceaclark chanceaclark left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some grammatical cleanup but ✅

packages/docs/pages/ButtonGroup/ButtonGroupPage.tsx Outdated Show resolved Hide resolved
packages/docs/pages/ButtonGroup/ButtonGroupPage.tsx Outdated Show resolved Hide resolved
@golcinho golcinho merged commit 2350481 into bigcommerce:master Jul 7, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

2 participants