Parcourir la source

WCAG 2.0, AA 2.4.7 Focus Visible

web_access_fix
Jason Chuang il y a 4 semaines
Parent
révision
27b5128b23
7 fichiers modifiés avec 159 ajouts et 45 suppressions
  1. +14
    -1
      src/assets/style/navbarStyles.css
  2. +57
    -1
      src/assets/style/styles.css
  3. +17
    -8
      src/components/AdminLogo/index.js
  4. +17
    -8
      src/components/MobileLogo/index.js
  5. +19
    -9
      src/layout/MainLayout/Header/HeaderContent/LocaleSelector.js
  6. +20
    -13
      src/layout/MainLayout/Header/HeaderContent/MobileSection.js
  7. +15
    -5
      src/layout/MainLayout/Header/HeaderContent/Notification.js

+ 14
- 1
src/assets/style/navbarStyles.css Voir le fichier

@@ -43,7 +43,7 @@
color: #0C489E;
}
#navbar div li a:hover::after,
#navbar div li a:focus::after{
#navbar div li a:focus-visible::after{
content: "";
width: 80%;
height: 3px;
@@ -73,6 +73,19 @@
opacity: 1;
display: block
}

/* Navbar: don't show focus ring on mouse click */
#navbar a:focus {
outline: none;
}

/* Navbar: show focus ring for keyboard navigation */
#navbar a:focus-visible {
outline: 3px solid #0C489E;
outline-offset: 2px;
border-radius: 10px; /* tweak to match your design */
}

/* #navbar div li:focus-within > ul,
#navbar div li ul:hover,
#navbar div li ul:focus {


+ 57
- 1
src/assets/style/styles.css Voir le fichier

@@ -74,4 +74,60 @@ a:active {
text-decoration: none;
}

/* iframe#webpack-dev-server-client-overlay{display:none!important} */
/* iframe#webpack-dev-server-client-overlay{display:none!important} */

/* ===== WCAG 2.4.7 Focus Visible (Global) ===== */
:where(
a,
button,
input,
select,
textarea,
summary,
[role="button"],
[role="link"],
[tabindex]:not([tabindex="-1"])
):focus-visible {
outline: 3px solid #0C489E;
outline-offset: 2px;
border-radius: 4px;
}

/* Fallback for browsers that don't support :focus-visible */
:where(
a,
button,
input,
select,
textarea,
summary,
[role="button"],
[role="link"],
[tabindex]:not([tabindex="-1"])
):focus {
outline: 3px solid #0C489E;
outline-offset: 2px;
border-radius: 4px;
}

/* ===== MUI DataGrid focus visible (WCAG 2.4.7) ===== */

/* Column headers */
.MuiDataGrid-columnHeader:focus,
.MuiDataGrid-columnHeader:focus-within {
outline: 3px solid #0C489E;
outline-offset: -2px;
}

/* Cells */
.MuiDataGrid-cell:focus,
.MuiDataGrid-cell:focus-within {
outline: 3px solid #0C489E;
outline-offset: -2px;
}

/* If outline is clipped, add halo */
.MuiDataGrid-columnHeader:focus-within,
.MuiDataGrid-cell:focus-within {
box-shadow: 0 0 0 3px rgba(12, 72, 158, 0.25);
}

+ 17
- 8
src/components/AdminLogo/index.js Voir le fichier

@@ -23,14 +23,23 @@ const LogoSection = ({ sx, to }) => {
return (
<Stack direction="column" justifyContent="center" alignItems="center" >
<ButtonBase
disableRipple
component={Link}
onClick={() => dispatch(activeItem({ openItem: [defaultId] }))}
to={!to ? config.defaultPath : to}
sx={sx}
>
<Logo />
</ButtonBase>
disableRipple
component={Link}
onClick={() => dispatch(activeItem({ openItem: [defaultId] }))}
to={!to ? config.defaultPath : to}
sx={{
...sx,

/* ✅ WCAG 2.4.7 focus indicator */
'&:focus-visible': {
outline: '3px solid #0C489E',
outlineOffset: '2px',
borderRadius: '6px'
}
}}
>
<Logo />
</ButtonBase>
<span style={{ color: checkSysEnv()!=''?'red':'#0C489E'}} id="systemTitle">PNSPS</span>
</Stack>



+ 17
- 8
src/components/MobileLogo/index.js Voir le fichier

@@ -17,14 +17,23 @@ const LogoSection = ({ sx, to }) => {
const dispatch = useDispatch();
return (
<ButtonBase
disableRipple
component={Link}
onClick={() => dispatch(activeItem({ openItem: [defaultId] }))}
to={!to ? config.defaultPath : to}
sx={sx}
>
<Logo />
</ButtonBase>
disableRipple
component={Link}
onClick={() => dispatch(activeItem({ openItem: [defaultId] }))}
to={!to ? config.defaultPath : to}
sx={{
...sx,

/* WCAG 2.4.7 – visible keyboard focus */
'&:focus-visible': {
outline: '3px solid #0C489E',
outlineOffset: '2px',
borderRadius: '6px'
}
}}
>
<Logo />
</ButtonBase>
);
};



+ 19
- 9
src/layout/MainLayout/Header/HeaderContent/LocaleSelector.js Voir le fichier

@@ -47,16 +47,26 @@ const LocaleSelector = () => {
return (
<Box sx={{ flexShrink: 0, ml: 0.75 }}>
<IconButton
disableRipple
color="secondary"
sx={{ color: 'text.primary', bgcolor: open ? iconBackColorOpen : iconBackColor }}
aria-label="open profile"
ref={anchorRef}
aria-controls={open ? 'profile-grow' : undefined}
aria-haspopup="true"
onClick={handleToggle}
disableRipple
color="secondary"
sx={{
color: 'text.primary',
bgcolor: open ? iconBackColorOpen : iconBackColor,

/* ✅ WCAG 2.4.7 focus indicator */
'&:focus-visible': {
outline: '3px solid #0C489E',
outlineOffset: '2px',
borderRadius: '6px'
}
}}
aria-label="open profile"
ref={anchorRef}
aria-controls={open ? 'profile-grow' : undefined}
aria-haspopup="true"
onClick={handleToggle}
>
<LanguageIcon />
<LanguageIcon />
</IconButton>
<Popper
placement={matchesXs ? 'bottom' : 'bottom-end'}


+ 20
- 13
src/layout/MainLayout/Header/HeaderContent/MobileSection.js Voir le fichier

@@ -45,19 +45,26 @@ const MobileSection = () => {
<>
<Box sx={{ flexShrink: 0, ml: 0.75 }}>
<IconButton
component="span"
disableRipple
sx={{
bgcolor: open ? 'grey.300' : 'grey.100'
}}
ref={anchorRef}
aria-controls={open ? 'menu-list-grow' : undefined}
aria-haspopup="true"
onClick={handleToggle}
color="inherit"
>
<MoreOutlined />
</IconButton>
component="span"
disableRipple
sx={{
bgcolor: open ? 'grey.300' : 'grey.100',

/* WCAG 2.4.7 – visible keyboard focus */
'&:focus-visible': {
outline: '3px solid #0C489E',
outlineOffset: '2px',
borderRadius: '6px'
}
}}
ref={anchorRef}
aria-controls={open ? 'menu-list-grow' : undefined}
aria-haspopup="true"
onClick={handleToggle}
color="inherit"
>
<MoreOutlined />
</IconButton>
</Box>
<Popper
placement="bottom-end"


+ 15
- 5
src/layout/MainLayout/Header/HeaderContent/Notification.js Voir le fichier

@@ -71,17 +71,27 @@ const Notification = () => {
<IconButton
disableRipple
color="secondary"
sx={{ color: 'text.primary', bgcolor: open ? iconBackColorOpen : iconBackColor }}
sx={{
color: 'text.primary',
bgcolor: open ? iconBackColorOpen : iconBackColor,

/* ✅ WCAG 2.4.7 focus indicator */
'&:focus-visible': {
outline: '3px solid #0C489E',
outlineOffset: '2px',
borderRadius: '6px'
}
}}
aria-label="open profile"
ref={anchorRef}
aria-controls={open ? 'profile-grow' : undefined}
aria-haspopup="true"
onClick={handleToggle}
>
<Badge badgeContent={4} color="primary">
<BellOutlined />
</Badge>
</IconButton>
<Badge badgeContent={4} color="primary">
<BellOutlined />
</Badge>
</IconButton>
<Popper
placement={matchesXs ? 'bottom' : 'bottom-end'}
open={open}


Chargement…
Annuler
Enregistrer