diff --git a/src/app/app.html b/src/app/app.html index be2cdf4..259bb58 100644 --- a/src/app/app.html +++ b/src/app/app.html @@ -1,10 +1,10 @@ - {{ translation.common.skipToContent }} + -
+
diff --git a/src/app/app.scss b/src/app/app.scss index e69de29..475477e 100644 --- a/src/app/app.scss +++ b/src/app/app.scss @@ -0,0 +1,3 @@ +main:focus-visible { + outline: none; +} diff --git a/src/app/app.ts b/src/app/app.ts index 0f2e228..03de666 100644 --- a/src/app/app.ts +++ b/src/app/app.ts @@ -1,4 +1,4 @@ -import { Component, inject, effect, PLATFORM_ID } from '@angular/core'; +import { Component, inject, effect, PLATFORM_ID, ElementRef, viewChild } from '@angular/core'; import { RouterOutlet } from '@angular/router'; import { HeaderMenu } from './features/header-menu/header-menu'; import { PopupService } from './services/popup.service'; @@ -19,6 +19,8 @@ export class App { protected translation = inject(TranslationService).translation; private platformID = inject(PLATFORM_ID); + private contentElement = viewChild>("content"); + private document = inject(DOCUMENT); private rootHtmlElement!: HTMLElement; @@ -50,4 +52,11 @@ export class App { const reduceMotion = this.settingsService.reduceAnimation(); this.rootHtmlElement.classList.toggle('reduce-motion', reduceMotion); } + + skipToContent() { + this.contentElement()!.nativeElement.tabIndex = 0; + this.contentElement()!.nativeElement.focus(); + + this.contentElement()!.nativeElement.tabIndex = -1; + } } diff --git a/src/app/components/level-card/level-card.html b/src/app/components/level-card/level-card.html index 1037c30..18b995f 100644 --- a/src/app/components/level-card/level-card.html +++ b/src/app/components/level-card/level-card.html @@ -13,10 +13,10 @@
- -
diff --git a/src/app/components/level-card/level-card.scss b/src/app/components/level-card/level-card.scss index 2b3a404..7d009a1 100644 --- a/src/app/components/level-card/level-card.scss +++ b/src/app/components/level-card/level-card.scss @@ -21,14 +21,17 @@ $default_animation_duration: 0.2s; outline: light-dark(oklch(0 0 0 / 20%), oklch(1 0 0 / 20%)) 2px solid; overflow: hidden; + &:focus-visible { + outline-offset: 0; + outline: 2px solid var(--selection-outline-color); + } + section.information { width: calc(100% - 64px); padding: 12px; box-sizing: border-box; flex-shrink: 0; - border-radius: 8px; - z-index: 1; background-color: light-dark(white, black); @@ -103,7 +106,7 @@ $default_animation_duration: 0.2s; flex-shrink: 0; flex-grow: 1; - margin-left: -80px; + margin-left: 0; button { display: flex; @@ -127,12 +130,24 @@ $default_animation_duration: 0.2s; --hover-state: 1; } + &:focus-visible { + outline-offset: -2px; + } + div.button-icon { width: 40px; height: 40px; margin-right: 12px; user-select: none; } + + &:first-child { + border-top-right-radius: 8px; + } + + &:last-child { + border-bottom-right-radius: 8px; + } } } } diff --git a/src/app/components/level-card/level-card.ts b/src/app/components/level-card/level-card.ts index b72d561..0d59a73 100644 --- a/src/app/components/level-card/level-card.ts +++ b/src/app/components/level-card/level-card.ts @@ -1,15 +1,21 @@ -import { Component, computed, input } from '@angular/core'; +import { Component, computed, inject, input } from '@angular/core'; +import { TranslationService } from '../../services/translation.service'; @Component({ selector: 'level-card', imports: [], templateUrl: './level-card.html', styleUrl: './level-card.scss', + host: { + tabindex: '0', + }, }) export class LevelCard { - artist = input.required() - trackName = input.required() + protected translation = inject(TranslationService).translation; + + artist = input.required(); + trackName = input.required(); creator = input([]); - creatorString = computed(() => this.creator().join(" & ")); + creatorString = computed(() => this.creator().join(' & ')); } diff --git a/src/app/components/skip-links/skip-links.scss b/src/app/components/skip-links/skip-links.scss index b768a59..b5d7bad 100644 --- a/src/app/components/skip-links/skip-links.scss +++ b/src/app/components/skip-links/skip-links.scss @@ -30,11 +30,19 @@ $default_animation_duration: 0.4s; outline: 2px solid var(--selection-outline-color); } - ::ng-deep a { + ::ng-deep * { + appearance: none; color: light-dark(black, white); text-decoration: none; + background: none; + font: inherit; + border: none; outline: none; + min-width: unset; + min-height: unset; + padding: 0; + margin: 0; width: 0; opacity: 0; diff --git a/src/app/i18n/en.ts b/src/app/i18n/en.ts index a80962f..502f19e 100644 --- a/src/app/i18n/en.ts +++ b/src/app/i18n/en.ts @@ -22,6 +22,8 @@ export const EN = { close: 'Close', save: 'Save', skipToContent: 'Skip to main content', + preview: 'Soundtrack Preview', + download: 'Download', }, }; diff --git a/src/app/i18n/jp.ts b/src/app/i18n/jp.ts index 27fdd27..fe660af 100644 --- a/src/app/i18n/jp.ts +++ b/src/app/i18n/jp.ts @@ -24,5 +24,7 @@ export const JP: Translation = { close: '閉じる', save: '保存', skipToContent: '本文へスキップ', + preview: '楽曲プレビュー', + download: 'ダウンロード', }, }; diff --git a/src/app/i18n/kr.ts b/src/app/i18n/kr.ts index 0e01afb..56ae8c3 100644 --- a/src/app/i18n/kr.ts +++ b/src/app/i18n/kr.ts @@ -24,5 +24,7 @@ export const KR: Translation = { close: '닫기', save: '저장', skipToContent: '본문으로 건너뛰기', + preview: '곡 프리뷰', + download: '다운로드', }, };