Add Skip Links Component

This commit is contained in:
copecone committed 2026-05-02 18:04:10 +09:00
1 parent 713f0ef75b
commit 1a49cd132b
5 files changed
+75 -7

No files matched your search

+4
View File
@@ -1,3 +1,7 @@
<skip-links ngSkipHydration>
<a href="#main-content">{{ translation.common.skipToContent }}</a>
</skip-links>
<header-menu></header-menu> <header-menu></header-menu>
<main id="main-content"> <main id="main-content">
+10 -7
View File
@@ -4,25 +4,28 @@ import { HeaderMenu } from './features/header-menu/header-menu';
import { PopupService } from './services/popup.service'; import { PopupService } from './services/popup.service';
import { SettingsService } from './services/settings.service'; import { SettingsService } from './services/settings.service';
import { NgComponentOutlet, isPlatformBrowser, isPlatformServer, DOCUMENT } from '@angular/common'; import { NgComponentOutlet, isPlatformBrowser, isPlatformServer, DOCUMENT } from '@angular/common';
import { SkipLinks } from './components/skip-links/skip-links';
import { TranslationService } from './services/translation.service';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
imports: [RouterOutlet, HeaderMenu, NgComponentOutlet], imports: [RouterOutlet, HeaderMenu, NgComponentOutlet, SkipLinks],
templateUrl: './app.html', templateUrl: './app.html',
styleUrl: './app.scss', styleUrl: './app.scss',
}) })
export class App { export class App {
protected popupService = inject(PopupService); protected popupService = inject(PopupService);
protected settingsService = inject(SettingsService); protected settingsService = inject(SettingsService);
private platformId = inject(PLATFORM_ID); protected translation = inject(TranslationService).translation;
private platformID = inject(PLATFORM_ID);
private document = inject(DOCUMENT); private document = inject(DOCUMENT);
private rootHtmlElement!: HTMLElement; private rootHtmlElement!: HTMLElement;
constructor() { constructor() {
if (isPlatformServer(this.platformId)) { if (isPlatformServer(this.platformID)) {
this.rootHtmlElement = this.document.documentElement; this.rootHtmlElement = this.document.documentElement;
} else if (isPlatformBrowser(this.platformId)) { } else if (isPlatformBrowser(this.platformID)) {
this.rootHtmlElement = document.documentElement; this.rootHtmlElement = document.documentElement;
} }
@@ -38,9 +41,9 @@ export class App {
const lang = this.settingsService.language(); const lang = this.settingsService.language();
const langMap: Record<string, string> = { const langMap: Record<string, string> = {
'KR': 'ko', KR: 'ko',
'JP': 'ja', JP: 'ja',
'EN': 'en' EN: 'en',
}; };
this.rootHtmlElement.lang = langMap[lang] || 'en'; this.rootHtmlElement.lang = langMap[lang] || 'en';
@@ -0,0 +1 @@
<ng-content></ng-content>
@@ -0,0 +1,48 @@
$default_animation_duration: 0.4s;
:host {
display: flex;
position: fixed;
align-items: center;
justify-content: center;
top: -140px;
left: 20px;
--animation-duration: calc(#{$default_animation_duration} * var(--motion-duration-multiplier));
background: light-dark(rgba(255, 255, 255, 0.9), rgba(15, 15, 15, 0.9));
padding: calc(40px + 12px) 24px 12px;
z-index: 20000;
transition: top var(--animation-duration) cubic-bezier(0.18, 0.89, 0.32, 1.28);
border-radius: 0 0 12px 12px;
box-shadow: 0 0 40px oklch(0 0 0 / 15%);
vertical-align: middle;
font-weight: 700;
font-size: 18px;
height: 40px;
&:focus-within {
top: -40px;
outline: 2px solid var(--selection-outline-color);
}
::ng-deep a {
color: light-dark(black, white);
text-decoration: none;
outline: none;
width: 0;
opacity: 0;
overflow: hidden;
&:focus {
width: unset;
opacity: 1;
}
}
}
@@ -0,0 +1,12 @@
import { Component } from '@angular/core';
@Component({
selector: 'skip-links',
imports: [],
templateUrl: './skip-links.html',
styleUrl: './skip-links.scss',
host: {
'tabindex': '-1',
}
})
export class SkipLinks {}