-
Notifications
You must be signed in to change notification settings - Fork 65
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
Conversation
|
||
const renderedDropdown = useMemo( | ||
() => ( | ||
<StyledFlexItem data-testid="button-group-dropdown" isVisible={isMenuVisible} ref={dropdownRef} role="listitem"> |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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:
<StyledFlexItem data-testid="button-group-dropdown" isVisible={isMenuVisible} ref={dropdownRef} role="listitem"> | |
<StyledFlexItem data-testid="buttongroup-dropdown-toggle" isVisible={isMenuVisible} ref={dropdownRef} role="listitem"> |
There was a problem hiding this comment.
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 ✅
&:focus { | ||
z-index: 1; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[...actionsState] | ||
.reverse() | ||
.sort(({ isVisible }) => (isVisible ? -1 : 1)) |
There was a problem hiding this comment.
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"
.
export interface ButtonGroupAction extends Omit<ButtonProps, 'children' | 'iconOnly' | 'iconRight' | 'iconLeft'> { | ||
text: string; | ||
icon?: React.ReactElement; | ||
} |
There was a problem hiding this comment.
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} { |
There was a problem hiding this comment.
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)
There was a problem hiding this 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!
const excludeIconProps = <T extends any>({ | ||
iconOnly, | ||
iconRight, | ||
iconLeft, | ||
...actionProps | ||
}: T): Pick<T, Exclude<keyof T, 'iconOnly' | 'iconRight' | 'iconLeft'>> => actionProps; |
There was a problem hiding this comment.
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:
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 🤷
There was a problem hiding this comment.
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"> |
There was a problem hiding this comment.
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:
<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(() => { |
There was a problem hiding this comment.
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?
const changeActionsVisibility = useCallback(() => { | |
const hideOverflowedActions = useCallback(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, thank you, done ✅
There was a problem hiding this 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 ✅
What?
Add the
ButtonGroup
component.Examples
Docs
Testing/Proof
Unit tests.
ping @chanceaclark @jorgemoya