a11y: allow access to folders' popup menu button for keyboard-users

Massimo Melina committed Mar 18, 2024 at 14:46 UTC d6ef17bc6a69b63b967af286deb22762376bf220
4 files changed +14 -16
admin/src/index.scss
+1 -1
@@ -1,4 +1,4 @@
1 -@use '../../shared/main';
1 +@import '../../shared/main';
2
3 :root {
4 height: 100dvh;
frontend/src/BrowseFiles.ts
+2 -2
@@ -5,7 +5,7 @@ import { createElement as h, Fragment, memo, MouseEvent, useCallback, useEffect,
5 useId} from 'react'
6 import { useMediaQuery, useWindowSize } from 'usehooks-ts'
7 import { domOn, formatBytes, ErrorMsg, hIcon, onlyTruthy, noAriaTitle, prefix, isMac } from './misc'
8 -import { Checkbox, CustomCode, Spinner } from './components'
8 +import { Checkbox, CustomCode, iconBtn, Spinner } from './components'
9 import { Head } from './Head'
10 import { DirEntry, state, useSnapState } from './state'
11 import { alertDialog } from './dialog'
@@ -242,7 +242,7 @@ const Entry = memo(({ entry, midnight, separator }: EntryProps) => {
242 entry.comment && h('div', { className: 'entry-comment' }, entry.comment),
243 h('div', { className: 'entry-panel' },
244 h(EntryDetails, { entry, midnight }),
245 - showingButton && h('button', { className: 'file-menu-button', onClick: fileMenu }, hIcon('menu')),
245 + showingButton && iconBtn('menu', fileMenu, { className: 'file-menu-button' }),
246 ),
247 h('div'),
248 )
frontend/src/components.ts
+3 -5
@@ -87,15 +87,13 @@ export function CustomCode({ name, props, ifEmpty }: { name: string, props?: any
87 return children.length || !ifEmpty ? h(Fragment, {}, children) : h(ifEmpty)
88 }
89
90 -interface IconBtnOptions extends ButtonHTMLAttributes<any> { small?: boolean, style?: any, title?: string }
91 -export function iconBtn(icon: string, onClick: MouseEventHandler, { title, small=true, style={}, ...props }: IconBtnOptions={}) {
90 +interface IconBtnOptions extends ButtonHTMLAttributes<any> { style?: any, title?: string }
91 +export function iconBtn(icon: string, onClick: MouseEventHandler, { title, ...props }: IconBtnOptions={}) {
92 return h('button', {
93 title: title ?? t(_.capitalize(icon)),
94 onClick,
95 ...props,
96 - ...small && {
97 - style: { padding: '.1em', width: 35, height: 30, ...style }
98 - }
96 + className: 'icon-button',
97 }, icon.length > 1 ? hIcon(icon) : icon )
98 }
99
frontend/src/index.scss
+8 -8
@@ -1,4 +1,4 @@
1 -@use '../../shared/main';
1 +@import '../../shared/main';
2
3 :root {
4 height: 100dvh; // workarounded chrome109-mobile's problem with sticky-bottom bar moving when scrolling
@@ -159,10 +159,9 @@ input, select, ul a {
159 }
160
161 .icon-button {
162 - font-size: 0.7em;
163 - padding: 0.2em 0.4em;
164 - margin-left: 0.4em;
165 - vertical-align: bottom;
162 + padding: .1em;
163 + font-size: 104%; height: 1.8em; // same height as text buttons (30px)
164 + width: 2em;
165 }
166
167 .error-msg {
@@ -291,7 +290,7 @@ ul.dir {
290 .popup-menu-button { display: none }
291 }
292 @media (hover: hover) {
294 - &:not(:hover) .popup-menu-button { display: none; }
293 + &:not(:hover):not(:focus,:focus-within) .popup-menu-button { opacity: .001; } // use opacity, as jaws is not setting :focus
294 &:hover { padding: 1em; margin: -1em; // add margin to avoid leaving the hover unintentionally. Using this on @media(hover:none) will result in some taps to be missed. It happened on a long folder with no spaces in the name to wrap.
295 .popup-menu-button { z-index: 1} // without this, attempting to hover from the name to the menu-button will easily lose the :hover if a comment is present
296 }
@@ -321,9 +320,10 @@ ul.dir {
320 padding-top: 0.3em;
321 display: flex;
322 align-items: center;
324 - .file-menu-button {
325 - @extend .icon-button;
323 + .icon-button {
324 margin: -3px 0 -3px 0.4em;
325 + font-size: 0.7em;
326 + width: 2.4em;
327 }
328 .entry-details {
329 font-size: 90%;