@yunlefun/vue 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/README.md +26 -37
  2. package/components/YlfAccordion.vue +165 -0
  3. package/components/YlfAvatar.vue +70 -0
  4. package/components/YlfBadge.vue +142 -0
  5. package/components/YlfBottomMenu.vue +23 -6
  6. package/components/YlfBottomMenuItem.vue +41 -21
  7. package/components/YlfButton.vue +290 -7
  8. package/components/YlfCard.vue +74 -3
  9. package/components/YlfCheckbox.vue +84 -0
  10. package/components/YlfDialog.vue +174 -0
  11. package/components/YlfDropdownMenu.vue +98 -0
  12. package/components/YlfLogo.vue +83 -7
  13. package/components/YlfPopover.vue +64 -0
  14. package/components/YlfProgress.vue +65 -0
  15. package/components/YlfRadioGroup.vue +120 -0
  16. package/components/YlfSelect.vue +195 -0
  17. package/components/YlfSeparator.vue +68 -0
  18. package/components/YlfSlider.vue +89 -0
  19. package/components/YlfSwitch.vue +111 -0
  20. package/components/YlfTabs.vue +117 -0
  21. package/components/YlfTooltip.vue +67 -0
  22. package/components/accordion/demo.vue +11 -0
  23. package/components/accordion/index.md +19 -0
  24. package/components/avatar/demo.vue +9 -0
  25. package/components/avatar/index.md +15 -0
  26. package/components/badge/demo.vue +84 -0
  27. package/components/badge/index.md +41 -0
  28. package/components/bottom-menu/demo.vue +19 -10
  29. package/components/bottom-menu/index.md +25 -0
  30. package/components/button/demo.vue +101 -3
  31. package/components/button/index.md +41 -0
  32. package/components/card/demo.vue +76 -3
  33. package/components/card/index.md +19 -0
  34. package/components/checkbox/demo.vue +28 -0
  35. package/components/checkbox/index.md +14 -0
  36. package/components/common/demo.vue +7 -1
  37. package/components/common/index.md +10 -0
  38. package/components/dialog/demo.vue +33 -0
  39. package/components/dialog/index.md +30 -0
  40. package/components/dropdown-menu/demo.vue +27 -0
  41. package/components/dropdown-menu/index.md +27 -0
  42. package/components/popover/demo.vue +18 -0
  43. package/components/popover/index.md +21 -0
  44. package/components/progress/demo.vue +24 -0
  45. package/components/progress/index.md +17 -0
  46. package/components/radio/demo.vue +20 -0
  47. package/components/radio/index.md +23 -0
  48. package/components/select/demo.vue +20 -0
  49. package/components/select/index.md +41 -0
  50. package/components/separator/demo.vue +52 -0
  51. package/components/separator/index.md +19 -0
  52. package/components/slider/demo.vue +23 -0
  53. package/components/slider/index.md +16 -0
  54. package/components/switch/demo.vue +33 -0
  55. package/components/switch/index.md +18 -0
  56. package/components/tabs/demo.vue +30 -0
  57. package/components/tabs/index.md +18 -0
  58. package/components/theme.ts +5 -0
  59. package/components/tooltip/demo.vue +19 -0
  60. package/components/tooltip/index.md +21 -0
  61. package/dist/index.cjs +2 -1
  62. package/dist/index.d.cts +7 -1
  63. package/dist/index.d.mts +7 -1
  64. package/dist/index.d.ts +7 -1
  65. package/package.json +32 -3
@@ -0,0 +1,89 @@
1
+ <script lang="ts" setup>
2
+ import { SliderRange, SliderRoot, SliderThumb, SliderTrack } from 'reka-ui'
3
+
4
+ withDefaults(defineProps<{
5
+ min?: number
6
+ max?: number
7
+ step?: number
8
+ disabled?: boolean
9
+ }>(), {
10
+ min: 0,
11
+ max: 100,
12
+ step: 1,
13
+ disabled: false,
14
+ })
15
+
16
+ const model = defineModel<number[]>({ default: () => [50] })
17
+ </script>
18
+
19
+ <template>
20
+ <SliderRoot
21
+ v-model="model"
22
+ :min="min"
23
+ :max="max"
24
+ :step="step"
25
+ :disabled="disabled"
26
+ class="ylf-slider"
27
+ >
28
+ <SliderTrack class="ylf-slider__track">
29
+ <SliderRange class="ylf-slider__range" />
30
+ </SliderTrack>
31
+ <SliderThumb v-for="(_, i) in model" :key="i" class="ylf-slider__thumb" />
32
+ </SliderRoot>
33
+ </template>
34
+
35
+ <style lang="scss">
36
+ .ylf-slider {
37
+ position: relative;
38
+ display: flex;
39
+ align-items: center;
40
+ width: 100%;
41
+ height: 20px;
42
+ touch-action: none;
43
+ user-select: none;
44
+
45
+ &[data-disabled] {
46
+ opacity: 0.5;
47
+ }
48
+
49
+ &__track {
50
+ position: relative;
51
+ flex-grow: 1;
52
+ height: 6px;
53
+ border-radius: 999px;
54
+ background: var(--ylf-c-bg-mute, #e2e8f0);
55
+ }
56
+
57
+ &__range {
58
+ position: absolute;
59
+ height: 100%;
60
+ border-radius: 999px;
61
+ background: var(--ylf-c-brand, #2563eb);
62
+ }
63
+
64
+ &__thumb {
65
+ display: block;
66
+ width: 18px;
67
+ height: 18px;
68
+ border-radius: 50%;
69
+ background: #fff;
70
+ border: 2px solid var(--ylf-c-brand, #2563eb);
71
+ box-shadow: var(--ylf-shadow-sm, 0 2px 8px -2px rgba(15, 23, 42, 0.12));
72
+ cursor: grab;
73
+ transition: box-shadow 0.2s ease;
74
+
75
+ &:hover {
76
+ box-shadow: 0 0 0 6px var(--ylf-c-brand-soft, #eff6ff);
77
+ }
78
+
79
+ &:focus-visible {
80
+ outline: none;
81
+ box-shadow: 0 0 0 4px var(--ylf-c-brand-soft, #eff6ff);
82
+ }
83
+
84
+ &:active {
85
+ cursor: grabbing;
86
+ }
87
+ }
88
+ }
89
+ </style>
@@ -0,0 +1,111 @@
1
+ <script lang="ts" setup>
2
+ import type { YlfAccentTone } from './theme'
3
+ // 行为 / 可访问性由 reka-ui 提供(role=switch、键盘、焦点、data-state);
4
+ // 外观全部走 --ylf token,所以视觉识别仍是「晴空蓝为主、高饱和纯色点缀」。
5
+ import { SwitchRoot, SwitchThumb } from 'reka-ui'
6
+
7
+ withDefaults(defineProps<{
8
+ /** on 态轨道:brand 主色(默认)或 accent 纯色;aurora 是 accent 的旧别名 */
9
+ variant?: 'brand' | 'accent' | 'aurora'
10
+ tone?: YlfAccentTone
11
+ size?: 'sm' | 'md'
12
+ disabled?: boolean
13
+ }>(), {
14
+ variant: 'brand',
15
+ tone: 'blue',
16
+ size: 'md',
17
+ disabled: false,
18
+ })
19
+
20
+ const checked = defineModel<boolean>({ default: false })
21
+ </script>
22
+
23
+ <template>
24
+ <SwitchRoot
25
+ v-model="checked"
26
+ :disabled="disabled"
27
+ class="ylf-switch"
28
+ :data-ylf-tone="tone"
29
+ :class="[`ylf-switch--${variant}`, `ylf-switch--${size}`]"
30
+ >
31
+ <SwitchThumb class="ylf-switch__thumb" />
32
+ </SwitchRoot>
33
+ </template>
34
+
35
+ <style lang="scss">
36
+ .ylf-switch {
37
+ --_w: 52px;
38
+ --_h: 30px;
39
+ --_pad: 3px;
40
+
41
+ position: relative;
42
+ flex: none;
43
+ width: var(--_w);
44
+ height: var(--_h);
45
+ padding: 0;
46
+ border: none;
47
+ border-radius: var(--ylf-radius-pill, 999px);
48
+ background: var(--ylf-c-bg-mute, #e2e8f0);
49
+ cursor: pointer;
50
+ -webkit-tap-highlight-color: transparent;
51
+ transition:
52
+ background var(--ylf-duration-normal, 240ms) var(--ylf-ease-standard, ease),
53
+ box-shadow var(--ylf-duration-fast, 160ms) var(--ylf-ease-standard, ease);
54
+
55
+ &--sm {
56
+ --_w: 40px;
57
+ --_h: 24px;
58
+ }
59
+
60
+ &:focus-visible {
61
+ outline: none;
62
+ box-shadow:
63
+ 0 0 0 3px var(--ylf-c-brand-soft, #eff6ff),
64
+ 0 0 0 5px var(--ylf-c-brand, #2563eb);
65
+ }
66
+
67
+ &[data-disabled] {
68
+ opacity: 0.5;
69
+ cursor: not-allowed;
70
+ }
71
+
72
+ // on 态:晴空蓝主色
73
+ &[data-state='checked'] {
74
+ background: var(--ylf-c-brand, #2563eb);
75
+ }
76
+
77
+ // 选中的强调轨道,前景与填充色成组。
78
+ &--accent[data-state='checked'],
79
+ &--aurora[data-state='checked'] {
80
+ background: var(--ylf-accent, var(--ylf-c-brand, #2563eb));
81
+ }
82
+
83
+ &__thumb {
84
+ display: block;
85
+ width: calc(var(--_h) - var(--_pad) * 2);
86
+ height: calc(var(--_h) - var(--_pad) * 2);
87
+ border-radius: 50%;
88
+ background: #fff;
89
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
90
+ transform: translateX(var(--_pad));
91
+ transition: transform var(--ylf-duration-normal, 240ms) var(--ylf-ease-bounce, cubic-bezier(0.34, 1.56, 0.64, 1));
92
+ will-change: transform;
93
+ }
94
+
95
+ &[data-state='checked'] &__thumb {
96
+ background: var(--ylf-c-text-on-accent, #fff);
97
+ transform: translateX(calc(var(--_w) - var(--_h) + var(--_pad)));
98
+ }
99
+ &--accent[data-state='checked'] &__thumb,
100
+ &--aurora[data-state='checked'] &__thumb {
101
+ background: var(--ylf-accent-on, var(--ylf-c-text-on-accent, #fff));
102
+ }
103
+ }
104
+
105
+ @media (prefers-reduced-motion: reduce) {
106
+ .ylf-switch,
107
+ .ylf-switch__thumb {
108
+ transition: none;
109
+ }
110
+ }
111
+ </style>
@@ -0,0 +1,117 @@
1
+ <script lang="ts" setup>
2
+ import { TabsContent, TabsIndicator, TabsList, TabsRoot, TabsTrigger } from 'reka-ui'
3
+
4
+ interface TabItem {
5
+ label: string
6
+ value: string
7
+ disabled?: boolean
8
+ }
9
+
10
+ withDefaults(defineProps<{
11
+ items: TabItem[]
12
+ orientation?: 'horizontal' | 'vertical'
13
+ }>(), {
14
+ orientation: 'horizontal',
15
+ })
16
+
17
+ const model = defineModel<string>()
18
+ </script>
19
+
20
+ <template>
21
+ <TabsRoot
22
+ v-model="model"
23
+ :orientation="orientation"
24
+ class="ylf-tabs"
25
+ :class="`ylf-tabs--${orientation}`"
26
+ >
27
+ <TabsList class="ylf-tabs__list">
28
+ <TabsIndicator class="ylf-tabs__indicator" />
29
+ <TabsTrigger
30
+ v-for="t in items"
31
+ :key="t.value"
32
+ :value="t.value"
33
+ :disabled="t.disabled"
34
+ class="ylf-tabs__trigger"
35
+ >
36
+ {{ t.label }}
37
+ </TabsTrigger>
38
+ </TabsList>
39
+ <TabsContent
40
+ v-for="t in items"
41
+ :key="t.value"
42
+ :value="t.value"
43
+ class="ylf-tabs__content"
44
+ >
45
+ <slot :name="t.value" />
46
+ </TabsContent>
47
+ </TabsRoot>
48
+ </template>
49
+
50
+ <style lang="scss">
51
+ .ylf-tabs__list {
52
+ position: relative;
53
+ display: flex;
54
+ gap: 4px;
55
+ border-bottom: 1px solid var(--ylf-c-border, #e2e8f0);
56
+ }
57
+
58
+ .ylf-tabs__trigger {
59
+ position: relative;
60
+ padding: 10px 16px;
61
+ font-family: inherit;
62
+ font-size: 15px;
63
+ font-weight: 500;
64
+ color: var(--ylf-c-text-2, #475569);
65
+ background: transparent;
66
+ border: none;
67
+ cursor: pointer;
68
+ transition: color 0.2s ease;
69
+
70
+ &:hover:not([data-disabled]) {
71
+ color: var(--ylf-c-text, #0f172a);
72
+ }
73
+
74
+ &[data-state='active'] {
75
+ color: var(--ylf-c-brand, #2563eb);
76
+ }
77
+
78
+ &[data-disabled] {
79
+ opacity: 0.45;
80
+ cursor: not-allowed;
81
+ }
82
+
83
+ &:focus-visible {
84
+ outline: none;
85
+ border-radius: var(--ylf-radius-sm, 10px);
86
+ box-shadow: 0 0 0 3px var(--ylf-c-brand-soft, #eff6ff);
87
+ }
88
+ }
89
+
90
+ .ylf-tabs__indicator {
91
+ position: absolute;
92
+ bottom: -1px;
93
+ left: 0;
94
+ width: var(--reka-tabs-indicator-size);
95
+ height: 2.5px;
96
+ border-radius: 999px;
97
+ background: var(--ylf-c-brand, #2563eb);
98
+ transform: translateX(var(--reka-tabs-indicator-position));
99
+ transition:
100
+ transform 0.25s var(--ylf-ease-bounce, cubic-bezier(0.34, 1.56, 0.64, 1)),
101
+ width 0.25s ease;
102
+ }
103
+
104
+ .ylf-tabs__content {
105
+ padding-top: 16px;
106
+
107
+ &:focus-visible {
108
+ outline: none;
109
+ }
110
+ }
111
+
112
+ @media (prefers-reduced-motion: reduce) {
113
+ .ylf-tabs__indicator {
114
+ transition: none;
115
+ }
116
+ }
117
+ </style>
@@ -0,0 +1,67 @@
1
+ <script lang="ts" setup>
2
+ // 行为 / 定位 / a11y 由 reka-ui 提供;皮肤走 token。
3
+ import { TooltipArrow, TooltipContent, TooltipPortal, TooltipProvider, TooltipRoot, TooltipTrigger } from 'reka-ui'
4
+
5
+ withDefaults(defineProps<{
6
+ content?: string
7
+ side?: 'top' | 'right' | 'bottom' | 'left'
8
+ delay?: number
9
+ }>(), {
10
+ side: 'top',
11
+ delay: 300,
12
+ })
13
+ </script>
14
+
15
+ <template>
16
+ <TooltipProvider :delay-duration="delay">
17
+ <TooltipRoot>
18
+ <TooltipTrigger as-child>
19
+ <slot />
20
+ </TooltipTrigger>
21
+ <TooltipPortal>
22
+ <TooltipContent :side="side" :side-offset="6" class="ylf-tooltip">
23
+ <slot name="content">
24
+ {{ content }}
25
+ </slot>
26
+ <TooltipArrow class="ylf-tooltip__arrow" :width="10" :height="5" />
27
+ </TooltipContent>
28
+ </TooltipPortal>
29
+ </TooltipRoot>
30
+ </TooltipProvider>
31
+ </template>
32
+
33
+ <style lang="scss">
34
+ .ylf-tooltip {
35
+ z-index: 110;
36
+ max-width: 240px;
37
+ padding: 7px 11px;
38
+ font-size: 13px;
39
+ line-height: 1.5;
40
+ color: var(--ylf-c-bg, #fbfcff);
41
+ background: var(--ylf-c-text, #0f172a);
42
+ border-radius: var(--ylf-radius-sm, 10px);
43
+ box-shadow: var(--ylf-shadow, 0 10px 28px -8px rgba(15, 23, 42, 0.16));
44
+ transform-origin: var(--reka-tooltip-content-transform-origin);
45
+
46
+ &[data-state='delayed-open'] {
47
+ animation: ylf-pop-in 0.16s ease;
48
+ }
49
+
50
+ &__arrow {
51
+ fill: var(--ylf-c-text, #0f172a);
52
+ }
53
+ }
54
+
55
+ @keyframes ylf-pop-in {
56
+ from {
57
+ opacity: 0;
58
+ transform: scale(0.94);
59
+ }
60
+ }
61
+
62
+ @media (prefers-reduced-motion: reduce) {
63
+ .ylf-tooltip[data-state='delayed-open'] {
64
+ animation: none;
65
+ }
66
+ }
67
+ </style>
@@ -0,0 +1,11 @@
1
+ <script setup lang="ts">
2
+ const items = [
3
+ { value: 'a', title: '什么是 YunLeFun Design?', content: '云乐坊设计系统,统一设计规范、品牌视觉与 UI 实现;默认晴空蓝为主,高饱和纯色点缀。' },
4
+ { value: 'b', title: '为什么基于 reka-ui?', content: 'reka 管行为与可访问性,我们只管皮肤——省心,且无障碍达标。' },
5
+ { value: 'c', title: '支持暗色吗?', content: '晴空白与深蓝夜空两套中性色,token 驱动,零配置随主题切换。' },
6
+ ]
7
+ </script>
8
+
9
+ <template>
10
+ <YlfAccordion :items="items" />
11
+ </template>
@@ -0,0 +1,19 @@
1
+ ---
2
+ title: Accordion
3
+ title_zh: 手风琴
4
+ ---
5
+
6
+ 手风琴:展开/收起、键盘导航、单开/多开基于 [reka-ui](https://reka-ui.com),高度过渡与外观走 token。
7
+
8
+ ## Props
9
+
10
+ | 属性 | 说明 | 类型 | 默认值 |
11
+ | ------------- | -------------------------------------------- | --------------------- | -------- |
12
+ | `v-model` | 展开项 | `string \| string[]` | — |
13
+ | `items` | 列表 `{ value, title, content?, disabled? }` | `AccordionItemData[]` | — |
14
+ | `type` | 单开 / 多开 | `single \| multiple` | `single` |
15
+ | `collapsible` | 单开模式允许全部收起 | `boolean` | `true` |
16
+
17
+ ## Slots
18
+
19
+ 每项内容可用 `value` 同名插槽覆盖 `content`。
@@ -0,0 +1,9 @@
1
+ <template>
2
+ <div class="flex flex-wrap items-center gap-4">
3
+ <YlfAvatar src="https://avatars.githubusercontent.com/u/24221472" alt="YunYouJun" size="lg" />
4
+ <YlfAvatar src="https://avatars.githubusercontent.com/u/24221472" alt="YunYouJun" />
5
+ <YlfAvatar src="https://avatars.githubusercontent.com/u/24221472" alt="YunYouJun" size="sm" />
6
+ <YlfAvatar fallback="云" />
7
+ <YlfAvatar fallback="YLF" size="lg" />
8
+ </div>
9
+ </template>
@@ -0,0 +1,15 @@
1
+ ---
2
+ title: Avatar
3
+ title_zh: 头像
4
+ ---
5
+
6
+ 头像:图片加载状态管理与回退基于 [reka-ui](https://reka-ui.com),加载失败时优雅回退到首字。
7
+
8
+ ## Props
9
+
10
+ | 属性 | 说明 | 类型 | 默认值 |
11
+ | ---------- | ---------------------- | ---------------- | ------ |
12
+ | `src` | 图片地址 | `string` | — |
13
+ | `alt` | 替代文字 | `string` | — |
14
+ | `fallback` | 回退文字(如姓名首字) | `string` | — |
15
+ | `size` | 尺寸 | `sm \| md \| lg` | `md` |
@@ -0,0 +1,84 @@
1
+ <script setup lang="ts">
2
+ const tones = [
3
+ { value: 'blue', label: '晴空蓝' },
4
+ { value: 'sun', label: '精选集' },
5
+ { value: 'cyan', label: '工具' },
6
+ { value: 'coral', label: '活动' },
7
+ { value: 'pink', label: '创作' },
8
+ { value: 'green', label: '已完成' },
9
+ ] as const
10
+ const appearances = [
11
+ { value: 'solid', label: '实色' },
12
+ { value: 'soft', label: '柔色' },
13
+ { value: 'outline', label: '描边' },
14
+ ] as const
15
+ const statuses = [
16
+ { value: 'success', label: '已发布' },
17
+ { value: 'warning', label: '测试中' },
18
+ { value: 'danger', label: '发布失败' },
19
+ { value: 'info', label: '待审核' },
20
+ ] as const
21
+ </script>
22
+
23
+ <template>
24
+ <div class="ylf-badge-demo">
25
+ <div class="ylf-badge-demo__group">
26
+ <p>品牌与内容</p>
27
+ <div class="ylf-badge-demo__row">
28
+ <YlfBadge>新上线</YlfBadge>
29
+ <YlfBadge variant="featured">
30
+ 精选
31
+ </YlfBadge>
32
+ <YlfBadge variant="neutral">
33
+ 已归档
34
+ </YlfBadge>
35
+ </div>
36
+ </div>
37
+ <div class="ylf-badge-demo__group">
38
+ <p>分类与强调</p>
39
+ <div v-for="appearance in appearances" :key="appearance.value" class="ylf-badge-demo__row">
40
+ <span class="ylf-badge-demo__label">{{ appearance.label }}</span>
41
+ <YlfBadge v-for="tone in tones" :key="tone.value" variant="accent" :tone="tone.value" :appearance="appearance.value">
42
+ {{ tone.label }}
43
+ </YlfBadge>
44
+ </div>
45
+ </div>
46
+ <div class="ylf-badge-demo__group">
47
+ <p>状态与反馈</p>
48
+ <div v-for="appearance in appearances" :key="appearance.value" class="ylf-badge-demo__row">
49
+ <span class="ylf-badge-demo__label">{{ appearance.label }}</span>
50
+ <YlfBadge v-for="status in statuses" :key="status.value" :variant="status.value" :appearance="appearance.value">
51
+ {{ status.label }}
52
+ </YlfBadge>
53
+ </div>
54
+ </div>
55
+ </div>
56
+ </template>
57
+
58
+ <style scoped>
59
+ .ylf-badge-demo {
60
+ display: grid;
61
+ gap: var(--ylf-space-6);
62
+ }
63
+
64
+ .ylf-badge-demo__group > p {
65
+ margin: 0 0 var(--ylf-space-3);
66
+ color: var(--ylf-c-text-2);
67
+ font-size: 12px;
68
+ line-height: 1.5;
69
+ }
70
+
71
+ .ylf-badge-demo__row {
72
+ display: flex;
73
+ align-items: center;
74
+ flex-wrap: wrap;
75
+ gap: var(--ylf-space-3);
76
+ margin-top: var(--ylf-space-3);
77
+ }
78
+
79
+ .ylf-badge-demo__label {
80
+ width: 100%;
81
+ color: var(--ylf-c-text-2);
82
+ font-size: 12px;
83
+ }
84
+ </style>
@@ -0,0 +1,41 @@
1
+ ---
2
+ title: Badge
3
+ title_zh: 徽标
4
+ ---
5
+
6
+ 默认以轻浅晴空蓝标记内容,明黄星芒点缀精选;分类和状态使用同一套高饱和实色,搭配经过对比度校验的前景文字。
7
+
8
+ ## 选择徽标
9
+
10
+ - `brand`:新内容、版本等日常品牌标记。
11
+ - `featured`:精选、推荐等品牌标记,明黄星芒、浅黄底和中性文字。
12
+ - `accent`:高饱和实色,默认晴空蓝,使用 `tone` 选择明黄、青、珊瑚橙、桃粉或鲜绿。
13
+ - `neutral`:已归档、草稿等普通信息,无需暗示成功或错误。
14
+ - `success` / `warning` / `danger` / `info`:分别使用鲜绿、明黄、珊瑚橙与青色实底,配套状态图形和文字。
15
+
16
+ 徽标使用系统正文字体,默认 12px、500 字重,无阴影、发光或持续动画。前景、底色和描边使用配套 token,随明暗主题调整。使用简短明确的文字描述状态,颜色辅助识别。
17
+
18
+ 晴空蓝实底在浅色主题使用白字、深色主题使用深蓝字;其余纯色标签使用同色相深色文字,保证各组填充与前景的对比度。状态与强调色共享 token,详见[色彩与组件](/guide/colors#状态也来自同一套色板)。
19
+
20
+ 徽标用于展示信息;需要点击筛选或执行操作时,使用按钮等交互组件。
21
+
22
+ ## 强调程度
23
+
24
+ 同一个色彩角色可以选择 `appearance="solid"`(实色重点)、`soft`(柔色分类)或 `outline`(描边次级)。该属性只作用于 `accent` 与状态变体,其余变体沿用自身外观。
25
+
26
+ ## Props
27
+
28
+ | 属性 | 说明 | 类型 | 默认值 |
29
+ | ------------ | ----------------------------- | -------------------------------------------------------------------------------- | ------- |
30
+ | `variant` | 语义与品牌用途 | `featured \| accent \| brand \| neutral \| success \| warning \| danger \| info` | `brand` |
31
+ | `tone` | 强调色,仅作用于 `accent` | `blue \| sun \| cyan \| coral \| pink \| green` | `blue` |
32
+ | `appearance` | `accent` 与状态变体的强调程度 | `solid \| soft \| outline` | `solid` |
33
+ | `round` | 胶囊圆角;关闭后使用小圆角 | `boolean` | `true` |
34
+
35
+ `tone` 可选 `blue | sun | cyan | coral | pink | green`,默认 `blue`(晴空蓝),仅作用于 `accent`。`featured` 始终使用精选 token,不随 `tone` 改变。旧 `aurora` 值映射到 `featured`。
36
+
37
+ ## Slots
38
+
39
+ | 名称 | 说明 |
40
+ | --------- | -------- |
41
+ | `default` | 徽标内容 |
@@ -1,5 +1,5 @@
1
1
  <script lang="ts" setup>
2
- import type { BottomMenuItem } from '@yunlefun/vue'
2
+ import type { BottomMenuItem } from './index'
3
3
  import { ref } from 'vue'
4
4
 
5
5
  const items: BottomMenuItem[] = [
@@ -15,6 +15,12 @@ const items: BottomMenuItem[] = [
15
15
  title: '发现',
16
16
  to: '/discover',
17
17
  },
18
+ {
19
+ icon: 'i-ri-copper-coin-line',
20
+ activeIcon: 'i-ri-copper-coin-fill',
21
+ title: '云币',
22
+ to: '/coin',
23
+ },
18
24
  {
19
25
  icon: 'i-ri-user-line',
20
26
  activeIcon: 'i-ri-user-fill',
@@ -37,13 +43,16 @@ function onClick(item: BottomMenuItem) {
37
43
  </script>
38
44
 
39
45
  <template>
40
- <YlfBottomMenu shadow>
41
- <YlfBottomMenuItem
42
- v-for="item in items"
43
- :key="item.to"
44
- :item="item"
45
- :active="active === item.to"
46
- @click="onClick"
47
- />
48
- </YlfBottomMenu>
46
+ <div class="mx-auto max-w-xs overflow-hidden border border-$ylf-c-border rounded-ylf-xl">
47
+ <div class="h-28 op-90 bg-brand-gradient" />
48
+ <YlfBottomMenu shadow>
49
+ <YlfBottomMenuItem
50
+ v-for="item in items"
51
+ :key="item.to"
52
+ :item="item"
53
+ :active="active === item.to"
54
+ @click="onClick"
55
+ />
56
+ </YlfBottomMenu>
57
+ </div>
49
58
  </template>
@@ -2,3 +2,28 @@
2
2
  title: Bottom Menu
3
3
  title_zh: 底部菜单
4
4
  ---
5
+
6
+ 云玻璃底部导航:背景模糊通透,激活项使用晴空蓝主色。适合 H5 / 子应用的主导航。
7
+
8
+ ## YlfBottomMenu Props
9
+
10
+ | 属性 | 说明 | 类型 | 默认值 |
11
+ | -------- | -------- | --------- | ------- |
12
+ | `shadow` | 浮起阴影 | `boolean` | `false` |
13
+
14
+ ## YlfBottomMenuItem Props
15
+
16
+ | 属性 | 说明 | 类型 |
17
+ | -------- | ---------- | ---------------- |
18
+ | `item` | 菜单项数据 | `BottomMenuItem` |
19
+ | `active` | 是否激活 | `boolean` |
20
+
21
+ ## BottomMenuItem
22
+
23
+ | 字段 | 说明 | 类型 |
24
+ | ------------ | ---------------- | -------------------------- |
25
+ | `title` | 标题 | `string` |
26
+ | `icon` | 图标 class | `string` |
27
+ | `activeIcon` | 激活态图标 class | `string?` |
28
+ | `to` | 路由目标 | `string?` |
29
+ | `onClick` | 点击回调 | `(...args: any[]) => void` |