|
1 | 1 | <script setup lang="ts"> |
2 | | -// import { useLocale, useRtl } from 'vuetify' |
3 | 2 | import { ssrClientHintsConfiguration } from 'virtual:vuetify-ssr-client-hints-configuration' |
4 | 3 | import prependAvatar from '~/assets/logo.svg' |
5 | 4 |
|
6 | 5 | definePageMeta({ |
7 | 6 | middleware: 'vuetify', |
8 | 7 | }) |
9 | 8 |
|
10 | | - const value = reactive<{ |
11 | | - name1?: string |
12 | | - name2?: string |
13 | | - name3?: string |
14 | | - }>({ |
15 | | - name1: undefined, |
16 | | - name2: undefined, |
17 | | - name3: undefined, |
18 | | - }) |
19 | | - const { locales, t } = useI18n() |
| 9 | + const { locales, t, locale } = useI18n() |
20 | 10 | const { current } = useLocale() |
21 | 11 | const { isRtl } = useRtl() |
22 | | - const x = useDate() |
23 | | -
|
24 | | - console.log(x.date) |
25 | | -
|
26 | | - if (import.meta.client) { |
27 | | - console.log(useNuxtApp().$vuetify.icons) |
28 | | - } |
29 | | -
|
30 | | - const ssrClientHints = useNuxtApp().$ssrClientHints |
31 | | - const { width, height, md } = useDisplay() |
| 12 | + const { width, height, name: displayName } = useDisplay() |
32 | 13 | const theme = useTheme() |
33 | 14 |
|
34 | | - const enableToogleTheme = computed(() => { |
35 | | - if (ssrClientHintsConfiguration.prefersColorScheme && ssrClientHintsConfiguration.prefersColorSchemeOptions) |
36 | | - return !ssrClientHintsConfiguration.prefersColorSchemeOptions.useBrowserThemeOnly |
37 | | -
|
38 | | - return false |
| 15 | + const isDark = computed({ |
| 16 | + get: () => theme.global.name.value === 'dark', |
| 17 | + set: () => theme.cycle(), |
39 | 18 | }) |
40 | 19 |
|
41 | | - function toogleTheme () { |
42 | | - theme.global.name.value = theme.global.name.value === 'light' ? 'dark' : 'light' |
43 | | - } |
| 20 | + const ssrClientHints = useNuxtApp().$ssrClientHints |
44 | 21 |
|
45 | | - // const rtl = ref(isRtl.value) |
| 22 | + const formData = reactive({ |
| 23 | + name: '', |
| 24 | + email: '', |
| 25 | + select: null, |
| 26 | + date: undefined, |
| 27 | + }) |
46 | 28 |
|
47 | | - watch(isRtl, x => { |
48 | | - console.log('isRtl', x) |
49 | | - // rtl.value = x |
| 29 | + watch(isRtl, val => { |
| 30 | + console.log('RTL changed:', val) |
50 | 31 | }, { immediate: true }) |
51 | 32 |
|
52 | | - watch(current, () => { |
53 | | - console.log('current', t('xxx', { locale: current.value })) |
54 | | - }) |
55 | 33 | </script> |
56 | 34 |
|
57 | 35 | <template> |
58 | | - <div> |
59 | | - <NuxtLink to="/no-ssr"> |
60 | | - Go To No-SSR Page |
61 | | - </NuxtLink> |
62 | | - <v-img height="48" src="~/assets/logo.svg" width="48" /> |
63 | | - <v-card height="48" prepend-avatar="~/assets/logo.svg" width="48" /> |
64 | | - <v-card height="48" :prepend-avatar="prependAvatar" width="48" /> |
65 | | - <div> |
66 | | - <h2>SSR Client Hints Headers:</h2> |
67 | | - <pre class="text-body-2">{{ ssrClientHints }}</pre> |
68 | | - <h2>useDisplay</h2> |
69 | | - <div>Resize the screen and refresh the page</div> |
70 | | - <pre>{{ width }} x {{ height }} (md {{ md }}?)</pre> |
71 | | - <div> |
72 | | - <h2>useTheme: {{ theme.global.name }}</h2> |
73 | | - <v-btn v-if="enableToogleTheme" @click="toogleTheme"> |
74 | | - toogle theme |
75 | | - </v-btn> |
76 | | - </div> |
77 | | - </div> |
78 | | - <div>Vuetify useLocale(): {{ current }}</div> |
79 | | - <div>$i18n current: {{ $i18n.locale }}</div> |
80 | | - <div>$vuetify.locale.current: {{ $vuetify.locale.current }}</div> |
81 | | - <div>t without locale: {{ t('xxx') }}</div> |
82 | | - <div>t with I18N locale: {{ t('xxx', { locale: $i18n.locale }) }}</div> |
83 | | - <div>t with Vuetify current locale: {{ t('xxx', { locale: current }) }}</div> |
84 | | - <div>$t {{ $t('xxx') }}</div> |
85 | | - <div>$vuetify.locale.t {{ $vuetify.locale.t('xxx') }}</div> |
86 | | - <v-select |
87 | | - v-model="current" |
88 | | - item-title="name" |
89 | | - item-value="code" |
90 | | - :items="locales" |
91 | | - outlined |
92 | | - /> |
93 | | - <v-text-field |
94 | | - v-model="value.name1" |
95 | | - clearable |
96 | | - :error="true" |
97 | | - hint="name 1" |
98 | | - :label="t('xxx')" |
99 | | - outlined |
100 | | - persistent-hint |
101 | | - /> |
102 | | - <v-btn>{{ t('xxx') }}</v-btn> |
103 | | - <v-locale-provider locale="es-ES"> |
104 | | - <v-btn>{{ $t('xxx') }}</v-btn> |
105 | | - </v-locale-provider> |
106 | | - <!-- <v-icon icon="fas fa-home" /> --> |
107 | | - <!-- <v-icon icon="$account" /> --> |
108 | | - <v-icon class="i-mdi:account" /> |
109 | | - <i class="i-mdi:account block" /> |
110 | | - <v-checkbox |
111 | | - :false-value="false" |
112 | | - label="isRtl" |
113 | | - :model-value="isRtl" |
114 | | - readonly |
115 | | - :true-value="true" |
116 | | - /> |
117 | | - <v-checkbox |
118 | | - base-color="red" |
119 | | - false-icon="i-mdi:account" |
120 | | - :false-value="false" |
121 | | - label="isRtl" |
122 | | - :model-value="isRtl" |
123 | | - readonly |
124 | | - /> |
125 | | - <div style="display: flex"> |
126 | | - <v-date-picker /> |
127 | | - <!-- we cannot use this when using lazy: missing messages since ar-EG not being loaded --> |
128 | | - <!-- <v-locale-provider locale="ar-EG" rtl> |
129 | | - <v-date-picker /> |
130 | | - </v-locale-provider> --> |
131 | | - </div> |
132 | | - <button class="mb-2 ml-2 px-2 my-button text-white bg-primary rounded-lg"> |
133 | | - Reserve |
134 | | - </button> |
135 | | - </div> |
136 | | -</template> |
| 36 | + <v-container fluid> |
| 37 | + <v-row> |
| 38 | + <!-- Welcome Section --> |
| 39 | + <v-col cols="12"> |
| 40 | + <v-card class="mb-4" color="primary" variant="tonal"> |
| 41 | + <v-card-text class="d-flex align-center"> |
| 42 | + <v-avatar class="mr-4" size="64"> |
| 43 | + <v-img alt="Logo" :src="prependAvatar" /> |
| 44 | + </v-avatar> |
| 45 | + <div> |
| 46 | + <div class="text-h4 font-weight-bold">Vuetify Nuxt Playground</div> |
| 47 | + <div class="text-subtitle-1">Explore features, components, and configurations</div> |
| 48 | + </div> |
| 49 | + <v-spacer /> |
| 50 | + <v-btn |
| 51 | + color="surface" |
| 52 | + prepend-icon="i-mdi:earth-off" |
| 53 | + to="/no-ssr" |
| 54 | + variant="elevated" |
| 55 | + > |
| 56 | + No-SSR Page |
| 57 | + </v-btn> |
| 58 | + </v-card-text> |
| 59 | + </v-card> |
| 60 | + </v-col> |
| 61 | + |
| 62 | + <!-- Theme & Display --> |
| 63 | + <v-col cols="12" md="6"> |
| 64 | + <v-card height="100%" prepend-icon="i-mdi:monitor-dashboard" title="Theme & Display"> |
| 65 | + <v-card-text> |
| 66 | + <v-row align="center"> |
| 67 | + <v-col cols="6"> |
| 68 | + <v-switch |
| 69 | + v-model="isDark" |
| 70 | + color="primary" |
| 71 | + hide-details |
| 72 | + inset |
| 73 | + label="Dark Theme" |
| 74 | + /> |
| 75 | + </v-col> |
| 76 | + <v-col cols="6"> |
| 77 | + <v-chip :color="isDark ? 'white' : 'black'" variant="outlined"> |
| 78 | + Current: {{ theme.global.name }} |
| 79 | + </v-chip> |
| 80 | + </v-col> |
| 81 | + </v-row> |
| 82 | + <v-divider class="my-3" /> |
| 83 | + <div class="text-subtitle-2 mb-2">Display Dimensions</div> |
| 84 | + <v-list class="bg-grey-lighten-4 rounded" density="compact" nav> |
| 85 | + <v-list-item prepend-icon="i-mdi:resize" :subtitle="width + 'px'" title="Width" /> |
| 86 | + <v-list-item prepend-icon="i-mdi:resize" :subtitle="height + 'px'" title="Height" /> |
| 87 | + <v-list-item prepend-icon="i-mdi:tablet" :subtitle="displayName" title="Breakpoint" /> |
| 88 | + </v-list> |
| 89 | + </v-card-text> |
| 90 | + </v-card> |
| 91 | + </v-col> |
| 92 | + |
| 93 | + <!-- Localization --> |
| 94 | + <v-col cols="12" md="6"> |
| 95 | + <v-card height="100%" prepend-icon="i-mdi:translate" title="Localization"> |
| 96 | + <v-card-text> |
| 97 | + <v-select |
| 98 | + v-model="current" |
| 99 | + density="comfortable" |
| 100 | + item-title="name" |
| 101 | + item-value="code" |
| 102 | + :items="locales" |
| 103 | + label="Select Locale" |
| 104 | + prepend-inner-icon="i-mdi:web" |
| 105 | + variant="outlined" |
| 106 | + /> |
137 | 107 |
|
138 | | -<style lang="scss"> |
139 | | - @use '../assets/settings'; |
| 108 | + <v-row class="mt-2"> |
| 109 | + <v-col cols="6"> |
| 110 | + <div class="text-caption">Vuetify Locale: <strong>{{ current }}</strong></div> |
| 111 | + <div class="text-caption">i18n Locale: <strong>{{ locale }}</strong></div> |
| 112 | + </v-col> |
| 113 | + <v-col cols="6"> |
| 114 | + <v-checkbox |
| 115 | + v-model="isRtl" |
| 116 | + color="secondary" |
| 117 | + density="compact" |
| 118 | + hide-details |
| 119 | + label="RTL Mode" |
| 120 | + /> |
| 121 | + </v-col> |
| 122 | + </v-row> |
| 123 | + |
| 124 | + <v-divider class="my-3" /> |
| 125 | + |
| 126 | + <div class="text-subtitle-2 mb-2">Translation Test</div> |
| 127 | + <v-alert border="start" border-color="primary" density="compact" variant="tonal"> |
| 128 | + t('xxx'): {{ t('xxx') }} |
| 129 | + </v-alert> |
| 130 | + </v-card-text> |
| 131 | + </v-card> |
| 132 | + </v-col> |
| 133 | + |
| 134 | + <!-- Components Showcase --> |
| 135 | + <v-col cols="12" md="6"> |
| 136 | + <v-card height="100%" prepend-icon="i-mdi:view-grid-plus" title="Components Showcase"> |
| 137 | + <v-card-text> |
| 138 | + <v-form> |
| 139 | + <v-text-field |
| 140 | + v-model="formData.name" |
| 141 | + clearable |
| 142 | + hint="Type something..." |
| 143 | + label="Interactive Input" |
| 144 | + persistent-hint |
| 145 | + prepend-inner-icon="i-mdi:pencil" |
| 146 | + variant="outlined" |
| 147 | + /> |
| 148 | + </v-form> |
| 149 | + |
| 150 | + <div class="my-4"> |
| 151 | + <div class="text-subtitle-2 mb-2">Buttons & Icons</div> |
| 152 | + <div class="d-flex gap-2 flex-wrap align-center"> |
| 153 | + <v-btn color="primary" prepend-icon="i-mdi:check">Primary</v-btn> |
| 154 | + <v-btn color="secondary" variant="tonal">Tonal</v-btn> |
| 155 | + <v-btn color="info" variant="outlined">Outlined</v-btn> |
| 156 | + |
| 157 | + <v-divider class="mx-2" vertical /> |
| 158 | + |
| 159 | + <v-badge color="success" dot> |
| 160 | + <v-icon icon="i-mdi:bell" size="large" /> |
| 161 | + </v-badge> |
| 162 | + |
| 163 | + <v-badge color="error" content="3"> |
| 164 | + <v-icon icon="i-mdi:email" size="large" /> |
| 165 | + </v-badge> |
| 166 | + |
| 167 | + <v-icon class="i-mdi:account" size="large" /> |
| 168 | + </div> |
| 169 | + </div> |
| 170 | + </v-card-text> |
| 171 | + </v-card> |
| 172 | + </v-col> |
| 173 | + |
| 174 | + <!-- Date Picker --> |
| 175 | + <v-col cols="12" md="6"> |
| 176 | + <v-card height="100%" prepend-icon="i-mdi:calendar" title="Date Picker"> |
| 177 | + <div class="d-flex justify-center pa-4"> |
| 178 | + <v-date-picker |
| 179 | + v-model="formData.date" |
| 180 | + elevation="2" |
| 181 | + rounded="lg" |
| 182 | + /> |
| 183 | + </div> |
| 184 | + </v-card> |
| 185 | + </v-col> |
| 186 | + |
| 187 | + <!-- SSR Info --> |
| 188 | + <v-col cols="12"> |
| 189 | + <v-expansion-panels> |
| 190 | + <v-expansion-panel title="SSR Client Hints & Configuration"> |
| 191 | + <v-expansion-panel-text> |
| 192 | + <v-row> |
| 193 | + <v-col cols="12" md="6"> |
| 194 | + <div class="text-subtitle-2 mb-2">Client Hints</div> |
| 195 | + <pre class="overflow-auto pa-4 bg-grey-lighten-4 rounded text-caption">{{ JSON.stringify(ssrClientHints, null, 2) }}</pre> |
| 196 | + </v-col> |
| 197 | + <v-col cols="12" md="6"> |
| 198 | + <div class="text-subtitle-2 mb-2">Configuration</div> |
| 199 | + <pre class="overflow-auto pa-4 bg-grey-lighten-4 rounded text-caption">{{ JSON.stringify(ssrClientHintsConfiguration, null, 2) }}</pre> |
| 200 | + </v-col> |
| 201 | + </v-row> |
| 202 | + </v-expansion-panel-text> |
| 203 | + </v-expansion-panel> |
| 204 | + </v-expansion-panels> |
| 205 | + </v-col> |
| 206 | + </v-row> |
| 207 | + </v-container> |
| 208 | +</template> |
140 | 209 |
|
141 | | - .my-button { |
142 | | - height: settings.$button-height; |
143 | | - } |
| 210 | +<style scoped> |
| 211 | +.gap-2 { |
| 212 | + gap: 8px; |
| 213 | +} |
144 | 214 | </style> |
0 commit comments