AniBTUI
✦ 组件@anibt/badgeregistry JSON

Badge

20 高的事实标签、模切白边贴纸、计数胶囊,以及带点和字的状态。

1080p简中内封字幕MKV
✦ NEW23:3012同步中

安装

npx shadcn@latest add @anibt/badge

第一次用之前:在 components.json 里登记 @anibt,再单独运行一次 npx shadcn@latest add @anibt/theme(见快速开始)。只有单独安装主题时,CLI 才会把 shadcn 的标准颜色换成白樱 / 夜樱;随组件带进来的主题只补上 AniBT 自己的变量和配方。

手动安装
  1. 1. 先装主题组件只读 @anibt/theme 的 token 和配方,没有主题就没有样子。
    npx shadcn@latest add @anibt/theme
  2. 2. 安装依赖
    npm install class-variance-authority radix-ui
  3. 3. 把下面的文件放进项目
    components/ui/badge.tsx
    import * as React from "react"
    import { cva, type VariantProps } from "class-variance-authority"
    import { Slot } from "radix-ui"
    
    import { cn } from "@/lib/utils"
    
    /**
     * Badge, StatusBadge and StatusDot — the AniBT 「贴纸手账」 label family.
     *
     * `Badge`:
     * - tags (20px, radius 6): `default` (neutral — a spec, a category), `res`
     *   (blue: resolution, format, time — in the round face), `lang` (pink:
     *   language, subtitles), and the status words `success` / `warning` /
     *   `destructive` (mint / amber / red, no dot).
     * - stickers (die-cut white rim, tilted by `tilt`): `sticker`, and the filled
     *   `candy` and `water`. A label stuck on — use sparingly.
     * - counts (20px pill): `count` (candy) and `count-quiet` (neutral).
     * - `secondary` and `outline` exist only so code written against shadcn's
     *   badge keeps compiling; both are the neutral tag.
     *
     * `StatusBadge` is a state with its word and a 6px dot: ok (mint), run (blue,
     * the dot blinks), fail (red), warn (amber), mute (grey), on (pink). The word
     * is required — colour never speaks alone.
     *
     * `StatusDot` is the label-less 6px dot beside copy that already says the
     * state (a legend, a rail count). It is `aria-hidden`.
     */
    const badgeVariants = cva(
      "inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring focus-visible:outline-solid [&>svg]:pointer-events-none [&>svg]:size-3",
      {
        variants: {
          variant: {
            default: "anibt-tag",
            secondary: "anibt-tag",
            outline: "anibt-tag",
            res: "anibt-tag anibt-tag-res",
            lang: "anibt-tag anibt-tag-lang",
            success: "anibt-tag anibt-tag-ok",
            warning: "anibt-tag anibt-tag-warn",
            destructive: "anibt-tag anibt-tag-danger",
            sticker: "anibt-sticker",
            candy: "anibt-sticker anibt-sticker-candy",
            water: "anibt-sticker anibt-sticker-water",
            count: "anibt-count",
            "count-quiet": "anibt-count anibt-count-quiet",
          },
          /** Specs and figures take the round face; a word takes the body face. */
          face: {
            spec: "anibt-num",
            text: "",
          },
          size: {
            default: "",
            /** A 24px tag for a header row. */
            lg: "h-6 px-2.5",
          },
        },
        defaultVariants: {
          variant: "default",
          face: "spec",
          size: "default",
        },
      }
    )
    
    type BadgeProps = React.ComponentProps<"span"> &
      VariantProps<typeof badgeVariants> & {
        asChild?: boolean
        /** Tilt in degrees for the sticker variants (A uses −4 … 4). */
        tilt?: number
      }
    
    function Badge({ className, variant, face, size, asChild = false, tilt, style, ...props }: BadgeProps) {
      const Comp = asChild ? Slot.Root : "span"
      const tiltStyle =
        tilt === undefined ? style : ({ ...style, "--anibt-tilt": `${tilt}deg` } as React.CSSProperties)
    
      return (
        <Comp
          data-slot="badge"
          data-variant={variant ?? "default"}
          className={cn(badgeVariants({ variant, face, size }), className)}
          style={tiltStyle}
          {...props}
        />
      )
    }
    
    const statusBadgeVariants = cva("anibt-status", {
      variants: {
        tone: {
          ok: "anibt-status-ok",
          run: "anibt-status-run",
          fail: "anibt-status-fail",
          warn: "anibt-status-warn",
          mute: "anibt-status-mute",
          on: "anibt-status-on",
        },
      },
      defaultVariants: {
        tone: "mute",
      },
    })
    
    type StatusBadgeProps = React.ComponentProps<"span"> &
      VariantProps<typeof statusBadgeVariants> & {
        /** The word that names the state. */
        children: React.ReactNode
      }
    
    function StatusBadge({ className, tone, ...props }: StatusBadgeProps) {
      return (
        <span
          data-slot="status-badge"
          data-tone={tone ?? "mute"}
          className={cn(statusBadgeVariants({ tone }), className)}
          {...props}
        />
      )
    }
    
    const statusDotVariants = cva("anibt-dot", {
      variants: {
        variant: {
          default: "",
          ok: "anibt-dot-ok",
          warn: "anibt-dot-warn",
          danger: "anibt-dot-danger",
          time: "anibt-dot-time",
          hollow: "anibt-dot-hollow",
          mute: "anibt-dot-mute",
        },
      },
      defaultVariants: {
        variant: "default",
      },
    })
    
    type StatusDotProps = Omit<React.ComponentProps<"span">, "children"> &
      VariantProps<typeof statusDotVariants>
    
    function StatusDot({ className, variant, ...props }: StatusDotProps) {
      return (
        <span
          data-slot="status-dot"
          aria-hidden="true"
          className={cn(statusDotVariants({ variant }), className)}
          {...props}
        />
      )
    }
    
    export { Badge, badgeVariants, StatusBadge, statusBadgeVariants, StatusDot, statusDotVariants }
    export type { BadgeProps, StatusBadgeProps, StatusDotProps }

用法

用法
import { Badge, StatusBadge, StatusDot } from "@/components/ui/badge"

<Badge variant="res">1080p</Badge>
<Badge variant="candy" tilt={-3}>✦ NEW</Badge>
<StatusBadge tone="ok">已同步</StatusBadge>

标签

HEVC-10bit2160p1080p简繁内封日语
完结过期失效S2 · 24

标签说的是这条记录的事实:规格、分类、语言。

  • default:中性,下沉底加一圈细边。
  • res:蓝色,用于分辨率、格式、时间,圆体。
  • lang:粉色,用于语言、字幕。
  • success / warning / destructive:薄荷 / 琥珀 / 红色的状态词,没有点。带点的状态用 StatusBadge。

face 默认是 "spec":拉丁字母和数字用 Fredoka 圆体。标签写的是中文词时用 face="text"。size="lg" 是表头里用的 24 高。

贴纸

ANIME✦ 推荐周六 23:30TV · 2026 秋

贴纸是贴上去的标签:2px 模切白边、一点阴影,tilt 控制倾斜角度(A 常用 −4° 到 4°)。candy 和 water 是实心的糖果粉、水蓝。少用,一屏两三个就够。

计数

399+128

count 是 20 高的糖果胶囊,带贴纸白边,适合贴在图标按钮角上;count-quiet 是中性的计数,用在侧栏这类安静的位置。

状态

已同步同步中同步失败排队中已关闭订阅中
做种 12今晚更新你的订阅未开始

StatusBadge 是一个淡底里放 6px 的点和一个词:ok 完成(薄荷)、run 进行中(蓝,点会闪)、fail 失败(红)、warn 需要注意(琥珀)、mute 关闭(灰)、on 启用 / 订阅中(粉)。必须有字,颜色从不单独表达状态。

StatusDot 只画点,给已经写明状态的文字配一个记号(图例、侧栏计数)。它是 aria-hidden 的。

属性

Badge
variant"default" | "res" | "lang" | "success" | "warning" | "destructive" | "sticker" | "candy" | "water" | "count" | "count-quiet" | "secondary" | "outline"默认 "default"secondary、outline 等同 default,只为兼容 shadcn
face"spec" | "text"默认 "spec"spec 用圆体写规格和数字,text 用正文字体写词
size"default" | "lg"默认 "default"20 高 / 24 高
tiltnumber默认 —贴纸的倾斜角度(度),写进 --anibt-tilt
asChildboolean默认 false把样式交给唯一的子元素
StatusBadge
tone"ok" | "run" | "fail" | "warn" | "mute" | "on"默认 "mute"状态色
childrenReactNode默认 —必填:状态的文字
StatusDot
variant"default" | "ok" | "warn" | "danger" | "time" | "hollow" | "mute"默认 "default"default 是粉色笔画;hollow 是空心圈