@@ -23,6 +23,19 @@ afterEach(() => {
2323 jest . restoreAllMocks ( ) ;
2424} ) ;
2525
26+ function getDirectionButton ( direction : Direction ) {
27+ return document . querySelector < HTMLButtonElement > (
28+ `.${ styles [ `direction-button-wrapper-${ direction } ` ] } .${ styles [ 'direction-button' ] } `
29+ ) ;
30+ }
31+
32+ function expectDirectionButtonHidden ( direction : Direction ) {
33+ // Direction buttons get hidden via transition which doesn't end in JSDOM, so we just listen
34+ // for the exiting classname instead.
35+ const motionExitingClass = styles [ 'direction-button-wrapper-motion-exiting' ] ;
36+ expect ( getDirectionButton ( direction ) ?. parentElement ) . toHaveClass ( motionExitingClass ) ;
37+ }
38+
2639function renderDragHandle ( props : Omit < DragHandleWrapperProps , 'children' > ) {
2740 const { container } = render (
2841 < DragHandleWrapper { ...props } >
@@ -39,11 +52,6 @@ function renderDragHandle(props: Omit<DragHandleWrapperProps, 'children'>) {
3952 container . querySelector < HTMLButtonElement > ( '#drag-button' ) ! . focus ( ) ;
4053 } ,
4154 getTooltip : ( ) => document . querySelector ( `.${ tooltipStyles . root } ` ) ,
42- getDirectionButton : ( direction : Direction ) => {
43- return document . querySelector < HTMLButtonElement > (
44- `.${ styles [ `direction-button-wrapper-${ direction } ` ] } .${ styles [ 'direction-button' ] } `
45- ) ;
46- } ,
4755 } ;
4856}
4957
@@ -127,43 +135,125 @@ test('hides tooltip on Escape', () => {
127135} ) ;
128136
129137test ( "doesn't show direction buttons by default" , ( ) => {
130- const { getDirectionButton } = renderDragHandle ( {
138+ renderDragHandle ( {
131139 directions : { 'block-start' : 'active' } ,
132- tooltipText : 'Click me!' ,
133140 } ) ;
134141
135142 expect ( getDirectionButton ( 'block-start' ) ) . not . toBeInTheDocument ( ) ;
136143 expect ( getDirectionButton ( 'block-end' ) ) . not . toBeInTheDocument ( ) ;
137144} ) ;
138145
139- test ( 'shows direction buttons when focus enters the button as result of a key input' , ( ) => {
140- const { dragHandle, getDirectionButton } = renderDragHandle ( {
141- directions : { 'block-start' : 'active' , 'block-end' : 'active' } ,
142- tooltipText : 'Click me!' ,
146+ describe ( 'triggerMode = focus (default)' , ( ) => {
147+ test ( 'shows direction buttons when focus enters the button' , ( ) => {
148+ const { dragHandle } = renderDragHandle ( {
149+ directions : { 'block-start' : 'active' , 'block-end' : 'active' } ,
150+ } ) ;
151+
152+ document . body . dataset . awsuiFocusVisible = 'true' ;
153+ dragHandle . focus ( ) ;
154+ expect ( getDirectionButton ( 'block-start' ) ) . toBeVisible ( ) ;
155+ expect ( getDirectionButton ( 'block-end' ) ) . toBeVisible ( ) ;
156+ expect ( getDirectionButton ( 'inline-start' ) ) . not . toBeInTheDocument ( ) ;
143157 } ) ;
144158
145- document . body . dataset . awsuiFocusVisible = 'true' ;
146- dragHandle . focus ( ) ;
147- expect ( getDirectionButton ( 'block-start' ) ) . toBeVisible ( ) ;
148- expect ( getDirectionButton ( 'block-end' ) ) . toBeVisible ( ) ;
149- expect ( getDirectionButton ( 'inline-start' ) ) . not . toBeInTheDocument ( ) ;
159+ test ( 'hides direction buttons when focus leaves the button' , ( ) => {
160+ const { dragHandle } = renderDragHandle ( {
161+ directions : { 'block-start' : 'active' , 'block-end' : 'active' } ,
162+ tooltipText : 'Click me!' ,
163+ } ) ;
164+
165+ document . body . dataset . awsuiFocusVisible = 'true' ;
166+ dragHandle . focus ( ) ;
167+
168+ expect ( getDirectionButton ( 'block-start' ) ) . toBeInTheDocument ( ) ;
169+ expect ( getDirectionButton ( 'block-end' ) ) . toBeInTheDocument ( ) ;
170+
171+ fireEvent . blur ( dragHandle ) ;
172+ expectDirectionButtonHidden ( 'block-start' ) ;
173+ expectDirectionButtonHidden ( 'block-end' ) ;
174+ } ) ;
150175} ) ;
151176
152- test ( 'hides direction buttons when focus leaves the button' , ( ) => {
153- const { dragHandle, getDirectionButton } = renderDragHandle ( {
154- directions : { 'block-start' : 'active' , 'block-end' : 'active' } ,
155- tooltipText : 'Click me!' ,
177+ describe ( 'triggerMode = keyboard-activate' , ( ) => {
178+ test ( 'does not show direction buttons when focus enters the button' , ( ) => {
179+ const { dragHandle } = renderDragHandle ( {
180+ directions : { 'block-start' : 'active' , 'block-end' : 'active' } ,
181+ triggerMode : 'keyboard-activate' ,
182+ } ) ;
183+
184+ document . body . dataset . awsuiFocusVisible = 'true' ;
185+ dragHandle . focus ( ) ;
186+ expect ( getDirectionButton ( 'block-start' ) ) . toBeNull ( ) ;
187+ expect ( getDirectionButton ( 'block-end' ) ) . toBeNull ( ) ;
188+ expect ( getDirectionButton ( 'inline-start' ) ) . toBeNull ( ) ;
189+ expect ( getDirectionButton ( 'inline-end' ) ) . toBeNull ( ) ;
156190 } ) ;
157191
158- document . body . dataset . awsuiFocusVisible = 'true' ;
159- fireEvent . focusIn ( dragHandle , { relatedElement : document . body } ) ;
160- fireEvent . focusOut ( dragHandle , { relatedElement : document . body } ) ;
161- expect ( getDirectionButton ( 'block-start' ) ) . not . toBeInTheDocument ( ) ;
162- expect ( getDirectionButton ( 'block-end' ) ) . not . toBeInTheDocument ( ) ;
192+ test . each ( [ 'Enter' , ' ' ] ) ( 'show direction buttons when "%s" key is pressed on the focused button' , key => {
193+ const { dragHandle } = renderDragHandle ( {
194+ directions : { 'block-start' : 'active' , 'block-end' : 'active' } ,
195+ triggerMode : 'keyboard-activate' ,
196+ } ) ;
197+
198+ document . body . dataset . awsuiFocusVisible = 'true' ;
199+ dragHandle . focus ( ) ;
200+ expect ( getDirectionButton ( 'block-start' ) ) . not . toBeInTheDocument ( ) ;
201+ expect ( getDirectionButton ( 'block-end' ) ) . not . toBeInTheDocument ( ) ;
202+ expect ( getDirectionButton ( 'inline-start' ) ) . not . toBeInTheDocument ( ) ;
203+ expect ( getDirectionButton ( 'inline-end' ) ) . not . toBeInTheDocument ( ) ;
204+
205+ fireEvent . keyDown ( dragHandle , { key } ) ;
206+
207+ expect ( getDirectionButton ( 'block-start' ) ) . toBeInTheDocument ( ) ;
208+ expect ( getDirectionButton ( 'block-end' ) ) . toBeInTheDocument ( ) ;
209+ expect ( getDirectionButton ( 'inline-start' ) ) . not . toBeInTheDocument ( ) ;
210+ expect ( getDirectionButton ( 'inline-end' ) ) . not . toBeInTheDocument ( ) ;
211+ } ) ;
212+
213+ test ( 'hides direction buttons when focus leaves the button' , ( ) => {
214+ const { dragHandle } = renderDragHandle ( {
215+ directions : { 'block-start' : 'active' , 'block-end' : 'active' } ,
216+ triggerMode : 'keyboard-activate' ,
217+ } ) ;
218+
219+ document . body . dataset . awsuiFocusVisible = 'true' ;
220+
221+ dragHandle . focus ( ) ;
222+ fireEvent . keyDown ( dragHandle , { key : 'Enter' } ) ;
223+ expect ( getDirectionButton ( 'block-start' ) ) . toBeInTheDocument ( ) ;
224+ expect ( getDirectionButton ( 'block-end' ) ) . toBeInTheDocument ( ) ;
225+ expect ( getDirectionButton ( 'inline-start' ) ) . not . toBeInTheDocument ( ) ;
226+ expect ( getDirectionButton ( 'inline-end' ) ) . not . toBeInTheDocument ( ) ;
227+
228+ fireEvent . blur ( dragHandle ) ;
229+ expectDirectionButtonHidden ( 'block-start' ) ;
230+ expectDirectionButtonHidden ( 'block-end' ) ;
231+ } ) ;
232+
233+ test . each ( [ 'Enter' , ' ' ] ) ( 'hides direction buttons when toggling "%s" key' , key => {
234+ const { dragHandle } = renderDragHandle ( {
235+ directions : { 'block-start' : 'active' , 'block-end' : 'active' } ,
236+ triggerMode : 'keyboard-activate' ,
237+ } ) ;
238+
239+ document . body . dataset . awsuiFocusVisible = 'true' ;
240+
241+ fireEvent . keyDown ( dragHandle , { key } ) ;
242+
243+ expect ( getDirectionButton ( 'block-start' ) ) . toBeInTheDocument ( ) ;
244+ expect ( getDirectionButton ( 'block-end' ) ) . toBeInTheDocument ( ) ;
245+ expect ( getDirectionButton ( 'inline-start' ) ) . not . toBeInTheDocument ( ) ;
246+ expect ( getDirectionButton ( 'inline-end' ) ) . not . toBeInTheDocument ( ) ;
247+
248+ fireEvent . keyDown ( dragHandle , { key } ) ;
249+
250+ expectDirectionButtonHidden ( 'block-start' ) ;
251+ expectDirectionButtonHidden ( 'block-end' ) ;
252+ } ) ;
163253} ) ;
164254
165255test ( 'shows direction buttons when clicked' , ( ) => {
166- const { dragHandle, getDirectionButton } = renderDragHandle ( {
256+ const { dragHandle } = renderDragHandle ( {
167257 directions : { 'block-start' : 'active' } ,
168258 tooltipText : 'Click me!' ,
169259 } ) ;
@@ -174,7 +264,7 @@ test('shows direction buttons when clicked', () => {
174264} ) ;
175265
176266test ( `doesn't show direction buttons when drag is "cancelled"` , ( ) => {
177- const { dragHandle, getDirectionButton } = renderDragHandle ( {
267+ const { dragHandle } = renderDragHandle ( {
178268 directions : { 'block-start' : 'active' } ,
179269 tooltipText : 'Click me!' ,
180270 } ) ;
@@ -185,7 +275,7 @@ test(`doesn't show direction buttons when drag is "cancelled"`, () => {
185275} ) ;
186276
187277test ( 'shows direction buttons when dragged 2 pixels' , ( ) => {
188- const { dragHandle, getDirectionButton } = renderDragHandle ( {
278+ const { dragHandle } = renderDragHandle ( {
189279 directions : { 'block-start' : 'active' } ,
190280 tooltipText : 'Click me!' ,
191281 } ) ;
@@ -197,7 +287,7 @@ test('shows direction buttons when dragged 2 pixels', () => {
197287} ) ;
198288
199289test ( "doesn't show direction buttons when dragged more than 3 pixels" , ( ) => {
200- const { dragHandle, getDirectionButton } = renderDragHandle ( {
290+ const { dragHandle } = renderDragHandle ( {
201291 directions : { 'block-start' : 'active' } ,
202292 tooltipText : 'Click me!' ,
203293 } ) ;
@@ -209,21 +299,18 @@ test("doesn't show direction buttons when dragged more than 3 pixels", () => {
209299} ) ;
210300
211301test ( 'hides direction buttons on Escape keypress' , ( ) => {
212- const { dragHandle, showButtons, getDirectionButton } = renderDragHandle ( {
302+ const { dragHandle, showButtons } = renderDragHandle ( {
213303 directions : { 'block-start' : 'active' } ,
214304 tooltipText : 'Click me!' ,
215305 } ) ;
216306
217307 showButtons ( ) ;
218308 fireEvent . keyDown ( dragHandle , { key : 'Escape' } ) ;
219- // This kicks off an exit transition which doesn't end in JSDOM, so we just listen
220- // for the exiting classname instead.
221- const transitionWrapper = getDirectionButton ( 'block-start' ) ?. parentElement ;
222- expect ( transitionWrapper ) . toHaveClass ( styles [ 'direction-button-wrapper-motion-exiting' ] ) ;
309+ expectDirectionButtonHidden ( 'block-start' ) ;
223310} ) ;
224311
225312test ( 'renders disabled direction buttons' , ( ) => {
226- const { showButtons, getDirectionButton } = renderDragHandle ( {
313+ const { showButtons } = renderDragHandle ( {
227314 directions : { 'block-start' : 'active' } ,
228315 tooltipText : 'Click me!' ,
229316 } ) ;
@@ -233,7 +320,7 @@ test('renders disabled direction buttons', () => {
233320} ) ;
234321
235322test ( "doesn't render direction buttons if value for direction is undefined" , ( ) => {
236- const { showButtons, getDirectionButton } = renderDragHandle ( {
323+ const { showButtons } = renderDragHandle ( {
237324 directions : { 'block-start' : 'active' , 'inline-start' : undefined } ,
238325 tooltipText : 'Click me!' ,
239326 } ) ;
@@ -244,7 +331,7 @@ test("doesn't render direction buttons if value for direction is undefined", ()
244331} ) ;
245332
246333test ( 'focus returns to drag button after direction button is clicked' , ( ) => {
247- const { dragHandle, showButtons, getDirectionButton } = renderDragHandle ( {
334+ const { dragHandle, showButtons } = renderDragHandle ( {
248335 directions : { 'block-start' : 'active' , 'inline-start' : undefined } ,
249336 tooltipText : 'Click me!' ,
250337 } ) ;
@@ -257,7 +344,7 @@ test('focus returns to drag button after direction button is clicked', () => {
257344
258345test ( 'calls onDirectionClick when direction button is pressed' , ( ) => {
259346 const onDirectionClick = jest . fn ( ) ;
260- const { showButtons, getDirectionButton } = renderDragHandle ( {
347+ const { showButtons } = renderDragHandle ( {
261348 directions : { 'block-start' : 'active' , 'block-end' : 'active' , 'inline-start' : 'active' , 'inline-end' : 'active' } ,
262349 tooltipText : 'Click me!' ,
263350 onDirectionClick,
@@ -282,7 +369,7 @@ test('calls onDirectionClick when direction button is pressed', () => {
282369
283370test ( "doesn't call onDirectionClick when disabled direction button is pressed" , ( ) => {
284371 const onDirectionClick = jest . fn ( ) ;
285- const { showButtons, getDirectionButton } = renderDragHandle ( {
372+ const { showButtons } = renderDragHandle ( {
286373 directions : { 'block-start' : 'disabled' } ,
287374 tooltipText : 'Click me!' ,
288375 onDirectionClick,
0 commit comments