Skip to content

Commit b38f743

Browse files
authored
Merge branch 'main' into VanAnderson/action-menu-external-open
2 parents 978fb81 + 4c2e1a2 commit b38f743

File tree

9 files changed

+69
-26
lines changed

9 files changed

+69
-26
lines changed

.changeset/happy-plums-work.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@primer/components": patch
3+
---
4+
5+
Allow custom `children` in `ActionItem`. `text` and `description` can still be provided as a shortcut, but `children` is now available if you need more control over the rending of the item, without sacrificing benefits from `Item` by using `renderItem`.

.changeset/long-chefs-bathe.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@primer/components": patch
3+
---
4+
5+
Export useConfirm hook and ConfirmationDialog component from index.

src/ActionList/Item.tsx

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import {get} from '../constants'
44
import sx, {SxProp} from '../sx'
55
import {ItemInput} from './List'
66
import styled from 'styled-components'
7-
import {themeGet} from '..'
87

98
/**
109
* Contract for props passed to the `Item` component.
@@ -13,7 +12,7 @@ export interface ItemProps extends React.ComponentPropsWithoutRef<'div'>, SxProp
1312
/**
1413
* Primary text which names an `Item`.
1514
*/
16-
text: string
15+
text?: string
1716

1817
/**
1918
* Secondary text which provides additional information about an `Item`.
@@ -75,9 +74,9 @@ export interface ItemProps extends React.ComponentPropsWithoutRef<'div'>, SxProp
7574
const getItemVariant = (variant = 'default', disabled?: boolean) => {
7675
if (disabled) {
7776
return {
78-
color: themeGet('colors.text.disabled'),
79-
iconColor: themeGet('colors.text.disabled'),
80-
annotationColor: themeGet('colors.text.disabled'),
77+
color: get('colors.text.disabled'),
78+
iconColor: get('colors.text.disabled'),
79+
annotationColor: get('colors.text.disabled'),
8180
hoverBackground: 'inherit',
8281
hoverCursor: 'default'
8382
}
@@ -86,18 +85,18 @@ const getItemVariant = (variant = 'default', disabled?: boolean) => {
8685
switch (variant) {
8786
case 'danger':
8887
return {
89-
color: themeGet('colors.text.danger'),
90-
iconColor: themeGet('colors.icon.danger'),
91-
annotationColor: themeGet('colors.text.disabled'),
92-
hoverBackground: themeGet('colors.bg.danger'),
88+
color: get('colors.text.danger'),
89+
iconColor: get('colors.icon.danger'),
90+
annotationColor: get('colors.text.disabled'),
91+
hoverBackground: get('colors.bg.danger'),
9392
hoverCursor: 'pointer'
9493
}
9594
default:
9695
return {
9796
color: 'inherit',
98-
iconColor: themeGet('colors.text.disabled'),
99-
annotationColor: themeGet('colors.text.disabled'),
100-
hoverBackground: themeGet('colors.selectMenu.tapHighlight'),
97+
iconColor: get('colors.text.disabled'),
98+
annotationColor: get('colors.text.disabled'),
99+
hoverBackground: get('colors.selectMenu.tapHighlight'),
101100
hoverCursor: 'pointer'
102101
}
103102
}
@@ -179,6 +178,7 @@ export function Item(itemProps: Partial<ItemProps> & {item?: ItemInput}): JSX.El
179178
disabled,
180179
onAction,
181180
onKeyPress,
181+
children,
182182
onClick,
183183
...props
184184
} = itemProps
@@ -224,10 +224,13 @@ export function Item(itemProps: Partial<ItemProps> & {item?: ItemInput}): JSX.El
224224
<LeadingVisual />
225225
</LeadingVisualContainer>
226226
)}
227-
<StyledTextContainer descriptionVariant={descriptionVariant}>
228-
<div>{text}</div>
229-
{description && <DescriptionContainer>{description}</DescriptionContainer>}
230-
</StyledTextContainer>
227+
{children}
228+
{(text || description) && (
229+
<StyledTextContainer descriptionVariant={descriptionVariant}>
230+
{text && <div>{text}</div>}
231+
{description && <DescriptionContainer>{description}</DescriptionContainer>}
232+
</StyledTextContainer>
233+
)}
231234
{(TrailingIcon || trailingText) && (
232235
<TrailingVisualContainer variant={variant} disabled={disabled}>
233236
{trailingText && <div>{trailingText}</div>}

src/Dialog/ConfirmationDialog.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import React, {useCallback} from 'react'
22
import ReactDOM from 'react-dom'
33
import styled from 'styled-components'
4-
import {Box, ThemeProvider, useTheme} from '..'
4+
import Box from '../Box'
5+
import {ThemeProvider, useTheme, ThemeProviderProps} from '../ThemeProvider'
56
import {FocusKeys} from '../behaviors/focusZone'
67
import {get} from '../constants'
78
import {Dialog, DialogProps, DialogHeaderProps, DialogButtonProps} from '../Dialog/Dialog'
89
import {useFocusZone} from '../hooks/useFocusZone'
9-
import {ThemeProviderProps} from '../ThemeProvider'
1010

1111
/**
1212
* Props to customize the ConfirmationDialog.

src/Dialog/Dialog.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import React, {useCallback, useEffect, useRef} from 'react'
22
import styled from 'styled-components'
3-
import {Button, ButtonPrimary, ButtonDanger, ButtonProps, Flex, Box} from '..'
3+
import Button, {ButtonPrimary, ButtonDanger, ButtonProps} from '../Button'
4+
import Flex from '../Flex'
5+
import Box from '../Box'
46
import {get, SystemCommonProps, SystemPositionProps, COMMON, POSITION} from '../constants'
57
import {useOnEscapePress} from '../hooks'
68
import {useFocusTrap} from '../hooks/useFocusTrap'

src/__tests__/ActionMenu.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ describe('ActionMenu', () => {
7878
})
7979
portalRoot = menu.baseElement.querySelector('#__primerPortalRoot__')
8080
expect(portalRoot).toBeTruthy()
81-
const menuItem = await menu.queryByText(items[0].text)
81+
const menuItem = await menu.queryByText(items[0].text!)
8282
act(() => {
8383
fireEvent.click(menuItem as Element)
8484
})

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export {useOnOutsideClick} from './hooks/useOnOutsideClick'
2424
export {useOpenAndCloseFocus} from './hooks/useOpenAndCloseFocus'
2525
export {useOnEscapePress} from './hooks/useOnEscapePress'
2626
export {useOverlay} from './hooks/useOverlay'
27+
export {useConfirm} from './Dialog/ConfirmationDialog'
2728

2829
// Components
2930
export {ActionList} from './ActionList'
@@ -71,6 +72,7 @@ export {default as Details} from './Details'
7172
export type {DetailsProps} from './Details'
7273
export {default as Dialog} from './Dialog'
7374
export type {DialogProps, DialogHeaderProps} from './Dialog'
75+
export {ConfirmationDialog} from './Dialog/ConfirmationDialog'
7476
export {default as Dropdown} from './Dropdown'
7577
export type {
7678
DropdownProps,

src/stories/ActionList.stories.tsx

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,14 @@ import {
77
NoteIcon,
88
ProjectIcon,
99
FilterIcon,
10-
GearIcon
10+
GearIcon,
11+
ArrowRightIcon,
12+
ArrowLeftIcon
1113
} from '@primer/octicons-react'
1214
import {Meta} from '@storybook/react'
1315
import React from 'react'
1416
import styled from 'styled-components'
15-
import {ThemeProvider} from '..'
17+
import {Label, ThemeProvider} from '..'
1618
import {ActionList as _ActionList} from '../ActionList'
1719
import {Header} from '../ActionList/Header'
1820
import BaseStyles from '../BaseStyles'
@@ -238,3 +240,27 @@ export function HeaderStory(): JSX.Element {
238240
)
239241
}
240242
HeaderStory.storyName = 'Header'
243+
244+
export function CustomItemChildren(): JSX.Element {
245+
return (
246+
<>
247+
<h1>Custom Item Children</h1>
248+
<ErsatzOverlay>
249+
<ActionList
250+
items={[
251+
{
252+
leadingVisual: ArrowRightIcon,
253+
children: (
254+
<Label outline borderColor="border.success">
255+
Choose this one
256+
</Label>
257+
),
258+
trailingIcon: ArrowLeftIcon
259+
}
260+
]}
261+
/>
262+
</ErsatzOverlay>
263+
</>
264+
)
265+
}
266+
CustomItemChildren.storyName = 'Custom Item Children'

src/stories/ActionMenu.stories.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ const ErsatzOverlay = styled.div`
4949
export function ActionsStory(): JSX.Element {
5050
const [option, setOption] = useState('Select an option')
5151
const onAction = (itemProps: ItemProps) => {
52-
setOption(itemProps.text)
52+
setOption(itemProps.text ?? '')
5353
}
5454
return (
5555
<>
@@ -86,7 +86,7 @@ ActionsStory.storyName = 'Actions'
8686
export function SimpleListStory(): JSX.Element {
8787
const [option, setOption] = useState('Select an option')
8888
const onAction = (itemProps: ItemProps) => {
89-
setOption(itemProps.text)
89+
setOption(itemProps.text || '')
9090
}
9191
return (
9292
<>
@@ -156,7 +156,7 @@ ExternalOpenState.storyName = 'External Open State'
156156
export function ComplexListStory(): JSX.Element {
157157
const [option, setOption] = useState('Select an option')
158158
const onAction = (itemProps: ItemProps) => {
159-
setOption(itemProps.text)
159+
setOption(itemProps.text || '')
160160
}
161161
return (
162162
<>
@@ -217,7 +217,7 @@ export function CustomTrigger(): JSX.Element {
217217
const customAnchor = (props: LinkProps) => <Link {...props} sx={{cursor: 'pointer'}} />
218218
const [option, setOption] = useState('Select an option')
219219
const onAction = useCallback((itemProps: ItemProps) => {
220-
setOption(itemProps.text)
220+
setOption(itemProps.text || '')
221221
}, [])
222222
return (
223223
<>

0 commit comments

Comments
 (0)