Skip to content

Commit

Permalink
feat: menu
Browse files Browse the repository at this point in the history
  • Loading branch information
JasKang committed Mar 27, 2024
1 parent 5eb6d51 commit 6791dcc
Show file tree
Hide file tree
Showing 19 changed files with 194 additions and 13 deletions.
4 changes: 4 additions & 0 deletions packages/docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@ export default defineConfigWithTheme<ThemeConfig>({
{ key: 'Switch', link: '/components/switch' },
],
},
{
title: '展示',
children: [{ key: 'Menu', link: '/components/menu' }],
},
{
title: '反馈',
children: [
Expand Down
53 changes: 53 additions & 0 deletions packages/docs/components/menu.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<script setup>
import { ref } from 'vue'
import { Menu } from 'tailv'

const items = ref([
{
key: '1',
type: 'group',
label: 'Group title',
children: [
{key: '1-1', label: '1st menu item',
},
{key: '1-2', label: '2nd menu item',
},
],
},
{
key: '2',
label: 'sub menu',
children: [
{key: '2-1', label: '3rd menu item',
},
{key: '2-2', label: '4th menu item',},
],
},
{
key: '3',
label: 'disabled sub menu',
disabled: true,
children: [
{
key: '3-1',
label: '5d menu item',
},
{
key: '3-2',
label: '6th menu item',
},
],
},
])

</script>

# CheckboxGroup

## Default

<div class="flex flex-wrap gap-2 not-prose">
<div class="border border-slate-300">
<Menu :items="items" />
</div>
</div>
2 changes: 1 addition & 1 deletion packages/vue/src/Anchor/Anchor.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script setup lang="ts">
import { ref, computed, type PropType, toRef, provide, inject, watchEffect } from 'vue'
import { ref, computed, type PropType } from 'vue'
import type { AnchorItem } from './types'
defineOptions({ name: 'Anchor' })
Expand Down
17 changes: 17 additions & 0 deletions packages/vue/src/Badge/Badge.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<script setup lang="ts">
import { ref, computed } from 'vue'
defineOptions({ name: 'Badge' })
const emit = defineEmits<{ click: [any] }>()
const slots = defineSlots<{ default?(_: {}): any }>()
const props = defineProps({
color: String,
})
</script>
<template>
<span
class="inline-flex items-center rounded-md bg-slate-50 py-1 px-2 text-xs font-medium text-slate-600 ring-1 ring-gray-500/10 ring-inset"
>
<slot />
</span>
</template>
2 changes: 1 addition & 1 deletion packages/vue/src/Base/Popper/Popper.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
} from './core'
import { useModelValue } from '../../use/useModelValue'
defineOptions({ name: 'TPopover' })
defineOptions({ name: 'Popover' })
const props = defineProps({
open: { type: Boolean, default: undefined },
Expand Down
2 changes: 1 addition & 1 deletion packages/vue/src/Button/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type { ColorAlias } from '@/utils/theme'
import { createButtonCss } from './style'
defineOptions({ name: 'TButton' })
defineOptions({ name: 'Button' })
defineEmits<{ click: [Event] }>()
const slots = defineSlots<{ default?(_: {}): any; icon?(_: {}): any }>()
const props = defineProps({
Expand Down
2 changes: 1 addition & 1 deletion packages/vue/src/Checkbox/Checkbox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useModelValue } from '@/use/useModelValue'
import { computed, inject } from 'vue'
import { CheckboxGroupInjectKey } from './types'
defineOptions({ name: 'TCheckbox' })
defineOptions({ name: 'Checkbox' })
const emit = defineEmits<{ 'update:checked': [boolean]; change: [boolean] }>()
const props = defineProps({
value: { type: null, required: true },
Expand Down
4 changes: 2 additions & 2 deletions packages/vue/src/Checkbox/CheckboxGroup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import { type PropType, provide } from 'vue'
import { CheckboxGroupInjectKey } from './types'
import { useModelValue } from '@/use/useModelValue'
defineOptions({ name: 'TCheckboxGroup' })
defineOptions({ name: 'CheckboxGroup' })
const props = defineProps({ name: String, value: Array as PropType<unknown[]>, disabled: Boolean })
const emit = defineEmits<{ 'update:value': [unknown[]]; change: [unknown[]] }>()
const [modelValue, setModelValue] = useModelValue<unknown[]>(props, {
defaultValue: [],
onChange: (val: unknown[]) => {
emit('change', val)
emit('change', val)
},
})
provide(CheckboxGroupInjectKey, {
Expand Down
24 changes: 24 additions & 0 deletions packages/vue/src/Dropdown/Dropdown.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<script setup lang="ts">
import { ref, computed } from 'vue'
defineOptions({ name: 'Dropdown' })
const emit = defineEmits<{ click: [any] }>()
const slots = defineSlots<{ default?(_: {}): any }>()
const props = defineProps({
menu: Array,
})
</script>
<template>
<Popper trigger="click" placement="bottom" ref="popperRef">
<slot />
<template #content>
<div class="z-popover ring-opacity-5 rounded-md bg-white ring-1 shadow-lg ring-slate-300">
<slot name="content">
<div class="px-2">
{{ content }}
</div>
</slot>
</div>
</template>
</Popper>
</template>
2 changes: 1 addition & 1 deletion packages/vue/src/Input/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { type VNode, ref } from 'vue'
import { useModelValue } from '../use/useModelValue'
import RingInput from '../Base/RingInput.vue'
defineOptions({ name: 'TInput' })
defineOptions({ name: 'Input' })
const emit = defineEmits<{
'update:value': [string | number]
change: [string | number]
Expand Down
48 changes: 48 additions & 0 deletions packages/vue/src/Menu/Menu.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<script setup lang="ts">
import { ref, computed, type PropType } from 'vue'
import { isDividerItem, isGroupItem, isMenuItem, type MenuItem, type MenuItemType } from './types'
defineOptions({ name: 'Menu' })
const emit = defineEmits<{ click: [any] }>()
const slots = defineSlots<{ default?(_: {}): any }>()
const props = defineProps({
title: String,
items: {
type: Array as PropType<MenuItem[]>,
default: () => [],
},
})
const current = ref<MenuItemType>()
const isCurrent = (item: MenuItemType) => {
return item.key === current.value?.key
}
</script>
<template>
<nav class="flex flex-1 flex-col p-1" aria-label="Sidebar">
<ul role="list" class="space-y-1">
<li v-for="item in items">
<div v-if="isDividerItem(item)" class="bg-muted -mx-1 my-1 h-px" />
<div v-if="isGroupItem(item)" class="text-xs font-semibold leading-6 text-slate-400">{{ item.label }}</div>
<a
v-if="isMenuItem(item)"
:class="[
isCurrent(item) ? 'text-primary-600 bg-gray-50' : 'hover:text-primary-600 text-gray-700 hover:bg-gray-50',
'group flex gap-x-3 rounded-md p-2 text-sm font-semibold leading-6',
]"
>
<component
:is="item.icon"
:class="[
isCurrent(item) ? 'text-primary-600' : 'group-hover:text-primary-600 text-gray-400',
'h-6 w-6 shrink-0',
]"
aria-hidden="true"
/>
{{ item.label }}
</a>
</li>
</ul>
</nav>
</template>
2 changes: 2 additions & 0 deletions packages/vue/src/Menu/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as Menu } from './Menu.vue'
export type { MenuItem, MenuItemDividerType, MenuItemGroupType, MenuItemType } from './types'
32 changes: 32 additions & 0 deletions packages/vue/src/Menu/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import type { Component } from 'vue'

export type MenuItemType = {
type: never
key: string
label: string
disabled?: boolean
icon?: Component
children?: MenuItem[]
}

export type MenuItemGroupType = {
type: 'group'
label: string
children: MenuItem[]
}

export type MenuItemDividerType = {
type: 'divider'
}

export type MenuItem = MenuItemDividerType | MenuItemGroupType | MenuItemType

export function isDividerItem(item: MenuItem): item is MenuItemDividerType {
return item.type === 'divider'
}
export function isGroupItem(item: MenuItem): item is MenuItemGroupType {
return item.type === 'group'
}
export function isMenuItem(item: MenuItem): item is MenuItemType {
return !isGroupItem(item) && !isDividerItem(item)
}
2 changes: 1 addition & 1 deletion packages/vue/src/Popover/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { type PropType, ref } from 'vue'
import { Popper, type PopperPlacement, type PopperSizer, type PopperTrigger } from '../Base/Popper'
defineOptions({ name: 'TPopover' })
defineOptions({ name: 'Popover' })
defineProps({
content: String,
sizer: Function as PropType<PopperSizer>,
Expand Down
2 changes: 1 addition & 1 deletion packages/vue/src/Radio/Radio.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useModelValue } from '@/use/useModelValue'
import { computed, inject } from 'vue'
import { RadioGroupInjectKey } from './types'
defineOptions({ name: 'TRadio' })
defineOptions({ name: 'Radio' })
const emit = defineEmits<{ 'update:checked': [boolean]; change: [boolean] }>()
const props = defineProps({
value: { type: null, required: true },
Expand Down
4 changes: 2 additions & 2 deletions packages/vue/src/Select/Select.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import ChevronUpDown from '../Icon/ChevronUpDown.vue'
import type { PopperSizer } from '@/Base/Popper/core'
import { ScrollArea } from '../ScrollArea'
defineOptions({ name: 'TSelect', inheritAttrs: false })
defineOptions({ name: 'Select', inheritAttrs: false })
const emit = defineEmits(['update:value', 'change', 'select'])
const props = defineProps({
Expand Down Expand Up @@ -77,7 +77,7 @@ const focused = ref(false)
:key="item.value"
@click="selectHandler(item)"
class="relative cursor-default py-2 px-3 select-none"
:class="[item.value === modelValue ? 'bg-primary-500 text-white' : 'hover:bg-slate-100']"
:class="[item.value === modelValue ? 'bg-primary-100 text-primary-500 font-medium' : 'hover:bg-slate-100']"
>
{{ item.label }}
</div>
Expand Down
2 changes: 1 addition & 1 deletion packages/vue/src/Switch/Switch.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { useModelValue } from '@/use/useModelValue'
import { ref, computed } from 'vue'
defineOptions({ name: 'TSwitch' })
defineOptions({ name: 'Switch' })
const emit = defineEmits<{ 'update:checked': [boolean]; change: [boolean] }>()
const slots = defineSlots<{ default?(_: {}): any; open?(_: {}): any; close?(_: {}): any }>()
const props = defineProps({
Expand Down
2 changes: 1 addition & 1 deletion packages/vue/src/Tooltip/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { type PropType } from 'vue'
import { Popper, type PopperPlacement } from '../Base/Popper'
defineOptions({ name: 'TTooltip' })
defineOptions({ name: 'Tooltip' })
defineProps({
content: String,
placement: { type: String as PropType<PopperPlacement>, default: 'top' },
Expand Down
1 change: 1 addition & 0 deletions packages/vue/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export { ScrollArea } from './ScrollArea'
export { default as Input } from './Input/index.vue'
export { Select, type SelectOption } from './Select'
export { Switch } from './Switch'
export { Menu, type MenuItem, type MenuItemType, type MenuItemGroupType, type MenuItemDividerType } from './Menu'
export { default as Popover } from './Popover/index.vue'
export { default as Tooltip } from './Tooltip/index.vue'
export { default as SpaceCompact } from './Space/SpaceCompact.vue'
Expand Down

0 comments on commit 6791dcc

Please sign in to comment.