mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-31 20:28:09 +01:00
feat(Form): new component (#4)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
This commit is contained in:
@@ -1,19 +1,48 @@
|
||||
<script setup lang="ts">
|
||||
import { splitByCase, upperFirst } from 'scule'
|
||||
|
||||
useHead({
|
||||
bodyAttrs: {
|
||||
class: 'antialiased font-sans text-gray-900 dark:text-white bg-white dark:bg-gray-900'
|
||||
}
|
||||
})
|
||||
|
||||
const components = ['avatar', 'badge', 'button', 'card', 'chip', 'collapsible', 'kbd', 'modal', 'popover', 'skeleton', 'slideover', 'tabs', 'tooltip']
|
||||
const components = [
|
||||
'avatar',
|
||||
'badge',
|
||||
'button',
|
||||
'card',
|
||||
'chip',
|
||||
'collapsible',
|
||||
'form',
|
||||
'form-field',
|
||||
'input',
|
||||
'kbd',
|
||||
'modal',
|
||||
'popover',
|
||||
'skeleton',
|
||||
'slideover',
|
||||
'tabs',
|
||||
'tooltip'
|
||||
]
|
||||
|
||||
function upperName (name: string) {
|
||||
return splitByCase(name).map(p => upperFirst(p)).join('')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UProvider>
|
||||
<UContainer class="min-h-screen flex flex-col gap-4 items-center justify-center overflow-y-auto">
|
||||
<div class="flex gap-1.5 py-4 overflow-x-auto w-full">
|
||||
<ULink v-for="component in components" :key="component" :to="`/${component}`" active-class="text-primary-500 dark:text-primary-400 font-medium" class="capitalize text-sm">
|
||||
{{ component }}
|
||||
<div class="flex gap-1.5 py-4">
|
||||
<ULink
|
||||
v-for="component in components"
|
||||
:key="component"
|
||||
:to="`/${component}`"
|
||||
active-class="text-primary-500 dark:text-primary-400 font-medium"
|
||||
class="capitalize text-sm"
|
||||
>
|
||||
{{ upperName(component) }}
|
||||
</ULink>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
export default defineNuxtConfig({
|
||||
modules: ['../src/module'],
|
||||
ui: {
|
||||
colors: ['primary']
|
||||
colors: ['primary', 'red']
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,3 +1,20 @@
|
||||
<script setup lang="ts">
|
||||
import chip from '#build/ui/chip'
|
||||
|
||||
const sizes = Object.keys(chip.variants.size)
|
||||
const positions = Object.keys(chip.variants.position)
|
||||
|
||||
const items = [{
|
||||
name: 'messages',
|
||||
icon: 'i-heroicons-chat-bubble-oval-left',
|
||||
count: 3
|
||||
}, {
|
||||
name: 'notifications',
|
||||
icon: 'i-heroicons-bell',
|
||||
count: 0
|
||||
}]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex items-center gap-2">
|
||||
@@ -19,20 +36,3 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import chip from '#build/ui/chip'
|
||||
|
||||
const sizes = Object.keys(chip.variants.size)
|
||||
const positions = Object.keys(chip.variants.position)
|
||||
|
||||
const items = [{
|
||||
name: 'messages',
|
||||
icon: 'i-heroicons-chat-bubble-oval-left',
|
||||
count: 3
|
||||
}, {
|
||||
name: 'notifications',
|
||||
icon: 'i-heroicons-bell',
|
||||
count: 0
|
||||
}]
|
||||
</script>
|
||||
|
||||
35
playground/pages/form-field.vue
Normal file
35
playground/pages/form-field.vue
Normal file
@@ -0,0 +1,35 @@
|
||||
<script setup lang="ts">
|
||||
import formField from '#build/ui/formField'
|
||||
|
||||
const feedbacks = [
|
||||
{ description: 'This is a description' },
|
||||
{ error: 'This is an error' },
|
||||
{ hint: 'This is a hint' },
|
||||
{ help: 'Help! I need somebody!' },
|
||||
{ required: true }
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col items-center gap-4">
|
||||
<div class="flex flex-col gap-4 -ml-[258px]">
|
||||
<div v-for="(feedback, count) in feedbacks" :key="count" class="flex items-center">
|
||||
<UFormField v-bind="feedback" label="Email" name="email">
|
||||
<UInput placeholder="john@lennon.com" />
|
||||
</UFormField>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-4">
|
||||
<UFormField
|
||||
v-for="size in Object.keys(formField.variants.size)"
|
||||
:key="size"
|
||||
:size="(size as any)"
|
||||
label="Email"
|
||||
name="email"
|
||||
>
|
||||
<UInput placeholder="john@lennon.com" />
|
||||
</UFormField>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
104
playground/pages/form.vue
Normal file
104
playground/pages/form.vue
Normal file
@@ -0,0 +1,104 @@
|
||||
<script setup lang="ts">
|
||||
import { z } from 'zod'
|
||||
import type { Form, FormSubmitEvent } from '#ui/types/form'
|
||||
|
||||
type User = {
|
||||
email: string
|
||||
password: string
|
||||
}
|
||||
|
||||
const state = ref<User>({ email: '', password: '' })
|
||||
const state2 = ref<User>({ email: '', password: '' })
|
||||
const state3 = ref<User>({ email: '', password: '' })
|
||||
|
||||
const schema = z.object({
|
||||
email: z.string().email(),
|
||||
password: z.string().min(8)
|
||||
})
|
||||
|
||||
const disabledForm = ref<Form<User>>()
|
||||
|
||||
function onSubmit (event: FormSubmitEvent<User>) {
|
||||
console.log(event.data)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex gap-4">
|
||||
<UForm
|
||||
:state="state"
|
||||
:schema="schema"
|
||||
class="gap-4 flex flex-col w-60"
|
||||
@submit="(event) => onSubmit(event)"
|
||||
>
|
||||
<UFormField label="Email" name="email">
|
||||
<UInput v-model="state.email" placeholder="john@lennon.com" />
|
||||
</UFormField>
|
||||
|
||||
<UFormField label="Password" name="password">
|
||||
<UInput v-model="state.password" type="password" />
|
||||
</UFormField>
|
||||
|
||||
<div>
|
||||
<UButton color="gray" type="submit">
|
||||
Submit
|
||||
</UButton>
|
||||
</div>
|
||||
</UForm>
|
||||
|
||||
<UForm
|
||||
:state="state2"
|
||||
:schema="schema"
|
||||
class="gap-4 flex flex-col w-60"
|
||||
:validate-on-input-delay="2000"
|
||||
@submit="(event) => onSubmit(event)"
|
||||
>
|
||||
<UFormField label="Email" name="email">
|
||||
<UInput v-model="state2.email" placeholder="john@lennon.com" />
|
||||
</UFormField>
|
||||
|
||||
<UFormField
|
||||
label="Password"
|
||||
name="password"
|
||||
:validate-on-input-delay="50"
|
||||
eager-validation
|
||||
>
|
||||
<UInput v-model="state2.password" type="password" />
|
||||
</UFormField>
|
||||
|
||||
<div>
|
||||
<UButton color="gray" type="submit">
|
||||
Submit
|
||||
</UButton>
|
||||
</div>
|
||||
</UForm>
|
||||
|
||||
<UForm
|
||||
ref="disabledForm"
|
||||
:state="state3"
|
||||
:schema="schema"
|
||||
class="gap-4 flex flex-col w-60"
|
||||
disabled
|
||||
@submit="(event) => onSubmit(event)"
|
||||
>
|
||||
<UFormField label="Email" name="email">
|
||||
<UInput v-model="state2.email" placeholder="john@lennon.com" />
|
||||
</UFormField>
|
||||
|
||||
<UFormField
|
||||
label="Password"
|
||||
name="password"
|
||||
:validate-on-input-delay="50"
|
||||
eager-validation
|
||||
>
|
||||
<UInput v-model="state2.password" type="password" />
|
||||
</UFormField>
|
||||
|
||||
<div>
|
||||
<UButton color="gray" type="submit" :disabled="disabledForm?.disabled">
|
||||
Submit
|
||||
</UButton>
|
||||
</div>
|
||||
</UForm>
|
||||
</div>
|
||||
</template>
|
||||
19
playground/pages/input.vue
Normal file
19
playground/pages/input.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
import input from '#build/ui/input'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col items-center gap-4">
|
||||
<div class="flex flex-col gap-4 -ml-[258px]">
|
||||
<UInput placeholder="Write something..." autofocus />
|
||||
<UInput placeholder="Write something..." />
|
||||
<UInput placeholder="Write something..." color="gray" />
|
||||
<UInput placeholder="Write something..." color="primary" />
|
||||
<UInput placeholder="Write something..." color="red" />
|
||||
<UInput placeholder="Write something..." disabled />
|
||||
</div>
|
||||
<div class="flex items-center gap-4">
|
||||
<UInput v-for="size in Object.keys(input.variants.size)" :key="size" placeholder="Write something..." :size="(size as any)" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,3 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
const open = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col gap-2">
|
||||
<UModal title="First modal">
|
||||
@@ -47,7 +51,3 @@
|
||||
</UModal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const open = ref(false)
|
||||
</script>
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
<script setup lang="ts">
|
||||
const open = ref(false)
|
||||
const loading = ref(false)
|
||||
|
||||
function send () {
|
||||
loading.value = true
|
||||
|
||||
setTimeout(() => {
|
||||
loading.value = false
|
||||
open.value = false
|
||||
}, 1000)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="text-center">
|
||||
<UPopover v-model:open="open" arrow>
|
||||
@@ -48,17 +62,3 @@
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const open = ref(false)
|
||||
const loading = ref(false)
|
||||
|
||||
function send () {
|
||||
loading.value = true
|
||||
|
||||
setTimeout(() => {
|
||||
loading.value = false
|
||||
open.value = false
|
||||
}, 1000)
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
const open = ref(false)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col gap-2">
|
||||
<USlideover title="First slideover">
|
||||
@@ -103,7 +107,3 @@
|
||||
</USlideover>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const open = ref(false)
|
||||
</script>
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
<template>
|
||||
<UTabs :items="items" class="w-96">
|
||||
<template #tab1="{ item }">
|
||||
{{ item.label }}
|
||||
</template>
|
||||
</UTabs>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const items = [{
|
||||
label: 'Tab1',
|
||||
@@ -19,3 +11,11 @@ const items = [{
|
||||
content: 'Finally, this is the content for Tab3'
|
||||
}]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UTabs :items="items" class="w-96">
|
||||
<template #tab1="{ item }">
|
||||
{{ item.label }}
|
||||
</template>
|
||||
</UTabs>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user