feat(ui): Add Toaster and Textarea components
- Introduce Toaster component using vue-sonner for notifications - Implement Textarea component with v-model support and customizable classes
This commit is contained in:
parent
13b3adf876
commit
8515b1343e
6 changed files with 67 additions and 11 deletions
25
package-lock.json
generated
25
package-lock.json
generated
|
|
@ -11,7 +11,7 @@
|
|||
"@tanstack/vue-table": "^8.21.2",
|
||||
"@types/qrcode": "^1.5.5",
|
||||
"@vueuse/components": "^12.5.0",
|
||||
"@vueuse/core": "^12.5.0",
|
||||
"@vueuse/core": "^12.8.2",
|
||||
"@vueuse/head": "^2.0.0",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
|
|
@ -23,13 +23,14 @@
|
|||
"pinia": "^2.3.1",
|
||||
"qrcode": "^1.5.4",
|
||||
"radix-vue": "^1.9.13",
|
||||
"reka-ui": "^2.0.2",
|
||||
"reka-ui": "^2.3.2",
|
||||
"tailwind-merge": "^2.6.0",
|
||||
"tailwind-variants": "^0.3.1",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"vue": "^3.5.13",
|
||||
"vue-i18n": "^9.14.2",
|
||||
"vue-router": "^4.5.0",
|
||||
"vue-sonner": "^2.0.1",
|
||||
"web-vitals": "^3.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
@ -10932,9 +10933,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/ohash": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/ohash/-/ohash-1.1.6.tgz",
|
||||
"integrity": "sha512-TBu7PtV8YkAZn0tSxobKY2n2aAQva936lhRrj6957aDaCf9IEtqsKbgMzXE/F/sjqYOwmrukeORHNLe5glk7Cg==",
|
||||
"version": "2.0.11",
|
||||
"resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz",
|
||||
"integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/once": {
|
||||
|
|
@ -11922,9 +11923,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/reka-ui": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/reka-ui/-/reka-ui-2.0.2.tgz",
|
||||
"integrity": "sha512-pC2UF6Z+kJF96aJvIErhkSO4DJYIeq9pgvh3pntNqcZb3zFGMzw8h2uny+GnLX2CKiQV54kZNYXxecYIiPMGyg==",
|
||||
"version": "2.3.2",
|
||||
"resolved": "https://registry.npmjs.org/reka-ui/-/reka-ui-2.3.2.tgz",
|
||||
"integrity": "sha512-lCysSCILH2uqShEnt93/qzlXnB7ySvK7scR0Q5C+a2iXwFVzHhvZQsMaSnbQYueoCihx6yyUZTYECepnmKrbRA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/dom": "^1.6.13",
|
||||
|
|
@ -11936,7 +11937,7 @@
|
|||
"@vueuse/shared": "^12.5.0",
|
||||
"aria-hidden": "^1.2.4",
|
||||
"defu": "^6.1.4",
|
||||
"ohash": "^1.1.4"
|
||||
"ohash": "^2.0.11"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": ">= 3.2.0"
|
||||
|
|
@ -13998,6 +13999,12 @@
|
|||
"vue": "^3.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vue-sonner": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/vue-sonner/-/vue-sonner-2.0.1.tgz",
|
||||
"integrity": "sha512-sn4vjCRzRcnMaxaLa9aNSyZQi6S+gshiea5Lc3eqpkj0ES9LH8ljg+WJCkxefr28V4PZ9xkUXBIWpxGfQxstIg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/vue-tsc": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-2.2.0.tgz",
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
"@tanstack/vue-table": "^8.21.2",
|
||||
"@types/qrcode": "^1.5.5",
|
||||
"@vueuse/components": "^12.5.0",
|
||||
"@vueuse/core": "^12.5.0",
|
||||
"@vueuse/core": "^12.8.2",
|
||||
"@vueuse/head": "^2.0.0",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
|
|
@ -32,13 +32,14 @@
|
|||
"pinia": "^2.3.1",
|
||||
"qrcode": "^1.5.4",
|
||||
"radix-vue": "^1.9.13",
|
||||
"reka-ui": "^2.0.2",
|
||||
"reka-ui": "^2.3.2",
|
||||
"tailwind-merge": "^2.6.0",
|
||||
"tailwind-variants": "^0.3.1",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"vue": "^3.5.13",
|
||||
"vue-i18n": "^9.14.2",
|
||||
"vue-router": "^4.5.0",
|
||||
"vue-sonner": "^2.0.1",
|
||||
"web-vitals": "^3.5.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
|||
18
src/components/ui/sonner/Sonner.vue
Normal file
18
src/components/ui/sonner/Sonner.vue
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
<script lang="ts" setup>
|
||||
import { Toaster as Sonner, type ToasterProps } from 'vue-sonner'
|
||||
|
||||
const props = defineProps<ToasterProps>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Sonner
|
||||
class="toaster group"
|
||||
v-bind="props"
|
||||
:style="{
|
||||
'--normal-bg': 'var(--popover)',
|
||||
'--normal-text': 'var(--popover-foreground)',
|
||||
'--normal-border': 'var(--border)',
|
||||
|
||||
}"
|
||||
/>
|
||||
</template>
|
||||
1
src/components/ui/sonner/index.ts
Normal file
1
src/components/ui/sonner/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export { default as Toaster } from './Sonner.vue'
|
||||
28
src/components/ui/textarea/Textarea.vue
Normal file
28
src/components/ui/textarea/Textarea.vue
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<script setup lang="ts">
|
||||
import type { HTMLAttributes } from 'vue'
|
||||
import { useVModel } from '@vueuse/core'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const props = defineProps<{
|
||||
class?: HTMLAttributes['class']
|
||||
defaultValue?: string | number
|
||||
modelValue?: string | number
|
||||
}>()
|
||||
|
||||
const emits = defineEmits<{
|
||||
(e: 'update:modelValue', payload: string | number): void
|
||||
}>()
|
||||
|
||||
const modelValue = useVModel(props, 'modelValue', emits, {
|
||||
passive: true,
|
||||
defaultValue: props.defaultValue,
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<textarea
|
||||
v-model="modelValue"
|
||||
data-slot="textarea"
|
||||
:class="cn('border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm', props.class)"
|
||||
/>
|
||||
</template>
|
||||
1
src/components/ui/textarea/index.ts
Normal file
1
src/components/ui/textarea/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export { default as Textarea } from './Textarea.vue'
|
||||
Loading…
Add table
Add a link
Reference in a new issue