Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions packages/ui-a11y-utils/src/FocusRegion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,14 @@ class FocusRegion {
}

handleDocumentClick = (event: React.PointerEvent) => {
// Only proceed if we have a valid mouse down target from this interaction.
// This prevents dismissal when a FocusRegion is activated via keyboard
// (e.g., opening a select dropdown with keyboard) and then a click occurs
// in a parent FocusRegion before any mousedown was captured.
if (!this._documentClickTarget) {
return
}

// we used event.pointerType === 'mouse' here, but it is not supported in Safari
// https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/pointerType
// TODO: Check this in the future, because the linked Webkit bug is marked as fixed in 2025-09
Expand Down
2 changes: 2 additions & 0 deletions packages/ui-a11y-utils/src/__tests__/FocusRegion.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ describe('FocusRegion', () => {
const outsideElement = document.createElement('div')
document.body.appendChild(outsideElement)

// Proper mousedown + click sequence (as happens in real user interactions)
fireEvent.mouseDown(outsideElement)
fireEvent.click(outsideElement, { button: 0, detail: 1 })

await waitFor(() => {
Expand Down
64 changes: 27 additions & 37 deletions packages/ui-alerts/src/Alert/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,43 +14,33 @@ space above or below the alert.
---
type: example
---
<div>
<Alert
variant="success"
renderCloseButtonLabel="Close"
margin="small"
transition="none"
variantScreenReaderLabel="Success, "
>
Sample success alert text. I will close w/o a transition out if you close me
</Alert>
<Alert
variant="info"
renderCloseButtonLabel="Close"
margin="small"
variantScreenReaderLabel="Information, "
>
Sample info text. I will fade out if you close me.
</Alert>
<Alert
variant="error"
renderCloseButtonLabel="Close"
margin="small"
variantScreenReaderLabel="Error, "
>
Sample error text that continues for a while
to demonstrate what happens when the content stretches over
several lines. It really does take a lot of prose to get the
text to wrap when you are on a high resolution screen.
</Alert>
<Alert
variant="warning"
margin="small"
variantScreenReaderLabel="Warning, "
>
Sample warning text. This alert is not dismissible and cannot be closed.
</Alert>
</div>
const Example = () => {
const [modalOpen, setModalOpen] = React.useState(false);

return (
<>
<Button onClick={() => setModalOpen(true)}>Open modal</Button>
<Modal open={modalOpen} onDismiss={() => setModalOpen(false)} label="Modal">
<div style={{ display: 'flex', gap: '20px' }}>
<SimpleSelect renderLabel="Use only keyboard to open this select">
<SimpleSelect.Option id="foo" value="foo">
Foo
</SimpleSelect.Option>
<SimpleSelect.Option id="bar" value="bar">
Bar
</SimpleSelect.Option>
<SimpleSelect.Option id="baz" value="baz">
Baz
</SimpleSelect.Option>
</SimpleSelect>
<Button>Click by mouse when select is open</Button>
</div>
</Modal>
</>
);
};

render(<Example/>)
```

The `timeout` prop can be used to automatically dismiss an alert after a time.
Expand Down
Loading