Input
32 高的文本框:纸面加一圈细边,聚焦是粉色边和光晕,出错变红,只读和禁用是下沉的浅底。
input-demo.tsx
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
export default function InputDemo() {
return (
<div className="grid w-full max-w-sm gap-1.5">
<Label htmlFor="input-demo-title">中文标题</Label>
<Input id="input-demo-title" defaultValue="药屋少女的呢喃 第二季" />
</div>
)
}安装
npx shadcn@latest add @anibt/input第一次用之前:在 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/input.tsx
import * as React from "react" import { cn } from "@/lib/utils" /** * Input — the AniBT 「贴纸手账」 text field. * * 32 high on radius 10: paper under a 1px `--input` inset ring. Hover turns * the ring pink; focus is a 1.5px `--ring` edge with the soft pink halo * outside; invalid (`aria-invalid`) is the same in red and stays red while * focused; read-only is the sunk `--muted` well; disabled is `--muted` under * the weak ink — never an opacity wash. A phone keeps 16px text so iOS does * not zoom the page on focus; from `md` it is A's 13. * * Inside shadcn's `InputGroup` (`data-slot="input-group-control"`) the field * drops its own ring and paper, so the group draws the one edge. * * Textarea, the select trigger and the search and password fields spell the * same material out — shadcn keeps each primitive self-contained. */ function Input({ className, type, ...props }: React.ComponentProps<"input">) { return ( <input type={type} data-slot="input" 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", "h-8 w-full min-w-0 rounded-[10px] border-0 px-3 py-0 text-base transition-[background-color,box-shadow] duration-150 outline-none md:text-[13px]", "file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-[13px] file:font-semibold file:text-foreground", "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 { Input }
用法
用法
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
<Label htmlFor="title">中文标题</Label>
<Input id="title" placeholder="番剧的中文名" />标签放在输入框上方、离它 6px。表单里用 Field,它会替你排好标签、说明和错误。
状态
input-states.tsx
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
export default function InputStates() {
return (
<div className="grid w-full max-w-xl gap-4 sm:grid-cols-2">
<div className="grid gap-1.5">
<Label htmlFor="input-states-empty">关键词</Label>
<Input id="input-states-empty" placeholder="例如:简繁内封 1080p" />
</div>
<div className="grid gap-1.5">
<Label htmlFor="input-states-num">集数</Label>
{/* Figures take the round face: add anibt-num. */}
<Input id="input-states-num" type="number" className="anibt-num" defaultValue={24} />
</div>
<div className="grid gap-1.5">
<Label htmlFor="input-states-invalid">官网</Label>
<Input id="input-states-invalid" aria-invalid defaultValue="kusuriya-anime" />
</div>
<div className="grid gap-1.5">
<Label htmlFor="input-states-readonly">Slug</Label>
<Input id="input-states-readonly" readOnly className="anibt-num" defaultValue="sakura-subs" />
</div>
<div className="grid gap-1.5">
<Label htmlFor="input-states-disabled">种子哈希</Label>
<Input id="input-states-disabled" disabled defaultValue="3f9a…c21e" />
</div>
<div className="grid gap-1.5">
<Label htmlFor="input-states-file">种子文件</Label>
<Input id="input-states-file" type="file" accept=".torrent" />
</div>
</div>
)
}- 静止:纸面加 1px
input色内边;悬停时边变粉。 - 聚焦:1.5px
ring色边,外面一圈粉色光晕。 - 出错:
aria-invalid让边和光晕变红,聚焦时仍然是红色。 - 只读:
readOnly是下沉的muted底、ink2字;仍然能聚焦、能复制。 - 禁用:
muted底、弱字,边退成border。不用透明度,禁用的字也读得清。 - 数字(集数、年份、体积、哈希)加
anibt-num,换成 Fredoka 圆体的等宽数字。 - 手机上字号是 16px,iOS 聚焦时不会放大页面;
md起是 A 的 13px。
放进 InputGroup
放进 shadcn 的 InputGroup 时(data-slot="input-group-control"),输入框会去掉自己的边、光晕和底色,由组画那一圈边。
属性
Input
typestring默认 —原生 type;搜索框和密码框另有 SearchInput、PasswordInput
aria-invalidboolean默认 —出错:红边红光晕。Field 的 error 会自动加上
readOnlyboolean默认 —只读:下沉的浅底
disabledboolean默认 —禁用:浅底弱字,不用透明度
Input 就是一个 <input>:其余原生属性和 ref 原样透传。
