Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions playgrounds/nuxt/app/composables/useNavigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { upperName } from '../utils'
const components = [
'accordion',
'alert',
'alert-group',
'auth-form',
'avatar',
'badge',
Expand Down
53 changes: 53 additions & 0 deletions playgrounds/nuxt/app/pages/components/alert-group.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<script setup lang="ts">
import type { AlertProps } from '@nuxt/ui'
import { reactive } from 'vue'

const alertItems: AlertProps[] = [
{
title: 'First Alert',
description: 'This is the first alert in the group.',
icon: 'i-lucide-info',
color: 'primary'
},
{
title: 'Second Alert',
description: 'This is the second alert in the group. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque euismod, urna eu tincidunt consectetur, nisi nisl aliquam nunc, eget aliquam massa nisl quis neque. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Integer ac sem euismod, dictum erat at, dictum enim. Etiam euismod, urna eu tincidunt consectetur, nisi nisl aliquam nunc, eget aliquam massa nisl quis neque.',
icon: 'i-lucide-alert-triangle',
color: 'warning'
},
{
title: 'Third Alert',
description: 'This is the third alert in the group.',
icon: 'i-lucide-check-circle',
color: 'success'
},
{
title: 'Fourth Alert',
description: 'This is the fourth alert in the group.',
icon: 'i-lucide-x-circle',
color: 'error'
},
{
title: 'Fifth Alert',
description: 'This is the fifth alert in the group.',
icon: 'i-lucide-help-circle',
color: 'info'
}
]

const attrs = reactive<Record<string, any>>({
expand: [false],
max: [5]
})
</script>

<template>
<Navbar>
<UCheckbox v-model="attrs.expand[0]" label="Expand" />
<UInputNumber v-model="attrs.max[0]" :min="1" :max="10" label="Max" />
</Navbar>

<Matrix v-slot="props" :attrs="attrs" container-class="max-w-196">
<UAlertGroup :items="alertItems" v-bind="props" />
</Matrix>
</template>
71 changes: 71 additions & 0 deletions src/runtime/components/AlertGroup.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<script lang="ts">
import theme from '#build/ui/alert-group'
import type { AppConfig } from '@nuxt/schema'
import type { AlertProps } from '@nuxt/ui'
import type { ComponentConfig } from '../types/tv'

type AlertGroup = ComponentConfig<typeof theme, AppConfig, 'alertGroup'>

export interface AlertGroupProps {
items: AlertProps[]
/**
* @defaultValue false
*/
expand?: boolean
/**
* @defaultValue 5
*/
max?: number
class?: any
ui?: AlertGroup['slots']
}
</script>

<script setup lang="ts">
import { computed, ref } from 'vue'
import { useAppConfig } from '#imports'
import { useComponentUI } from '../composables/useComponentUI'
import { tv } from '../utils/tv'

const props = withDefaults(defineProps<AlertGroupProps>(), {
expand: false,
max: 5
})

const appConfig = useAppConfig() as AlertGroup['AppConfig']
const uiProp = useComponentUI('alertGroup', props)

// eslint-disable-next-line vue/no-dupe-keys
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.alertGroup || {}) })({}))

const hovered = ref(false)
const expanded = computed(() => props.expand || hovered.value)
</script>

<template>
<div
:data-expanded="expanded"
data-slot="root"
:class="ui.root({ class: [uiProp?.root, props.class] })"
@mouseenter="hovered = true"
@mouseleave="hovered = false"
@focusin="hovered = true"
@focusout="hovered = false"
>
<UAlert
v-for="(item, index) in props.items"
:key="`alert-${index}`"
v-bind="item"
:tabindex="0"
:data-expanded="expanded"
:data-front="index === 0"
:class="ui.items({ class: [uiProp?.items, props.class] })"
:style="{
width: expanded ? '100%' : `${Math.max(0, 100 - index * 3)}%`,
marginTop: expanded || index === 0 ? '0' : (index >= props.max ? '-51px' : '-33px'),
zIndex: props.items.length - index,
maxHeight: !expanded && index !== 0 ? '51px' : undefined
}"
/>
</div>
</template>
1 change: 1 addition & 0 deletions src/runtime/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from '../components/Accordion.vue'
export * from '../components/Alert.vue'
export * from '../components/AlertGroup.vue'
export * from '../components/App.vue'
export * from '../components/AuthForm.vue'
export * from '../components/Avatar.vue'
Expand Down
6 changes: 6 additions & 0 deletions src/theme/alert-group.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export default {
slots: {
root: 'group flex flex-col transition-all duration-300 data-[expanded=true]:gap-2 data-[expanded=false]:gap-0',
items: 'transition-all duration-300 mx-auto overflow-hidden not-first:group-data-[expanded=false]:*:invisible'
}
}
1 change: 1 addition & 0 deletions src/theme/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export { default as accordion } from './accordion'
export { default as alert } from './alert'
export { default as alertGroup } from './alert-group'
export { default as authForm } from './auth-form'
export { default as avatar } from './avatar'
export { default as avatarGroup } from './avatar-group'
Expand Down
Loading