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

ButtonGroup: Fix button and icon button styling when tooltips are used on them (#4210) #4251

Closed
wants to merge 11 commits into from
5 changes: 5 additions & 0 deletions .changeset/wild-bears-pay.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@primer/react': patch
---

ButtonGroup: Fix button and icon button styling when tooltips are used on them
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
Diff not rendered.
226 changes: 218 additions & 8 deletions e2e/components/ButtonGroup.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,24 +31,24 @@ test.describe('ButtonGroup', () => {
}
})

test.describe('Playground', () => {
test.describe('Icon Buttons', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-buttongroup--playground',
id: 'components-buttongroup-features--icon-buttons',
globals: {
colorScheme: theme,
},
})

// Default state
expect(await page.screenshot()).toMatchSnapshot(`ButtonGroup.Playground.${theme}.png`)
expect(await page.screenshot()).toMatchSnapshot(`ButtonGroup.Icon Buttons.${theme}.png`)
})

test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-buttongroup--playground',
id: 'components-buttongroup-features--icon-buttons',
globals: {
colorScheme: theme,
},
Expand All @@ -59,24 +59,234 @@ test.describe('ButtonGroup', () => {
}
})

test.describe('Icon Buttons', () => {
test.describe('Button And Link', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-buttongroup-features--icon-buttons',
id: 'components-buttongroup-features--button-and-link',
globals: {
colorScheme: theme,
},
})

// Default state
expect(await page.screenshot()).toMatchSnapshot(`ButtonGroup.Icon Buttons.${theme}.png`)
expect(await page.screenshot()).toMatchSnapshot(`ButtonGroup.Button And Link.${theme}.png`)
})

test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-buttongroup-features--icon-buttons',
id: 'components-buttongroup-features--button-and-link',
globals: {
colorScheme: theme,
},
})
await expect(page).toHaveNoViolations()
})
})
}
})

test.describe('Button And Link With Tooltip 1', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-buttongroup-devonly--button-and-link-with-tooltip-1',
globals: {
colorScheme: theme,
},
})

await page.keyboard.press('Tab')
expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot(
`ButtonGroup.Button And Link With Tooltip 1.${theme}.png`,
)
})

test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-buttongroup-devonly--button-and-link-with-tooltip-1',
globals: {
colorScheme: theme,
},
})
await expect(page).toHaveNoViolations()
})
})
}
})

test.describe('Button And Link With Tooltip 2', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-buttongroup-devonly--button-and-link-with-tooltip-2',
globals: {
colorScheme: theme,
},
})

await page.keyboard.press('Tab')
expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot(
`ButtonGroup.Button And Link With Tooltip 2.${theme}.png`,
)
})

test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-buttongroup-devonly--button-and-link-with-tooltip-2',
globals: {
colorScheme: theme,
},
})
await expect(page).toHaveNoViolations()
})
})
}
})

test.describe('Icon Buttons With Tooltip 1', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-buttongroup-devonly--icon-buttons-with-tooltip-1',
globals: {
colorScheme: theme,
},
})

await page.keyboard.press('Tab')
expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot(
`ButtonGroup.Icon Buttons With Tooltip 1.${theme}.png`,
)
})

test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-buttongroup-devonly--icon-buttons-with-tooltip-1',
globals: {
colorScheme: theme,
},
})
await expect(page).toHaveNoViolations()
})
})
}
})

test.describe('Link And Button With Tooltip 1', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-buttongroup-devonly--link-and-button-with-tooltip-1',
globals: {
colorScheme: theme,
},
})

await page.keyboard.press('Tab')
expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot(
`ButtonGroup.Link And Button With Tooltip 1.${theme}.png`,
)
})

test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-buttongroup-devonly--link-and-button-with-tooltip-1',
globals: {
colorScheme: theme,
},
})
await expect(page).toHaveNoViolations()
})
})
}
})

test.describe('Link And Button With Tooltip 2', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-buttongroup-devonly--link-and-button-with-tooltip-2',
globals: {
colorScheme: theme,
},
})

await page.keyboard.press('Tab')
expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot(
`ButtonGroup.Link And Button With Tooltip 2.${theme}.png`,
)
})

test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-buttongroup-devonly--link-and-button-with-tooltip-2',
globals: {
colorScheme: theme,
},
})
await expect(page).toHaveNoViolations()
})
})
}
})

test.describe('Links With Tooltip 1', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-buttongroup-devonly--links-with-tooltip-1',
globals: {
colorScheme: theme,
},
})

await page.keyboard.press('Tab')
expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot(
`ButtonGroup.Links With Tooltip 1.${theme}.png`,
)
})

test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-buttongroup-devonly--links-with-tooltip-1',
globals: {
colorScheme: theme,
},
})
await expect(page).toHaveNoViolations()
})
})
}
})

test.describe('Links With Tooltip 2', () => {
for (const theme of themes) {
test.describe(theme, () => {
test('default @vrt', async ({page}) => {
await visit(page, {
id: 'components-buttongroup-devonly--links-with-tooltip-2',
globals: {
colorScheme: theme,
},
})

await page.keyboard.press('Tab')
expect(await page.screenshot({animations: 'disabled'})).toMatchSnapshot(
`ButtonGroup.Links With Tooltip 2.${theme}.png`,
)
})

test('axe @aat', async ({page}) => {
await visit(page, {
id: 'components-buttongroup-devonly--links-with-tooltip-2',
globals: {
colorScheme: theme,
},
Expand Down
119 changes: 119 additions & 0 deletions packages/react/src/ButtonGroup/ButtonGroup.dev.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import React from 'react'
import type {Meta} from '@storybook/react'
import ButtonGroup from './ButtonGroup'
import {Button, IconButton} from '../Button'
import {PlusIcon, DashIcon, CopilotIcon} from '@primer/octicons-react'
import {Tooltip as TooltipV2} from '../drafts'
import {Box, Tooltip, ThemeProvider, BaseStyles} from '..'

const meta: Meta<typeof ButtonGroup> = {
title: 'Components/ButtonGroup/DevOnly',
component: ButtonGroup,
decorators: [
Story => {
// Add some padding to the wrapper box to make sure tooltip v1 is always in the viewport
return (
<ThemeProvider>
<BaseStyles>
<Box padding={5}>{Story()}</Box>
</BaseStyles>
</ThemeProvider>
)
},
],
}

export default meta

export const IconButtonsWithTooltip1 = () => (
<ButtonGroup>
<Tooltip text="Add" direction="s">
<IconButton icon={PlusIcon} aria-label="Add" />
</Tooltip>
<Tooltip text="Subtract" direction="s">
<IconButton icon={DashIcon} aria-label="Subtract" />
</Tooltip>
</ButtonGroup>
)

export const LinksWithTooltip1 = () => (
<ButtonGroup>
<Tooltip text="Additonal text for link 1" direction="s">
<Button as="a" href="https://primer.style">
Sample Link 1
</Button>
</Tooltip>
<Tooltip text="Additonal text for link 2" direction="s">
<Button as="a" href="https://primer.style">
Sample Link 2
</Button>
</Tooltip>
</ButtonGroup>
)

export const LinksWithTooltip2 = () => (
<ButtonGroup>
<TooltipV2 text="Additonal text for link 1" direction="s">
<Button as="a" href="https://primer.style">
Sample Link 1
</Button>
</TooltipV2>
<TooltipV2 text="Additonal text for link 2" direction="s">
<Button as="a" href="https://primer.style">
Sample Link 2
</Button>
</TooltipV2>
</ButtonGroup>
)

export const LinkAndButtonWithTooltip1 = () => (
<ButtonGroup sx={{pl: 2}}>
<Tooltip text="Additional info about the link">
<Button as="a" href="https://primer.style">
Link
</Button>
</Tooltip>
<Tooltip text="Open GitHub Copilot chat" direction="s">
<IconButton icon={CopilotIcon} aria-label="Open GitHub Copilot chat" />
</Tooltip>
</ButtonGroup>
)

export const ButtonAndLinkWithTooltip1 = () => (
<ButtonGroup sx={{pl: 2}}>
<Tooltip text="Open GitHub Copilot chat" direction="se">
<IconButton icon={CopilotIcon} aria-label="Open GitHub Copilot chat" />
</Tooltip>
<Tooltip text="Additional info about the link">
<Button as="a" href="https://primer.style">
Link
</Button>
</Tooltip>
</ButtonGroup>
)

export const LinkAndButtonWithTooltip2 = () => (
<ButtonGroup sx={{pl: 2}}>
<TooltipV2 text="Additional info about the link">
<Button as="a" href="https://primer.style">
Link
</Button>
</TooltipV2>
<TooltipV2 text="Open GitHub Copilot chat" direction="s">
<IconButton icon={CopilotIcon} aria-label="Open GitHub Copilot chat" />
</TooltipV2>
</ButtonGroup>
)

export const ButtonAndLinkWithTooltip2 = () => (
<ButtonGroup sx={{pl: 2}}>
<TooltipV2 text="Open GitHub Copilot chat" direction="s">
<IconButton icon={CopilotIcon} aria-label="Open GitHub Copilot chat" />
</TooltipV2>
<TooltipV2 text="Additional info about the link">
<Button as="a" href="https://primer.style">
Link
</Button>
</TooltipV2>
</ButtonGroup>
)
Loading
Loading