You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js14中Shadcn Sheet组件内Tailwind样式不生效求助

问题

基于Next.js 14、Tailwind和shadcn组件开发项目时,遇到shadcn的Sheet组件内部组件无法应用Tailwind样式的问题:Sheet内所有Tailwind样式均被忽略,比如给按钮设置bg-yellow-300类,按钮会失去颜色变得“不可见”,但在Sheet外使用该类则正常生效,仿佛Sheet内的Tailwind属性未被编译。

表单代码(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>
                ))}
                {/* 该className未生效 */}
                <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>
                    {/* 该className未生效,无法给按钮设置任何样式 */}
                    <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组件代码(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样式正常工作,其他shadcn组件内的按钮也能正常应用样式,已排查tailwind.config.ts、components.json、globals.css的正确性,但问题仍未解决。

解决方案
  • 调整SheetContent的样式设置方式
    shadcn的SheetContent内置样式可能干扰内部组件,建议移除SheetContent上的space-y-4,改用内部容器包裹内容来设置间距:

    <SheetContent>
      <div className="space-y-4 w-full">
        <SheetHeader>
          {/* 原内容 */}
        </SheetHeader>
        <EntryForm onSubmit={onSubmit} disabled={mutation.isPending} />
      </div>
    </SheetContent>
    
  • 确认Tailwind配置的内容覆盖路径
    检查tailwind.config.ts中的content数组,确保包含EntryForm所在的目录(比如features),避免Tailwind未编译该组件的样式:

    /** @type {import('tailwindcss').Config} */
    module.exports = {
      content: [
        "./app/**/*.{js,ts,jsx,tsx,mdx}",
        "./components/**/*.{js,ts,jsx,tsx,mdx}",
        "./features/**/*.{js,ts,jsx,tsx,mdx}", // 必须包含此路径
      ],
      theme: {
        extend: {},
      },
      plugins: [],
    }
    
  • 排查样式优先级问题
    shadcn的Button组件默认样式优先级可能高于自定义Tailwind类,可临时用!important测试是否生效(仅用于排查,不推荐长期使用):

    <Button className="w-fit !bg-zinc-600">
      <Plus className="size-4 mr-2"/>
      Add property
    </Button>
    

    若生效,可修改components/ui/button.tsx中的默认样式,或通过Tailwind自定义变体来覆盖默认样式。

  • 清除缓存并重启开发服务
    缓存可能导致样式未更新,执行以下操作:

    1. 删除.next目录
    2. 重启开发服务器:npm run dev(或yarn dev)
    3. 若仍无效,尝试执行npm run build后再启动开发服务
  • 检查globals.css中的样式重置
    确保globals.css中没有对Sheet内部元素的全局样式重置,比如是否存在* { background: transparent !important; }这类极端样式规则。

内容的提问来源于stack exchange,提问作者MACROSystems

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 16:07:02