Textarea
多行文本框,材质和状态与 Input 相同,随内容长高。
textarea-demo.tsx
import { Label } from "@/components/ui/label"
import { Textarea } from "@/components/ui/textarea"
export default function TextareaDemo() {
return (
<div className="grid w-full max-w-md gap-1.5">
<Label htmlFor="textarea-demo-notes">发布说明</Label>
<Textarea
id="textarea-demo-notes"
placeholder="写给下载的人:片源、字幕、修正了什么"
defaultValue={"片源:Baha WEB-DL\n字幕:简繁内封,修正了第 3 集的时间轴。"}
/>
</div>
)
}安装
npx shadcn@latest add @anibt/textarea第一次用之前:在 components.json 里登记 @anibt,再单独运行一次 npx shadcn@latest add @anibt/theme(见快速开始)。只有单独安装主题时,CLI 才会把 shadcn 的标准颜色换成白樱 / 夜樱;随组件带进来的主题只补上 AniBT 自己的变量和配方。
手动安装
- 1. 先装主题组件只读
@anibt/theme的 token 和配方,没有主题就没有样子。npx shadcn@latest add @anibt/theme - 2. 把下面的文件放进项目components/ui/textarea.tsx
import * as React from "react" import { cn } from "@/lib/utils" /** * Textarea — the multi-line AniBT 「贴纸手账」 field. * * The same material and state ladder as `Input` (paper, the 1px `--input` * ring, pink on hover, the 1.5px `--ring` edge and halo on focus, red when * `aria-invalid`, the sunk well when read-only or disabled). It differs only * in height: `field-sizing-content` grows the box with the copy from a * two-line minimum, and the user can still drag it taller. */ function Textarea({ className, ...props }: React.ComponentProps<"textarea">) { return ( <textarea data-slot="textarea" className={cn( "bg-card text-foreground inset-ring-1 inset-ring-input placeholder:text-muted-foreground selection:bg-anibt-wash2 selection:text-foreground hover:inset-ring-anibt-wash-line focus-visible:inset-ring-[1.5px] focus-visible:inset-ring-ring focus-visible:ring-4 focus-visible:ring-ring/20 aria-invalid:inset-ring-[1.5px] aria-invalid:inset-ring-anibt-danger-fill aria-invalid:ring-4 aria-invalid:ring-anibt-danger-fill/15 [&[readonly]]:bg-muted [&[readonly]]:text-anibt-ink2 disabled:cursor-not-allowed disabled:bg-muted disabled:text-muted-foreground disabled:inset-ring-border", "flex field-sizing-content min-h-16 w-full rounded-[10px] border-0 px-3 py-2 text-base leading-normal transition-[background-color,box-shadow] duration-150 outline-none md:text-[13px]", "data-[slot=input-group-control]:bg-transparent data-[slot=input-group-control]:inset-ring-0 data-[slot=input-group-control]:ring-0", className )} {...props} /> ) } export { Textarea }
用法
用法
import { Label } from "@/components/ui/label"
import { Textarea } from "@/components/ui/textarea"
<Label htmlFor="notes">发布说明</Label>
<Textarea id="notes" placeholder="片源、字幕、修正了什么" />状态
textarea-states.tsx
import { Label } from "@/components/ui/label"
import { Textarea } from "@/components/ui/textarea"
export default function TextareaStates() {
return (
<div className="grid w-full max-w-xl gap-4 sm:grid-cols-2">
<div className="grid gap-1.5">
<Label htmlFor="textarea-states-invalid">驳回理由</Label>
<Textarea id="textarea-states-invalid" aria-invalid defaultValue="太短" />
</div>
<div className="grid gap-1.5">
<Label htmlFor="textarea-states-disabled">字幕组简介</Label>
<Textarea id="textarea-states-disabled" disabled defaultValue="由站长维护,暂不可编辑。" />
</div>
</div>
)
}材质、悬停、聚焦、出错、只读、禁用都和 Input 一样。不同的只有高度:field-sizing-content 让文本框从两行起随内容长高,用户还能往下拖高。需要固定高度时给 className="h-40 field-sizing-fixed"。
收 Markdown 的地方用 Markdown 编辑器;公开页按纯文本显示的简介(番剧简介、字幕组简介)用普通文本框。
属性
Textarea
aria-invalidboolean默认 —出错:红边红光晕
readOnlyboolean默认 —只读:下沉的浅底
disabledboolean默认 —禁用:浅底弱字,不用透明度
Textarea 就是一个 <textarea>:其余原生属性和 ref 原样透传。
