Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
5 changes: 5 additions & 0 deletions .changeset/silver-peas-end.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tanstack/query-devtools': minor
---

improve a11y around screenreader + resizing
141 changes: 128 additions & 13 deletions packages/query-devtools/src/Devtools.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,13 @@ const DraggablePanel: Component<DevtoolsPanelProps> = (props) => {
return theme() === 'dark' ? darkStyles(css) : lightStyles(css)
})

let closeBtnRef!: HTMLButtonElement

// Focus the close button when the panel opens for screen reader accessibility
onMount(() => {
closeBtnRef.focus()
})

const [isResizing, setIsResizing] = createSignal(false)

const position = createMemo(
Expand Down Expand Up @@ -583,14 +590,68 @@ const DraggablePanel: Component<DevtoolsPanelProps> = (props) => {
aria-label="Tanstack query devtools"
>
<div
role="separator"
aria-orientation={
position() === 'top' || position() === 'bottom'
? 'horizontal'
: 'vertical'
}
aria-label="Resize devtools panel"
aria-valuenow={
position() === 'top' || position() === 'bottom'
? Number(props.localStore.height || DEFAULT_HEIGHT)
: Number(props.localStore.width || DEFAULT_WIDTH)
}
tabindex="0"
class={cx(
styles().dragHandle,
styles()[`dragHandle-position-${position()}`],
'tsqd-drag-handle',
)}
onMouseDown={handleDragStart}
onKeyDown={(e) => {
const step = 10
const minHeight = convertRemToPixels(3.5)
const minWidth = convertRemToPixels(12)
if (position() === 'top' || position() === 'bottom') {
if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
e.preventDefault()
const currentHeight = Number(
props.localStore.height || DEFAULT_HEIGHT,
)
const delta =
position() === 'bottom'
? e.key === 'ArrowUp'
? step
: -step
: e.key === 'ArrowDown'
? step
: -step
const newHeight = Math.max(minHeight, currentHeight + delta)
props.setLocalStore('height', String(newHeight))
}
} else {
if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
e.preventDefault()
const currentWidth = Number(
props.localStore.width || DEFAULT_WIDTH,
)
const delta =
position() === 'right'
? e.key === 'ArrowLeft'
? step
: -step
: e.key === 'ArrowRight'
? step
: -step
const newWidth = Math.max(minWidth, currentWidth + delta)
props.setLocalStore('width', String(newWidth))
}
}
}}
></div>
<button
ref={closeBtnRef}
aria-label="Close tanstack query devtools"
class={cx(
styles().closeBtn,
Expand Down Expand Up @@ -796,6 +857,7 @@ export const ContentView: Component<ContentViewProps> = (props) => {
<RadioGroup.Root
class={cx(styles().viewToggle)}
value={selectedView()}
aria-label="Toggle between queries and mutations view"
onChange={(value) => {
setSelectedView(value as 'queries' | 'mutations')
setSelectedQueryHash(null)
Expand Down Expand Up @@ -869,6 +931,7 @@ export const ContentView: Component<ContentViewProps> = (props) => {
<select
value={sort()}
name="tsqd-queries-filter-sort"
aria-label="Sort queries by"
onChange={(e) => {
props.setLocalStore('sort', e.currentTarget.value)
}}
Expand All @@ -882,6 +945,7 @@ export const ContentView: Component<ContentViewProps> = (props) => {
<select
value={mutationSort()}
name="tsqd-mutations-filter-sort"
aria-label="Sort mutations by"
onChange={(e) => {
props.setLocalStore('mutationSort', e.currentTarget.value)
}}
Expand Down Expand Up @@ -1212,10 +1276,10 @@ export const ContentView: Component<ContentViewProps> = (props) => {
styles().settingsMenu,
'tsqd-settings-submenu',
)}
aria-label="Hide disabled queries setting"
>
<DropdownMenu.RadioGroup
value={props.localStore.hideDisabledQueries}
aria-label="Hide disabled queries setting"
onChange={(value) =>
props.setLocalStore('hideDisabledQueries', value)
}
Expand Down Expand Up @@ -1409,7 +1473,7 @@ const QueryRow: Component<{ query: Query }> = (props) => {
styles().selectedQueryRow,
'tsqd-query-row',
)}
aria-label={`Query key ${props.query.queryHash}`}
aria-label={`Query key ${props.query.queryHash}${isDisabled() ? ', disabled' : ''}${isStatic() ? ', static' : ''}`}
>
<div
class={cx(getObserverCountColorStyles(), 'tsqd-query-observer-count')}
Expand All @@ -1418,10 +1482,14 @@ const QueryRow: Component<{ query: Query }> = (props) => {
</div>
<code class="tsqd-query-hash">{props.query.queryHash}</code>
<Show when={isDisabled()}>
<div class="tsqd-query-disabled-indicator">disabled</div>
<div class="tsqd-query-disabled-indicator" aria-hidden="true">
disabled
</div>
</Show>
<Show when={isStatic()}>
<div class="tsqd-query-static-indicator">static</div>
<div class="tsqd-query-static-indicator" aria-hidden="true">
static
</div>
</Show>
</button>
</Show>
Expand Down Expand Up @@ -1942,7 +2010,11 @@ const QueryDetails = () => {
<div
class={cx(styles().detailsContainer, 'tsqd-query-details-container')}
>
<div class={cx(styles().detailsHeader, 'tsqd-query-details-header')}>
<div
role="heading"
aria-level="2"
class={cx(styles().detailsHeader, 'tsqd-query-details-header')}
>
Query Details
</div>
<div
Expand Down Expand Up @@ -1975,7 +2047,11 @@ const QueryDetails = () => {
</span>
</div>
</div>
<div class={cx(styles().detailsHeader, 'tsqd-query-details-header')}>
<div
role="heading"
aria-level="2"
class={cx(styles().detailsHeader, 'tsqd-query-details-header')}
>
Actions
</div>
<div
Expand Down Expand Up @@ -2172,6 +2248,7 @@ const QueryDetails = () => {
Trigger Error
<select
disabled={queryStatus() === 'pending'}
aria-label="Select error type to trigger"
onChange={(e) => {
const errorType = errorTypes().find(
(et) => et.name === e.currentTarget.value,
Expand All @@ -2191,7 +2268,11 @@ const QueryDetails = () => {
</div>
</Show>
</div>
<div class={cx(styles().detailsHeader, 'tsqd-query-details-header')}>
<div
role="heading"
aria-level="2"
class={cx(styles().detailsHeader, 'tsqd-query-details-header')}
>
Data {dataMode() === 'view' ? 'Explorer' : 'Editor'}
</div>
<Show when={dataMode() === 'view'}>
Expand Down Expand Up @@ -2235,6 +2316,7 @@ const QueryDetails = () => {
>
<textarea
name="data"
aria-label="Edit query data as JSON"
class={styles().devtoolsEditTextarea}
onFocus={() => setDataEditError(false)}
data-error={dataEditError()}
Expand Down Expand Up @@ -2271,7 +2353,11 @@ const QueryDetails = () => {
</div>
</form>
</Show>
<div class={cx(styles().detailsHeader, 'tsqd-query-details-header')}>
<div
role="heading"
aria-level="2"
class={cx(styles().detailsHeader, 'tsqd-query-details-header')}
>
Query Explorer
</div>
<div
Expand Down Expand Up @@ -2356,7 +2442,11 @@ const MutationDetails = () => {
<div
class={cx(styles().detailsContainer, 'tsqd-query-details-container')}
>
<div class={cx(styles().detailsHeader, 'tsqd-query-details-header')}>
<div
role="heading"
aria-level="2"
class={cx(styles().detailsHeader, 'tsqd-query-details-header')}
>
Mutation Details
</div>
<div
Expand Down Expand Up @@ -2395,7 +2485,11 @@ const MutationDetails = () => {
</span>
</div>
</div>
<div class={cx(styles().detailsHeader, 'tsqd-query-details-header')}>
<div
role="heading"
aria-level="2"
class={cx(styles().detailsHeader, 'tsqd-query-details-header')}
>
Variables Details
</div>
<div
Expand All @@ -2410,7 +2504,11 @@ const MutationDetails = () => {
value={activeMutation()!.state.variables}
/>
</div>
<div class={cx(styles().detailsHeader, 'tsqd-query-details-header')}>
<div
role="heading"
aria-level="2"
class={cx(styles().detailsHeader, 'tsqd-query-details-header')}
>
Context Details
</div>
<div
Expand All @@ -2425,7 +2523,11 @@ const MutationDetails = () => {
value={activeMutation()!.state.context}
/>
</div>
<div class={cx(styles().detailsHeader, 'tsqd-query-details-header')}>
<div
role="heading"
aria-level="2"
class={cx(styles().detailsHeader, 'tsqd-query-details-header')}
>
Data Explorer
</div>
<div
Expand All @@ -2440,7 +2542,11 @@ const MutationDetails = () => {
value={activeMutation()!.state.data}
/>
</div>
<div class={cx(styles().detailsHeader, 'tsqd-query-details-header')}>
<div
role="heading"
aria-level="2"
class={cx(styles().detailsHeader, 'tsqd-query-details-header')}
>
Mutations Explorer
</div>
<div
Expand Down Expand Up @@ -2897,6 +3003,15 @@ const stylesFactory = (
&:hover {
background-color: ${colors.purple[400]}${t('', alpha[90])};
}
&:focus {
outline: none;
background-color: ${colors.purple[400]}${t('', alpha[90])};
}
&:focus-visible {
outline: 2px solid ${colors.blue[800]};
outline-offset: -2px;
background-color: ${colors.purple[400]}${t('', alpha[90])};
}
z-index: 4;
`,
'dragHandle-position-top': css`
Expand Down
Loading