While building a project in Nextjs 14 using Tailwind and shadcn
components I ran into an awkward issue, particularly with the Sheet
component from shadcn
, making it impossible to style components inside of it. For example, when setting a background color to a Button
in a Form
inside the Sheet
component, the background of the Button
becomes completely transparent/white.
Basically any Tailwind style is ignored inside the Sheet
.
Interesting behaviour is, for example, if you set the bg-color
of the button
to a color, for example bg-yellow-300
, the button
will lose any color and become "hidden", but if outside this Sheet
you use that same color, the background color will be applied correctly to the button
. Very strange behaviour, is like inside the Sheet
that Tailwind property is not compiled (?).
Code of the Form
entry-form.tsx
import {useFieldArray, useForm} from "react-hook-form";
import {zodResolver} from "@hookform/resolvers/zod";
import {z} from "zod";
import {Form, FormControl, FormField, FormItem, FormLabel} from "@/components/ui/form";
import {Input} from "@/components/ui/input";
import {Button} from "@/components/ui/button";
import {Select} from "@/components/select";
import {Plus} from "lucide-react";
const dynamicFieldSchema = z.object({
name: z.string(),
type: z.string(),
})
const propertiesSchema = z.array(dynamicFieldSchema)
const formSchema = z.object({
name: z.string(),
url: z.string(),
properties: propertiesSchema
})
type FormValues = z.input<typeof formSchema>
type Props = {
id?: string;
defaultValues?: FormValues;
onSubmit: (values: FormValues) => void;
onDelete?: () => void;
disabled?: boolean;
}
export const EntryForm = (
{
id,
defaultValues,
onSubmit,
onDelete,
disabled
}: Props
) => {
const form = useForm<FormValues>({
resolver: zodResolver(formSchema),
defaultValues: {
name: "",
url: "",
properties: []
}
})
const {control, handleSubmit} = form
const {fields, append, remove} = useFieldArray({
control,
name: "properties"
})
const typeOptions = [
{label: "STRING", value: "string"},
{label: "NUMBER", value: "number"},
{label: "BOOLEAN", value: "boolean"},
{label: "DOUBLE", value: "double"},
]
const submit = (values: FormValues) => {
console.log({values})
onSubmit(values)
}
const handleDelete = () => {
onDelete?.()
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(submit)} className="space-y-4">
<FormField
name={"name"}
control={form.control}
render={({field}) => (
<FormItem>
<FormLabel>
Name of set
</FormLabel>
<FormControl>
<Input
disabled={disabled}
placeholder={"Posts..."}
{...field}
/>
</FormControl>
</FormItem>
)}
/>
<FormField
name={"url"}
control={form.control}
render={({field}) => (
<FormItem>
<FormLabel>
URL of set
</FormLabel>
<FormControl>
<Input
disabled={disabled}
placeholder={"https://myweb.com/user?=1/posts..."}
{...field}
/>
</FormControl>
</FormItem>
)}
/>
{fields.map((item, index) => (
<div key={item.id} className="flex flex-col space-y-4">
<div className="flex flex-row gap-x-2">
<FormField
name={`properties.${index}.name`}
control={form.control}
render={({field}) => (
<FormItem>
<FormLabel>
Name
</FormLabel>
<FormControl>
<Input
disabled={disabled}
placeholder={"name"}
{...field}
/>
</FormControl>
</FormItem>
)}
/>
<FormField
name={`properties.${index}.type`}
control={form.control}
render={({field}) => (
<FormItem>
<FormLabel>
Type
</FormLabel>
<FormControl>
<Select
placeholder={"STRING"}
options={typeOptions}
disabled={disabled}
onCreate={(name) => {
console.log("Creating", name)
}}
value={field.value}
onChange={field.onChange}
/>
</FormControl>
</FormItem>
)}
/>
</div>
<Button
type={"button"}
onClick={() => remove(index)}
>
Remove property
</Button>
</div>
))}
{/* this className is not applied, not a single attribute */}
<div className="flex flex-col space-y-4 border-2 border-sky-700 rounded-md">
<p className="text-sm font-medium">
Define your object response type
</p>
{/* this className is not applied, no way to set any styling to the button*/}
<Button
type={"button"}
onClick={() => append({name: "", type: ""})}
className="w-fit bg-zinc-600"
>
<Plus className="size-4 mr-2"/>
Add property
</Button>
</div>
<Button className="w-full" disabled={disabled}>
{id ? "Save changes" : "Create set"}
</Button>
</form>
</Form>
)
}
Code of the Sheet
new-entry-sheet.tsx
import {insertEntrySchema} from "@/db/schema";
import {z} from "zod";
import {useNewEntry} from "@/features/entry/hooks/use-new-entry";
import {useCreateEntry} from "@/features/entry/api/use-create-entry";
import {Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle} from "@/components/ui/sheet";
import {EntryForm} from "@/features/entry/components/entry-form";
const formSchema = insertEntrySchema.omit({
userId: true
})
type FormValues = z.input<typeof formSchema>
export const NewEntrySheet = () => {
const { isOpen, onClose } = useNewEntry()
const mutation = useCreateEntry()
const onSubmit = (values: FormValues) => {
mutation.mutate(values, {
onSuccess: () => {
onClose();
}
})
}
return (
<Sheet open={isOpen} onOpenChange={onClose}>
<SheetContent className="space-y-4">
<SheetHeader>
<SheetTitle>
New Data Set
</SheetTitle>
<SheetDescription className={"text-yellow-600"}>
Create a new data set to track your data and manage your data.
</SheetDescription>
</SheetHeader>
<EntryForm onSubmit={onSubmit} disabled={mutation.isPending} />
</SheetContent>
</Sheet>
)
}
Tailwind is working correctly in the rest of the project, and in the rest of the shadcn
components, styles can be applied to buttons outside of the Sheet
.
I have tried:
tailwind.config.ts
is correct.components.json
is correct.globals.css
is correct.Any help is appreciated, let me know what else should I attach. Thanks in advance.
Found the solution, and it was a very stpd miss configuration.
I divided the functionality of the app in a folder called features
. As you can imagine, the features
path was not included in the content
array of the tailwind.config.ts
.
adding the features
path to the content
of the tailwind.config.ts
file solved the issue.
This is how it looks now:
content: [
'./pages/**/*.{ts,tsx}',
'./components/**/*.{ts,tsx}',
'./app/**/*.{ts,tsx}',
'./features/**/*.{js,ts,jsx,tsx}'
]