Skip to content

Commit 9dbd3bf

Browse files
authored
Merge pull request #141 from vuejs-jp/feature/locale-switch
Feat/Add LocaleSwitch component
2 parents 6d4cd2e + 2a9e462 commit 9dbd3bf

File tree

4 files changed

+179
-5
lines changed

4 files changed

+179
-5
lines changed

apps/web/app/components/FooterPageSection.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,11 @@ const snsLinkList: LinkList[] = [
3939
const internalLinkList: LinkList[] = [
4040
{
4141
href: '/privacy',
42-
text: t('privacy.title'),
42+
text: 'privacy.title',
4343
},
4444
{
4545
href: '/code-of-conduct',
46-
text: t('code_of_conduct.title'),
46+
text: 'code_of_conduct.title',
4747
},
4848
]
4949
const vueFesLinkList: LinkList[] = [
@@ -86,14 +86,14 @@ const vueFesLinkList: LinkList[] = [
8686
<ul class="footer-list">
8787
<li v-for="(link, index) in internalLinkList" :key="index">
8888
<VFTextLink :href="`${localePath}${link.href}`" color="white">
89-
{{ link.text }}
89+
{{ t(link.text) }}
9090
</VFTextLink>
9191
</li>
9292
</ul>
9393
<ul class="footer-list">
9494
<li v-for="(link, index) in vueFesLinkList" :key="index">
9595
<VFTextLink :href="link.href" target="_blank" color="white">
96-
{{ link.text }}
96+
{{ t(link.text) }}
9797
</VFTextLink>
9898
</li>
9999
</ul>

packages/ui/.storybook/preview.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { setup } from '@storybook/vue3'
22
import { INITIAL_VIEWPORTS } from '@storybook/addon-viewport'
33
import { createI18n } from 'vue-i18n'
4+
import { createRouter, createMemoryHistory } from 'vue-router'
45

56
import './global.css'
67

@@ -33,14 +34,29 @@ const i18n = createI18n({
3334
// end dummy
3435
sponsor: {
3536
start_date: 'April 8',
36-
end_date: '25,',
37+
end_date: '25,',
3738
},
3839
},
3940
},
4041
})
4142

43+
const routes = [
44+
{
45+
path: '/',
46+
name: 'ja',
47+
},
48+
{
49+
path: '/en',
50+
name: 'en',
51+
},
52+
]
53+
54+
// 画面遷移は発生しないが、StorybookではURLを直接使えないため、createMemoryHistoryで生成
55+
const router = createRouter({ history: createMemoryHistory(), routes })
56+
4257
setup((app) => {
4358
app.use(i18n)
59+
app.use(router)
4460
})
4561

4662
export const parameters = {
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { StoryFn } from '@storybook/vue3'
2+
import LocaleSwitch from './LocaleSwitch.vue'
3+
4+
export default {
5+
title: 'common/LocaleSwitch',
6+
component: LocaleSwitch,
7+
}
8+
9+
const Template: StoryFn<unknown> = () => ({
10+
components: { LocaleSwitch },
11+
setup() {
12+
return {}
13+
},
14+
template: '<LocaleSwitch />',
15+
})
16+
17+
export const Default = Template.bind({})
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
<script setup lang="ts">
2+
import { onMounted, ref, watch } from 'vue'
3+
import { useRouter } from 'vue-router'
4+
5+
const LANGUAGES = {
6+
JAPANESE: 'ja',
7+
ENGLISH: 'en',
8+
} as const
9+
10+
const router = useRouter()
11+
const isLoaded = ref(false)
12+
const isChecked = ref(false)
13+
14+
const getPath = () => {
15+
if (isChecked.value) {
16+
return `/${LANGUAGES.ENGLISH}${router.currentRoute.value.path}`
17+
}
18+
return router.currentRoute.value.path.replace(`/${LANGUAGES.ENGLISH}`, '')
19+
}
20+
const setSwitchStatus = () => {
21+
isChecked.value = router.currentRoute.value.path.includes(`/${LANGUAGES.ENGLISH}/`)
22+
}
23+
24+
const toggleStatus = () => {
25+
isChecked.value = !isChecked.value
26+
const path = getPath()
27+
router.push(path)
28+
}
29+
onMounted(() => {
30+
setSwitchStatus()
31+
isLoaded.value = true
32+
})
33+
watch(
34+
() => router.currentRoute.value.path,
35+
() => {
36+
setSwitchStatus()
37+
},
38+
)
39+
</script>
40+
41+
<template>
42+
<button
43+
v-if="isLoaded"
44+
type="button"
45+
role="switch"
46+
class="locale-switch-button"
47+
aria-label="translate english"
48+
:aria-checked="isChecked"
49+
@click="toggleStatus"
50+
>
51+
<span
52+
class="locale-switch-button-switch"
53+
:class="{ 'locale-switch-button-switch-checked': !isChecked }"
54+
aria-hidden="true"
55+
>
56+
<span
57+
v-if="isChecked"
58+
class="locale-switch-button-language"
59+
:class="{ 'locale-switch-button-language-checked': !isChecked }"
60+
>
61+
<span>{{ LANGUAGES.JAPANESE }}</span>
62+
</span>
63+
<span class="locale-switch-button-circle">
64+
{{ isChecked ? LANGUAGES.ENGLISH : LANGUAGES.JAPANESE }}
65+
</span>
66+
<span
67+
v-if="!isChecked"
68+
class="locale-switch-button-language"
69+
:class="{ 'locale-switch-button-language-checked': isChecked }"
70+
>
71+
<span>{{ LANGUAGES.ENGLISH }}</span>
72+
</span>
73+
</span>
74+
</button>
75+
</template>
76+
77+
<style scoped>
78+
.locale-switch-button {
79+
--box-shadow: 0 1px 4px color-mix(in srgb, var(--color-vue-blue), transparent calc(100% - 14%));
80+
81+
border: 0;
82+
user-select: none;
83+
line-height: 1.2;
84+
width: 5.125rem;
85+
height: 2.5rem;
86+
display: grid;
87+
place-content: center;
88+
color: var(--color-white);
89+
background-color: transparent;
90+
position: relative;
91+
}
92+
93+
.locale-switch-button-switch {
94+
display: flex;
95+
align-items: center;
96+
box-shadow: var(--box-shadow);
97+
background-color: #d2d6db;
98+
border-radius: 0.9375rem;
99+
height: 1.8125rem;
100+
width: 3.5625rem;
101+
font-size: 1.125rem;
102+
font-weight: bold;
103+
padding-left: 0.5rem;
104+
box-sizing: border-box;
105+
}
106+
107+
.locale-switch-button-switch-checked {
108+
justify-content: flex-end;
109+
padding-left: 0;
110+
padding-right: 0.5rem;
111+
}
112+
113+
.locale-switch-button-language {
114+
font-size: 0.875rem;
115+
font-weight: bold;
116+
}
117+
118+
.locale-switch-button-circle {
119+
position: absolute;
120+
display: flex;
121+
justify-content: center;
122+
padding-top: 0.25rem;
123+
box-sizing: border-box;
124+
border-radius: 50%;
125+
top: calc(50% - 1rem);
126+
right: 50%;
127+
height: 2rem;
128+
width: 2rem;
129+
background: #34495e;
130+
box-shadow: var(--box-shadow);
131+
}
132+
133+
.locale-switch-button[aria-checked='true'] .locale-switch-button-circle {
134+
right: 0;
135+
left: 50%;
136+
}
137+
138+
.locale-switch-button:hover {
139+
cursor: pointer;
140+
}
141+
</style>

0 commit comments

Comments
 (0)