feat: harden ai agent admin workflow experience
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
export * from './authentication';
|
||||
export * from './basic';
|
||||
export * from './iframe';
|
||||
export * from './widgets';
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, nextTick } from 'vue';
|
||||
|
||||
import { VbenButton } from '@vben-core/shadcn-ui';
|
||||
import { computed } from 'vue';
|
||||
|
||||
interface Props {
|
||||
modelValue?: boolean;
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
@@ -15,81 +14,43 @@ defineOptions({
|
||||
});
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
modelValue: false,
|
||||
type: 'normal',
|
||||
});
|
||||
|
||||
const isDark = defineModel<boolean>();
|
||||
const emit = defineEmits<{
|
||||
'update:modelValue': [value: boolean];
|
||||
}>();
|
||||
|
||||
const theme = computed(() => {
|
||||
return isDark.value ? 'light' : 'dark';
|
||||
return props.modelValue ? 'light' : 'dark';
|
||||
});
|
||||
|
||||
const bindProps = computed(() => {
|
||||
const type = props.type;
|
||||
const buttonClass = computed(() => {
|
||||
const base =
|
||||
'inline-flex items-center justify-center whitespace-nowrap font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50';
|
||||
const mode =
|
||||
props.type === 'normal'
|
||||
? 'h-9 rounded-md px-4 py-2 text-sm hover:bg-heavy hover:text-heavy-foreground'
|
||||
: 'h-8 w-8 rounded-full px-1 text-lg hover:bg-accent hover:text-accent-foreground text-foreground/80';
|
||||
|
||||
return type === 'normal'
|
||||
? {
|
||||
variant: 'heavy' as const,
|
||||
}
|
||||
: {
|
||||
class: 'rounded-full',
|
||||
size: 'icon' as const,
|
||||
style: { padding: '7px' },
|
||||
variant: 'icon' as const,
|
||||
};
|
||||
return `${base} ${mode}`;
|
||||
});
|
||||
|
||||
function toggleTheme(event: MouseEvent) {
|
||||
const isAppearanceTransition =
|
||||
// @ts-expect-error
|
||||
document.startViewTransition &&
|
||||
!window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||
if (!isAppearanceTransition || !event) {
|
||||
isDark.value = !isDark.value;
|
||||
return;
|
||||
}
|
||||
const x = event.clientX;
|
||||
const y = event.clientY;
|
||||
const endRadius = Math.hypot(
|
||||
Math.max(x, innerWidth - x),
|
||||
Math.max(y, innerHeight - y),
|
||||
);
|
||||
// @ts-ignore startViewTransition
|
||||
const transition = document.startViewTransition(async () => {
|
||||
isDark.value = !isDark.value;
|
||||
await nextTick();
|
||||
});
|
||||
transition.ready.then(() => {
|
||||
const clipPath = [
|
||||
`circle(0px at ${x}px ${y}px)`,
|
||||
`circle(${endRadius}px at ${x}px ${y}px)`,
|
||||
];
|
||||
const animate = document.documentElement.animate(
|
||||
{
|
||||
clipPath: isDark.value ? [...clipPath].reverse() : clipPath,
|
||||
},
|
||||
{
|
||||
duration: 450,
|
||||
easing: 'ease-in',
|
||||
pseudoElement: isDark.value
|
||||
? '::view-transition-old(root)'
|
||||
: '::view-transition-new(root)',
|
||||
},
|
||||
);
|
||||
animate.onfinish = () => {
|
||||
transition.skipTransition();
|
||||
};
|
||||
});
|
||||
event.preventDefault();
|
||||
emit('update:modelValue', !props.modelValue);
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VbenButton
|
||||
<button
|
||||
:aria-label="theme"
|
||||
:class="[`is-${theme}`]"
|
||||
:class="[buttonClass, `is-${theme}`]"
|
||||
aria-live="polite"
|
||||
class="theme-toggle cursor-pointer border-none bg-none hover:animate-[shrink_0.3s_ease-in-out]"
|
||||
v-bind="bindProps"
|
||||
style="padding: 7px"
|
||||
type="button"
|
||||
@click.stop="toggleTheme"
|
||||
>
|
||||
<svg aria-hidden="true" height="24" viewBox="0 0 24 24" width="24">
|
||||
@@ -121,7 +82,7 @@ function toggleTheme(event: MouseEvent) {
|
||||
<line x1="18.36" x2="19.78" y1="5.64" y2="4.22" />
|
||||
</g>
|
||||
</svg>
|
||||
</VbenButton>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
Reference in New Issue
Block a user