Skip to content

Commit 7dad313

Browse files
authored
feat: Expose closeToast in useToasts hook action object (#914)
* feat: Expose showStickyToast in useToasts hook * chore: Rename to closeToast and move inside action object * chore: Add test to describe block
1 parent 141dcee commit 7dad313

File tree

4 files changed

+63
-1
lines changed

4 files changed

+63
-1
lines changed

src/toast/static-toast.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import styles from './toast.module.css'
1111
type ToastActionObject = {
1212
label: string
1313
onClick: () => void
14+
closeToast?: boolean
1415
}
1516

1617
type StaticToastProps = {

src/toast/toast.stories.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,22 @@ export function NotificationToastsStory() {
8888
>
8989
Show toast with action
9090
</Button>
91+
<Button
92+
variant="primary"
93+
onClick={() => {
94+
const actionLabel = getRandom(actions)
95+
showToast({
96+
message: `${count.current++}: ${getRandom(message)}`,
97+
action: {
98+
label: actionLabel,
99+
onClick: storybookAction(actionLabel),
100+
closeToast: false,
101+
},
102+
})
103+
}}
104+
>
105+
Show toast without closing on action
106+
</Button>
91107
</Inline>
92108
</Box>
93109
<SwitchField

src/toast/toast.test.tsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,47 @@ describe('useToast', () => {
124124
expect(within(screen.getByRole('alert')).getByTestId('test-icon')).toBeInTheDocument()
125125
})
126126

127+
describe('if `closeToast` is false', () => {
128+
it('keeps the toast visible after the action button is clicked', () => {
129+
const actionFn = jest.fn()
130+
const { showToast } = renderTestCase()
131+
showToast({
132+
action: { label: 'A sticky toast action', onClick: actionFn, closeToast: false },
133+
})
134+
expect(actionFn).not.toHaveBeenCalled()
135+
userEvent.click(
136+
within(screen.getByRole('alert')).getByRole('button', {
137+
name: 'A sticky toast action',
138+
}),
139+
)
140+
expect(actionFn).toHaveBeenCalledTimes(1)
141+
142+
// closeToast has kept it in view
143+
expect(screen.getByRole('alert')).toBeInTheDocument()
144+
})
145+
})
146+
147+
describe('if `closeToast` is true', () => {
148+
it('removes the toast from view after the action button is clicked', async () => {
149+
const actionFn = jest.fn()
150+
const { showToast } = renderTestCase()
151+
showToast({
152+
action: { label: 'A sticky toast action', onClick: actionFn },
153+
})
154+
expect(actionFn).not.toHaveBeenCalled()
155+
userEvent.click(
156+
within(screen.getByRole('alert')).getByRole('button', {
157+
name: 'A sticky toast action',
158+
}),
159+
)
160+
expect(actionFn).toHaveBeenCalledTimes(1)
161+
162+
await waitFor(() => {
163+
expect(screen.queryByRole('alert')).not.toBeInTheDocument()
164+
})
165+
})
166+
})
167+
127168
describe('Dismiss button', () => {
128169
it('is rendered with a default label', () => {
129170
const { showToast } = renderTestCase()

src/toast/use-toasts.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,17 @@ const InternalToast = React.forwardRef<HTMLDivElement, InternalToastProps>(funct
109109

110110
return {
111111
...action,
112+
closeToast: action.closeToast ?? true,
112113
onClick: function handleActionClick() {
113114
if (!action) {
114115
return
115116
}
116117

117118
action.onClick()
118-
removeToast()
119+
120+
if (action.closeToast ?? true) {
121+
removeToast()
122+
}
119123
},
120124
}
121125
}, [action, removeToast])

0 commit comments

Comments
 (0)