Skip to content
This repository has been archived by the owner on Sep 24, 2024. It is now read-only.

feat: add Notifications component #136

Merged
merged 2 commits into from
Sep 13, 2023
Merged
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
2 changes: 1 addition & 1 deletion packages/nuxt-ui-vue/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nuxt-ui-vue",
"version": "1.0.1-beta.0",
"version": "1.0.1-beta.1",
"private": false,
"exports": {
".": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,12 @@ export interface UNotification extends UComponentRoot {
default?: objectProp
}

export interface UNotifications extends UComponentRoot {
position?: string
width?: string
container?: string
}

export interface UPagination extends UComponentRoot {
paginationBase?: string
rounded?: string
Expand Down Expand Up @@ -637,6 +643,7 @@ export type UTabsVariants = WithVariantProps<UTabs>
export type UTextareaVariants = WithVariantProps<UTextarea>
export type UModalVariants = WithVariantProps<UModal>
export type UNotificationVariants = WithVariantProps<UNotification>
export type UNotificationsVariants = WithVariantProps<UNotifications>
export type UKbdVariants = WithVariantProps<UKbd>
export type UPaginationVariants = WithVariantProps<UPagination>
export type UPopoverVariants = WithVariantProps<UPopover>
Expand Down
1 change: 1 addition & 0 deletions packages/nuxt-ui-vue/src/Types/enums/Components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export enum Components {
UKbd = 'UKbd',
UModal = 'UModal',
UNotification = 'UNotification',
UNotifications = 'UNotifications',
UPagination = 'UPagination',
UPopover = 'UPopover',
URadio = 'URadio',
Expand Down
3 changes: 2 additions & 1 deletion packages/nuxt-ui-vue/src/Types/variant.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Components } from './enums/Components'
import type { UAccordionVariants, UAlertVariants, UAvatarVariants, UBadgeVariants, UButtonGroupVariants, UButtonVariants, UCardVariants, UCheckboxVariants, UCommandPaletteVariants, UContainerVariants, UContextMenuVariants, UDropdownVariants, UFormGroupVariants, UIconVariants, UInputVariants, UKbdVariants, UModalVariants, UNotificationVariants, UPaginationVariants, URadioVariants, URangeVariants, USelectMenuVariants, USelectVariants, USkeletonVariants, USlideoverVariants, UTabsVariants, UTextareaVariants, UToggleVariants, UTooltipVariants, UVerticalNavigationVariants } from './componentsTypes/components'
import type { UAccordionVariants, UAlertVariants, UAvatarVariants, UBadgeVariants, UButtonGroupVariants, UButtonVariants, UCardVariants, UCheckboxVariants, UCommandPaletteVariants, UContainerVariants, UContextMenuVariants, UDropdownVariants, UFormGroupVariants, UIconVariants, UInputVariants, UKbdVariants, UModalVariants, UNotificationVariants, UNotificationsVariants, UPaginationVariants, URadioVariants, URangeVariants, USelectMenuVariants, USelectVariants, USkeletonVariants, USlideoverVariants, UTabsVariants, UTextareaVariants, UToggleVariants, UTooltipVariants, UVerticalNavigationVariants } from './componentsTypes/components'

export declare interface CSSClassKeyValuePair {
[key: string]: any
Expand Down Expand Up @@ -48,6 +48,7 @@ export interface NuxtLabsUIConfiguration {
[Components.UKbd]?: UKbdVariants
[Components.UModal]?: UModalVariants
[Components.UNotification]?: UNotificationVariants
[Components.UNotifications]?: UNotificationsVariants
[Components.UTextarea]?: UTextareaVariants
[Components.UPagination]?: UPaginationVariants
[Components.URadio]?: URadioVariants
Expand Down
1 change: 1 addition & 0 deletions packages/nuxt-ui-vue/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export { default as UIcon } from './elements/Icon/UIcon.vue'
export { default as UKbd } from './elements/Kbd/UKbd.vue'
export { default as UModal } from './overlays/Modal/UModal.vue'
export { default as UNotification } from './overlays/Notification/UNotification.vue'
export { default as UNotifications } from './overlays/Notification/UNotifications.vue'
export { default as UInput } from './forms/Input/UInput.vue'
export { default as ULink } from './elements/Link/ULink.vue'
export { default as UPagination } from './navigation/Pagination/UPagination.vue'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<!-- eslint-disable @typescript-eslint/ban-types -->
<script setup lang="ts">
import type { PropType } from 'vue'
import { computed, defineComponent, useAttrs } from 'vue'
import { omit } from 'lodash-es'
import classNames from 'classnames'
import UNotification from './UNotification.vue'
import type { VariantJSWithClassesListProps } from '@/utils/getVariantProps'
import { getVariantPropsWithClassesList } from '@/utils/getVariantProps'
import { useToast } from '@/composables/useToast'
import { Components } from '@/Types/enums/Components'
import type { UNotifications } from '@/Types/componentsTypes/components'
import { Positions } from '@/Types/enums/Positions'
import { useVariants } from '@/composables/useVariants'
import nuxtLabsTheme from '@/theme/nuxtLabsTheme'

export type Position = 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left'

const props = defineProps({
...getVariantPropsWithClassesList<UNotifications>(),
position: {
type: String as PropType<Position>,
default: Positions.BR,
},
})

const variant = computed(() => {
const customProps = {
...props,
variant: props.variant,
}
return useVariants<UNotifications>(
Components.UNotifications,
customProps as VariantJSWithClassesListProps<UNotifications>,
)
})

const { notifications, remove } = useToast()

const wrapperClass = computed(() => {
return classNames(
variant.value.root,
nuxtLabsTheme.UNotifications.base.position[props.position],
variant.value.width,
)
})

const attrs = useAttrs()

const attrsOmitted = omit(attrs, ['class'])
</script>

<script lang="ts">
export default defineComponent({
name: Components.UNotifications,
inheritAttrs: false,
})
</script>

<template>
<div :class="wrapperClass" v-bind="attrsOmitted">
<div v-if="notifications.length" :class="variant.container">
<div v-for="notification of notifications" :key="notification.id">
<UNotification
v-bind="notification"
:class="notification.click && 'cursor-pointer'"
@click="notification.click && notification.click(notification)"
@close="remove(notification.id)"
>
<template v-for="(_, name) in $slots" #[name]="slotData">
<slot :name="name" v-bind="slotData" />
</template>
</UNotification>
</div>
</div>
</div>
</template>
4 changes: 2 additions & 2 deletions packages/nuxt-ui-vue/src/composables/useCopyToClipboard.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { useClipboard } from '@vueuse/core'
import useToast from './useToast'
import { injectToast } from './useToast'
import type { Notification } from '@/Types/components/notification'

export function useCopyToClipboard(options: Partial<Notification> = {}) {
const { copy: copyToClipboard, isSupported } = useClipboard()
const toast = useToast()
const toast = injectToast()

function copy(text: string, success: { title?: string; description?: string } = {}, failure: { title?: string; description?: string } = {}) {
if (!isSupported)
Expand Down
28 changes: 22 additions & 6 deletions packages/nuxt-ui-vue/src/composables/useToast.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
import { ref } from 'vue'
/* eslint-disable symbol-description */
import type { InjectionKey } from 'vue'
import { inject, provide, ref } from 'vue'
import type { Notification } from '@/Types/components/notification'

function useToast() {
const notifications = ref([])
interface ToastProvider {
add: (notification: Partial<Notification>) => void
remove: (id: string) => void
}

const toastSymbol: InjectionKey<ToastProvider | any> = Symbol()

export function injectToast() {
const notifications = ref<Notification[]>([])

function add(notification: Partial<Notification>) {
const body = {
Expand All @@ -12,8 +21,6 @@ function useToast() {

const index = notifications.value.findIndex((n: Notification) => n.id === body.id)
if (index === -1)
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
notifications.value.push(body as Notification)

return body
Expand All @@ -23,10 +30,19 @@ function useToast() {
notifications.value = notifications.value.filter((n: Notification) => n.id !== id)
}

provide(toastSymbol, {
notifications,
add,
remove,
})

return {
notifications,
add,
remove,
}
}

export default useToast
export function useToast() {
return inject(toastSymbol)
}
2 changes: 1 addition & 1 deletion packages/nuxt-ui-vue/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export { useCopyToClipboard } from '@/composables/useCopyToClipboard'

export { useShortcuts } from '@/composables/useShortcuts'

export { default as useToast } from '@/composables/useToast'
export { useToast, injectToast } from '@/composables/useToast'

export { NuxtUIVueComponentResolver } from '@/componentResolver'

Expand Down
27 changes: 26 additions & 1 deletion packages/nuxt-ui-vue/src/theme/nuxtLabsTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -842,7 +842,7 @@ export default {
closeButton: {
icon: 'heroicons:x-mark-20-solid',
color: 'gray',
variant: 'link',
intent: 'link',
padded: false,
},
actionButton: {
Expand All @@ -863,6 +863,31 @@ export default {
},
},

UNotifications: {
base: {
root: 'fixed flex flex-col justify-end z-[55]',
position: {
'top-right': 'top-0 right-0',
'bottom-right': 'bottom-0 right-0',
'top-left': 'top-0 left-0',
'bottom-left': 'bottom-0 left-0',
},
width: 'w-full sm:w-96',
container: 'px-4 sm:px-6 py-6 space-y-3 overflow-y-auto',
},

variants: {
default: {
position: {
'top-right': 'top-0 right-0',
'bottom-right': 'bottom-0 right-0',
'top-left': 'top-0 left-0',
'bottom-left': 'bottom-0 left-0',
},
},
},
},

UPagination: {
base: {
root: 'flex items-center -space-x-px',
Expand Down
Loading