Commit 125576d
Changed files (12)
src
components
misc
search
widgets
SideToolBar
i18n
src/components/misc/CategoryBar.astro
@@ -15,7 +15,12 @@ const { categories, currentCategory } = Astro.props;
id="category-bar"
class="card border-base-300 bg-base-200/25 swup-transition-slide mb-4 w-full border"
>
- <div class="card-body flex flex-row items-center gap-2 overflow-auto px-2 py-3">
+ <nav
+ class="card-body flex flex-row items-center gap-2 overflow-auto px-2 py-3"
+ title={i18n(I18nKey.categories)}
+ aria-label={i18n(I18nKey.categories)}
+ role="navigation"
+ >
<a
href={`/`}
class:list={[
@@ -38,7 +43,7 @@ const { categories, currentCategory } = Astro.props;
</a>
))
}
- </div>
+ </nav>
</div>
<script>
src/components/search/Pagefind.vue
@@ -3,6 +3,8 @@ import type {
PagefindSearchResult,
PagefindSearchResults,
} from '@/types/PagefindSearchAPI.d.ts';
+import I18nKey from '@i18n/I18nKey';
+import { i18n } from '@i18n/translation';
import { type Ref, onMounted, ref } from 'vue';
const isLoading = ref(false);
@@ -107,6 +109,8 @@ defineExpose({
<slot></slot>
<div
class="search-result mt-4 flex h-fit max-h-[calc(60vh-8rem)] flex-col items-center gap-2 overflow-y-auto text-center"
+ :aria-label="i18n(I18nKey.searchResults)"
+ tabindex="-1"
>
<template v-if="isLoading">
<div v-for="i in 2" :key="i" class="w-full rounded-md p-2">
@@ -117,7 +121,7 @@ defineExpose({
<div class="skeleton mt-1 h-4 w-3/4"></div>
</div>
</template>
- <template v-else-if="noResults"> No results found </template>
+ <template v-else-if="noResults">{{ i18n(I18nKey.noSearchResults) }}</template>
<template v-else>
<a
v-for="result in searchResults"
src/components/widgets/SideToolBar/TocButton.vue
@@ -66,11 +66,15 @@ onUnmounted(() => {
class="btn btn-circle btn-secondary btn-sm"
@click="isOpen = !isOpen"
:title="i18n(I18nKey.toc)"
+ :aria-label="i18n(I18nKey.toc)"
+ :aria-expanded="isOpen"
+ :aria-controls="'stb-toc-wrapper'"
>
<slot name="icon" />
</button>
<div
ref="tocWrapper"
+ id="stb-toc-wrapper"
class="rounded-box absolute w-[calc(100vw-4rem)] -translate-x-1/2 -translate-y-1/2 max-w-72 backdrop-blur-md duration-300 text-base-content text-start"
:inert="!isOpen || isWideScreen"
:class="{
src/components/widgets/Pagination.astro
@@ -1,4 +1,6 @@
---
+import I18nKey from '@i18n/I18nKey';
+import { i18n } from '@i18n/translation';
import { Icon } from 'astro-icon/components';
import Button from './Button.astro';
@@ -43,11 +45,17 @@ else {
}
---
-<div id="pagination" class="flex w-full justify-between max-md:px-2">
+<nav id="pagination" class="flex w-full justify-between max-md:px-2">
<div>
{
current > 1 && (
- <Button id="prev-page-btn" class="btn-primary" href={getPageUrl(current - 1)}>
+ <Button
+ id="prev-page-btn"
+ class="btn-primary"
+ href={getPageUrl(current - 1)}
+ title={i18n(I18nKey.prevPage)}
+ aria-label={i18n(I18nKey.prevPage)}
+ >
<Icon name="material-symbols:chevron-left-rounded" class="my-1 text-2xl" />
</Button>
)
@@ -101,13 +109,19 @@ else {
<div>
{
current < total && (
- <Button id="next-page-btn" class="btn-primary" href={getPageUrl(current + 1)}>
+ <Button
+ id="next-page-btn"
+ class="btn-primary"
+ href={getPageUrl(current + 1)}
+ title={i18n(I18nKey.nextPage)}
+ aria-label={i18n(I18nKey.nextPage)}
+ >
<Icon name="material-symbols:chevron-right-rounded" class="my-1 text-2xl" />
</Button>
)
}
</div>
-</div>
+</nav>
<style>
/* hide arrows from number input */
src/components/Comment.astro
@@ -4,9 +4,11 @@ import Artalk from '@components/comment/Artalk.astro';
import Giscus from '@components/comment/Giscus.astro';
import Twikoo from '@components/comment/Twikoo.astro';
import Waline from '@components/comment/Waline.astro';
+import I18nKey from '@i18n/I18nKey';
+import { i18n } from '@i18n/translation';
---
-<div id="page-comment">
+<div id="page-comment" title={i18n(I18nKey.comments)} aria-label={i18n(I18nKey.comments)}>
{
(() => {
switch (commentConfig.provider) {
src/components/Search.astro
@@ -9,7 +9,11 @@ import Pagefind from './search/Pagefind.vue';
<dialog id="search_modal" class="modal">
<div class="modal-box">
<form method="dialog">
- <button class="btn btn-circle btn-ghost btn-sm absolute top-2 right-2">✕</button>
+ <button
+ class="btn btn-circle btn-ghost btn-sm absolute top-2 right-2"
+ title={i18n(I18nKey.close)}
+ aria-label={i18n(I18nKey.close)}>✕</button
+ >
</form>
<div class="w-full p-4">
{
@@ -21,7 +25,11 @@ import Pagefind from './search/Pagefind.vue';
<label class="input input-bordered flex w-full items-center gap-2">
<input
id="search-input"
- type="text"
+ type="search"
+ spellcheck="false"
+ autocorrect="off"
+ autocomplete="off"
+ autocapitalize="off"
class="grow"
placeholder={i18n(I18nKey.search)}
/>
@@ -60,6 +68,6 @@ import Pagefind from './search/Pagefind.vue';
</div>
</div>
<form method="dialog" class="modal-backdrop">
- <button>close</button>
+ <button>{i18n(I18nKey.close)}</button>
</form>
</dialog>
src/components/SideToolBar.astro
@@ -8,7 +8,11 @@ import DarkModeButton from './widgets/DarkModeButton.astro';
import TocButton from './widgets/SideToolBar/TocButton.vue';
---
-<div id="side-toolbar" class="fixed right-0 bottom-10 z-30 grid grid-cols-1 gap-2">
+<div
+ id="side-toolbar"
+ class="fixed right-0 bottom-10 z-30 grid grid-cols-1 gap-2"
+ aria-label={i18n(I18nKey.toolBar)}
+>
<div
id="stb-hide"
class="grid translate-x-full grid-cols-1 gap-2 pr-4 duration-500 ease-in-out"
@@ -19,25 +23,30 @@ import TocButton from './widgets/SideToolBar/TocButton.vue';
const { icon, text } = item;
if ('href' in item)
return (
- <Button href={item.href} target={item.blank ? '_blank' : undefined} title={text}>
+ <Button
+ href={item.href}
+ target={item.blank ? '_blank' : undefined}
+ title={text}
+ aria-label={text}
+ >
<Icon name={icon} slot="icon" />
</Button>
);
if ('onclick' in item) {
if (typeof item.onclick === 'string')
return (
- <Button onclick={item.onclick}>
+ <Button onclick={item.onclick} title={text} aria-label={text}>
<Icon name={icon} slot="icon" />
</Button>
);
return (
- <Button id={`stb-${item.onclick!.id}`} title={text}>
+ <Button id={`stb-${item.onclick!.id}`} title={text} aria-label={text}>
<Icon name={icon} slot="icon" />
</Button>
);
}
return (
- <Button title={text}>
+ <Button title={text} aria-label={text}>
<Icon name={icon} slot="icon" />
</Button>
);
@@ -68,6 +77,7 @@ import TocButton from './widgets/SideToolBar/TocButton.vue';
<Button id="stb-back-to-top" class="group btn-circle btn-secondary btn-sm">
<span
id="stb-read-percentage"
+ aria-label={i18n(I18nKey.toolBarReadingPercentage)}
class="absolute text-sm opacity-0 duration-300 group-hover:opacity-0">0</span
>
<Icon
src/i18n/langs/en.ts
@@ -9,6 +9,11 @@ export const en: Translation = {
[Key.links]: 'Links',
[Key.time]: 'Time',
[Key.menu]: 'Menu',
+ [Key.close]: 'Close',
+ [Key.open]: 'Open',
+
+ [Key.prevPage]: 'Previous Page',
+ [Key.nextPage]: 'Next Page',
[Key.tags]: 'Tags',
[Key.categories]: 'Categories',
@@ -40,8 +45,14 @@ export const en: Translation = {
[Key.categoryCount]: 'category',
[Key.categoriesCount]: 'categories',
+ [Key.searchResults]: 'Search Results',
+ [Key.noSearchResults]: 'No Results Found',
+
[Key.toc]: 'Table of Content',
+ [Key.toolBar]: 'Tool Bar',
+ [Key.toolBarReadingPercentage]: 'Reading Percentage',
+
[Key.themeToggle]: 'Toggle Theme',
[Key.lightMode]: 'Light',
[Key.darkMode]: 'Dark',
src/i18n/langs/zh_CN.ts
@@ -9,6 +9,11 @@ export const zh_CN: Translation = {
[Key.links]: '友链',
[Key.time]: '时间',
[Key.menu]: '菜单',
+ [Key.close]: '关闭',
+ [Key.open]: '打开',
+
+ [Key.prevPage]: '上一页',
+ [Key.nextPage]: '下一页',
[Key.tags]: '标签',
[Key.categories]: '分类',
@@ -40,8 +45,14 @@ export const zh_CN: Translation = {
[Key.categoryCount]: '个分类',
[Key.categoriesCount]: '个分类',
+ [Key.searchResults]: '搜索结果',
+ [Key.noSearchResults]: '没有找到结果',
+
[Key.toc]: '目录',
+ [Key.toolBar]: '工具栏',
+ [Key.toolBarReadingPercentage]: '阅读进度',
+
[Key.themeToggle]: '主题切换',
[Key.lightMode]: '亮色',
[Key.darkMode]: '暗色',
src/i18n/langs/zh_TW.ts
@@ -9,6 +9,11 @@ export const zh_TW: Translation = {
[Key.links]: '連結',
[Key.time]: '時間',
[Key.menu]: '選單',
+ [Key.close]: '關閉',
+ [Key.open]: '開啟',
+
+ [Key.prevPage]: '上一頁',
+ [Key.nextPage]: '下一頁',
[Key.tags]: '標籤',
[Key.categories]: '分類',
@@ -40,8 +45,14 @@ export const zh_TW: Translation = {
[Key.categoryCount]: '個分類',
[Key.categoriesCount]: '個分類',
+ [Key.searchResults]: '搜尋結果',
+ [Key.noSearchResults]: '沒有找到結果',
+
[Key.toc]: '目錄',
+ [Key.toolBar]: '工具列',
+ [Key.toolBarReadingPercentage]: '閱讀進度',
+
[Key.themeToggle]: '主題切換',
[Key.lightMode]: '亮色',
[Key.darkMode]: '暗色',
src/i18n/I18nKey.ts
@@ -6,6 +6,11 @@ enum I18nKey {
links = 'links',
time = 'time',
menu = 'menu',
+ close = 'close',
+ open = 'open',
+
+ prevPage = 'prevPage',
+ nextPage = 'nextPage',
tags = 'tags',
categories = 'categories',
@@ -37,8 +42,14 @@ enum I18nKey {
categoryCount = 'categoryCount',
categoriesCount = 'categoriesCount',
+ searchResults = 'searchResults',
+ noSearchResults = 'noSearchResults',
+
toc = 'toc',
+ toolBar = 'toolBar',
+ toolBarReadingPercentage = 'toolBarReadingPercentage',
+
themeToggle = 'themeToggle',
lightMode = 'lightMode',
darkMode = 'darkMode',