@tanstack/query-devtools 5.91.0 → 5.92.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/Devtools.tsx CHANGED
@@ -417,6 +417,13 @@ const DraggablePanel: Component<DevtoolsPanelProps> = (props) => {
417
417
  return theme() === 'dark' ? darkStyles(css) : lightStyles(css)
418
418
  })
419
419
 
420
+ let closeBtnRef!: HTMLButtonElement
421
+
422
+ // Focus the close button when the panel opens for screen reader accessibility
423
+ onMount(() => {
424
+ closeBtnRef.focus()
425
+ })
426
+
420
427
  const [isResizing, setIsResizing] = createSignal(false)
421
428
 
422
429
  const position = createMemo(
@@ -480,7 +487,7 @@ const DraggablePanel: Component<DevtoolsPanelProps> = (props) => {
480
487
  setIsResizing(false)
481
488
  }
482
489
  document.removeEventListener('mousemove', runDrag, false)
483
- document.removeEventListener('mouseUp', unsubscribe, false)
490
+ document.removeEventListener('mouseup', unsubscribe, false)
484
491
  }
485
492
 
486
493
  document.addEventListener('mousemove', runDrag, false)
@@ -583,14 +590,73 @@ const DraggablePanel: Component<DevtoolsPanelProps> = (props) => {
583
590
  aria-label="Tanstack query devtools"
584
591
  >
585
592
  <div
593
+ role="separator"
594
+ aria-orientation={
595
+ position() === 'top' || position() === 'bottom'
596
+ ? 'horizontal'
597
+ : 'vertical'
598
+ }
599
+ aria-label="Resize devtools panel"
600
+ aria-valuemin={
601
+ position() === 'top' || position() === 'bottom'
602
+ ? convertRemToPixels(3.5)
603
+ : convertRemToPixels(12)
604
+ }
605
+ aria-valuenow={
606
+ position() === 'top' || position() === 'bottom'
607
+ ? Number(props.localStore.height || DEFAULT_HEIGHT)
608
+ : Number(props.localStore.width || DEFAULT_WIDTH)
609
+ }
610
+ tabindex="0"
586
611
  class={cx(
587
612
  styles().dragHandle,
588
613
  styles()[`dragHandle-position-${position()}`],
589
614
  'tsqd-drag-handle',
590
615
  )}
591
616
  onMouseDown={handleDragStart}
617
+ onKeyDown={(e) => {
618
+ const step = 10
619
+ const minHeight = convertRemToPixels(3.5)
620
+ const minWidth = convertRemToPixels(12)
621
+ if (position() === 'top' || position() === 'bottom') {
622
+ if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
623
+ e.preventDefault()
624
+ const currentHeight = Number(
625
+ props.localStore.height || DEFAULT_HEIGHT,
626
+ )
627
+ const delta =
628
+ position() === 'bottom'
629
+ ? e.key === 'ArrowUp'
630
+ ? step
631
+ : -step
632
+ : e.key === 'ArrowDown'
633
+ ? step
634
+ : -step
635
+ const newHeight = Math.max(minHeight, currentHeight + delta)
636
+ props.setLocalStore('height', String(newHeight))
637
+ }
638
+ } else {
639
+ if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
640
+ e.preventDefault()
641
+ const currentWidth = Number(
642
+ props.localStore.width || DEFAULT_WIDTH,
643
+ )
644
+ const delta =
645
+ position() === 'right'
646
+ ? e.key === 'ArrowLeft'
647
+ ? step
648
+ : -step
649
+ : e.key === 'ArrowRight'
650
+ ? step
651
+ : -step
652
+ const newWidth = Math.max(minWidth, currentWidth + delta)
653
+ props.setLocalStore('width', String(newWidth))
654
+ }
655
+ }
656
+ }}
592
657
  ></div>
593
658
  <button
659
+ ref={closeBtnRef}
594
660
  aria-label="Close tanstack query devtools"
595
661
  class={cx(
596
662
  styles().closeBtn,
@@ -796,6 +862,7 @@ export const ContentView: Component<ContentViewProps> = (props) => {
796
862
  <RadioGroup.Root
797
863
  class={cx(styles().viewToggle)}
798
864
  value={selectedView()}
865
+ aria-label="Toggle between queries and mutations view"
799
866
  onChange={(value) => {
800
867
  setSelectedView(value as 'queries' | 'mutations')
801
868
  setSelectedQueryHash(null)
@@ -869,6 +936,7 @@ export const ContentView: Component<ContentViewProps> = (props) => {
869
936
  <select
870
937
  value={sort()}
871
938
  name="tsqd-queries-filter-sort"
939
+ aria-label="Sort queries by"
872
940
  onChange={(e) => {
873
941
  props.setLocalStore('sort', e.currentTarget.value)
874
942
  }}
@@ -882,6 +950,7 @@ export const ContentView: Component<ContentViewProps> = (props) => {
882
950
  <select
883
951
  value={mutationSort()}
884
952
  name="tsqd-mutations-filter-sort"
953
+ aria-label="Sort mutations by"
885
954
  onChange={(e) => {
886
955
  props.setLocalStore('mutationSort', e.currentTarget.value)
887
956
  }}
@@ -1000,7 +1069,7 @@ export const ContentView: Component<ContentViewProps> = (props) => {
1000
1069
  'tsqd-action-open-pip',
1001
1070
  )}
1002
1071
  aria-label="Open in picture-in-picture mode"
1003
- title={`Open in picture-in-picture mode`}
1072
+ title="Open in picture-in-picture mode"
1004
1073
  >
1005
1074
  <PiPIcon />
1006
1075
  </button>
@@ -1013,6 +1082,8 @@ export const ContentView: Component<ContentViewProps> = (props) => {
1013
1082
  'tsqd-actions-btn',
1014
1083
  'tsqd-action-settings',
1015
1084
  )}
1085
+ aria-label="Open settings menu"
1086
+ title="Open settings menu"
1016
1087
  >
1017
1088
  <Settings />
1018
1089
  </DropdownMenu.Trigger>
@@ -1061,62 +1132,58 @@ export const ContentView: Component<ContentViewProps> = (props) => {
1061
1132
  'tsqd-settings-submenu',
1062
1133
  )}
1063
1134
  >
1064
- <DropdownMenu.Item
1065
- onSelect={() => {
1066
- setDevtoolsPosition('top')
1067
- }}
1068
- as="button"
1069
- class={cx(
1070
- styles().settingsSubButton,
1071
- 'tsqd-settings-menu-position-btn',
1072
- 'tsqd-settings-menu-position-btn-top',
1073
- )}
1074
- >
1075
- <span>Top</span>
1076
- <ArrowUp />
1077
- </DropdownMenu.Item>
1078
- <DropdownMenu.Item
1079
- onSelect={() => {
1080
- setDevtoolsPosition('bottom')
1081
- }}
1082
- as="button"
1083
- class={cx(
1084
- styles().settingsSubButton,
1085
- 'tsqd-settings-menu-position-btn',
1086
- 'tsqd-settings-menu-position-btn-bottom',
1087
- )}
1088
- >
1089
- <span>Bottom</span>
1090
- <ArrowDown />
1091
- </DropdownMenu.Item>
1092
- <DropdownMenu.Item
1093
- onSelect={() => {
1094
- setDevtoolsPosition('left')
1095
- }}
1096
- as="button"
1097
- class={cx(
1098
- styles().settingsSubButton,
1099
- 'tsqd-settings-menu-position-btn',
1100
- 'tsqd-settings-menu-position-btn-left',
1101
- )}
1102
- >
1103
- <span>Left</span>
1104
- <ArrowLeft />
1105
- </DropdownMenu.Item>
1106
- <DropdownMenu.Item
1107
- onSelect={() => {
1108
- setDevtoolsPosition('right')
1109
- }}
1110
- as="button"
1111
- class={cx(
1112
- styles().settingsSubButton,
1113
- 'tsqd-settings-menu-position-btn',
1114
- 'tsqd-settings-menu-position-btn-right',
1115
- )}
1135
+ <DropdownMenu.RadioGroup
1136
+ aria-label="Position settings"
1137
+ value={props.localStore.position}
1138
+ onChange={(value) =>
1139
+ setDevtoolsPosition(value as DevtoolsPosition)
1140
+ }
1116
1141
  >
1117
- <span>Right</span>
1118
- <ArrowRight />
1119
- </DropdownMenu.Item>
1142
+ <DropdownMenu.RadioItem
1143
+ value="top"
1144
+ class={cx(
1145
+ styles().settingsSubButton,
1146
+ 'tsqd-settings-menu-position-btn',
1147
+ 'tsqd-settings-menu-position-btn-top',
1148
+ )}
1149
+ >
1150
+ <span>Top</span>
1151
+ <ArrowUp />
1152
+ </DropdownMenu.RadioItem>
1153
+ <DropdownMenu.RadioItem
1154
+ value="bottom"
1155
+ class={cx(
1156
+ styles().settingsSubButton,
1157
+ 'tsqd-settings-menu-position-btn',
1158
+ 'tsqd-settings-menu-position-btn-bottom',
1159
+ )}
1160
+ >
1161
+ <span>Bottom</span>
1162
+ <ArrowDown />
1163
+ </DropdownMenu.RadioItem>
1164
+ <DropdownMenu.RadioItem
1165
+ value="left"
1166
+ class={cx(
1167
+ styles().settingsSubButton,
1168
+ 'tsqd-settings-menu-position-btn',
1169
+ 'tsqd-settings-menu-position-btn-left',
1170
+ )}
1171
+ >
1172
+ <span>Left</span>
1173
+ <ArrowLeft />
1174
+ </DropdownMenu.RadioItem>
1175
+ <DropdownMenu.RadioItem
1176
+ value="right"
1177
+ class={cx(
1178
+ styles().settingsSubButton,
1179
+ 'tsqd-settings-menu-position-btn',
1180
+ 'tsqd-settings-menu-position-btn-right',
1181
+ )}
1182
+ >
1183
+ <span>Right</span>
1184
+ <ArrowRight />
1185
+ </DropdownMenu.RadioItem>
1186
+ </DropdownMenu.RadioGroup>
1120
1187
  </DropdownMenu.SubContent>
1121
1188
  </DropdownMenu.Portal>
1122
1189
  </DropdownMenu.Sub>
@@ -1146,54 +1213,47 @@ export const ContentView: Component<ContentViewProps> = (props) => {
1146
1213
  'tsqd-settings-submenu',
1147
1214
  )}
1148
1215
  >
1149
- <DropdownMenu.Item
1150
- onSelect={() => {
1151
- props.setLocalStore('theme_preference', 'light')
1216
+ <DropdownMenu.RadioGroup
1217
+ value={props.localStore.theme_preference}
1218
+ onChange={(value) => {
1219
+ props.setLocalStore('theme_preference', value)
1152
1220
  }}
1153
- as="button"
1154
- class={cx(
1155
- styles().settingsSubButton,
1156
- props.localStore.theme_preference === 'light' &&
1157
- styles().themeSelectedButton,
1158
- 'tsqd-settings-menu-position-btn',
1159
- 'tsqd-settings-menu-position-btn-top',
1160
- )}
1161
- >
1162
- <span>Light</span>
1163
- <Sun />
1164
- </DropdownMenu.Item>
1165
- <DropdownMenu.Item
1166
- onSelect={() => {
1167
- props.setLocalStore('theme_preference', 'dark')
1168
- }}
1169
- as="button"
1170
- class={cx(
1171
- styles().settingsSubButton,
1172
- props.localStore.theme_preference === 'dark' &&
1173
- styles().themeSelectedButton,
1174
- 'tsqd-settings-menu-position-btn',
1175
- 'tsqd-settings-menu-position-btn-bottom',
1176
- )}
1177
- >
1178
- <span>Dark</span>
1179
- <Moon />
1180
- </DropdownMenu.Item>
1181
- <DropdownMenu.Item
1182
- onSelect={() => {
1183
- props.setLocalStore('theme_preference', 'system')
1184
- }}
1185
- as="button"
1186
- class={cx(
1187
- styles().settingsSubButton,
1188
- props.localStore.theme_preference === 'system' &&
1189
- styles().themeSelectedButton,
1190
- 'tsqd-settings-menu-position-btn',
1191
- 'tsqd-settings-menu-position-btn-left',
1192
- )}
1221
+ aria-label="Theme preference"
1193
1222
  >
1194
- <span>System</span>
1195
- <Monitor />
1196
- </DropdownMenu.Item>
1223
+ <DropdownMenu.RadioItem
1224
+ value="light"
1225
+ class={cx(
1226
+ styles().settingsSubButton,
1227
+ 'tsqd-settings-menu-position-btn',
1228
+ 'tsqd-settings-menu-position-btn-top',
1229
+ )}
1230
+ >
1231
+ <span>Light</span>
1232
+ <Sun />
1233
+ </DropdownMenu.RadioItem>
1234
+ <DropdownMenu.RadioItem
1235
+ value="dark"
1236
+ class={cx(
1237
+ styles().settingsSubButton,
1238
+ 'tsqd-settings-menu-position-btn',
1239
+ 'tsqd-settings-menu-position-btn-bottom',
1240
+ )}
1241
+ >
1242
+ <span>Dark</span>
1243
+ <Moon />
1244
+ </DropdownMenu.RadioItem>
1245
+ <DropdownMenu.RadioItem
1246
+ value="system"
1247
+ class={cx(
1248
+ styles().settingsSubButton,
1249
+ 'tsqd-settings-menu-position-btn',
1250
+ 'tsqd-settings-menu-position-btn-left',
1251
+ )}
1252
+ >
1253
+ <span>System</span>
1254
+ <Monitor />
1255
+ </DropdownMenu.RadioItem>
1256
+ </DropdownMenu.RadioGroup>
1197
1257
  </DropdownMenu.SubContent>
1198
1258
  </DropdownMenu.Portal>
1199
1259
  </DropdownMenu.Sub>
@@ -1222,50 +1282,48 @@ export const ContentView: Component<ContentViewProps> = (props) => {
1222
1282
  'tsqd-settings-submenu',
1223
1283
  )}
1224
1284
  >
1225
- <DropdownMenu.Item
1226
- onSelect={() => {
1227
- props.setLocalStore('hideDisabledQueries', 'false')
1228
- }}
1229
- as="button"
1230
- class={cx(
1231
- styles().settingsSubButton,
1232
- props.localStore.hideDisabledQueries !== 'true' &&
1233
- styles().themeSelectedButton,
1234
- 'tsqd-settings-menu-position-btn',
1235
- 'tsqd-settings-menu-position-btn-show',
1236
- )}
1285
+ <DropdownMenu.RadioGroup
1286
+ value={props.localStore.hideDisabledQueries}
1287
+ aria-label="Hide disabled queries setting"
1288
+ onChange={(value) =>
1289
+ props.setLocalStore('hideDisabledQueries', value)
1290
+ }
1237
1291
  >
1238
- <span>Show</span>
1239
- <Show
1240
- when={
1241
- props.localStore.hideDisabledQueries !== 'true'
1242
- }
1292
+ <DropdownMenu.RadioItem
1293
+ value="false"
1294
+ class={cx(
1295
+ styles().settingsSubButton,
1296
+ 'tsqd-settings-menu-position-btn',
1297
+ 'tsqd-settings-menu-position-btn-show',
1298
+ )}
1243
1299
  >
1244
- <CheckCircle />
1245
- </Show>
1246
- </DropdownMenu.Item>
1247
- <DropdownMenu.Item
1248
- onSelect={() => {
1249
- props.setLocalStore('hideDisabledQueries', 'true')
1250
- }}
1251
- as="button"
1252
- class={cx(
1253
- styles().settingsSubButton,
1254
- props.localStore.hideDisabledQueries === 'true' &&
1255
- styles().themeSelectedButton,
1256
- 'tsqd-settings-menu-position-btn',
1257
- 'tsqd-settings-menu-position-btn-hide',
1258
- )}
1259
- >
1260
- <span>Hide</span>
1261
- <Show
1262
- when={
1263
- props.localStore.hideDisabledQueries === 'true'
1264
- }
1300
+ <span>Show</span>
1301
+ <Show
1302
+ when={
1303
+ props.localStore.hideDisabledQueries !== 'true'
1304
+ }
1305
+ >
1306
+ <CheckCircle />
1307
+ </Show>
1308
+ </DropdownMenu.RadioItem>
1309
+ <DropdownMenu.RadioItem
1310
+ value="true"
1311
+ class={cx(
1312
+ styles().settingsSubButton,
1313
+ 'tsqd-settings-menu-position-btn',
1314
+ 'tsqd-settings-menu-position-btn-hide',
1315
+ )}
1265
1316
  >
1266
- <CheckCircle />
1267
- </Show>
1268
- </DropdownMenu.Item>
1317
+ <span>Hide</span>
1318
+ <Show
1319
+ when={
1320
+ props.localStore.hideDisabledQueries === 'true'
1321
+ }
1322
+ >
1323
+ <CheckCircle />
1324
+ </Show>
1325
+ </DropdownMenu.RadioItem>
1326
+ </DropdownMenu.RadioGroup>
1269
1327
  </DropdownMenu.SubContent>
1270
1328
  </DropdownMenu.Portal>
1271
1329
  </DropdownMenu.Sub>
@@ -1420,7 +1478,7 @@ const QueryRow: Component<{ query: Query }> = (props) => {
1420
1478
  styles().selectedQueryRow,
1421
1479
  'tsqd-query-row',
1422
1480
  )}
1423
- aria-label={`Query key ${props.query.queryHash}`}
1481
+ aria-label={`Query key ${props.query.queryHash}${isDisabled() ? ', disabled' : ''}${isStatic() ? ', static' : ''}`}
1424
1482
  >
1425
1483
  <div
1426
1484
  class={cx(getObserverCountColorStyles(), 'tsqd-query-observer-count')}
@@ -1429,10 +1487,14 @@ const QueryRow: Component<{ query: Query }> = (props) => {
1429
1487
  </div>
1430
1488
  <code class="tsqd-query-hash">{props.query.queryHash}</code>
1431
1489
  <Show when={isDisabled()}>
1432
- <div class="tsqd-query-disabled-indicator">disabled</div>
1490
+ <div class="tsqd-query-disabled-indicator" aria-hidden="true">
1491
+ disabled
1492
+ </div>
1433
1493
  </Show>
1434
1494
  <Show when={isStatic()}>
1435
- <div class="tsqd-query-static-indicator">static</div>
1495
+ <div class="tsqd-query-static-indicator" aria-hidden="true">
1496
+ static
1497
+ </div>
1436
1498
  </Show>
1437
1499
  </button>
1438
1500
  </Show>
@@ -1721,6 +1783,7 @@ const QueryStatus: Component<QueryStatusProps> = (props) => {
1721
1783
  }}
1722
1784
  disabled={showLabel()}
1723
1785
  ref={tagRef}
1786
+ aria-label={`${props.label}: ${props.count}`}
1724
1787
  class={cx(
1725
1788
  styles().queryStatusTag,
1726
1789
  !showLabel() &&
@@ -1752,6 +1815,7 @@ const QueryStatus: Component<QueryStatusProps> = (props) => {
1752
1815
  </div>
1753
1816
  </Show>
1754
1817
  <span
1818
+ aria-hidden="true"
1755
1819
  class={cx(
1756
1820
  css`
1757
1821
  width: ${tokens.size[1.5]};
@@ -1953,7 +2017,11 @@ const QueryDetails = () => {
1953
2017
  <div
1954
2018
  class={cx(styles().detailsContainer, 'tsqd-query-details-container')}
1955
2019
  >
1956
- <div class={cx(styles().detailsHeader, 'tsqd-query-details-header')}>
2020
+ <div
2021
+ role="heading"
2022
+ aria-level="2"
2023
+ class={cx(styles().detailsHeader, 'tsqd-query-details-header')}
2024
+ >
1957
2025
  Query Details
1958
2026
  </div>
1959
2027
  <div
@@ -1968,6 +2036,8 @@ const QueryDetails = () => {
1968
2036
  </pre>
1969
2037
  <span
1970
2038
  class={cx(styles().queryDetailsStatus, getQueryStatusColors())}
2039
+ role="status"
2040
+ aria-live="polite"
1971
2041
  >
1972
2042
  {statusLabel()}
1973
2043
  </span>
@@ -1983,7 +2053,11 @@ const QueryDetails = () => {
1983
2053
  </span>
1984
2054
  </div>
1985
2055
  </div>
1986
- <div class={cx(styles().detailsHeader, 'tsqd-query-details-header')}>
2056
+ <div
2057
+ role="heading"
2058
+ aria-level="2"
2059
+ class={cx(styles().detailsHeader, 'tsqd-query-details-header')}
2060
+ >
1987
2061
  Actions
1988
2062
  </div>
1989
2063
  <div
@@ -2004,6 +2078,7 @@ const QueryDetails = () => {
2004
2078
  disabled={statusLabel() === 'fetching'}
2005
2079
  >
2006
2080
  <span
2081
+ aria-hidden="true"
2007
2082
  class={css`
2008
2083
  background-color: ${t(colors.blue[600], colors.blue[400])};
2009
2084
  `}
@@ -2028,6 +2103,7 @@ const QueryDetails = () => {
2028
2103
  disabled={queryStatus() === 'pending'}
2029
2104
  >
2030
2105
  <span
2106
+ aria-hidden="true"
2031
2107
  class={css`
2032
2108
  background-color: ${t(colors.yellow[600], colors.yellow[400])};
2033
2109
  `}
@@ -2052,6 +2128,7 @@ const QueryDetails = () => {
2052
2128
  disabled={queryStatus() === 'pending'}
2053
2129
  >
2054
2130
  <span
2131
+ aria-hidden="true"
2055
2132
  class={css`
2056
2133
  background-color: ${t(colors.gray[600], colors.gray[400])};
2057
2134
  `}
@@ -2077,6 +2154,7 @@ const QueryDetails = () => {
2077
2154
  disabled={statusLabel() === 'fetching'}
2078
2155
  >
2079
2156
  <span
2157
+ aria-hidden="true"
2080
2158
  class={css`
2081
2159
  background-color: ${t(colors.pink[500], colors.pink[400])};
2082
2160
  `}
@@ -2126,6 +2204,7 @@ const QueryDetails = () => {
2126
2204
  }}
2127
2205
  >
2128
2206
  <span
2207
+ aria-hidden="true"
2129
2208
  class={css`
2130
2209
  background-color: ${t(colors.cyan[500], colors.cyan[400])};
2131
2210
  `}
@@ -2155,6 +2234,7 @@ const QueryDetails = () => {
2155
2234
  disabled={queryStatus() === 'pending'}
2156
2235
  >
2157
2236
  <span
2237
+ aria-hidden="true"
2158
2238
  class={css`
2159
2239
  background-color: ${t(colors.red[500], colors.red[400])};
2160
2240
  `}
@@ -2173,6 +2253,7 @@ const QueryDetails = () => {
2173
2253
  )}
2174
2254
  >
2175
2255
  <span
2256
+ aria-hidden="true"
2176
2257
  class={css`
2177
2258
  background-color: ${tokens.colors.red[400]};
2178
2259
  `}
@@ -2180,6 +2261,7 @@ const QueryDetails = () => {
2180
2261
  Trigger Error
2181
2262
  <select
2182
2263
  disabled={queryStatus() === 'pending'}
2264
+ aria-label="Select error type to trigger"
2183
2265
  onChange={(e) => {
2184
2266
  const errorType = errorTypes().find(
2185
2267
  (et) => et.name === e.currentTarget.value,
@@ -2199,7 +2281,11 @@ const QueryDetails = () => {
2199
2281
  </div>
2200
2282
  </Show>
2201
2283
  </div>
2202
- <div class={cx(styles().detailsHeader, 'tsqd-query-details-header')}>
2284
+ <div
2285
+ role="heading"
2286
+ aria-level="2"
2287
+ class={cx(styles().detailsHeader, 'tsqd-query-details-header')}
2288
+ >
2203
2289
  Data {dataMode() === 'view' ? 'Explorer' : 'Editor'}
2204
2290
  </div>
2205
2291
  <Show when={dataMode() === 'view'}>
@@ -2243,6 +2329,7 @@ const QueryDetails = () => {
2243
2329
  >
2244
2330
  <textarea
2245
2331
  name="data"
2332
+ aria-label="Edit query data as JSON"
2246
2333
  class={styles().devtoolsEditTextarea}
2247
2334
  onFocus={() => setDataEditError(false)}
2248
2335
  data-error={dataEditError()}
@@ -2279,7 +2366,11 @@ const QueryDetails = () => {
2279
2366
  </div>
2280
2367
  </form>
2281
2368
  </Show>
2282
- <div class={cx(styles().detailsHeader, 'tsqd-query-details-header')}>
2369
+ <div
2370
+ role="heading"
2371
+ aria-level="2"
2372
+ class={cx(styles().detailsHeader, 'tsqd-query-details-header')}
2373
+ >
2283
2374
  Query Explorer
2284
2375
  </div>
2285
2376
  <div
@@ -2364,7 +2455,11 @@ const MutationDetails = () => {
2364
2455
  <div
2365
2456
  class={cx(styles().detailsContainer, 'tsqd-query-details-container')}
2366
2457
  >
2367
- <div class={cx(styles().detailsHeader, 'tsqd-query-details-header')}>
2458
+ <div
2459
+ role="heading"
2460
+ aria-level="2"
2461
+ class={cx(styles().detailsHeader, 'tsqd-query-details-header')}
2462
+ >
2368
2463
  Mutation Details
2369
2464
  </div>
2370
2465
  <div
@@ -2386,6 +2481,8 @@ const MutationDetails = () => {
2386
2481
  </pre>
2387
2482
  <span
2388
2483
  class={cx(styles().queryDetailsStatus, getQueryStatusColors())}
2484
+ role="status"
2485
+ aria-live="polite"
2389
2486
  >
2390
2487
  <Show when={color() === 'purple'}>pending</Show>
2391
2488
  <Show when={color() !== 'purple'}>{status()}</Show>
@@ -2400,7 +2497,11 @@ const MutationDetails = () => {
2400
2497
  </span>
2401
2498
  </div>
2402
2499
  </div>
2403
- <div class={cx(styles().detailsHeader, 'tsqd-query-details-header')}>
2500
+ <div
2501
+ role="heading"
2502
+ aria-level="2"
2503
+ class={cx(styles().detailsHeader, 'tsqd-query-details-header')}
2504
+ >
2404
2505
  Variables Details
2405
2506
  </div>
2406
2507
  <div
@@ -2415,7 +2516,11 @@ const MutationDetails = () => {
2415
2516
  value={activeMutation()!.state.variables}
2416
2517
  />
2417
2518
  </div>
2418
- <div class={cx(styles().detailsHeader, 'tsqd-query-details-header')}>
2519
+ <div
2520
+ role="heading"
2521
+ aria-level="2"
2522
+ class={cx(styles().detailsHeader, 'tsqd-query-details-header')}
2523
+ >
2419
2524
  Context Details
2420
2525
  </div>
2421
2526
  <div
@@ -2430,7 +2535,11 @@ const MutationDetails = () => {
2430
2535
  value={activeMutation()!.state.context}
2431
2536
  />
2432
2537
  </div>
2433
- <div class={cx(styles().detailsHeader, 'tsqd-query-details-header')}>
2538
+ <div
2539
+ role="heading"
2540
+ aria-level="2"
2541
+ class={cx(styles().detailsHeader, 'tsqd-query-details-header')}
2542
+ >
2434
2543
  Data Explorer
2435
2544
  </div>
2436
2545
  <div
@@ -2445,7 +2554,11 @@ const MutationDetails = () => {
2445
2554
  value={activeMutation()!.state.data}
2446
2555
  />
2447
2556
  </div>
2448
- <div class={cx(styles().detailsHeader, 'tsqd-query-details-header')}>
2557
+ <div
2558
+ role="heading"
2559
+ aria-level="2"
2560
+ class={cx(styles().detailsHeader, 'tsqd-query-details-header')}
2561
+ >
2449
2562
  Mutations Explorer
2450
2563
  </div>
2451
2564
  <div
@@ -2902,6 +3015,15 @@ const stylesFactory = (
2902
3015
  &:hover {
2903
3016
  background-color: ${colors.purple[400]}${t('', alpha[90])};
2904
3017
  }
3018
+ &:focus {
3019
+ outline: none;
3020
+ background-color: ${colors.purple[400]}${t('', alpha[90])};
3021
+ }
3022
+ &:focus-visible {
3023
+ outline: 2px solid ${colors.blue[800]};
3024
+ outline-offset: -2px;
3025
+ background-color: ${colors.purple[400]}${t('', alpha[90])};
3026
+ }
2905
3027
  z-index: 4;
2906
3028
  `,
2907
3029
  'dragHandle-position-top': css`
@@ -3521,15 +3643,15 @@ const stylesFactory = (
3521
3643
  outline-offset: 2px;
3522
3644
  outline: 2px solid ${colors.blue[800]};
3523
3645
  }
3524
- `,
3525
- themeSelectedButton: css`
3526
- background-color: ${t(colors.purple[100], colors.purple[900])};
3527
- color: ${t(colors.purple[700], colors.purple[300])};
3528
- & svg {
3529
- color: ${t(colors.purple[700], colors.purple[300])};
3530
- }
3531
- &:hover {
3646
+ &[data-checked] {
3532
3647
  background-color: ${t(colors.purple[100], colors.purple[900])};
3648
+ color: ${t(colors.purple[700], colors.purple[300])};
3649
+ & svg {
3650
+ color: ${t(colors.purple[700], colors.purple[300])};
3651
+ }
3652
+ &:hover {
3653
+ background-color: ${t(colors.purple[100], colors.purple[900])};
3654
+ }
3533
3655
  }
3534
3656
  `,
3535
3657
  viewToggle: css`