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: '다운로드',
},
};