Skip to content

Commit 090e669

Browse files
committed
test: add story and test for overlay placement
1 parent 54d8783 commit 090e669

File tree

3 files changed

+284
-1
lines changed

3 files changed

+284
-1
lines changed

src/__tests__/AnchoredOverlay.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, {useCallback, useState} from 'react'
22
import {AnchoredOverlay} from '../AnchoredOverlay'
3-
import {behavesAsComponent, checkExports} from '../utils/testing'
3+
import {behavesAsComponent, checkExports, render} from '../utils/testing'
44
import {render as HTMLRender, cleanup, fireEvent} from '@testing-library/react'
55
import {axe, toHaveNoViolations} from 'jest-axe'
66
import 'babel-polyfill'
@@ -141,4 +141,9 @@ describe('AnchoredOverlay', () => {
141141
expect(mockCloseCallback).toHaveBeenCalledTimes(1)
142142
expect(mockCloseCallback).toHaveBeenCalledWith('escape')
143143
})
144+
145+
it('should render consistently when open', () => {
146+
const anchoredOverlay = HTMLRender(<AnchoredOverlayTestComponent initiallyOpen={true} />)
147+
expect(anchoredOverlay).toMatchSnapshot()
148+
})
144149
})

src/__tests__/__snapshots__/AnchoredOverlay.tsx.snap

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,3 +92,241 @@ exports[`AnchoredOverlay renders consistently 1`] = `
9292
</button>
9393
</div>
9494
`;
95+
96+
exports[`AnchoredOverlay should render consistently when open 1`] = `
97+
Object {
98+
"asFragment": [Function],
99+
"baseElement": .c0 {
100+
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";
101+
line-height: 1.5;
102+
color: #24292e;
103+
}
104+
105+
.c1 {
106+
position: relative;
107+
display: inline-block;
108+
padding: 6px 16px;
109+
font-family: inherit;
110+
font-weight: 600;
111+
line-height: 20px;
112+
white-space: nowrap;
113+
vertical-align: middle;
114+
cursor: pointer;
115+
-webkit-user-select: none;
116+
-moz-user-select: none;
117+
-ms-user-select: none;
118+
user-select: none;
119+
border-radius: 6px;
120+
-webkit-appearance: none;
121+
-moz-appearance: none;
122+
appearance: none;
123+
-webkit-text-decoration: none;
124+
text-decoration: none;
125+
text-align: center;
126+
font-size: 14px;
127+
color: #24292e;
128+
background-color: #fafbfc;
129+
border: 1px solid rgba(27,31,35,0.15);
130+
box-shadow: 0 1px 0 rgba(27,31,35,0.04),inset 0 1px 0 rgba(255,255,255,0.25);
131+
}
132+
133+
.c1:hover {
134+
-webkit-text-decoration: none;
135+
text-decoration: none;
136+
}
137+
138+
.c1:focus {
139+
outline: none;
140+
}
141+
142+
.c1:disabled {
143+
cursor: default;
144+
}
145+
146+
.c1:disabled svg {
147+
opacity: 0.6;
148+
}
149+
150+
.c1:hover {
151+
background-color: #f3f4f6;
152+
border-color: rgba(27,31,35,0.15);
153+
}
154+
155+
.c1:focus {
156+
border-color: rgba(27,31,35,0.15);
157+
box-shadow: 0 0 0 3px rgba(3,102,214,0.3);
158+
}
159+
160+
.c1:active {
161+
background-color: hsla(220,14%,94%,1);
162+
box-shadow: inset 0 0.15em 0.3em rgba(27,31,35,0.15);
163+
}
164+
165+
.c1:disabled {
166+
color: #959da5;
167+
background-color: #fafbfc;
168+
border-color: rgba(27,31,35,0.15);
169+
}
170+
171+
.c2 {
172+
background-color: #ffffff;
173+
box-shadow: 0 1px 3px rgba(27,31,35,0.12),0 8px 24px rgba(68,77,86,0.12);
174+
position: absolute;
175+
min-width: 192px;
176+
max-width: 640px;
177+
height: auto;
178+
width: auto;
179+
border-radius: 12px;
180+
overflow: hidden;
181+
-webkit-animation: overlay-appear 200ms cubic-bezier(0.33,1,0.68,1);
182+
animation: overlay-appear 200ms cubic-bezier(0.33,1,0.68,1);
183+
visibility: var(--styled-overlay-visibility);
184+
top: 4px;
185+
left: 0px;
186+
}
187+
188+
.c2:focus {
189+
outline: none;
190+
}
191+
192+
<body>
193+
<div>
194+
<div
195+
class="c0"
196+
color="text.primary"
197+
data-portal-root="true"
198+
font-family="normal"
199+
>
200+
<button
201+
aria-haspopup="true"
202+
aria-labelledby="__primer_id_10000"
203+
class="c1"
204+
id="__primer_id_10000"
205+
tabindex="0"
206+
>
207+
Anchor Button
208+
</button>
209+
<div
210+
id="__primerPortalRoot__"
211+
>
212+
<div
213+
style="position: relative; z-index: 1;"
214+
>
215+
<div
216+
class="c2"
217+
data-focus-trap="active"
218+
height="auto"
219+
role="none"
220+
style="--styled-overlay-visibility: visible;"
221+
width="auto"
222+
>
223+
<button
224+
class="focus-visible"
225+
data-focus-visible-added=""
226+
tabindex="0"
227+
type="button"
228+
>
229+
Focusable Child
230+
</button>
231+
</div>
232+
</div>
233+
</div>
234+
</div>
235+
</div>
236+
</body>,
237+
"container": <div>
238+
<div
239+
class="BaseStyles__Base-qvuaww-0 dhupSQ"
240+
color="text.primary"
241+
data-portal-root="true"
242+
font-family="normal"
243+
>
244+
<button
245+
aria-haspopup="true"
246+
aria-labelledby="__primer_id_10000"
247+
class="ButtonBase-sc-181ps9o-0 Button-xjtz72-0 jhgDtb"
248+
id="__primer_id_10000"
249+
tabindex="0"
250+
>
251+
Anchor Button
252+
</button>
253+
<div
254+
id="__primerPortalRoot__"
255+
>
256+
<div
257+
style="position: relative; z-index: 1;"
258+
>
259+
<div
260+
class="Overlay__StyledOverlay-jhwkzw-0 leFwDU"
261+
data-focus-trap="active"
262+
height="auto"
263+
role="none"
264+
style="--styled-overlay-visibility: visible;"
265+
width="auto"
266+
>
267+
<button
268+
class="focus-visible"
269+
data-focus-visible-added=""
270+
tabindex="0"
271+
type="button"
272+
>
273+
Focusable Child
274+
</button>
275+
</div>
276+
</div>
277+
</div>
278+
</div>
279+
</div>,
280+
"debug": [Function],
281+
"findAllByAltText": [Function],
282+
"findAllByDisplayValue": [Function],
283+
"findAllByLabelText": [Function],
284+
"findAllByPlaceholderText": [Function],
285+
"findAllByRole": [Function],
286+
"findAllByTestId": [Function],
287+
"findAllByText": [Function],
288+
"findAllByTitle": [Function],
289+
"findByAltText": [Function],
290+
"findByDisplayValue": [Function],
291+
"findByLabelText": [Function],
292+
"findByPlaceholderText": [Function],
293+
"findByRole": [Function],
294+
"findByTestId": [Function],
295+
"findByText": [Function],
296+
"findByTitle": [Function],
297+
"getAllByAltText": [Function],
298+
"getAllByDisplayValue": [Function],
299+
"getAllByLabelText": [Function],
300+
"getAllByPlaceholderText": [Function],
301+
"getAllByRole": [Function],
302+
"getAllByTestId": [Function],
303+
"getAllByText": [Function],
304+
"getAllByTitle": [Function],
305+
"getByAltText": [Function],
306+
"getByDisplayValue": [Function],
307+
"getByLabelText": [Function],
308+
"getByPlaceholderText": [Function],
309+
"getByRole": [Function],
310+
"getByTestId": [Function],
311+
"getByText": [Function],
312+
"getByTitle": [Function],
313+
"queryAllByAltText": [Function],
314+
"queryAllByDisplayValue": [Function],
315+
"queryAllByLabelText": [Function],
316+
"queryAllByPlaceholderText": [Function],
317+
"queryAllByRole": [Function],
318+
"queryAllByTestId": [Function],
319+
"queryAllByText": [Function],
320+
"queryAllByTitle": [Function],
321+
"queryByAltText": [Function],
322+
"queryByDisplayValue": [Function],
323+
"queryByLabelText": [Function],
324+
"queryByPlaceholderText": [Function],
325+
"queryByRole": [Function],
326+
"queryByTestId": [Function],
327+
"queryByText": [Function],
328+
"queryByTitle": [Function],
329+
"rerender": [Function],
330+
"unmount": [Function],
331+
}
332+
`;

src/stories/SelectPanel.stories.tsx

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,43 @@ export function SelectPanelHeightInitialWithUnderflowingItemsAfterFetch(): JSX.E
216216
}
217217
SelectPanelHeightInitialWithUnderflowingItemsAfterFetch.storyName =
218218
'SelectPanel, Height: Initial, Underflowing Items (After Fetch)'
219+
220+
export function SelectPanelAboveTallBody(): JSX.Element {
221+
const [selected, setSelected] = React.useState<ItemInput | undefined>(items[0])
222+
const [filter, setFilter] = React.useState('')
223+
const filteredItems = items.filter(item => item.text.toLowerCase().startsWith(filter.toLowerCase()))
224+
const [open, setOpen] = useState(false)
225+
226+
return (
227+
<>
228+
<h1>Single Select Panel</h1>
229+
<div>Please select a label that describe your issue:</div>
230+
<SelectPanel
231+
renderAnchor={({children, 'aria-labelledby': ariaLabelledBy, ...anchorProps}) => (
232+
<DropdownButton aria-labelledby={` ${ariaLabelledBy}`} {...anchorProps}>
233+
{children ?? 'Select Labels'}
234+
</DropdownButton>
235+
)}
236+
placeholderText="Filter Labels"
237+
open={open}
238+
onOpenChange={setOpen}
239+
items={filteredItems}
240+
selected={selected}
241+
onSelectedChange={setSelected}
242+
onFilterChange={setFilter}
243+
showItemDividers={true}
244+
overlayProps={{width: 'small', height: 'xsmall'}}
245+
/>
246+
<div
247+
style={{
248+
backgroundColor: 'cornflowerblue',
249+
height: '100vh'
250+
}}
251+
>
252+
This element makes the body really tall. This is to test that we do not have layout/focus issues if the Portal
253+
is far down the page
254+
</div>
255+
</>
256+
)
257+
}
258+
SelectPanelAboveTallBody.storyName = 'SelectPanel, Above a Tall Body'

0 commit comments

Comments
 (0)