TL;DR

dot-loaders là toolkit TypeScript mới từ @grixate để dựng loading animation kiểu Unicode/braille, drop thẳng vào shadcn/ui mà không phải đánh nhau với Tailwind hay Radix. Mỗi loader là một typed schema (frames, cadence, effects, symbol map) — cùng định nghĩa đó render ra SVG grid, text inline, hoặc terminal output. Core package zero React dependency, MIT license, TypeScript strict mode.

Có gì mới

Mặc định của hệ sinh thái shadcn/ui cho trạng thái loading là <Loader className="animate-spin" /> — một lucide icon xoay vòng. Nó chạy được, nhưng mọi trang shadcn trên Internet đang dùng đúng cái spinner đó, nhìn giống hệt nhau.

dot-loaders chọn hướng khác: thay vì icon xoay, nó dùng ký tự Unicode braille và các symbol block để tạo khung hình:

⠋ ⠙ ⠹ ⠸ ⠼ ⠴ ⠦ ⠧ ⠇ ⠏
▰▱▱▱ ▰▰▱▱ ▰▰▰▱ ▰▰▰▰ ▰▰▰▱ ▰▰▱▱ ▰▱▱▱

Ví dụ tích hợp vào shadcn <Button> pending state:

<Button disabled={pending} className="gap-2 rounded-full px-4">
  {pending ? (
    <>
      <LoaderInline loader="braille" renderer="svg-grid" />
      <span>Rendering</span>
    </>
  ) : "Publish"}
</Button>

Vì sao đáng quan tâm

Chi tiết design micro như loading spinner là chỗ các shadcn site bắt đầu trông giống nhau. Khi mọi nút đều animate-spin cùng một lucide icon, sản phẩm của bạn mất dấu ấn ở đúng khoảnh khắc người dùng chú ý — lúc họ đang chờ.

dot-loaders không phải là CSS animation thứ n, mà là một cách mô hình hóa spinner thành dữ liệu. Schema là đơn vị, renderer chỉ là consumer. Cùng một loader braille có thể xuất hiện trên web dưới dạng SVG grid, trong CLI dưới dạng ký tự terminal, hoặc cắm vào một toast inline — không cần viết lại logic cadence.

Điểm tinh tế: currentColor inherit nghĩa là loader tự lấy màu từ text color của parent, không cần prop color; className thread-through cho phép bạn chồng utility Tailwind lên root mà không cần override; và prefers-reduced-motion được respect sẵn — ba chi tiết mà phần lớn custom spinner bỏ qua và sau đó mới sửa bằng patch.

Chi tiết kỹ thuật

  • Monorepo 3 package: @dot-loaders/core (engine, zero deps runtime), @dot-loaders/react (React bindings), @dot-loaders/presets (loader curated).
  • Schema mỗi loader: { frames, cadence, effects, symbolMap } — typed, immutable, serializable.
  • 3 renderer: svg-grid, text inline, terminal output.
  • Effect pipeline: glow, gradients, labels, finishers, custom symbol maps.
  • Theming: currentColor inherit tự động, className thread qua root element, prefers-reduced-motion respected mặc định.
  • Dependencies: core không phụ thuộc React; React package yêu cầu React 18+; Node 20+ cho dev.
  • License: MIT. TypeScript strict mode bật.

So sánh nhanh

Giải phápOutputReact depData-driven
lucide + animate-spinSVG xoayKhông
cli-spinnersTerminalKhôngPartial (frame array)
Framer Motion spinnerSVG/HTMLCó (Motion runtime)Không
dot-loadersSVG + text + terminalKhông (core)Có (typed schema)

Use case

  • Pending state trên shadcn <Button>, <Form> submit, toast, dialog.
  • Dev tool / CLI dùng đúng loader schema mà web UI đang dùng — đồng bộ branding loading giữa terminal và browser.
  • Designer muốn trạng thái loading có dấu ấn mà không phải viết Framer Motion choreography.
  • Component library muốn loading primitive framework-agnostic — core không kéo React, có thể nhúng vào Vue/Svelte wrapper.
  • Dashboard/admin panel có nhiều pending state song song: dùng nhiều preset khác nhau để ám chỉ loại tác vụ (upload, render, sync) mà không cần icon khác nhau.
  • Copy-paste vào RSC pending boundary hoặc Server Action — zero-runtime cost ở core package nghĩa là không kéo thêm client bundle đáng kể.

Cài đặt nhanh

Cài ba package cần thiết cho project React:

pnpm add @dot-loaders/core @dot-loaders/react @dot-loaders/presets

Nếu chỉ cần dùng trong Node CLI hoặc build tool, chỉ cần @dot-loaders/core và tự viết adapter theo renderer text/terminal — không kéo React vào bundle.

Giới hạn & giá

MIT, miễn phí, open source. Yêu cầu React 18+ nếu dùng package React. Landing page hiện chỉ show rõ preset braille; các preset khác cần xem qua live composer trong apps/docs của repo. Chưa có số liệu npm download public vào thời điểm ra mắt.

Tiếp theo

Monorepo chia sẵn apps/shadcn-demo như reference implementation — tín hiệu tốt cho việc mở rộng thêm adapter cho framework khác và nhiều preset hơn trong @dot-loaders/presets. Với thiết kế schema-first, cộng đồng có thể đóng góp loader mới chỉ bằng một JSON/TS object, không chạm vào engine.

Nguồn: grixate.github.io/dot-loaders, GitHub repo, tweet gốc.