feat(ui): adopt Tailwind v4 design system and archive change
- Add tailwindcss v4 + @tailwindcss/vite to mall, shop-admin, admin - Add @vmall/shared/theme.css tokens with html[data-accent] presets - Add @vmall/ui kit (VBtn/VBadge/VField/VInput/VCard/VPanel/VTable/VPage, VAccentSwatch, useAccent) as a Nuxt module - Convert all three apps to kit + utilities; delete ui.css/mall.css and every <style scoped>; consoles get accent presets, mall locked to red - Fix VCard boolean prop default (padding) and PDP/store stale useAsyncData keys on param navigation - Archive adopt-tailwind-design-system; new frontend-ui capability spec
This commit is contained in:
@@ -31,145 +31,69 @@ const cats = computed(() =>
|
||||
|
||||
const active = computed(() => cats.value.find((g) => g.cat.id === hoverId.value) ?? null);
|
||||
|
||||
const rootClass = computed(() =>
|
||||
props.pinned
|
||||
? "relative z-[700] flex h-hero w-[240px]"
|
||||
: "absolute left-0 top-10 z-[700] flex w-[960px]",
|
||||
);
|
||||
|
||||
const railClass = computed(() =>
|
||||
props.pinned
|
||||
? "box-border h-hero min-h-[450px] w-[240px] list-none bg-[rgba(30,30,30,0.92)] py-2"
|
||||
: "min-h-[434px] w-[240px] list-none bg-[rgba(30,30,30,0.92)] py-2",
|
||||
);
|
||||
|
||||
const subClass = computed(() =>
|
||||
props.pinned
|
||||
? "absolute left-[240px] top-0 box-border h-hero min-h-[450px] w-[700px] overflow-auto bg-surface px-[30px] py-5 shadow-lg"
|
||||
: "min-h-[434px] flex-1 bg-surface px-[30px] py-5 shadow-lg",
|
||||
);
|
||||
|
||||
defineExpose({ open });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="catmenu" :class="{ pinned: props.pinned }" @mouseleave="hoverId = null">
|
||||
<ul class="lvl1">
|
||||
<div :class="rootClass" @mouseleave="hoverId = null">
|
||||
<ul :class="railClass">
|
||||
<li
|
||||
v-for="g in cats"
|
||||
:key="g.cat.id"
|
||||
:class="{ on: hoverId === g.cat.id }"
|
||||
class="cursor-pointer px-[15px] py-[10px]"
|
||||
:class="hoverId === g.cat.id ? 'bg-surface' : ''"
|
||||
@mouseenter="hoverId = g.cat.id"
|
||||
>
|
||||
<NuxtLink :to="`/search?category=${g.cat.id}`" class="c1">{{ pick(g.cat.name, locale) }}</NuxtLink>
|
||||
<span class="c2s">
|
||||
<NuxtLink
|
||||
:to="`/search?category=${g.cat.id}`"
|
||||
class="block text-sm no-underline"
|
||||
:class="hoverId === g.cat.id ? 'text-primary' : 'text-white'"
|
||||
>{{ pick(g.cat.name, locale) }}</NuxtLink>
|
||||
<span class="mt-0.5 block">
|
||||
<NuxtLink
|
||||
v-for="cc in g.children.slice(0, 3)"
|
||||
:key="cc.cat.id"
|
||||
:to="`/search?category=${cc.cat.id}`"
|
||||
class="c2"
|
||||
class="mr-2 text-[12px] no-underline"
|
||||
:class="hoverId === g.cat.id ? 'text-primary' : 'text-[#bbb] hover:text-white'"
|
||||
>{{ pick(cc.cat.name, locale) }}</NuxtLink>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div v-if="active" class="sub">
|
||||
<div v-for="cc in active.children" :key="cc.cat.id" class="sub-row">
|
||||
<NuxtLink :to="`/search?category=${cc.cat.id}`" class="sub-title">{{ pick(cc.cat.name, locale) }}</NuxtLink>
|
||||
<div class="sub-items">
|
||||
|
||||
<div v-if="active" :class="subClass">
|
||||
<div v-for="cc in active.children" :key="cc.cat.id" class="flex border-b border-border py-3 last:border-b-0">
|
||||
<NuxtLink
|
||||
:to="`/search?category=${cc.cat.id}`"
|
||||
class="w-[120px] shrink-0 text-[14px] font-semibold text-text no-underline"
|
||||
>{{ pick(cc.cat.name, locale) }}</NuxtLink>
|
||||
<div>
|
||||
<NuxtLink
|
||||
v-for="gc in cc.grandchildren"
|
||||
:key="gc.id"
|
||||
:to="`/search?category=${gc.id}`"
|
||||
class="mb-2 mr-[18px] inline-block text-[13px] text-muted no-underline transition-colors hover:text-primary"
|
||||
>{{ pick(gc.name, locale) }}</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.catmenu {
|
||||
position: absolute;
|
||||
top: 40px;
|
||||
left: 0;
|
||||
z-index: 700;
|
||||
display: flex;
|
||||
width: 960px;
|
||||
}
|
||||
/* pinned: in-flow left rail of the home hero row, flyout overlays the carousel */
|
||||
.catmenu.pinned {
|
||||
position: relative;
|
||||
top: auto;
|
||||
left: auto;
|
||||
flex: none;
|
||||
width: 240px;
|
||||
height: 450px;
|
||||
}
|
||||
.lvl1 {
|
||||
width: 240px;
|
||||
margin: 0;
|
||||
padding: 8px 0;
|
||||
list-style: none;
|
||||
background: rgba(30, 30, 30, 0.92);
|
||||
min-height: 434px;
|
||||
}
|
||||
.lvl1 li {
|
||||
padding: 10px 15px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.lvl1 li.on {
|
||||
background: #fff;
|
||||
}
|
||||
.lvl1 li.on .c1,
|
||||
.lvl1 li.on .c2 {
|
||||
color: var(--mall-red);
|
||||
}
|
||||
.c1 {
|
||||
display: block;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
text-decoration: none;
|
||||
}
|
||||
.c2s {
|
||||
display: block;
|
||||
margin-top: 2px;
|
||||
}
|
||||
.c2 {
|
||||
color: #bbb;
|
||||
font-size: 12px;
|
||||
margin-right: 8px;
|
||||
text-decoration: none;
|
||||
}
|
||||
.c2:hover {
|
||||
color: #fff;
|
||||
}
|
||||
.sub {
|
||||
flex: 1;
|
||||
background: #fff;
|
||||
box-shadow: var(--mall-shadow);
|
||||
padding: 20px 30px;
|
||||
min-height: 434px;
|
||||
}
|
||||
.sub-row {
|
||||
display: flex;
|
||||
border-bottom: 1px solid var(--mall-line);
|
||||
padding: 12px 0;
|
||||
}
|
||||
.sub-row:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
.sub-title {
|
||||
width: 120px;
|
||||
font-weight: 600;
|
||||
color: var(--mall-ink);
|
||||
text-decoration: none;
|
||||
}
|
||||
.sub-items a {
|
||||
display: inline-block;
|
||||
margin: 0 18px 8px 0;
|
||||
color: var(--mall-muted);
|
||||
font-size: 13px;
|
||||
text-decoration: none;
|
||||
}
|
||||
.sub-items a:hover {
|
||||
color: var(--mall-red);
|
||||
}
|
||||
/* pinned overrides: 240x450 rail, flyout opens to the right over the carousel */
|
||||
.catmenu.pinned .lvl1 {
|
||||
box-sizing: border-box;
|
||||
height: 450px;
|
||||
min-height: 450px;
|
||||
}
|
||||
.catmenu.pinned .sub {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 240px;
|
||||
box-sizing: border-box;
|
||||
width: 700px;
|
||||
height: 450px;
|
||||
min-height: 450px;
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user