diff --git a/src/app/[locale]/_components/DashboardInput.tsx b/src/app/[locale]/_components/DashboardInput.tsx
index 1624a9ac..73db5598 100644
--- a/src/app/[locale]/_components/DashboardInput.tsx
+++ b/src/app/[locale]/_components/DashboardInput.tsx
@@ -28,8 +28,9 @@ export const DashboardInput = () => {
}
};
+ // add main landmark
return (
- <>
+
@@ -38,6 +39,6 @@ export const DashboardInput = () => {
:
- >
+
);
};
diff --git a/src/app/[locale]/_components/ManualAasInput.tsx b/src/app/[locale]/_components/ManualAasInput.tsx
index 2dc695c0..233749f2 100644
--- a/src/app/[locale]/_components/ManualAasInput.tsx
+++ b/src/app/[locale]/_components/ManualAasInput.tsx
@@ -76,6 +76,7 @@ export function ManualAasInput(props: { onSubmit: (input: string) => Promise {
setInputValue('');
}}
+ aria-label="Reset input"
>
@@ -90,6 +91,7 @@ export function ManualAasInput(props: { onSubmit: (input: string) => Promise
);
diff --git a/src/app/[locale]/_components/QrScanner.tsx b/src/app/[locale]/_components/QrScanner.tsx
index 578f1ba9..b7d9e148 100644
--- a/src/app/[locale]/_components/QrScanner.tsx
+++ b/src/app/[locale]/_components/QrScanner.tsx
@@ -1,6 +1,6 @@
'use client';
-import { useCallback, useState } from 'react';
+import React, { useCallback, useState } from 'react';
import ScannerLogo from 'assets/ScannerLogo.svg';
import { Box, CircularProgress, IconButton, useTheme } from '@mui/material';
import { QrStream } from 'app/[locale]/_components/QrStream';
@@ -41,15 +41,22 @@ export function QrScanner(props: { onScan: (scanResult: string) => Promise
}
}, []);
- const expandFromCenter = keyframes`
- 0% {
- width: 0;
- left: 50%;
- }
- 100% {
- width: 100%;
- left: 0;
+ const handleKeyDown = (state: State) => (event: React.KeyboardEvent) => {
+ if (!(event.key === 'Enter')) {
+ return;
}
+ setState(state);
+ };
+
+ const expandFromCenter = keyframes`
+ 0% {
+ width: 0;
+ left: 50%;
+ }
+ 100% {
+ width: 100%;
+ left: 0;
+ }
`;
interface VideoContainerProps {
@@ -109,11 +116,15 @@ export function QrScanner(props: { onScan: (scanResult: string) => Promise
{state === State.Stopped && (
setState(State.LoadScanner)}
+ onKeyDown={handleKeyDown(State.LoadScanner)}
padding="50px"
position="absolute"
height={size}
width={size}
data-testid="scanner-start"
+ aria-label="open QR code scanner"
+ tabIndex={0}
+ role="button"
>
@@ -123,11 +134,13 @@ export function QrScanner(props: { onScan: (scanResult: string) => Promise
data-testid="scanner-close-button"
aria-label="close scanner"
onClick={() => setState(State.Stopped)}
+ onKeyDown={handleKeyDown(State.Stopped)}
style={{
position: 'absolute',
zIndex: 995,
right: 0,
}} // Align to the right top corner and render in front of everything
+ tabIndex={0}
>
diff --git a/src/app/[locale]/compare/_components/add-aas/AddAasToCompareCard.tsx b/src/app/[locale]/compare/_components/add-aas/AddAasToCompareCard.tsx
index 78f62d59..0c447a2f 100644
--- a/src/app/[locale]/compare/_components/add-aas/AddAasToCompareCard.tsx
+++ b/src/app/[locale]/compare/_components/add-aas/AddAasToCompareCard.tsx
@@ -20,6 +20,10 @@ export function AddAasToCompareCard(props: AddAasToCompareCardProps) {
onClick={props.onClick}
sx={{ cursor: 'pointer' }}
data-testid="add-aas-to-compare-button"
+ // a custom component acting like a button
+ role="button"
+ // make it keyboard accessible
+ tabIndex={0}
>
diff --git a/src/app/[locale]/layout.tsx b/src/app/[locale]/layout.tsx
index da2bb389..b502015e 100644
--- a/src/app/[locale]/layout.tsx
+++ b/src/app/[locale]/layout.tsx
@@ -11,7 +11,7 @@ export type LocalizedIndexLayoutProps = {
};
export const metadata: Metadata = {
- title: 'Mnestix',
+ title: 'Dashboard | Mnestix',
description: 'AAS made easy',
};
diff --git a/src/app/[locale]/list/layout.tsx b/src/app/[locale]/list/layout.tsx
new file mode 100644
index 00000000..f524fcc0
--- /dev/null
+++ b/src/app/[locale]/list/layout.tsx
@@ -0,0 +1,16 @@
+import type { Metadata } from 'next';
+import { ReactNode } from 'react';
+
+// add this file to every page for distinctive page titles
+export const metadata: Metadata = {
+ title: 'AAS List | Mnestix',
+ description: 'A list of AAS',
+};
+
+interface Props {
+ children: ReactNode;
+}
+
+export default function ClientLayout({ children }: Props) {
+ return children;
+}
diff --git a/src/app/[locale]/settings/layout.tsx b/src/app/[locale]/settings/layout.tsx
new file mode 100644
index 00000000..8b7f6691
--- /dev/null
+++ b/src/app/[locale]/settings/layout.tsx
@@ -0,0 +1,15 @@
+import type { Metadata } from 'next';
+import { ReactNode } from 'react';
+
+export const metadata: Metadata = {
+ title: 'Settings | Mnestix',
+ description: 'Settings',
+};
+
+interface Props {
+ children: ReactNode;
+}
+
+export default function ClientLayout({ children }: Props) {
+ return children;
+}
diff --git a/src/app/[locale]/templates/_components/ChooseTemplateItem.tsx b/src/app/[locale]/templates/_components/ChooseTemplateItem.tsx
index f6fa6a7f..78819fd6 100644
--- a/src/app/[locale]/templates/_components/ChooseTemplateItem.tsx
+++ b/src/app/[locale]/templates/_components/ChooseTemplateItem.tsx
@@ -22,7 +22,8 @@ const StyledBox = styled(Box)(({ theme }) => ({
export function ChooseTemplateItem(props: ChooseTemplateItemProps) {
return (
-
+ {/* make the box keyboard accessible */}
+
diff --git a/src/app/[locale]/templates/_components/CustomTemplateItem.tsx b/src/app/[locale]/templates/_components/CustomTemplateItem.tsx
index 72280030..1d1c2d68 100644
--- a/src/app/[locale]/templates/_components/CustomTemplateItem.tsx
+++ b/src/app/[locale]/templates/_components/CustomTemplateItem.tsx
@@ -82,14 +82,28 @@ export function CustomTemplateItem(props: CustomTemplateItemProps) {
}
};
+ // navigate to template when pressing Enter
+ const handleOnKeyDown = (event: React.KeyboardEvent) => {
+ if (!(event.code === 'Enter')) {
+ return;
+ }
+ navigateToTemplate();
+ };
+
const navigateToTemplate = () => {
if (props.item.id) {
navigate.push(`/templates/${encodeURIComponent(props.item.id)}`);
}
};
+
return (
<>
-
+
diff --git a/src/app/[locale]/templates/_components/template-edit/TemplateEditTreeItem.tsx b/src/app/[locale]/templates/_components/template-edit/TemplateEditTreeItem.tsx
index 4902ff1e..858a2112 100644
--- a/src/app/[locale]/templates/_components/template-edit/TemplateEditTreeItem.tsx
+++ b/src/app/[locale]/templates/_components/template-edit/TemplateEditTreeItem.tsx
@@ -1,4 +1,5 @@
import * as React from 'react';
+import { useState } from 'react';
import { TreeItem, TreeItemContentProps, TreeItemProps, useTreeItemState } from '@mui/x-tree-view';
import clsx from 'clsx';
import Typography from '@mui/material/Typography';
@@ -6,7 +7,6 @@ import { Box, styled } from '@mui/material';
import { TextSnippet } from '@mui/icons-material';
import { MultiplicityEnum } from 'lib/enums/Multiplicity.enum';
import { TemplateEditTreeItemMenu } from './TemplateEditTreeItemMenu';
-import { useState } from 'react';
import { messages } from 'lib/i18n/localization';
import { useIntl } from 'react-intl';
@@ -41,7 +41,7 @@ const StyledTreeItem = styled(TreeItem)(({ theme }) => ({
userSelect: 'none',
margin: 0,
'&.Mui-focused': {
- backgroundColor: 'transparent',
+ backgroundColor: theme.palette.action.selected,
},
'&.Mui-focused:hover': {
backgroundColor: theme.palette.action.hover,
diff --git a/src/app/[locale]/templates/layout.tsx b/src/app/[locale]/templates/layout.tsx
new file mode 100644
index 00000000..ee279ff0
--- /dev/null
+++ b/src/app/[locale]/templates/layout.tsx
@@ -0,0 +1,15 @@
+import type { Metadata } from 'next';
+import { ReactNode } from 'react';
+
+export const metadata: Metadata = {
+ title: 'Templates | Mnestix',
+ description: 'A list of templates',
+};
+
+interface Props {
+ children: ReactNode;
+}
+
+export default function ClientLayout({ children }: Props) {
+ return children;
+}
diff --git a/src/layout/HeaderLogo.tsx b/src/layout/HeaderLogo.tsx
index a1df4221..92760c73 100644
--- a/src/layout/HeaderLogo.tsx
+++ b/src/layout/HeaderLogo.tsx
@@ -1,6 +1,8 @@
import { Box, useTheme } from '@mui/material';
import { useRouter } from 'next/navigation';
import { MnestixLogo } from 'components/basics/MnestixLogo';
+import React from 'react';
+
export function HeaderLogo() {
const theme = useTheme();
const navigate = useRouter();
@@ -9,8 +11,23 @@ export function HeaderLogo() {
navigate.push('/');
};
+ const handleKeyDown = (event: React.KeyboardEvent) => {
+ if (!(event.key === 'Enter')) {
+ return;
+ }
+ goToHome();
+ };
+
return (
-
+
{theme?.productLogo?.logo ? (
) : (
diff --git a/src/layout/menu/MainMenu.tsx b/src/layout/menu/MainMenu.tsx
index 3518e540..f2b19b89 100644
--- a/src/layout/menu/MainMenu.tsx
+++ b/src/layout/menu/MainMenu.tsx
@@ -28,10 +28,11 @@ const StyledDrawer = styled(Drawer)(({ theme }) => ({
'.MuiListItemButton-root': {
color: theme.palette.primary.contrastText,
'&:hover': {
- backgroundColor: alpha(theme.palette.primary.dark, 0.8),
+ backgroundColor: alpha(theme.palette.primary.dark, 0.6),
},
+ // do not remove focus indicators
'&:focus': {
- backgroundColor: 'transparent',
+ backgroundColor: alpha(theme.palette.primary.dark, 0.8),
},
'&.active': {
backgroundColor: theme.palette.primary.light,
@@ -105,6 +106,7 @@ export default function MainMenu() {
label: ,
icon: ,
onClick: () => auth.logout(),
+ onKeyDown: () => auth.logout(),
},
];
@@ -113,6 +115,7 @@ export default function MainMenu() {
label: ,
icon: ,
onClick: () => auth.login(),
+ onKeyDown: () => auth.login(),
},
{
label: ,
@@ -150,6 +153,7 @@ export default function MainMenu() {
sx={{ m: 1, zIndex: 1 }}
onClick={handleMenuInteraction(true)}
data-testid="header-burgermenu"
+ aria-label="main menu"
>
@@ -166,7 +170,7 @@ export default function MainMenu() {
)}
-
+
{!useAuthentication || auth.isLoggedIn ? (
<>
diff --git a/src/layout/menu/MenuListItem.tsx b/src/layout/menu/MenuListItem.tsx
index d88a3c20..56daa091 100644
--- a/src/layout/menu/MenuListItem.tsx
+++ b/src/layout/menu/MenuListItem.tsx
@@ -8,6 +8,7 @@ export interface MenuListItemProps {
label?: React.ReactElement | string;
target?: string;
onClick?: React.MouseEventHandler;
+ onKeyDown?: React.KeyboardEventHandler;
}
export function MenuListItem(props: MenuListItemProps) {
@@ -24,10 +25,14 @@ export function MenuListItem(props: MenuListItemProps) {
href={props.to}
target={props.target}
onClick={props.onClick}
+ // not sure if any of this is actually needed; needs testing
+ onKeyDown={props.onKeyDown}
>
{content}
) : (
- {content}
+
+ {content}
+
);
}