feat: improve tippy demo (#5357)

This commit is contained in:
Netfan 2025-01-11 20:42:38 +08:00 committed by GitHub
parent a2637313f8
commit cb9c8db5ba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 191 additions and 113 deletions

View File

@ -10,25 +10,26 @@ import { usePreferences } from '@vben-core/preferences';
import useTippyDirective from './directive'; import useTippyDirective from './directive';
import 'tippy.js/dist/tippy.css'; import 'tippy.js/dist/tippy.css';
import 'tippy.js/dist/backdrop.css';
import 'tippy.js/themes/light.css'; import 'tippy.js/themes/light.css';
import 'tippy.js/animations/scale.css'; import 'tippy.js/animations/scale.css';
import 'tippy.js/animations/scale-subtle.css'; import 'tippy.js/animations/shift-toward.css';
import 'tippy.js/animations/scale-extreme.css';
import 'tippy.js/animations/shift-away.css'; import 'tippy.js/animations/shift-away.css';
import 'tippy.js/animations/perspective.css'; import 'tippy.js/animations/perspective.css';
const { isDark } = usePreferences(); const { isDark } = usePreferences();
export type TippyProps = Props & { export type TippyProps = Partial<
animation?: Props & {
| 'fade' animation?:
| 'perspective' | 'fade'
| 'scale' | 'perspective'
| 'scale-extreme' | 'scale'
| 'scale-subtle' | 'shift-away'
| 'shift-away' | 'shift-toward'
| boolean; | boolean;
theme?: 'auto' | 'dark' | 'light'; theme?: 'auto' | 'dark' | 'light';
}; }
>;
export function initTippy(app: App<Element>, options?: DefaultProps) { export function initTippy(app: App<Element>, options?: DefaultProps) {
setDefaultProps({ setDefaultProps({

View File

@ -253,7 +253,7 @@ const routes: RouteRecordRaw[] = [
path: '/examples/tippy', path: '/examples/tippy',
component: () => import('#/views/examples/tippy/index.vue'), component: () => import('#/views/examples/tippy/index.vue'),
meta: { meta: {
icon: 'material-symbols:chat-bubble', icon: 'mdi:message-settings-outline',
title: 'Tippy', title: 'Tippy',
}, },
}, },

View File

@ -1,5 +1,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed, reactive } from 'vue'; import type { TippyProps } from '@vben/common-ui';
import { reactive } from 'vue';
import { Page, Tippy } from '@vben/common-ui'; import { Page, Tippy } from '@vben/common-ui';
@ -7,129 +9,91 @@ import { Button, Card, Flex } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form'; import { useVbenForm } from '#/adapter/form';
const props = reactive({ const tippyProps = reactive<TippyProps>({
animation: 'shift-away', animation: 'shift-away',
arrow: true, arrow: true,
content: '这是一个提示', content: '这是一个提示',
delay: 200, delay: [200, 200],
duration: 200, duration: 200,
followCursor: '', followCursor: false,
hideOnClick: '', hideOnClick: false,
inertia: true,
maxWidth: 'none', maxWidth: 'none',
placement: 'top', placement: 'top',
theme: 'dark', theme: 'dark',
trigger: 'mouseenter focusin',
}); });
const tippyProps = computed(() => { function parseBoolean(value: string) {
return { switch (value) {
...props, case 'false': {
followCursor: ['', 'true'].includes(props.followCursor) return false;
? !!props.followCursor }
: props.followCursor, case 'true': {
hideOnClick: ['', 'true'].includes(props.hideOnClick) return true;
? !!props.hideOnClick }
: props.hideOnClick, default: {
}; return value;
}); }
}
}
const [Form] = useVbenForm({ const [Form] = useVbenForm({
handleValuesChange(values) { handleValuesChange(values) {
Object.assign(props, { ...values }); Object.assign(tippyProps, {
...values,
delay: [values.delay1, values.delay2],
followCursor: parseBoolean(values.followCursor),
hideOnClick: parseBoolean(values.hideOnClick),
trigger: values.trigger.join(' '),
});
}, },
schema: [ schema: [
{
component: 'Select',
componentProps: {
class: 'w-full',
options: [
{ label: 'shift-away', value: 'shift-away' },
{ label: 'scale', value: 'scale' },
{ label: 'scale-extreme', value: 'scale-extreme' },
{ label: 'scale-subtle', value: 'scale-subtle' },
{ label: 'perspective', value: 'perspective' },
{ label: 'fade', value: 'fade' },
],
},
defaultValue: props.animation,
fieldName: 'animation',
label: '动画',
},
{
component: 'InputNumber',
defaultValue: props.duration,
fieldName: 'duration',
label: '动画时长',
},
{
component: 'Input',
defaultValue: props.content,
fieldName: 'content',
label: '内容',
},
{
component: 'Switch',
defaultValue: props.arrow,
fieldName: 'arrow',
label: '箭头',
},
{
component: 'Select',
componentProps: {
class: 'w-full',
options: [
{ label: '不跟随', value: '' },
{ label: '完全跟随', value: 'true' },
{ label: '仅横向', value: 'horizontal' },
{ label: '仅纵向', value: 'vertical' },
{ label: '仅初始', value: 'initial' },
],
},
defaultValue: props.followCursor,
fieldName: 'followCursor',
label: '跟随指针',
},
{
component: 'Select',
componentProps: {
class: 'w-full',
options: [
{ label: '否', value: '' },
{ label: '是', value: 'true' },
{ label: '仅内部点击', value: 'toggle' },
],
},
defaultValue: props.hideOnClick,
fieldName: 'hideOnClick',
label: '点击后隐藏',
},
{
component: 'InputNumber',
defaultValue: 100,
fieldName: 'delay',
label: '延时',
},
{ {
component: 'RadioGroup', component: 'RadioGroup',
componentProps: { componentProps: {
buttonStyle: 'solid',
class: 'w-full',
options: [ options: [
{ label: 'auto', value: 'auto' }, { label: '自动', value: 'auto' },
{ label: 'dark', value: 'dark' }, { label: '暗色', value: 'dark' },
{ label: 'light', value: 'light' }, { label: '亮色', value: 'light' },
], ],
optionType: 'button',
}, },
defaultValue: props.theme, defaultValue: tippyProps.theme,
fieldName: 'theme', fieldName: 'theme',
label: '主题', label: '主题',
}, },
{ {
component: 'Input', component: 'Select',
componentProps: { componentProps: {
placeholder: 'none、200px', class: 'w-full',
options: [
{ label: '向上滑入', value: 'shift-away' },
{ label: '向下滑入', value: 'shift-toward' },
{ label: '缩放', value: 'scale' },
{ label: '透视', value: 'perspective' },
{ label: '淡入', value: 'fade' },
],
}, },
defaultValue: props.maxWidth, defaultValue: tippyProps.animation,
fieldName: 'maxWidth', fieldName: 'animation',
label: '最大宽度', label: '动画类型',
},
{
component: 'RadioGroup',
componentProps: {
buttonStyle: 'solid',
options: [
{ label: '是', value: true },
{ label: '否', value: false },
],
optionType: 'button',
},
defaultValue: tippyProps.inertia,
fieldName: 'inertia',
label: '动画惯性',
}, },
{ {
component: 'Select', component: 'Select',
@ -150,11 +114,124 @@ const [Form] = useVbenForm({
{ label: '右下', value: 'right-end' }, { label: '右下', value: 'right-end' },
], ],
}, },
defaultValue: 'top', defaultValue: tippyProps.placement,
fieldName: 'placement', fieldName: 'placement',
label: '位置', label: '位置',
}, },
{
component: 'InputNumber',
componentProps: {
addonAfter: '毫秒',
},
defaultValue: tippyProps.duration,
fieldName: 'duration',
label: '动画时长',
},
{
component: 'InputNumber',
componentProps: {
addonAfter: '毫秒',
},
defaultValue: 100,
fieldName: 'delay1',
label: '显示延时',
},
{
component: 'InputNumber',
componentProps: {
addonAfter: '毫秒',
},
defaultValue: 100,
fieldName: 'delay2',
label: '隐藏延时',
},
{
component: 'Input',
defaultValue: tippyProps.content,
fieldName: 'content',
label: '内容',
},
{
component: 'RadioGroup',
componentProps: {
buttonStyle: 'solid',
options: [
{ label: '是', value: true },
{ label: '否', value: false },
],
optionType: 'button',
},
defaultValue: tippyProps.arrow,
fieldName: 'arrow',
label: '指示箭头',
},
{
component: 'Select',
componentProps: {
class: 'w-full',
options: [
{ label: '不跟随', value: 'false' },
{ label: '完全跟随', value: 'true' },
{ label: '仅横向', value: 'horizontal' },
{ label: '仅纵向', value: 'vertical' },
{ label: '仅初始', value: 'initial' },
],
},
defaultValue: tippyProps.followCursor?.toString(),
fieldName: 'followCursor',
label: '跟随指针',
},
{
component: 'Select',
componentProps: {
class: 'w-full',
mode: 'multiple',
options: [
{ label: '鼠标移入', value: 'mouseenter' },
{ label: '被点击', value: 'click' },
{ label: '获得焦点', value: 'focusin' },
{ label: '无触发,仅手动', value: 'manual' },
],
},
defaultValue: tippyProps.trigger?.split(' '),
fieldName: 'trigger',
label: '触发方式',
},
{
component: 'Select',
componentProps: {
class: 'w-full',
options: [
{ label: '否', value: 'false' },
{ label: '是', value: 'true' },
{ label: '仅内部', value: 'toggle' },
],
},
defaultValue: tippyProps.hideOnClick?.toString(),
dependencies: {
componentProps(_, formAction) {
return {
disabled: !formAction.values.trigger.includes('click'),
};
},
triggerFields: ['trigger'],
},
fieldName: 'hideOnClick',
help: '只有在触发方式为`click`时才有效',
label: '点击后隐藏',
},
{
component: 'Input',
componentProps: {
allowClear: true,
placeholder: 'none、200px',
},
defaultValue: tippyProps.maxWidth,
fieldName: 'maxWidth',
label: '最大宽度',
},
], ],
showDefaultActions: false,
wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3', wrapperClass: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-3',
}); });