Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(Forms): transparent background color on validation error #765

Closed
wants to merge 8 commits into from
26 changes: 25 additions & 1 deletion docs/app.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,30 @@
export default defineAppConfig({
ui: {
primary: 'green',
gray: 'slate'
gray: 'slate',

input: {
color: {
white: {
'background': ''
}
}
},

select: {
color: {
white: {
'background': ''
}
}
},

selectMenu: {
color: {
white: {
'background': ''
}
}
}
}
})
146 changes: 127 additions & 19 deletions playground/app.vue
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@benjamincanac
I added this to enable you to test cases. Once you're finished, we will remove it.

Original file line number Diff line number Diff line change
@@ -1,23 +1,131 @@
<template>
<UContainer class="min-h-screen flex items-center">
<UCard class="flex-1" :ui="{ background: 'bg-gray-50 dark:bg-gray-800/50', ring: 'ring-1 ring-gray-300 dark:ring-gray-700', divide: 'divide-y divide-gray-300 dark:divide-gray-700', header: { base: 'font-bold' } }">
<template #header>
Welcome to the playground!
</template>

<p class="text-gray-500 dark:text-gray-400">
Try your components here!
</p>
</UCard>
</UContainer>
</template>
<script setup lang="ts">

<script setup>
const colorMode = useColorMode()

Check failure on line 3 in playground/app.vue

View workflow job for this annotation

GitHub Actions / ci (ubuntu-latest, 18)

Cannot find name 'useColorMode'.
const isDark = computed({

Check failure on line 4 in playground/app.vue

View workflow job for this annotation

GitHub Actions / ci (ubuntu-latest, 18)

Cannot find name 'computed'.
get () {
return colorMode.value === 'dark'
},
set () {
colorMode.preference = colorMode.value === 'dark' ? 'light' : 'dark'
}
})

</script>
const people = ['Wade Cooper', 'Arlene Mccoy', 'Devon Webb', 'Tom Cook', 'Tanya Fox', 'Hellen Schmidt', 'Caroline Schultz', 'Mason Heaney', 'Claudie Smitham', 'Emil Schaefer']
const countries = ['United States', 'Canada', 'Mexico']

const state = ref({

Check failure on line 16 in playground/app.vue

View workflow job for this annotation

GitHub Actions / ci (ubuntu-latest, 18)

Cannot find name 'ref'.
email: undefined,
password: undefined,
people: undefined,
country: undefined,
notification: undefined
})

<style>
body {
@apply antialiased font-sans text-gray-700 dark:text-gray-200 bg-white dark:bg-gray-900;
const validate = (state) => {
const errors = []
if (!state.email) errors.push({ path: 'email', message: 'Required' })
if (!state.password) errors.push({ path: 'password', message: 'Required' })
if (!state.people) errors.push({ path: 'people', message: 'Required' })
if (!state.country) errors.push({ path: 'country', message: 'Required' })
if (!state.notification) errors.push({ path: 'notification', message: 'Required' })
return errors
}
</style>

async function submit (event) {}

Check warning on line 34 in playground/app.vue

View workflow job for this annotation

GitHub Actions / ci (ubuntu-latest, 18)

'event' is defined but never used
</script>

<template>
<Body class="bg-gray-400" />

<!-- with bg -->
<UCard class="m-4">
<div class="flex flex-col gap-4">
<UButton
:icon="isDark ? 'i-heroicons-moon-20-solid' : 'i-heroicons-sun-20-solid'"
color="gray"
:label="isDark ? 'Dark' : 'Light'"
aria-label="Theme"
@click="isDark = !isDark"
/>

<UForm :validate="validate" :state="state" class="flex flex-col gap-6 py-6" @submit="submit">
<UFormGroup name="password">
<UInput v-model="state.password" type="text" />
</UFormGroup>

<UFormGroup name="password">
<UTextarea v-model="state.password" />
</UFormGroup>

<UFormGroup name="country">
<USelect v-model="state.country" :options="countries" />
</UFormGroup>

<UFormGroup name="people">
<USelectMenu v-model="state.people" :options="people" />
</UFormGroup>

<UFormGroup name="notification">
<UCheckbox v-model="state.notification" name="notifications" label="Notifications" />
</UFormGroup>

<UFormGroup name="notification">
<URadio v-model="state.notification" name="notifications" label="Notifications" />
</UFormGroup>

<UFormGroup name="notification">
<UToggle v-model="state.notification" name="notifications" />
</UFormGroup>

<UButton type="submit">
Submit
</UButton>
</UForm>
</div>
</UCard>

<!-- without bg -->
<div class="m-4 flex flex-col gap-4 border rounded p-5">
<UButton
:icon="isDark ? 'i-heroicons-moon-20-solid' : 'i-heroicons-sun-20-solid'"
color="gray"
:label="isDark ? 'Dark' : 'Light'"
aria-label="Theme"
@click="isDark = !isDark"
/>

<UForm :validate="validate" :state="state" class="flex flex-col gap-6 py-6" @submit="submit">
<UFormGroup name="password">
<UInput v-model="state.password" type="text" />
</UFormGroup>

<UFormGroup name="password">
<UTextarea v-model="state.password" />
</UFormGroup>

<UFormGroup name="country">
<USelect v-model="state.country" :options="countries" />
</UFormGroup>

<UFormGroup name="people">
<USelectMenu v-model="state.people" :options="people" />
</UFormGroup>

<UFormGroup name="notification">
<UCheckbox v-model="state.notification" name="notifications" label="Notifications" />
</UFormGroup>

<UFormGroup name="notification">
<URadio v-model="state.notification" name="notifications" label="Notifications" />
</UFormGroup>

<UFormGroup name="notification">
<UToggle v-model="state.notification" name="notifications" />
</UFormGroup>

<UButton type="submit">
Submit
</UButton>
</UForm>
</div>
</template>
3 changes: 2 additions & 1 deletion src/runtime/components/forms/Input.vue
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,15 @@ export default defineComponent({

const inputClass = computed(() => {
const variant = ui.value.color?.[color.value as string]?.[props.variant as string] || ui.value.variant[props.variant]
const background = ui.value.color[props.color]?.background || ui.value?.background || ''

return twMerge(twJoin(
ui.value.base,
ui.value.rounded,
ui.value.placeholder,
ui.value.size[size.value],
props.padded ? ui.value.padding[size.value] : 'p-0',
variant?.replaceAll('{color}', color.value),
`${variant?.replaceAll('{color}', color.value)} ${background}`.trim(),
(isLeading.value || slots.leading) && ui.value.leading.padding[size.value],
(isTrailing.value || slots.trailing) && ui.value.trailing.padding[size.value]
), props.inputClass)
Expand Down
3 changes: 2 additions & 1 deletion src/runtime/components/forms/Select.vue
Original file line number Diff line number Diff line change
Expand Up @@ -249,13 +249,14 @@ export default defineComponent({

const selectClass = computed(() => {
const variant = ui.value.color?.[color.value as string]?.[props.variant as string] || ui.value.variant[props.variant]
const background = ui.value.color[props.color]?.background || ui.value?.background || ''

return twMerge(twJoin(
ui.value.base,
ui.value.rounded,
ui.value.size[size.value],
props.padded ? ui.value.padding[size.value] : 'p-0',
variant?.replaceAll('{color}', color.value),
`${variant?.replaceAll('{color}', color.value)} ${background}`.trim(),
(isLeading.value || slots.leading) && ui.value.leading.padding[size.value],
(isTrailing.value || slots.trailing) && ui.value.trailing.padding[size.value]
), props.selectClass)
Expand Down
3 changes: 2 additions & 1 deletion src/runtime/components/forms/SelectMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ export default defineComponent({

const selectClass = computed(() => {
const variant = ui.value.color?.[color.value as string]?.[props.variant as string] || ui.value.variant[props.variant]
const background = ui.value.color[props.color]?.background || ui.value?.background || ''

return twMerge(twJoin(
ui.value.base,
Expand All @@ -333,7 +334,7 @@ export default defineComponent({
ui.value.size[size.value],
ui.value.gap[size.value],
props.padded ? ui.value.padding[size.value] : 'p-0',
variant?.replaceAll('{color}', color.value),
`${variant?.replaceAll('{color}', color.value)} ${background}`.trim(),
(isLeading.value || slots.leading) && ui.value.leading.padding[size.value],
(isTrailing.value || slots.trailing) && ui.value.trailing.padding[size.value],
'inline-flex items-center'
Expand Down
3 changes: 2 additions & 1 deletion src/runtime/components/forms/Textarea.vue
Original file line number Diff line number Diff line change
Expand Up @@ -184,14 +184,15 @@ export default defineComponent({

const textareaClass = computed(() => {
const variant = ui.value.color?.[color.value as string]?.[props.variant as string] || ui.value.variant[props.variant]
const background = ui.value.color[props.color]?.background || ui.value?.background || ''

return twMerge(twJoin(
ui.value.base,
ui.value.rounded,
ui.value.placeholder,
ui.value.size[size.value],
props.padded ? ui.value.padding[size.value] : 'p-0',
variant?.replaceAll('{color}', color.value),
`${variant?.replaceAll('{color}', color.value)} ${background}`.trim(),
!props.resize && 'resize-none'
), props.textareaClass)
})
Expand Down
11 changes: 7 additions & 4 deletions src/runtime/ui.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -421,17 +421,20 @@ export const input = {
xl: 'pe-12'
}
},
background: 'bg-transparent',
color: {
white: {
outline: 'shadow-sm bg-white dark:bg-gray-900 text-gray-900 dark:text-white ring-1 ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400'
background: 'bg-white dark:bg-gray-900',
outline: 'shadow-sm text-gray-900 dark:text-white ring-1 ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400'
},
gray: {
outline: 'shadow-sm bg-gray-50 dark:bg-gray-800 text-gray-900 dark:text-white ring-1 ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400'
background: 'bg-gray-50 dark:bg-gray-800',
outline: 'shadow-sm text-gray-900 dark:text-white ring-1 ring-inset ring-gray-300 dark:ring-gray-700 focus:ring-2 focus:ring-primary-500 dark:focus:ring-primary-400'
}
},
variant: {
outline: 'shadow-sm bg-transparent text-gray-900 dark:text-white ring-1 ring-inset ring-{color}-500 dark:ring-{color}-400 focus:ring-2 focus:ring-{color}-500 dark:focus:ring-{color}-400',
none: 'bg-transparent focus:ring-0 focus:shadow-none'
outline: 'shadow-sm text-gray-900 dark:text-white ring-1 ring-inset ring-{color}-500 dark:ring-{color}-400 focus:ring-2 focus:ring-{color}-500 dark:focus:ring-{color}-400',
none: 'focus:ring-0 focus:shadow-none'
},
icon: {
base: 'flex-shrink-0 text-gray-400 dark:text-gray-500',
Expand Down
Loading