При создании проекта в Nextjs 14 с использованием компонентов Tailwind и shadcn
я столкнулся с неловкой проблемой, особенно с компонентом Sheet
из shadcn
, из-за которой невозможно стилизовать компоненты внутри него. Например, при установке цвета фона на Button
в Form
внутри компонента Sheet
, фон Button
становится полностью прозрачным/белым.
По сути, любой стиль Tailwind внутри Sheet
игнорируется.
Интересное поведение: если вы установите для bg-color
button
цвет, например bg-yellow-300
, button
потеряет любой цвет и станет «скрытым», но если за пределами этого Sheet
вы используете тот же цвет, цвет фона будет правильно применять к button
. Очень странное поведение, как будто внутри Sheet
свойство Tailwind не компилируется (?).
Кодекс Form
запись-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.info({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.info("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>
)
}
Кодекс Sheet
новый-запись-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 работает корректно в остальной части проекта, а в остальных компонентах shadcn
стили можно применять к кнопкам за пределами Sheet
.
Я пробовал:
tailwind.config.ts
.components.json
.globals.css
.Любая помощь приветствуется, дайте мне знать, что еще мне следует приложить. Заранее спасибо.
@PinalTilva, мне очень жаль, вы правы, я указал неправильный код new-entry-form.tsx, теперь указан правильный код :D
Я только что попытался воспроизвести то же самое, запустив ваш код локально, но не смог найти ту же проблему. Не могли бы вы поделиться содержимым своего tailwind config file
?
@PinalTilva действительно была проблема, я опубликовал ответ с решением... в любом случае спасибо!
Решение найдено, и это была очень стандартная конфигурация.
Функционал приложения я разделил в папке features
. Как вы понимаете, путь features
не был включен в массив content
объекта tailwind.config.ts
.
добавление пути features
к content
файла tailwind.config.ts
решило проблему.
Вот как это выглядит сейчас:
content: [
'./pages/**/*.{ts,tsx}',
'./components/**/*.{ts,tsx}',
'./app/**/*.{ts,tsx}',
'./features/**/*.{js,ts,jsx,tsx}'
]
Вы не поделились своим кодом внутри компонента листа!