Skip to content

Commit

Permalink
Explore wrapping button group items with a div to simplify css selection
Browse files Browse the repository at this point in the history
  • Loading branch information
broccolinisoup committed Mar 8, 2024
1 parent 5c7571c commit 784d775
Show file tree
Hide file tree
Showing 3 changed files with 185 additions and 20 deletions.
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>
)
43 changes: 39 additions & 4 deletions packages/react/src/ButtonGroup/ButtonGroup.features.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,52 @@
import React from 'react'
import type {ComponentMeta} from '@storybook/react'
import type {Meta} from '@storybook/react'
import ButtonGroup from './ButtonGroup'
import {IconButton} from '../Button'
import {Button, IconButton} from '../Button'
import {PlusIcon, DashIcon} from '@primer/octicons-react'
import {Tooltip} from '../next'
import {Box, ThemeProvider, BaseStyles} from '..'

export default {
const meta: Meta<typeof ButtonGroup> = {
title: 'Components/ButtonGroup/Features',
component: ButtonGroup,
} as ComponentMeta<typeof 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 IconButtons = () => (
<ButtonGroup>
<IconButton icon={PlusIcon} aria-label="Add" />
<IconButton icon={DashIcon} aria-label="Subtract" />
</ButtonGroup>
)

export const IconButtonsWithTooltip = () => (
<ButtonGroup>
<Tooltip text="Add" type="label">
<IconButton icon={PlusIcon} aria-label="Add" />
</Tooltip>
<Tooltip text="Subtract" type="label">
<IconButton icon={DashIcon} aria-label="Subtract" />
</Tooltip>
</ButtonGroup>
)
export const ButtonAndLink = () => (
<ButtonGroup>
<Button>Button</Button>
<Button as="a" href="https://primer.style">
Link
</Button>
</ButtonGroup>
)
43 changes: 27 additions & 16 deletions packages/react/src/ButtonGroup/ButtonGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,48 @@
import styled from 'styled-components'
import {get} from '../constants'
import sx from '../sx'
import type {ComponentProps} from '../utils/types'
import {type SxProp} from '../sx'
import React from 'react'
import Box from '../Box'
import {defaultSxProp} from '../utils/defaultSxProp'

const ButtonGroup = styled.div`
export type ButtonGroupProps = SxProp & React.ComponentPropsWithoutRef<'div'>

function ButtonGroup({children, sx = defaultSxProp, ...rest}: React.PropsWithChildren<ButtonGroupProps>) {
const buttons = React.Children.map(children, (child, index) => (
<Box key={index} {...rest}>
{child}
</Box>
))

return <StyledButtonGroup sx={sx}>{buttons}</StyledButtonGroup>
}

const StyledButtonGroup = styled.div`
display: inline-flex;
vertical-align: middle;
isolation: isolate;
&& > * {
&& :is(button, a) {
margin-inline-end: -1px;
position: relative;
border-radius: 0;
:first-child {
border-top-left-radius: ${get('radii.2')};
border-bottom-left-radius: ${get('radii.2')};
}
:last-child {
border-top-right-radius: ${get('radii.2')};
border-bottom-right-radius: ${get('radii.2')};
}
:focus,
:active,
:hover {
z-index: 1;
}
}
${sx};
&& > :first-child :is(button, a) {
border-top-left-radius: ${get('radii.2')};
border-bottom-left-radius: ${get('radii.2')};
}
&& > :last-child :is(button, a) {
border-top-right-radius: ${get('radii.2')};
border-bottom-right-radius: ${get('radii.2')};
}
`

export type ButtonGroupProps = ComponentProps<typeof ButtonGroup>
export default ButtonGroup

0 comments on commit 784d775

Please sign in to comment.