Skip to content

Commit ac1a3e8

Browse files
Add landmark elements and regions for navigation (#527)
* Fix vertical scroll (data page) and icon picker position * Add landmark elements and regions for navigation * Add region role to action rows on testing model page Regions as of this PR: - header with the app-wide actions - main containing the table-like area - named action regions - "data samples toolbar" or "testing model toolbar" containing the page specific actions (intentionally avoided the word action here) - live graph We think the live graph makes sense as a separate region as the other actions aren't related to it and are different per page. It's also something we talk about a lot in docs etc. First cut of work for #517
1 parent 63a219c commit ac1a3e8

File tree

12 files changed

+129
-43
lines changed

12 files changed

+129
-43
lines changed

lang/ui.en.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@
3535
"defaultMessage": "Name of action",
3636
"description": "Placeholder text for user supplied name of a movement-related action, e.g. clapping"
3737
},
38+
"action-region": {
39+
"defaultMessage": "Action \"{action}\"",
40+
"description": "Region label for action row"
41+
},
3842
"action-tooltip": {
3943
"defaultMessage": "The type of movement you want {appNameFull} to recognise e.g. ‘waving’ or ‘clapping’.",
4044
"description": "Tooltip explaining action"
@@ -403,6 +407,10 @@
403407
"defaultMessage": "Show data features",
404408
"description": "Show data features button text"
405409
},
410+
"data-samples-actions-region": {
411+
"defaultMessage": "Data samples toolbar",
412+
"description": "Region label for data samples actions"
413+
},
406414
"data-samples-label": {
407415
"defaultMessage": "Data samples",
408416
"description": "Heading for data samples column"
@@ -1411,6 +1419,10 @@
14111419
"defaultMessage": "Terms of use",
14121420
"description": "Link or menu item link to view terms of use"
14131421
},
1422+
"testing-model-actions-region": {
1423+
"defaultMessage": "Testing model toolbar",
1424+
"description": "Region label for testing model actions"
1425+
},
14141426
"testing-model-title": {
14151427
"defaultMessage": "Testing model",
14161428
"description": "Testing model page title"

src/components/ActionBar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const ActionBar = ({
1717
}: ActionBarProps) => {
1818
return (
1919
<HStack
20-
px={5}
20+
as="header"
2121
alignItems="center"
2222
justifyContent="space-between"
2323
bgColor="brand2.500"

src/components/DataSamplesTableRow.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,17 @@ const DataSamplesTableRow = ({
5959
onConfirm={() => deleteAction(action.ID)}
6060
onCancel={deleteConfirmDisclosure.onClose}
6161
/>
62-
<Box display="contents" onFocusCapture={onSelectRow}>
62+
<Box
63+
role="region"
64+
aria-label={intl.formatMessage(
65+
{
66+
id: "action-region",
67+
},
68+
{ action: action.name }
69+
)}
70+
display="contents"
71+
onFocusCapture={onSelectRow}
72+
>
6373
<GridItem>
6474
<ActionNameCard
6575
value={action}

src/components/LedIconPicker.tsx

Lines changed: 29 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
PopoverBody,
77
PopoverContent,
88
PopoverTrigger,
9+
Portal,
910
} from "@chakra-ui/react";
1011
import { memo, useCallback } from "react";
1112
import { RiArrowDropDownFill } from "react-icons/ri";
@@ -29,7 +30,7 @@ const LedIconPicker = ({ actionName, onIconSelected }: LedIconPicker) => {
2930
);
3031

3132
return (
32-
<Popover placement="bottom-end" isLazy lazyBehavior="keepMounted">
33+
<Popover placement="right-start" isLazy lazyBehavior="keepMounted">
3334
{({ onClose }) => (
3435
<>
3536
<PopoverTrigger>
@@ -51,31 +52,33 @@ const LedIconPicker = ({ actionName, onIconSelected }: LedIconPicker) => {
5152
<RiArrowDropDownFill size={32} />
5253
</IconButton>
5354
</PopoverTrigger>
54-
<PopoverContent w="100%" height="300px" overflowY="auto">
55-
<PopoverArrow />
56-
<PopoverBody p={4}>
57-
<Grid templateColumns="repeat(4, 1fr)" gap={4}>
58-
{Object.keys(makecodeIcons).map((icon, idx) => (
59-
<IconButton
60-
key={idx}
61-
aria-label={intl.formatMessage(
62-
{ id: "select-icon-option-action-aria" },
63-
{
64-
iconName: intl.formatMessage({
65-
id: `led-icon-option-${icon.toLowerCase()}`,
66-
}),
67-
}
68-
)}
69-
onClick={() => handleClick(icon as MakeCodeIcon, onClose)}
70-
variant="unstyled"
71-
h={20}
72-
w={20}
73-
icon={<LedIconSvg icon={icon as MakeCodeIcon} />}
74-
/>
75-
))}
76-
</Grid>
77-
</PopoverBody>
78-
</PopoverContent>
55+
<Portal>
56+
<PopoverContent w="100%" height="300px" overflowY="auto">
57+
<PopoverArrow />
58+
<PopoverBody p={4}>
59+
<Grid templateColumns="repeat(4, 1fr)" gap={4}>
60+
{Object.keys(makecodeIcons).map((icon, idx) => (
61+
<IconButton
62+
key={idx}
63+
aria-label={intl.formatMessage(
64+
{ id: "select-icon-option-action-aria" },
65+
{
66+
iconName: intl.formatMessage({
67+
id: `led-icon-option-${icon.toLowerCase()}`,
68+
}),
69+
}
70+
)}
71+
onClick={() => handleClick(icon as MakeCodeIcon, onClose)}
72+
variant="unstyled"
73+
h={20}
74+
w={20}
75+
icon={<LedIconSvg icon={icon as MakeCodeIcon} />}
76+
/>
77+
))}
78+
</Grid>
79+
</PopoverBody>
80+
</PopoverContent>
81+
</Portal>
7982
</>
8083
)}
8184
</Popover>

src/components/LiveGraphPanel.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ const LiveGraphPanel = ({
6767
const intl = useIntl();
6868
return (
6969
<HStack
70+
role="region"
71+
aria-label={intl.formatMessage({ id: "live-data-graph" })}
7072
position="relative"
7173
h={160}
7274
width="100%"

src/components/TestingModelTable.tsx

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
Box,
23
Grid,
34
GridItem,
45
GridProps,
@@ -7,15 +8,16 @@ import {
78
VStack,
89
} from "@chakra-ui/react";
910
import { MakeCodeRenderBlocksProvider } from "@microbit/makecode-embed/react";
10-
import React, { useRef } from "react";
11+
import { useRef } from "react";
1112
import { RiArrowRightLine } from "react-icons/ri";
13+
import { useIntl } from "react-intl";
1214
import { useConnectionStage } from "../connection-stage-hooks";
1315
import { useProject } from "../hooks/project-hooks";
1416
import { mlSettings } from "../mlConfig";
1517
import { getMakeCodeLang } from "../settings";
1618
import { useSettings, useStore } from "../store";
17-
import ActionNameCard from "./ActionNameCard";
1819
import ActionCertaintyCard from "./ActionCertaintyCard";
20+
import ActionNameCard from "./ActionNameCard";
1921
import CodeViewCard from "./CodeViewCard";
2022
import CodeViewDefaultBlockCard from "./CodeViewDefaultBlockCard";
2123
import HeadingGrid from "./HeadingGrid";
@@ -51,6 +53,7 @@ const TestingModelTable = () => {
5153
const [{ languageId }] = useSettings();
5254
const makeCodeLang = getMakeCodeLang(languageId);
5355
const scrollableAreaRef = useRef<HTMLDivElement>(null);
56+
const intl = useIntl();
5457
return (
5558
<MakeCodeRenderBlocksProvider
5659
key={makeCodeLang}
@@ -83,7 +86,17 @@ const TestingModelTable = () => {
8386
{actions.map((action, idx) => {
8487
const { requiredConfidence: threshold } = action;
8588
return (
86-
<React.Fragment key={idx}>
89+
<Box
90+
key={idx}
91+
role="region"
92+
aria-label={intl.formatMessage(
93+
{
94+
id: "action-region",
95+
},
96+
{ action: action.name }
97+
)}
98+
display="contents"
99+
>
87100
<GridItem>
88101
<ActionNameCard
89102
value={action}
@@ -112,7 +125,7 @@ const TestingModelTable = () => {
112125
<CodeViewDefaultBlockCard action={action} />
113126
)}
114127
</GridItem>
115-
</React.Fragment>
128+
</Box>
116129
);
117130
})}
118131
</Grid>

src/messages/ui.en.json

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,20 @@
7171
"value": "Name of action"
7272
}
7373
],
74+
"action-region": [
75+
{
76+
"type": 0,
77+
"value": "Action \""
78+
},
79+
{
80+
"type": 1,
81+
"value": "action"
82+
},
83+
{
84+
"type": 0,
85+
"value": "\""
86+
}
87+
],
7488
"action-tooltip": [
7589
{
7690
"type": 0,
@@ -675,6 +689,12 @@
675689
"value": "Show data features"
676690
}
677691
],
692+
"data-samples-actions-region": [
693+
{
694+
"type": 0,
695+
"value": "Data samples toolbar"
696+
}
697+
],
678698
"data-samples-label": [
679699
{
680700
"type": 0,
@@ -2499,6 +2519,12 @@
24992519
"value": "Terms of use"
25002520
}
25012521
],
2522+
"testing-model-actions-region": [
2523+
{
2524+
"type": 0,
2525+
"value": "Testing model toolbar"
2526+
}
2527+
],
25022528
"testing-model-title": [
25032529
{
25042530
"type": 0,

src/pages/DataSamplesPage.tsx

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { Button, HStack, VStack } from "@chakra-ui/react";
1+
import { Button, Flex, HStack, VStack } from "@chakra-ui/react";
22
import { useCallback, useEffect, useRef, useState } from "react";
33
import { RiAddLine, RiArrowRightLine } from "react-icons/ri";
4-
import { FormattedMessage } from "react-intl";
4+
import { FormattedMessage, useIntl } from "react-intl";
55
import { useNavigate } from "react-router";
66
import DataSamplesTable from "../components/DataSamplesTable";
77
import DefaultPageLayout, {
@@ -45,7 +45,7 @@ const DataSamplesPage = () => {
4545
setSelectedActionIdx(actions.length);
4646
addNewAction();
4747
}, [addNewAction, actions]);
48-
48+
const intl = useIntl();
4949
return (
5050
<>
5151
<TrainModelDialogs finalFocusRef={trainButtonRef} />
@@ -55,12 +55,18 @@ const DataSamplesPage = () => {
5555
menuItems={<ProjectMenuItems />}
5656
toolbarItemsRight={<ProjectToolbarItems />}
5757
>
58-
<DataSamplesTable
59-
selectedActionIdx={selectedActionIdx}
60-
setSelectedActionIdx={setSelectedActionIdx}
61-
/>
58+
<Flex as="main" flexGrow={1} flexDir="column">
59+
<DataSamplesTable
60+
selectedActionIdx={selectedActionIdx}
61+
setSelectedActionIdx={setSelectedActionIdx}
62+
/>
63+
</Flex>
6264
<VStack w="full" flexShrink={0} bottom={0} gap={0} bg="gray.25">
6365
<HStack
66+
role="region"
67+
aria-label={intl.formatMessage({
68+
id: "data-samples-actions-region",
69+
})}
6470
justifyContent="space-between"
6571
px={5}
6672
py={2}

src/pages/HomePage.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,14 @@ const HomePage = () => {
4545
</Button>
4646
}
4747
>
48-
<Container centerContent gap={20} p={8} pb={20} maxW="container.lg">
48+
<Container
49+
as="main"
50+
centerContent
51+
gap={20}
52+
p={8}
53+
pb={20}
54+
maxW="container.lg"
55+
>
4956
<HStack
5057
gap={5}
5158
flexDir={{ base: "column", lg: "row" }}

src/pages/ImportPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ const ImportPage = () => {
9494
toolbarItemsRight={<HomeToolbarItem />}
9595
menuItems={<HomeMenuItem />}
9696
>
97-
<VStack justifyContent="center">
97+
<VStack as="main" justifyContent="center">
9898
<Stack
9999
bgColor="white"
100100
spacing={5}

0 commit comments

Comments
 (0)