Skip to content

Commit

Permalink
ActionBar: convert to CSS Modules + add new flush prop to adjust pa…
Browse files Browse the repository at this point in the history
…dding (#5540)

* add props

* fix border

* fix type

* remove label

* try fix test?

* Create shy-carpets-relax.md

* test(vrt): update snapshots

---------

Co-authored-by: langermank <[email protected]>
  • Loading branch information
langermank and langermank authored Jan 22, 2025
1 parent 191950e commit 20788da
Show file tree
Hide file tree
Showing 14 changed files with 104 additions and 87 deletions.
6 changes: 6 additions & 0 deletions .changeset/shy-carpets-relax.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@primer/react": minor
---

- Convert ActionBar to CSS Modules
- Add new padding prop for container padding
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.
14 changes: 14 additions & 0 deletions packages/react/src/ActionBar/ActionBar.docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,20 @@
"required": false,
"description": "Size of the action bar",
"defaultValue": ""
},
{
"name": "flush",
"type": "boolean",
"required": false,
"description": "Allows ActionBar to be flush with the container",
"defaultValue": "false"
},
{
"name": "className",
"type": "string",
"required": false,
"description": "Custom className",
"defaultValue": ""
}
],
"subcomponents": [
Expand Down
35 changes: 35 additions & 0 deletions packages/react/src/ActionBar/ActionBar.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
.List {
position: relative;
display: flex;
min-width: 0;

/* wonder why this is here */
/* stylelint-disable-next-line primer/spacing */
margin-bottom: -1px;
white-space: nowrap;
list-style: none;
align-items: center;
gap: var(--base-size-8);
}

.Nav {
display: flex;
padding-inline: var(--base-size-16);
justify-content: flex-end;
align-items: center;

&:where([data-flush='true']) {
padding-inline: 0;
}
}

.Divider {
&::before {
display: block;
width: var(--borderWidth-thin);
height: var(--base-size-20);
content: '';
/* stylelint-disable-next-line primer/colors */
background: var(--borderColor-muted);
}
}
35 changes: 33 additions & 2 deletions packages/react/src/ActionBar/ActionBar.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from 'react'
import type {Meta} from '@storybook/react'
import ActionBar from '.'
import {
BoldIcon,
Expand All @@ -13,11 +12,43 @@ import {
ListOrderedIcon,
TasklistIcon,
} from '@primer/octicons-react'
import type {Meta, StoryObj} from '@storybook/react'

export default {
const meta: Meta<typeof ActionBar> = {
title: 'Experimental/Components/ActionBar',
} as Meta<typeof ActionBar>

export default meta
type Story = StoryObj<typeof ActionBar>

export const Playground: Story = {
render: args => (
<ActionBar {...args}>
<ActionBar.IconButton icon={BoldIcon} aria-label="Bold"></ActionBar.IconButton>
<ActionBar.IconButton icon={ItalicIcon} aria-label="Italic"></ActionBar.IconButton>
<ActionBar.Divider />
<ActionBar.IconButton icon={CodeIcon} aria-label="Code"></ActionBar.IconButton>
</ActionBar>
),
}
Playground.argTypes = {
size: {
control: {
type: 'radio',
},
options: ['small', 'medium', 'large'],
},
flush: {
control: {
type: 'boolean',
},
},
}
Playground.args = {
size: 'medium',
flush: false,
}

export const Default = () => (
<ActionBar aria-label="Toolbar">
<ActionBar.IconButton icon={BoldIcon} aria-label="Bold"></ActionBar.IconButton>
Expand Down
101 changes: 16 additions & 85 deletions packages/react/src/ActionBar/ActionBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,17 @@ import React, {useState, useCallback, useRef, forwardRef} from 'react'
import {KebabHorizontalIcon} from '@primer/octicons-react'
import {ActionList} from '../ActionList'
import useIsomorphicLayoutEffect from '../utils/useIsomorphicLayoutEffect'
import styled from 'styled-components'
import sx from '../sx'
import {useOnEscapePress} from '../hooks/useOnEscapePress'
import type {ResizeObserverEntry} from '../hooks/useResizeObserver'
import {useResizeObserver} from '../hooks/useResizeObserver'

import {useOnOutsideClick} from '../hooks/useOnOutsideClick'
import type {IconButtonProps} from '../Button'
import {IconButton} from '../Button'
import Box from '../Box'
import {ActionMenu} from '../ActionMenu'
import {useFocusZone, FocusKeys} from '../hooks/useFocusZone'
import styles from './ActionBar.module.css'
import {clsx} from 'clsx'

type ChildSize = {
text: string
Expand Down Expand Up @@ -43,54 +42,13 @@ type A11yProps =
export type ActionBarProps = {
size?: Size
children: React.ReactNode
flush?: boolean
className?: string
} & A11yProps

export type ActionBarIconButtonProps = IconButtonProps

const NavigationList = styled.div`
${sx};
`

const GAP = 8

const listStyles = {
display: 'flex',
minWidth: 0,
listStyle: 'none',
whiteSpace: 'nowrap',
paddingY: 0,
paddingX: 0,
margin: 0,
marginBottom: '-1px',
alignItems: 'center',
gap: `${GAP}px`,
position: 'relative',
}

const MORE_BTN_WIDTH = 86
const navStyles = {
display: 'flex',
paddingX: 3,
justifyContent: 'flex-end',
align: 'row',
alignItems: 'center',
maxHeight: '32px',
}

const menuItemStyles = {
textDecoration: 'none',
}

const moreBtnStyles = {
//set margin 0 here because safari puts extra margin around the button, rest is to reset style to make it look like a list element
margin: 0,
border: 0,
background: 'transparent',
fontWeight: 'normal',
boxShadow: 'none',
paddingY: 1,
paddingX: 2,
}

const getValidChildren = (children: React.ReactNode) => {
return React.Children.toArray(children).filter(child => {
Expand Down Expand Up @@ -168,7 +126,7 @@ const overflowEffect = (
}

export const ActionBar: React.FC<React.PropsWithChildren<ActionBarProps>> = props => {
const {size = 'medium', children, 'aria-label': ariaLabel} = props
const {size = 'medium', children, 'aria-label': ariaLabel, flush = false, className} = props
const [childWidthArray, setChildWidthArray] = useState<ChildWidthArray>([])
const setChildrenWidth = useCallback((size: ChildSize) => {
setChildWidthArray(arr => {
Expand Down Expand Up @@ -243,34 +201,25 @@ export const ActionBar: React.FC<React.PropsWithChildren<ActionBarProps>> = prop

return (
<ActionBarContext.Provider value={{size, setChildrenWidth}}>
<Box ref={navRef} sx={navStyles}>
<NavigationList sx={listStyles} ref={listRef} role="toolbar">
<div ref={navRef} className={clsx(className, styles.Nav)} data-flush={flush}>
<div ref={listRef} role="toolbar" className={styles.List}>
{listItems}
{menuItems.length > 0 && (
<ActionMenu>
<ActionMenu.Anchor>
<IconButton sx={moreBtnStyles} aria-label={`More ${ariaLabel} items`} icon={KebabHorizontalIcon} />
<IconButton variant="invisible" aria-label={`More ${ariaLabel} items`} icon={KebabHorizontalIcon} />
</ActionMenu.Anchor>
<ActionMenu.Overlay>
<ActionList>
{menuItems.map((menuItem, index) => {
if (menuItem.type === ActionList.Divider) {
return <ActionList.Divider key={index} />
} else {
const {
children: menuItemChildren,
//'aria-current': ariaCurrent,
onClick,
icon: Icon,
'aria-label': ariaLabel,
} = menuItem.props
const {children: menuItemChildren, onClick, icon: Icon, 'aria-label': ariaLabel} = menuItem.props
return (
<ActionList.LinkItem
<ActionList.Item
key={menuItemChildren}
sx={menuItemStyles}
onClick={(
event: React.MouseEvent<HTMLAnchorElement> | React.KeyboardEvent<HTMLAnchorElement>,
) => {
onClick={(event: React.MouseEvent<HTMLLIElement, MouseEvent>) => {
closeOverlay()
focusOnMoreMenuBtn()
typeof onClick === 'function' && onClick(event)
Expand All @@ -282,16 +231,16 @@ export const ActionBar: React.FC<React.PropsWithChildren<ActionBarProps>> = prop
</ActionList.LeadingVisual>
) : null}
{ariaLabel}
</ActionList.LinkItem>
</ActionList.Item>
)
}
})}
</ActionList>
</ActionMenu.Overlay>
</ActionMenu>
)}
</NavigationList>
</Box>
</div>
</div>
</ActionBarContext.Provider>
)
}
Expand All @@ -308,31 +257,13 @@ export const ActionBarIconButton = forwardRef((props: ActionBarIconButtonProps,
return <IconButton ref={ref} size={size} {...props} variant="invisible" />
})

const sizeToHeight = {
small: '24px',
medium: '28px',
large: '32px',
}
export const VerticalDivider = () => {
const ref = useRef<HTMLDivElement>(null)
const {size, setChildrenWidth} = React.useContext(ActionBarContext)
const {setChildrenWidth} = React.useContext(ActionBarContext)
useIsomorphicLayoutEffect(() => {
const text = 'divider'
const domRect = (ref as MutableRefObject<HTMLElement>).current.getBoundingClientRect()
setChildrenWidth({text, width: domRect.width})
}, [ref, setChildrenWidth])
return (
<Box
ref={ref}
data-component="ActionBar.VerticalDivider"
aria-hidden="true"
sx={{
display: 'inline-block',
borderLeft: '1px solid',
borderColor: 'actionListItem.inlineDivider',
height: sizeToHeight[size],
mx: 2,
}}
/>
)
return <div ref={ref} data-component="ActionBar.VerticalDivider" aria-hidden="true" className={styles.Divider} />
}

0 comments on commit 20788da

Please sign in to comment.