mirror of
https://github.com/tiennm99/blog.git
synced 2026-10-14 00:16:34 +00:00
feat(a11y): skip-link, focus rings, render hooks, giscus paint fix
Add skip-to-content link, enhance focus indicators, implement custom render hooks for links and images, fix giscus dark mode paint issue.
This commit is contained in:
1 parent
8b023f39bd
commit
dd88949e97
7 files changed
+62
-3
No files matched your search
@@ -1,5 +1,24 @@
|
||||
/* tsuki: components — post cards, post meta, terms, pagination, code copy */
|
||||
|
||||
/* a11y: visible focus + skip-link */
|
||||
:focus-visible {
|
||||
outline: 2px solid var(--tsuki-accent);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
.skip-link {
|
||||
position: absolute;
|
||||
inset-inline-start: var(--tsuki-space-3);
|
||||
inset-block-start: -3rem;
|
||||
z-index: 100;
|
||||
padding: var(--tsuki-space-2) var(--tsuki-space-4);
|
||||
background: var(--tsuki-bg);
|
||||
color: var(--tsuki-fg);
|
||||
border: 1px solid var(--tsuki-border);
|
||||
border-radius: var(--tsuki-radius);
|
||||
transition: var(--tsuki-transition);
|
||||
}
|
||||
.skip-link:focus { inset-block-start: var(--tsuki-space-3); text-decoration: none; }
|
||||
|
||||
/* post card */
|
||||
.post-card {
|
||||
padding-block: var(--tsuki-space-6);
|
||||
@@ -170,6 +189,19 @@ pre:hover .code-copy,
|
||||
.code-copy:focus-visible { opacity: 1; }
|
||||
.code-copy:hover { color: var(--tsuki-fg); }
|
||||
|
||||
/* related posts (single page) */
|
||||
.related-posts {
|
||||
margin-block-start: var(--tsuki-space-12);
|
||||
padding-block-start: var(--tsuki-space-6);
|
||||
border-block-start: 1px solid var(--tsuki-border);
|
||||
}
|
||||
.related-heading {
|
||||
font-size: var(--tsuki-fs-xl);
|
||||
margin: 0 0 var(--tsuki-space-4);
|
||||
}
|
||||
.related-list { list-style: none; padding: 0; margin: 0; display: grid; gap: 0; }
|
||||
.related-list .post-card { padding-block: var(--tsuki-space-4); }
|
||||
|
||||
/* heading anchor */
|
||||
.heading-anchor {
|
||||
margin-inline-end: var(--tsuki-space-2);
|
||||
|
||||
@@ -79,7 +79,6 @@
|
||||
border: 1px solid var(--tsuki-border);
|
||||
border-radius: var(--tsuki-radius-lg);
|
||||
transition: var(--tsuki-transition);
|
||||
view-transition-name: var(--tsuki-vt-name, none);
|
||||
}
|
||||
.project-card:hover {
|
||||
border-color: var(--tsuki-accent);
|
||||
|
||||
@@ -12,5 +12,16 @@ if (giscus) {
|
||||
"https://giscus.app"
|
||||
);
|
||||
};
|
||||
// Push current theme as soon as Giscus iframe is ready so first paint matches.
|
||||
// Self-remove after first valid Giscus message; later theme changes are caught by the MutationObserver below.
|
||||
let primed = false;
|
||||
const onFirstGiscusMessage = (e) => {
|
||||
if (primed) return;
|
||||
if (e.origin !== "https://giscus.app" || !e.data || !e.data.giscus) return;
|
||||
primed = true;
|
||||
window.removeEventListener("message", onFirstGiscusMessage);
|
||||
send();
|
||||
};
|
||||
window.addEventListener("message", onFirstGiscusMessage);
|
||||
new MutationObserver(send).observe(root, { attributes: true, attributeFilter: ["data-theme"] });
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{{- /* In-content images get loading="lazy" + decoding="async" by default. */ -}}
|
||||
<img src="{{ .Destination | safeURL }}" alt="{{ .Text }}" loading="lazy" decoding="async"
|
||||
{{- with .Title }} title="{{ . }}"{{ end -}}
|
||||
>
|
||||
{{- /**/ -}}
|
||||
@@ -0,0 +1,11 @@
|
||||
{{- /* External markdown links get rel="noopener noreferrer". No target="_blank" — UX choice. */ -}}
|
||||
{{- $external := or
|
||||
(strings.HasPrefix .Destination "http://")
|
||||
(strings.HasPrefix .Destination "https://")
|
||||
(strings.HasPrefix .Destination "//")
|
||||
-}}
|
||||
<a href="{{ .Destination | safeURL }}"
|
||||
{{- with .Title }} title="{{ . }}"{{ end -}}
|
||||
{{- if $external }} rel="noopener noreferrer"{{ end -}}
|
||||
>{{ .Text | safeHTML }}</a>
|
||||
{{- /**/ -}}
|
||||
@@ -1,6 +1,6 @@
|
||||
<header class="site-header">
|
||||
<a class="site-title" href="{{ "/" | relURL }}">
|
||||
{{- with site.Params.profile.name }}{{ . }}{{ else }}{{ site.Title }}{{ end -}}
|
||||
{{- with site.Data.profile }}{{ .name | default site.Title }}{{ else }}{{ site.Title }}{{ end -}}
|
||||
</a>
|
||||
{{ partial "nav.html" . }}
|
||||
<div class="site-header-actions">
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
{{ block "head_extra" . }}{{ end }}
|
||||
</head>
|
||||
<body class="{{ block "body_class" . }}{{ end }}">
|
||||
<a class="skip-link" href="#main">{{ i18n "skipToContent" | default "Đến nội dung chính" }}</a>
|
||||
{{ partial "header.html" . }}
|
||||
<main>
|
||||
<main id="main">
|
||||
{{ block "main" . }}{{ end }}
|
||||
</main>
|
||||
{{ partial "footer.html" . }}
|
||||
|
||||
Reference in new issue
Block a user