Skip to content

Commit e698ad1

Browse files
committed
fix: apply suggested refactoring
1 parent 67db049 commit e698ad1

File tree

4 files changed

+74
-87
lines changed

4 files changed

+74
-87
lines changed

app/components/Chart/SplitSparkline.vue

Lines changed: 59 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,14 @@ const step = ref(0)
3737
3838
onMounted(() => {
3939
rootEl.value = document.documentElement
40-
resolvedMode.value = colorMode.value === 'dark' ? 'dark' : 'light'
4140
})
4241
4342
watch(
4443
() => colorMode.value,
4544
value => {
4645
resolvedMode.value = value === 'dark' ? 'dark' : 'light'
4746
},
48-
{ flush: 'sync' },
47+
{ flush: 'sync', immediate: true },
4948
)
5049
5150
const { colors } = useCssVariables(
@@ -191,71 +190,69 @@ const configs = computed(() => {
191190
</script>
192191

193192
<template>
194-
<div>
195-
<div class="grid gap-8 sm:grid-cols-2">
196-
<ClientOnly v-for="(config, i) in configs" :key="`config_${i}`">
197-
<div
198-
@mouseleave="resetHover"
199-
@keydown.esc="resetHover"
200-
class="w-full max-w-[400px] mx-auto"
201-
>
202-
<div class="flex gap-2 place-items-center">
203-
<div class="h-3 w-3">
204-
<svg viewBox="0 0 2 2" class="w-full">
205-
<rect
206-
x="0"
207-
y="0"
208-
width="2"
209-
height="2"
210-
rx="0.3"
211-
:fill="dataset?.[i]?.color ?? palette[i]"
212-
/>
213-
</svg>
214-
</div>
215-
{{ applyEllipsis(dataset?.[i]?.name ?? '', 28) }}
193+
<div class="grid gap-8 sm:grid-cols-2">
194+
<ClientOnly v-for="(config, i) in configs" :key="`config_${i}`">
195+
<div
196+
@mouseleave="resetHover"
197+
@keydown.esc="resetHover"
198+
class="w-full max-w-[400px] mx-auto"
199+
>
200+
<div class="flex gap-2 place-items-center">
201+
<div class="h-3 w-3">
202+
<svg viewBox="0 0 2 2" class="w-full">
203+
<rect
204+
x="0"
205+
y="0"
206+
width="2"
207+
height="2"
208+
rx="0.3"
209+
:fill="dataset?.[i]?.color ?? palette[i]"
210+
/>
211+
</svg>
216212
</div>
217-
<VueUiSparkline
218-
:key="`${i}_${step}`"
219-
:config
220-
:dataset="datasets?.[i]"
221-
:selectedIndex
222-
@hoverIndex="hoverIndex"
223-
>
224-
<!-- Keyboard navigation hint -->
225-
<template #hint="{ isVisible }">
226-
<p v-if="isVisible" class="text-accent text-xs text-center mt-2" aria-hidden="true">
227-
{{ $t('package.downloads.sparkline_nav_hint') }}
228-
</p>
229-
</template>
230-
231-
<template #skeleton>
232-
<!-- This empty div overrides the default built-in scanning animation on load -->
233-
<div />
234-
</template>
235-
</VueUiSparkline>
213+
{{ applyEllipsis(dataset?.[i]?.name ?? '', 28) }}
236214
</div>
215+
<VueUiSparkline
216+
:key="`${i}_${step}`"
217+
:config
218+
:dataset="datasets?.[i]"
219+
:selectedIndex
220+
@hoverIndex="hoverIndex"
221+
>
222+
<!-- Keyboard navigation hint -->
223+
<template #hint="{ isVisible }">
224+
<p v-if="isVisible" class="text-accent text-xs text-center mt-2" aria-hidden="true">
225+
{{ $t('package.downloads.sparkline_nav_hint') }}
226+
</p>
227+
</template>
237228

238-
<template #fallback>
239-
<!-- Skeleton matching VueUiSparkline layout (title 24px + SVG aspect 500:80) -->
240-
<div class="max-w-xs">
241-
<!-- Title row: fontSize * 2 = 24px -->
242-
<div class="h-6 flex items-center ps-3">
243-
<SkeletonInline class="h-3 w-36" />
229+
<template #skeleton>
230+
<!-- This empty div overrides the default built-in scanning animation on load -->
231+
<div />
232+
</template>
233+
</VueUiSparkline>
234+
</div>
235+
236+
<template #fallback>
237+
<!-- Skeleton matching VueUiSparkline layout (title 24px + SVG aspect 500:80) -->
238+
<div class="max-w-xs">
239+
<!-- Title row: fontSize * 2 = 24px -->
240+
<div class="h-6 flex items-center ps-3">
241+
<SkeletonInline class="h-3 w-36" />
242+
</div>
243+
<!-- Chart area: matches SVG viewBox 500:80 -->
244+
<div class="aspect-[500/80] flex items-center">
245+
<!-- Data label (covers ~42% width, matching dataLabel.offsetX) -->
246+
<div class="w-[42%] flex items-center ps-0.5">
247+
<SkeletonInline class="h-7 w-24" />
244248
</div>
245-
<!-- Chart area: matches SVG viewBox 500:80 -->
246-
<div class="aspect-[500/80] flex items-center">
247-
<!-- Data label (covers ~42% width, matching dataLabel.offsetX) -->
248-
<div class="w-[42%] flex items-center ps-0.5">
249-
<SkeletonInline class="h-7 w-24" />
250-
</div>
251-
<!-- Sparkline line placeholder -->
252-
<div class="flex-1 flex items-end pe-3">
253-
<SkeletonInline class="h-px w-full" />
254-
</div>
249+
<!-- Sparkline line placeholder -->
250+
<div class="flex-1 flex items-end pe-3">
251+
<SkeletonInline class="h-px w-full" />
255252
</div>
256253
</div>
257-
</template>
258-
</ClientOnly>
259-
</div>
254+
</div>
255+
</template>
256+
</ClientOnly>
260257
</div>
261258
</template>

app/components/Tab/Item.vue

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,16 @@ const props = withDefaults(
1919
2020
const attrs = useAttrs()
2121
22-
const selected = inject<WritableComputedRef<string>>('tabs-selected')!
23-
const getTabId = inject<(value: string) => string>('tabs-tab-id')!
24-
const getPanelId = inject<(value: string) => string>('tabs-panel-id')!
25-
22+
const selected = inject<WritableComputedRef<string>>('tabs-selected')
23+
const getTabId = inject<(value: string) => string>('tabs-tab-id')
24+
const getPanelId = inject<(value: string) => string>('tabs-panel-id')
25+
if (!selected || !getTabId || !getPanelId) {
26+
throw new Error('TabItem must be used inside a TabRoot component')
27+
}
2628
const isSelected = computed(() => selected.value === props.value)
2729
const resolvedTabId = computed(() => props.tabId ?? getTabId(props.value))
2830
const resolvedPanelId = computed(() => getPanelId(props.value))
29-
30-
function select() {
31+
const select = () =>{
3132
selected.value = props.value
3233
}
3334
</script>

app/components/Tab/Panel.vue

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@ const props = defineProps<{
66
panelId?: string
77
}>()
88
9-
const selected = inject<WritableComputedRef<string>>('tabs-selected')!
10-
const getTabId = inject<(value: string) => string>('tabs-tab-id')!
11-
const getPanelId = inject<(value: string) => string>('tabs-panel-id')!
9+
const selected = inject<WritableComputedRef<string>>('tabs-selected')
10+
const getTabId = inject<(value: string) => string>('tabs-tab-id')
11+
const getPanelId = inject<(value: string) => string>('tabs-panel-id')
12+
13+
if (!selected || !getTabId || !getPanelId) {
14+
throw new Error('TabItem must be used inside a TabRoot component')
15+
}
1216
1317
const isSelected = computed(() => selected.value === props.value)
1418
const resolvedPanelId = computed(() => props.panelId ?? getPanelId(props.value))

app/components/Tab/Root.vue

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,13 @@ defineOptions({ name: 'TabRoot' })
33
44
const props = withDefaults(
55
defineProps<{
6-
modelValue?: string
7-
defaultValue?: string
86
idPrefix?: string
97
}>(),
108
{
119
idPrefix: 'tab',
1210
},
1311
)
14-
15-
const emit = defineEmits<{
16-
'update:modelValue': [value: string]
17-
}>()
18-
19-
const internalValue = shallowRef(props.defaultValue ?? '')
20-
21-
const selectedValue = computed({
22-
get: () => props.modelValue ?? internalValue.value,
23-
set: (v: string) => {
24-
internalValue.value = v
25-
emit('update:modelValue', v)
26-
},
27-
})
12+
const selectedValue = defineModel<string>()
2813
2914
function tabId(value: string): string {
3015
return `${props.idPrefix}-${value}`

0 commit comments

Comments
 (0)