diff --git a/frontend/src/app/[id]/page.module.scss b/frontend/src/app/[id]/page.module.scss index a903f86..f5938be 100644 --- a/frontend/src/app/[id]/page.module.scss +++ b/frontend/src/app/[id]/page.module.scss @@ -52,6 +52,11 @@ border-top-left-radius: 5px; border-top-right-radius: 5px; cursor: pointer; + + &:focus-visible { + outline: var(--focus-ring); + outline-offset: 2px; + } } .tabSelected { diff --git a/frontend/src/app/[id]/page.tsx b/frontend/src/app/[id]/page.tsx index 6e40b37..34d01a8 100644 --- a/frontend/src/app/[id]/page.tsx +++ b/frontend/src/app/[id]/page.tsx @@ -20,7 +20,6 @@ export const generateMetadata = async ({ params }: PageProps): Promise const event = await getEvent(params.id).catch(() => undefined) const { t } = await useTranslation('event') - // TODO: More metadata return { title: event?.name ?? t('error.title'), } diff --git a/frontend/src/app/global.css b/frontend/src/app/global.css index eb2e31f..4cd66c9 100644 --- a/frontend/src/app/global.css +++ b/frontend/src/app/global.css @@ -89,6 +89,7 @@ body { background: var(--background); color: var(--text); font-weight: var(--font-weight); + --focus-ring: 2px solid var(--secondary); } .light { @@ -131,6 +132,11 @@ body { a { color: var(--primary); + border-radius: .2em; +} +a:focus-visible { + outline: var(--focus-ring); + outline-offset: 2px; } *::-webkit-scrollbar { diff --git a/frontend/src/components/AvailabilityViewer/AvailabilityViewer.module.scss b/frontend/src/components/AvailabilityViewer/AvailabilityViewer.module.scss index 664af46..ba1d875 100644 --- a/frontend/src/components/AvailabilityViewer/AvailabilityViewer.module.scss +++ b/frontend/src/components/AvailabilityViewer/AvailabilityViewer.module.scss @@ -146,6 +146,11 @@ cursor: pointer; padding: 2px 8px; user-select: none; + + &:focus-visible { + outline: var(--focus-ring); + outline-offset: 2px; + } } .personSelected { diff --git a/frontend/src/components/Button/Button.module.scss b/frontend/src/components/Button/Button.module.scss index 1c1d4ea..8801537 100644 --- a/frontend/src/components/Button/Button.module.scss +++ b/frontend/src/components/Button/Button.module.scss @@ -1,50 +1,57 @@ .button { - position: relative; - display: inline-flex; - align-items: center; - justify-content: center; - text-align: center; cursor: pointer; border: 0; text-decoration: none; font: inherit; - box-sizing: border-box; - background: var(--override-surface-color, var(--primary)); - color: var(--override-text-color, var(--background)); - font-weight: 600; - transition: transform 150ms cubic-bezier(0, 0, 0.58, 1); + padding: 0; + margin: 0; + background: none; border-radius: 3px; - padding: .6em 1.5em; - transform-style: preserve-3d; - margin-bottom: 5px; - & svg, & img { - height: 1.2em; - width: 1.2em; - margin-right: .5em; - } - - &::before { - content: ''; - position: absolute; - height: 100%; - width: 100%; - top: 0; - left: 0; - background: var(--override-shadow-color, var(--shadow)); + & > div { + position: relative; + display: inline-flex; + align-items: center; + justify-content: center; + text-align: center; + box-sizing: border-box; + background: var(--override-surface-color, var(--primary)); + color: var(--override-text-color, var(--background)); + font-weight: 600; + transition: transform 150ms cubic-bezier(0, 0, 0.58, 1); border-radius: inherit; - transform: translate3d(0, 5px, -1em); - transition: transform 150ms cubic-bezier(0, 0, 0.58, 1), box-shadow 150ms cubic-bezier(0, 0, 0.58, 1); + padding: .6em 1.5em; + transform-style: preserve-3d; + margin-bottom: 5px; + + & svg, & img { + height: 1.2em; + width: 1.2em; + margin-right: .5em; + } + + &::before { + content: ''; + position: absolute; + height: 100%; + width: 100%; + top: 0; + left: 0; + background: var(--override-shadow-color, var(--shadow)); + border-radius: inherit; + transform: translate3d(0, 5px, -1em); + transition: transform 150ms cubic-bezier(0, 0, 0.58, 1), box-shadow 150ms cubic-bezier(0, 0, 0.58, 1); + } } - &:hover, &:focus { + &:hover > div, &:focus > div { transform: translate(0, 1px); &::before { transform: translate3d(0, 4px, -1em); } } - &:active { + &:active > div { transform: translate(0, 5px); &::before { transform: translate3d(0, 0, -1em); @@ -52,13 +59,18 @@ } @media print { - &::before { + & > div::before { display: none; } } + + &:focus-visible { + outline: var(--focus-ring); + outline-offset: 2px; + } } -.iconButton { +.iconButton > div { height: 30px; width: 30px; padding: 0; @@ -68,14 +80,17 @@ } } -.small { +.small > div { padding: .4em 1.3em; } .loading { - color: transparent; cursor: wait; + & > div { + color: transparent; + } + & img { opacity: 0; } @@ -89,7 +104,7 @@ } } - &::after { + & > div::after { content: ''; position: absolute; top: calc(50% - 12px); @@ -103,7 +118,7 @@ } @media (prefers-reduced-motion: reduce) { - &::after { + & > div::after { content: 'loading...'; color: var(--override-text-color, var(--background)); animation: none; @@ -122,19 +137,21 @@ } .secondary { - background: transparent; - border: 1px solid var(--override-surface-color, var(--secondary)); - color: var(--override-surface-color, var(--secondary)); - margin-bottom: 0; + & > div { + background: transparent; + border: 1px solid var(--override-surface-color, var(--secondary)); + color: var(--override-surface-color, var(--secondary)); + margin-bottom: 0; - &::before { + @media print { + box-shadow: 0 4px 0 0 var(--override-shadow-color, var(--secondary)); + } + } + + & > div::before { content: none; } - &:hover, &:active, &:focus { + &:hover > div, &:active > div, &:focus > div { transform: none; } - - @media print { - box-shadow: 0 4px 0 0 var(--override-shadow-color, var(--secondary)); - } } diff --git a/frontend/src/components/Button/Button.tsx b/frontend/src/components/Button/Button.tsx index 7250954..0bff039 100644 --- a/frontend/src/components/Button/Button.tsx +++ b/frontend/src/components/Button/Button.tsx @@ -44,7 +44,7 @@ const Button: React.FC = ({ ...shadowColor && { '--override-shadow-color': shadowColor }, ...style, }, - children: <>{icon}{children}, + children:
{icon}{children}
, ...props, } diff --git a/frontend/src/components/CalendarField/components/Month/Month.module.scss b/frontend/src/components/CalendarField/components/Month/Month.module.scss index 82b964f..1443824 100644 --- a/frontend/src/components/CalendarField/components/Month/Month.module.scss +++ b/frontend/src/components/CalendarField/components/Month/Month.module.scss @@ -63,6 +63,13 @@ padding: 10px 0; user-select: none; touch-action: none; + position: relative; + + &:focus-visible { + outline: var(--focus-ring); + outline-offset: 2px; + z-index: 1; + } @media (prefers-reduced-motion: reduce) { transition: none; diff --git a/frontend/src/components/SelectField/SelectField.module.scss b/frontend/src/components/SelectField/SelectField.module.scss index 996c05b..3225e34 100644 --- a/frontend/src/components/SelectField/SelectField.module.scss +++ b/frontend/src/components/SelectField/SelectField.module.scss @@ -8,16 +8,14 @@ border: 1px solid var(--primary); box-shadow: inset 0 0 0 0 var(--primary); border-radius: 3px; - outline: none; - transition: border-color .15s, box-shadow .15s; appearance: none; background-image: url('data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%20100%20100%22%3E%3CforeignObject%20width%3D%22100px%22%20height%3D%22100px%22%3E%3Cdiv%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxhtml%22%20style%3D%22color%3A%23F79E00%3Bfont-size%3A60px%3Bdisplay%3Aflex%3Balign-items%3Acenter%3Bjustify-content%3Acenter%3Bheight%3A100%25%3Bwidth%3A100%25%3B%22%3E%E2%96%BC%3C%2Fdiv%3E%3C%2FforeignObject%3E%3C%2Fsvg%3E'); background-repeat: no-repeat; background-position: right 10px center; background-size: 1em; - &:focus { - border: 1px solid var(--secondary); - box-shadow: inset 0 -3px 0 0 var(--secondary); + &:focus-visible { + outline: var(--focus-ring); + outline-offset: 2px; } } diff --git a/frontend/src/components/Settings/Settings.module.scss b/frontend/src/components/Settings/Settings.module.scss index 30eb3d9..b81e75a 100644 --- a/frontend/src/components/Settings/Settings.module.scss +++ b/frontend/src/components/Settings/Settings.module.scss @@ -17,6 +17,10 @@ transition: transform .15s; padding: 0; + &:focus-visible { + outline: var(--focus-ring); + } + @media (prefers-reduced-motion: reduce) { transition: none; } diff --git a/frontend/src/components/TextField/TextField.module.scss b/frontend/src/components/TextField/TextField.module.scss index 965c5cc..e8659c5 100644 --- a/frontend/src/components/TextField/TextField.module.scss +++ b/frontend/src/components/TextField/TextField.module.scss @@ -9,11 +9,9 @@ box-shadow: inset 0 0 0 0 var(--primary); border-radius: 3px; font-size: 18px; - outline: none; - transition: border-color .15s, box-shadow .15s; - &:focus { - border: 1px solid var(--secondary); - box-shadow: inset 0 -3px 0 0 var(--secondary); + &:focus-visible { + outline: var(--focus-ring); + outline-offset: 2px; } } diff --git a/frontend/src/components/TimeRangeField/TimeRangeField.module.scss b/frontend/src/components/TimeRangeField/TimeRangeField.module.scss index 3e344d5..0400457 100644 --- a/frontend/src/components/TimeRangeField/TimeRangeField.module.scss +++ b/frontend/src/components/TimeRangeField/TimeRangeField.module.scss @@ -48,6 +48,11 @@ white-space: nowrap; padding-inline: var(--extra-padding); } + + &:focus-visible { + outline: var(--focus-ring); + outline-offset: 2px; + } } .selected { diff --git a/frontend/src/components/ToggleField/ToggleField.module.scss b/frontend/src/components/ToggleField/ToggleField.module.scss index bbc2619..1c5d25e 100644 --- a/frontend/src/components/ToggleField/ToggleField.module.scss +++ b/frontend/src/components/ToggleField/ToggleField.module.scss @@ -1,23 +1,15 @@ .toggleContainer { display: flex; - border: 1px solid var(--primary); border-radius: 3px; - overflow: hidden; - --focus-color: var(--primary); - transition: border .15s; - - &:focus-within { - --focus-color: var(--secondary); - border: 1px solid var(--focus-color); - & label { - box-shadow: inset 0 -3px 0 0 var(--focus-color); - } - } & > div:first-of-type label { + border-inline-start: 1px solid var(--primary); border-end-start-radius: 2px; + border-start-start-radius: 2px; } & > div:last-of-type label { + border-inline-end: 1px solid var(--primary); + border-start-end-radius: 2px; border-end-end-radius: 2px; } } @@ -38,7 +30,11 @@ &:checked + label { color: var(--background); - background-color: var(--focus-color); + background-color: var(--primary); + } + &:focus-visible + label { + outline: var(--focus-ring); + outline-offset: 2px; } } @@ -52,5 +48,5 @@ box-sizing: border-box; align-items: center; justify-content: center; - transition: box-shadow .15s, background-color .15s; + border-block: 1px solid var(--primary); } diff --git a/frontend/src/components/Video/Video.module.scss b/frontend/src/components/Video/Video.module.scss index b8423de..5f06936 100644 --- a/frontend/src/components/Video/Video.module.scss +++ b/frontend/src/components/Video/Video.module.scss @@ -20,6 +20,7 @@ max-width: 400px; margin: 0 auto; transition: transform .15s; + border-radius: 10px; &:hover, &:focus { transform: translateY(-2px); @@ -31,7 +32,7 @@ img { width: 100%; display: block; - border-radius: 10px; + border-radius: inherit; background-color: #CCC; } span {