Yugen UI

Hooks

Chín hook dùng chung mà chính các component của Yugen UI dùng — trạng thái, màn hình, lưu trữ, phím tắt, đo đạc.

Thư viện export các hook mà component bên trong dùng, để ứng dụng khỏi chép lại hoặc kéo thêm một thư viện hook thứ hai: useControllableState (mẫu x / defaultX / onXChange), useDisclosure, useMediaQuery, useLocalStorage (an toàn SSR, đồng bộ giữa tab), useClipboard, useHotkeys (bỏ qua ô nhập, mũi tên theo chiều chữ khi RTL), useDebouncedValue, useIntersection và useElementSize. Tất cả an toàn khi render ở server: chưa có window thì trả giá trị khởi đầu và đổi sau khi hydrate.
Nút thứ hai do cha điều khiển: đang mở

Import

Cài từ npm, chép mã nguồn vào dự án bằng @yugen-ui/cli hoặc shadcn CLI, hoặc import thẳng khi làm việc trong repo này.

TSX
// npm install yugen-uiimport {  useControllableState,  useDisclosure,  useMediaQuery,  useLocalStorage,  useClipboard,  useHotkeys,  useDebouncedValue,  useIntersection,  useElementSize,} from "yugen-ui";

Biến thể

Mỗi ô là một mẫu độc lập: hover để Copy, hoặc bấm Code để xem mã nguồn.

Bảng đang đóng.

useDisclosure

Mở / đóng / đảo cho dialog, menu, panel. Các hàm có identity ổn định nên truyền thẳng vào onClick.

Màn hẹpHệ thống: sángChuyển động đầy đủ

useMediaQuery

Theo dõi một CSS media query. Đổi cỡ cửa sổ hoặc chế độ sáng / tối của hệ điều hành để thấy đổi ngay, không nháy khi render lại.

Tải lại trang, hoặc mở tab thứ hai: giá trị theo bạn.

useLocalStorage

Lưu JSON vào localStorage, đồng bộ giữa các hook cùng khoá và giữa các tab. Server và lần hydrate đầu dùng giá trị ban đầu nên HTML không lệch.

yugen_live_4f9a2c71

useClipboard

Chép chữ vào bộ nhớ tạm; copied tự tắt sau timeout. Đã có sẵn đường lui cho ngữ cảnh không an toàn.

Bấm vào khung này rồi nhấn Ctrl / ⌘ + K, ? hoặc mũi tên. Gõ trong ô dưới: phím thường bị bỏ qua, phím có Ctrl / ⌘ vẫn chạy.

    useHotkeys

    Khoá là tổ hợp phím, mod là ⌘ trên Mac và Ctrl ở nơi khác. Phím thường không chạy khi đang gõ trong ô nhập; start / end đảo theo RTL.

    Đang gõ: “”

    Sau 400ms: “” — đã “gọi API” 0 lần

    useDebouncedValue

    Giá trị chỉ đổi khi người dùng ngừng gõ đủ delay — gọi API theo giá trị đã debounce thay vì mỗi phím.

    Thẻ ngoài khung
    Cuộn xuống…
    Thẻ được theo dõi

    useIntersection

    Biết phần tử có đang trong khung nhìn không. Dùng once để tải lười hoặc chạy hiệu ứng đúng một lần.

    0 × 0 px

    Bố cục gọn— kéo góc dưới phải để đổi cỡ.

    useElementSize

    Đo phần tử theo ResizeObserver, để đổi bố cục theo chỗ chứa thay vì theo cỡ cửa sổ.

    Cách dùng

    Nên
    • Dùng useControllableState cho mọi component có cặp x / defaultX / onXChange để hành vi controlled và uncontrolled giống nhau.
    • Dùng useMediaQuery cho logic (đổi component, đổi số cột); dùng breakpoint của Tailwind cho thay đổi thuần giao diện.
    • Đặt tên khoá useLocalStorage có tiền tố của ứng dụng, và chỉ lưu dữ liệu nhỏ, không nhạy cảm.
    • Đặt phím tắt toàn cục ở vài chỗ cấp cao; để useHotkeys bỏ qua ô nhập thay vì tự lọc.
    Không nên
    • Không đọc giá trị useLocalStorage khi render để quyết định HTML ở server — lần render đầu luôn là giá trị ban đầu.
    • Không lưu token hay dữ liệu cá nhân vào localStorage.
    • Không dùng left / right cho phím tắt điều hướng theo chiều chữ — dùng start / end để RTL đúng.
    • Không debounce giá trị mà người dùng cần thấy phản hồi ngay (ô nhập vẫn bind giá trị gốc).

    Props

    Prop · KiểuMặc địnhMô tả
    useControllableState({ value, defaultValue, onChange })[T, (next: SetStateAction<T>) => void]Mặc định: —Hàm set có identity ổn định, bỏ qua khi giá trị không đổi. value === undefined nghĩa là uncontrolled.
    useDisclosure({ open, defaultOpen, onOpenChange }){ open, setOpen, onOpen, onClose, onToggle }Mặc định: defaultOpen: falseTrạng thái mở / đóng, cũng dùng được ở chế độ controlled.
    useMediaQuery(query, { defaultValue })booleanMặc định: falseGiá trị khi chưa có window (server, test). Dựa trên useSyncExternalStore nên không nháy.
    useLocalStorage(key, initialValue, { serialize, deserialize })[T, set, remove]Mặc định: —set nhận giá trị hoặc hàm cập nhật; remove() xoá khoá và về giá trị ban đầu. Dữ liệu hỏng hoặc localStorage bị chặn vẫn không gây lỗi. Mặc định lưu JSON; serialize / deserialize để đọc khoá có sẵn ở dạng khác.
    useClipboard({ timeout }){ copy(text): Promise<boolean>, copied, reset }Mặc định: 1600timeout (ms) là thời gian giữ copied = true.
    useHotkeys(hotkeys, options)voidMặc định: —options: target (mặc định document), enabled (true), enableOnFormTags (false), preventDefault (true), repeat (false: giữ phím chỉ tính một lần). Khoá hợp lệ: mod / ctrl / meta / alt / shift + phím, cùng alias esc, space, up, down, left, right, start, end.
    useDebouncedValue(value, delay)TMặc định: 300Trả giá trị ngay lần đầu; sau đó chỉ đổi khi value đứng yên delay ms.
    useIntersection({ root, rootMargin, threshold, once }){ ref, isIntersecting, entry }Mặc định: —Gắn ref vào phần tử. Không có IntersectionObserver thì luôn false.
    useElementSize({ box, enabled }){ ref, width, height }Mặc định: box: "content-box", enabled: trueChưa đo được (server, lần render đầu) thì là 0 × 0. Đo lần đầu trước khi trình duyệt vẽ nên không nháy. Dùng được cả với chữ viết dọc. enabled: false khi kích thước đã biết trước (vd. độ rộng cố định): không đo, không ResizeObserver, không render thêm, luôn 0 × 0.