diff --git a/packages/opendesign/src/components/dropdown/ODropdown.vue b/packages/opendesign/src/components/dropdown/ODropdown.vue index ee5c145d1d4ed66b4dc26e86aa9dfa358509b8fc..cf48944f6d4b93570559810bcab948ded9aaab1c 100644 --- a/packages/opendesign/src/components/dropdown/ODropdown.vue +++ b/packages/opendesign/src/components/dropdown/ODropdown.vue @@ -1,17 +1,59 @@ - + diff --git a/packages/opendesign/src/components/dropdown/ODropdownItem.vue b/packages/opendesign/src/components/dropdown/ODropdownItem.vue new file mode 100644 index 0000000000000000000000000000000000000000..54c0ca1cc8eaccb15ecf14bcf4e7cac95d70f539 --- /dev/null +++ b/packages/opendesign/src/components/dropdown/ODropdownItem.vue @@ -0,0 +1,24 @@ + + + + + diff --git a/packages/opendesign/src/components/dropdown/__demo__/DropdownBasic.vue b/packages/opendesign/src/components/dropdown/__demo__/DropdownBasic.vue new file mode 100644 index 0000000000000000000000000000000000000000..3227b4dc823d75258fa630dd0edcdddfafdd0a8d --- /dev/null +++ b/packages/opendesign/src/components/dropdown/__demo__/DropdownBasic.vue @@ -0,0 +1,25 @@ + + + diff --git a/packages/opendesign/src/components/dropdown/__demo__/IndexDropdown.vue b/packages/opendesign/src/components/dropdown/__demo__/IndexDropdown.vue new file mode 100644 index 0000000000000000000000000000000000000000..0408b4ca437a2da23827efd7c8734a3f65cdabbe --- /dev/null +++ b/packages/opendesign/src/components/dropdown/__demo__/IndexDropdown.vue @@ -0,0 +1,11 @@ + + + diff --git a/packages/opendesign/src/components/dropdown/index.ts b/packages/opendesign/src/components/dropdown/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..b6ff5169abe181f9f220a0209b82a35463505b62 --- /dev/null +++ b/packages/opendesign/src/components/dropdown/index.ts @@ -0,0 +1,18 @@ +import type { App } from 'vue'; + +import _ODropdown from './ODropdown.vue'; +import _ODropdownItem from './ODropdownItem.vue'; + +const ODropdown = Object.assign(_ODropdown, { + install(app: App) { + app.component(_ODropdown.name, _ODropdown); + }, +}); + +const ODropdownItem = Object.assign(_ODropdownItem, { + install(app: App) { + app.component(_ODropdownItem.name, _ODropdownItem); + }, +}); + +export { ODropdown, ODropdownItem }; diff --git a/packages/opendesign/src/components/dropdown/provide.ts b/packages/opendesign/src/components/dropdown/provide.ts new file mode 100644 index 0000000000000000000000000000000000000000..77ee794c3efdb77d91172c71015085f74fd938a8 --- /dev/null +++ b/packages/opendesign/src/components/dropdown/provide.ts @@ -0,0 +1,5 @@ +import { InjectionKey } from 'vue'; + +export const dropdownInjectKey: InjectionKey<{ + updateVisible: (val: boolean) => void; +}> = Symbol('provide-dropdown'); diff --git a/packages/opendesign/src/components/dropdown/style/index.scss b/packages/opendesign/src/components/dropdown/style/index.scss new file mode 100644 index 0000000000000000000000000000000000000000..efd9d3489fe3c79dc85736017210d0421dfec716 --- /dev/null +++ b/packages/opendesign/src/components/dropdown/style/index.scss @@ -0,0 +1,32 @@ +@use './var.scss'; + +.o-dropdown-list { + list-style: none; + margin: 0; + padding: 0; + background-color: var(--dropdown-list-bg); + box-shadow: var(--dropdown-list-shadow); + border-radius: var(--dropdown-list-radius); + border: var(--dropdown-list-bd); +} + +.o-dropdown-item { + display: flex; + align-items: center; + padding: var(--dropdown-item-padding); + background-color: var(--dropdown-item-bg-color); + font-size: var(--dropdown-item-text-size); + line-height: var(--dropdown-item-text-height); + cursor: pointer; + + &:not(.o-dropdown-item-disabled) { + &:hover { + background-color: var(--dropdown-item-bg-color-hover); + color: var(--dropdown-item-color-hover); + } + &.active { + color: var(--dropdown-item-color-active); + background-color: var(--dropdown-item-bg-color-active); + } + } +} diff --git a/packages/opendesign/src/components/dropdown/style/index.ts b/packages/opendesign/src/components/dropdown/style/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..97806f75ad147dd20bd3802a7001ea21d7911191 --- /dev/null +++ b/packages/opendesign/src/components/dropdown/style/index.ts @@ -0,0 +1,3 @@ +import '../../style'; +import '../../popup/style'; +import './index.scss'; diff --git a/packages/opendesign/src/components/dropdown/style/var.scss b/packages/opendesign/src/components/dropdown/style/var.scss new file mode 100644 index 0000000000000000000000000000000000000000..702a01358a471b41164f4c48aad1f94f09f4217b --- /dev/null +++ b/packages/opendesign/src/components/dropdown/style/var.scss @@ -0,0 +1,25 @@ +.o-dropdown-list { + --dropdown-list-bg: var(--o-color-control-light); + --dropdown-list-shadow: none; + --dropdown-list-bd: 1px solid var(--o-color-primary2); + --dropdown-list-radius: var(--o-radius-s); +} + +.o-dropdown-item { + --dropdown-item-color: var(--o-color-info2); + --dropdown-item-color-hover: var(--o-color-info1-inverse); + --dropdown-item-color-active: var(--o-color-info1-inverse); + --dropdown-item-color-disabled: var(--o-color-info4); + + --dropdown-item-bg-color: transparent; + --dropdown-item-bg-color-hover: var(--o-color-primary3-light); + --dropdown-item-bg-color-active: var(--o-color-primary2-light); + --dropdown-item-bg-color-disabled: var(--o-color-control4-light); + + --dropdown-item-text-size: var(--o-font_size-text); + --dropdown-item-text-height: var(--o-line_height-text); + + --dropdown-item-padding: 5px 12px; + --dropdown-item-text-size: var(--o-font_size-text); + --dropdown-item-text-height: var(--o-line_height-text); +} diff --git a/packages/opendesign/src/components/dropdown/types.ts b/packages/opendesign/src/components/dropdown/types.ts new file mode 100644 index 0000000000000000000000000000000000000000..6db69939c0ac6fade965ea66a391c823f3dc1c59 --- /dev/null +++ b/packages/opendesign/src/components/dropdown/types.ts @@ -0,0 +1,100 @@ +import { PopupPositionT, PopupTriggerT } from '../popup'; +import { ExtractPropTypes, PropType } from 'vue'; +import type { SizeT, RoundT } from '../_shared/global'; + +export const dropdownProps = { + /** + * 弹出框是否可见 + */ + visible: { + type: Boolean, + }, + /** + * 非受控模式,弹出框是否默认可见 + */ + defaultVisible: { + type: Boolean, + default: false, + }, + /** + * 大小 + */ + size: { + type: String as PropType, + }, + /** + * 圆角值 + */ + round: { + type: String as PropType, + }, + /** + * 下拉选项触发方式 + */ + trigger: { + type: String as PropType, + default: 'click', + }, + /** + * 下拉选项位置 + */ + optionPosition: { + type: String as PropType, + default: 'bl', + }, + /** + * 下拉选项宽度自适应规则 + * 'auto':自动 | 'min-width':最小宽度与选择框一致 | 'width': 宽度与选择框一致 + */ + optionWidthMode: { + type: String as PropType<'auto' | 'min-width' | 'width'>, + default: 'min-width', + }, + /** + * 下拉容器自定义类 + */ + optionWrapClass: { + type: String, + }, + /** + * 是否在结束选择时,卸载下拉选项 + * v-model + */ + unmountOnHide: { + type: Boolean, + default: true, + }, + /** + * 过渡名称 + */ + transition: { + type: String, + }, +}; + +export type DropdownPropsT = ExtractPropTypes; + +export const dropdownItemProps = { + /** + * 显示文本 + */ + label: { + type: String, + default: '', + }, + /** + * 选项值 + */ + value: { + type: [String, Number] as PropType, + default: '', + }, + /** + * 是否禁用 + */ + disabled: { + type: Boolean, + }, +}; + +export type DropdownItemPropsT = ExtractPropTypes; diff --git a/packages/portal/src/router.ts b/packages/portal/src/router.ts index 4f1533f3c28469cc30d0494558d166078488ef9c..1e512dd62b751fc1a773314113dc37a0aa217b39 100644 --- a/packages/portal/src/router.ts +++ b/packages/portal/src/router.ts @@ -153,6 +153,12 @@ export const routes = [ label: '菜单', component: () => import('@components/menu/__demo__/IndexMenu.vue'), }, + { + path: '/dropdown', + name: 'ODropdown', + label: '下拉菜单', + component: () => import('@components/dropdown/__demo__/IndexDropdown.vue'), + }, ]; export const router = createRouter({