Mobile-first layout with breakpoints at 48rem (tablet) and 64rem (desktop): stacked nav on phones, progressive column counts for the article grid and footer, scrollable markdown tables, larger tap targets on nav links.
81 lines
1.9 KiB
Vue
81 lines
1.9 KiB
Vue
<script setup lang="ts">
|
|
const { locale, locales, t } = useI18n()
|
|
const switchLocalePath = useSwitchLocalePath()
|
|
const router = useRouter()
|
|
|
|
/**
|
|
* A native select: it gets keyboard support, the platform picker on mobile and
|
|
* correct labelling for free, which a hand-built dropdown would have to rebuild.
|
|
*/
|
|
function onChange(event: Event) {
|
|
const code = (event.target as HTMLSelectElement).value as typeof locale.value
|
|
const path = switchLocalePath(code)
|
|
if (path) router.push(path)
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="switcher">
|
|
<label class="visually-hidden" for="locale-select">{{ t('site.languageLabel') }}</label>
|
|
<select id="locale-select" :value="locale" @change="onChange">
|
|
<option v-for="option in locales" :key="option.code" :value="option.code">
|
|
{{ option.name }}
|
|
</option>
|
|
</select>
|
|
<span class="arrow" aria-hidden="true">▾</span>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.switcher {
|
|
position: relative;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
}
|
|
|
|
select {
|
|
appearance: none;
|
|
padding: 0.4rem 1.7rem 0.4rem 0.7rem;
|
|
border: 1px solid var(--color-border);
|
|
border-radius: 0;
|
|
background: transparent;
|
|
color: var(--color-body);
|
|
font: inherit;
|
|
/* Safari on iOS zooms the page when a control smaller than 16px is tapped,
|
|
so the picker stays at 1rem on phones and shrinks only from tablet up. */
|
|
font-size: 1rem;
|
|
font-weight: 600;
|
|
letter-spacing: 0.14em;
|
|
text-transform: uppercase;
|
|
cursor: pointer;
|
|
}
|
|
|
|
@media (min-width: 48rem) {
|
|
select {
|
|
padding: 0.35rem 1.6rem 0.35rem 0.7rem;
|
|
font-size: 0.75rem;
|
|
}
|
|
}
|
|
|
|
select:hover {
|
|
border-color: var(--color-ink);
|
|
color: var(--color-ink);
|
|
}
|
|
|
|
.arrow {
|
|
position: absolute;
|
|
right: 0.6rem;
|
|
font-size: 0.65rem;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.visually-hidden {
|
|
position: absolute;
|
|
width: 1px;
|
|
height: 1px;
|
|
overflow: hidden;
|
|
clip-path: inset(50%);
|
|
white-space: nowrap;
|
|
}
|
|
</style>
|