mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-14 12:14:41 +01:00
@@ -2,7 +2,7 @@ export default defineAppConfig({
|
||||
toaster: {
|
||||
position: 'bottom-right' as const,
|
||||
expand: true,
|
||||
duration: 60000
|
||||
duration: 5000
|
||||
},
|
||||
ui: {
|
||||
primary: 'sky',
|
||||
|
||||
@@ -109,7 +109,7 @@ function removeToast () {
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col items-center gap-8">
|
||||
<div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<URadioGroup v-model="appConfig.toaster.position" :options="positions" />
|
||||
<UCheckbox v-model="appConfig.toaster.expand" label="Expand" class="mt-1" />
|
||||
<UInput v-model="appConfig.toaster.duration" label="Duration" type="number" class="mt-1" />
|
||||
|
||||
@@ -5,7 +5,7 @@ import type { ToastRootProps, ToastRootEmits } from 'radix-vue'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
import _appConfig from '#build/app.config'
|
||||
import theme from '#build/ui/toast'
|
||||
import type { AvatarProps, ButtonProps, IconProps } from '#ui/types'
|
||||
import type { AvatarProps, ButtonProps, IconProps, ToasterContext } from '#ui/types'
|
||||
|
||||
const appConfig = _appConfig as AppConfig & { ui: { toast: Partial<typeof theme> } }
|
||||
|
||||
@@ -19,17 +19,17 @@ export interface ToastProps extends Omit<ToastRootProps, 'asChild' | 'forceMount
|
||||
icon?: IconProps['name']
|
||||
avatar?: AvatarProps
|
||||
color?: ToastVariants['color']
|
||||
actions?: (ButtonProps & { click?: () => void })[]
|
||||
actions?: ButtonProps[]
|
||||
close?: ButtonProps | null
|
||||
class?: any
|
||||
ui?: Partial<typeof toast.slots>
|
||||
}
|
||||
|
||||
export interface ToastEmits extends ToastRootEmits { }
|
||||
export interface ToastEmits extends ToastRootEmits {}
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { ref, computed, inject, onMounted } from 'vue'
|
||||
import { ToastRoot, ToastTitle, ToastDescription, ToastAction, ToastClose, useForwardPropsEmits } from 'radix-vue'
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
import { useAppConfig } from '#imports'
|
||||
@@ -38,14 +38,15 @@ import { UIcon, UAvatar } from '#components'
|
||||
const props = defineProps<ToastProps>()
|
||||
const emits = defineEmits<ToastEmits>()
|
||||
|
||||
const toaster = inject<ToasterContext>('Toaster')
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
const rootProps = useForwardPropsEmits(reactivePick(props, 'as', 'defaultOpen', 'duration', 'open', 'type'), emits)
|
||||
|
||||
const multiline = computed(() => !!props.title && !!props.description)
|
||||
const duration = computed(() => props.duration || toaster?.value.duration)
|
||||
|
||||
const ui = computed(() => tv({ extend: toast, slots: props.ui })({
|
||||
color: props.color
|
||||
}))
|
||||
const ui = computed(() => tv({ extend: toast, slots: props.ui })({ color: props.color }))
|
||||
|
||||
const el = ref()
|
||||
const height = ref(0)
|
||||
@@ -56,7 +57,7 @@ onMounted(() => {
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
height.value = el.value.$el.getBoundingClientRect().height
|
||||
height.value = el.value.$el.getBoundingClientRect()?.height
|
||||
}, 0)
|
||||
})
|
||||
|
||||
@@ -66,7 +67,13 @@ defineExpose({
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ToastRoot ref="el" v-bind="rootProps" :class="ui.root({ class: props.class, multiline })" :style="{ '--height': height }">
|
||||
<ToastRoot
|
||||
ref="el"
|
||||
v-slot="{ remaining }"
|
||||
v-bind="rootProps"
|
||||
:class="ui.root({ class: props.class, multiline })"
|
||||
:style="{ '--height': height }"
|
||||
>
|
||||
<UAvatar v-if="avatar" size="2xl" v-bind="avatar" :class="ui.avatar()" />
|
||||
<UIcon v-else-if="icon" :name="icon" :class="ui.icon()" />
|
||||
|
||||
@@ -110,7 +117,6 @@ defineExpose({
|
||||
</ToastClose>
|
||||
</div>
|
||||
|
||||
<div :class="ui.progress()" />
|
||||
<div :class="ui.mask()" />
|
||||
<div v-if="remaining && duration" :class="ui.progress()" :style="{ width: `${remaining / duration * 100}%` }" />
|
||||
</ToastRoot>
|
||||
</template>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<script lang="ts">
|
||||
import type { ComputedRef } from 'vue'
|
||||
import { tv, type VariantProps } from 'tailwind-variants'
|
||||
import type { ToastProviderProps } from 'radix-vue'
|
||||
import type { AppConfig } from '@nuxt/schema'
|
||||
@@ -17,17 +18,21 @@ export interface ToasterProps extends Omit<ToastProviderProps, 'swipeDirection'>
|
||||
class?: any
|
||||
ui?: Partial<typeof toaster.slots>
|
||||
}
|
||||
|
||||
export type ToasterContext = ComputedRef<{
|
||||
duration: number
|
||||
}>
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import { ref, computed, provide } from 'vue'
|
||||
import { ToastProvider, ToastViewport, useForwardProps } from 'radix-vue'
|
||||
import { reactivePick } from '@vueuse/core'
|
||||
import { useToast } from '#imports'
|
||||
import { UToast } from '#components'
|
||||
import { omit } from '#ui/utils'
|
||||
|
||||
const props = withDefaults(defineProps<ToasterProps>(), { expand: true })
|
||||
const props = withDefaults(defineProps<ToasterProps>(), { expand: true, duration: 5000 })
|
||||
|
||||
const providerProps = useForwardProps(reactivePick(props, 'duration', 'label', 'swipeThreshold'))
|
||||
|
||||
@@ -73,6 +78,8 @@ const frontHeight = computed(() => refs.value[refs.value.length - 1]?.height ||
|
||||
function getOffset (index: number) {
|
||||
return refs.value.slice(index + 1).reduce((acc, { height }) => acc + height + 16, 0)
|
||||
}
|
||||
|
||||
provide<ToasterContext>('Toaster', providerProps)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -7,8 +7,7 @@ export default (config: { colors: string[] }) => ({
|
||||
icon: 'shrink-0 size-5',
|
||||
avatar: 'shrink-0',
|
||||
actions: 'flex gap-1.5 shrink-0',
|
||||
progress: 'absolute inset-0 rounded-lg border-b-2 z-[-1]',
|
||||
mask: 'absolute top-0 inset-0 bottom-[2px] bg-white dark:bg-gray-900 z-[-1]',
|
||||
progress: 'absolute inset-0 border-b-2 z-[-1]',
|
||||
close: 'p-1'
|
||||
},
|
||||
variants: {
|
||||
|
||||
Reference in New Issue
Block a user