Skip to content

Commit 582ec21

Browse files
committed
LangSwitcher - #273
1 parent bed8dcf commit 582ec21

File tree

9 files changed

+182
-57
lines changed

9 files changed

+182
-57
lines changed

Diff for: .env.example

+1
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ NUXT_ENABLE_REGISTER_TICKET=
1010
NUXT_ENABLE_REGISTER_NAMECARD=
1111
NUXT_ENABLE_SHOW_TIMETABLE=
1212
NUXT_ENABLE_SHOW_SPEAKER_INFO=
13+
NUXT_ENABLE_SWITCH_LOCALE=

Diff for: app/assets/logo/arrow_down_logo.svg

+4-2
Loading

Diff for: app/components/LangSwitcher.vue

-40
This file was deleted.

Diff for: app/components/NavPageSection.vue

+24-15
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ import MenuLogo from '~/assets/logo/menu_logo.svg'
33
import VueFesLogo from '~/assets/logo/vuefes_logo.svg'
44
import VueFesUserLogo from '~/assets/logo/vuefes_user_logo.svg'
55
import TwitterLogo from '~/assets/logo/twitter_logo.svg'
6+
import LangSwitcher from '~/components/locale/LangSwitcher.vue'
67
import NavView from '~/components/nav/NavView.vue'
78
import { useNav } from '~/composables/useNav'
9+
import { useLocaleSwitcher } from '~/composables/useLocaleSwitcher'
810
import { conferenceTitle } from '~/utils/constants'
911
1012
const props = defineProps({
@@ -20,6 +22,7 @@ const props = defineProps({
2022
2123
const { navLinks, navRef } = useNav()
2224
const { isMobile } = useDevice()
25+
const { switchLocale } = useLocaleSwitcher()
2326
const htmlRef = ref()
2427
const showMenu = ref(false)
2528
@@ -48,7 +51,7 @@ onMounted(function () {
4851
<span class="sr-only">{{ conferenceTitle }}</span>
4952
</h1>
5053
<div v-if="!hasAuth" class="links">
51-
<ul v-for="l in navLinks" :key="l.link">
54+
<ul v-for="l in navLinks" :key="l.link" class="link-items">
5255
<li>
5356
<nuxt-link :to="`${l.link}`">{{ l.text }}</nuxt-link>
5457
</li>
@@ -62,6 +65,10 @@ onMounted(function () {
6265
>
6366
<TwitterLogo />
6467
</a>
68+
<LangSwitcher
69+
v-if="switchLocale"
70+
:top="hasAlert ? (isMobile ? '160px' : '130px') : '80px'"
71+
/>
6572
<slot name="avatar" />
6673
<!-- hamburger-menu -->
6774
<button v-if="!showMenu" class="hamburger-menu" @click="toggleMenu">
@@ -94,23 +101,25 @@ css({
94101
display: 'flex',
95102
alignItems: 'center',
96103
columnGap: '40px',
97-
'::v-deep(ul)': {
98-
display: 'block',
104+
},
105+
'.link-items': {
106+
display: 'block',
107+
},
108+
'.link-items a': {
109+
color: '{color.white}',
110+
fontSize: 'calc(16*{fontSize.base})',
111+
'&:hover': {
112+
color: '{color.vue.green}',
113+
transition: '.2s',
99114
},
100-
'::v-deep(a)': {
101-
color: '{color.white}',
102-
fontSize: 'calc(16*{fontSize.base})',
115+
},
116+
'.twitter': {
117+
'svg': {
118+
fill: '{color.white}',
103119
'&:hover': {
104-
color: '{color.vue.green}',
120+
fill: '{color.vue.green}',
105121
transition: '.2s',
106122
},
107-
'svg': {
108-
fill: '{color.white}',
109-
'&:hover': {
110-
fill: '{color.vue.green}',
111-
transition: '.2s',
112-
},
113-
},
114123
},
115124
},
116125
'.hamburger-menu':{
@@ -134,7 +143,7 @@ css({
134143
display: 'block',
135144
},
136145
'.links': {
137-
'ul': {
146+
'ul': {
138147
display: 'none',
139148
},
140149
'a': {

Diff for: app/components/locale/LangItem.vue

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<script setup lang="ts">
2+
import { useHover } from '~/composables/useHover'
3+
import { useLocaleSwitcher } from '~/composables/useLocaleSwitcher'
4+
5+
const props = defineProps({
6+
locale: {
7+
type: Object,
8+
required: true,
9+
},
10+
active: {
11+
type: Boolean,
12+
required: true,
13+
},
14+
})
15+
16+
interface LangItemEmit {
17+
(e: 'on-click'): void
18+
}
19+
20+
const emit = defineEmits<LangItemEmit>()
21+
22+
const hoverRef = ref()
23+
24+
const isHovered = useHover(hoverRef)
25+
const { switchLocalePath } = useLocaleSwitcher()
26+
27+
const onClick = () => {
28+
emit('on-click')
29+
}
30+
</script>
31+
32+
<template>
33+
<div ref="hoverRef" :class="active ? 'item active-item' : 'item'">
34+
<nuxt-link
35+
:to="switchLocalePath(locale.code)"
36+
:style="{
37+
color: isHovered ? '#42B983' : active ? '#ffffff' : '#35495E',
38+
}"
39+
class="item-link"
40+
@click="onClick"
41+
>
42+
{{ locale.code === 'ja' ? '日本語' : locale.code === 'en' ? '英語' : 'やさしいにほんご' }}
43+
</nuxt-link>
44+
</div>
45+
</template>
46+
47+
<style lang="ts" scoped>
48+
css({
49+
'.item': {
50+
padding: 'calc({space.8} * 2.5)',
51+
},
52+
'.active-item': {
53+
background: '{color.vue.green}',
54+
},
55+
'.item-link': {
56+
display: 'grid',
57+
placeItems: 'center',
58+
},
59+
})
60+
</style>

Diff for: app/components/locale/LangSwitcher.vue

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
<script lang="ts" setup>
2+
import ArrowDownLogo from '~/assets/logo/arrow_down_logo.svg'
3+
import LangItem from '~/components/locale/LangItem.vue'
4+
import { useDialog } from '~/composables/useDialog'
5+
import { useLocaleSwitcher } from '~/composables/useLocaleSwitcher'
6+
import { useToast } from '~/composables/useToast'
7+
8+
const props = defineProps({
9+
top: {
10+
type: String,
11+
required: true,
12+
},
13+
})
14+
15+
const { handle, isShow } = useDialog()
16+
const { currentLocale, availableLocales } = useLocaleSwitcher()
17+
const { onSuccess } = useToast()
18+
19+
const onClick = (localeCode: string) => {
20+
handle(isShow ? false : true)
21+
onSuccess(
22+
`${
23+
localeCode === 'ja' ? '日本語' : localeCode === 'en' ? '英語' : 'やさしいにほんご'
24+
} に切り替えました。`,
25+
3000,
26+
)
27+
}
28+
</script>
29+
30+
<template>
31+
<button class="switcher-button" @click="() => handle(isShow ? false : true)">
32+
Language
33+
<ArrowDownLogo />
34+
</button>
35+
<div v-if="isShow" class="switcher-root" :style="{ top: top }">
36+
<ul>
37+
<li v-for="locale in availableLocales" :key="locale.code">
38+
<LangItem
39+
:locale="locale"
40+
:active="locale.code === currentLocale"
41+
@on-click="() => onClick(locale.code)"
42+
/>
43+
</li>
44+
</ul>
45+
</div>
46+
</template>
47+
48+
<style lang="ts" scoped>
49+
css({
50+
'.switcher-button': {
51+
display: 'flex',
52+
color: '{color.white}',
53+
fontSize: 'calc(16*{fontSize.base})',
54+
'&:hover': {
55+
color: '{color.vue.green}',
56+
transition: '.2s',
57+
},
58+
'svg': {
59+
fill: '{color.white}',
60+
'&:hover': {
61+
fill: '{color.vue.green}',
62+
transition: '.2s',
63+
},
64+
},
65+
},
66+
'.switcher-root': {
67+
position: 'absolute',
68+
right: '2%',
69+
'::v-deep(ul)': {
70+
background: '{color.white}',
71+
width: '168px',
72+
borderRadius: '4px',
73+
},
74+
},
75+
})
76+
</style>

Diff for: app/composables/useFeature.ts

+1
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ export function useFeature() {
66
registerNamecard: config.public.registerNamecard,
77
showTimetable: config.public.showTimetable === 'true',
88
showSpeakerInfo: config.public.showSpeakerInfo,
9+
switchLocale: config.public.switchLocale,
910
}
1011
}

Diff for: app/composables/useLocaleSwitcher.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { LocaleObject } from '@nuxtjs/i18n/dist/runtime/composables'
2+
import { useFeature } from '~/composables/useFeature'
3+
4+
export function useLocaleSwitcher() {
5+
const { switchLocale } = useFeature()
6+
const { locales, locale: currentLocale } = useI18n({ useScope: 'global' })
7+
8+
const availableLocales = computed(() => {
9+
return locales.value as unknown as LocaleObject
10+
})
11+
12+
const switchLocalePath = useSwitchLocalePath()
13+
14+
return { switchLocale, currentLocale, availableLocales, switchLocalePath }
15+
}

Diff for: nuxt.config.ts

+1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ export default defineNuxtConfig({
9292
registerNamecard: process.env.NUXT_ENABLE_REGISTER_NAMECARD,
9393
showTimetable: process.env.NUXT_ENABLE_SHOW_TIMETABLE,
9494
showSpeakerInfo: process.env.NUXT_ENABLE_SHOW_SPEAKER_INFO,
95+
switchLocale: process.env.NUXT_ENABLE_SWITCH_LOCALE,
9596
// supabase
9697
supabaseProjectUrl: process.env.SUPABASE_URL,
9798
supabaseApiKey: process.env.SUPABASE_KEY,

0 commit comments

Comments
 (0)