Mundarija (30)
- Bu darsda
- 1. Nega bu kerak?
- 2. Mantine: hooklar, forma va tayyor CSS
- 2.1 Qanday qurilgan
- 2.2 @mantine/hooks — eng foydali qism
- 2.3 @mantine/form
- 3. Chakra UI v3: Ark UI ustida
- 3.1 Qanday qurilgan
- 3.2 Tema: createSystem
- 3.3 Snippetlar: shadcn g'oyasi Chakra'da
- 3.4 Ark UI va Park UI
- 4. HeroUI: React Aria + Tailwind
- 4.1 Qanday qurilgan
- 4.2 Esc tasdiq oynasini yopmadi — ataylab
- 5. React Aria Components: xulq — Adobe'dan
- 5.1 Qanday qurilgan
- 5.2 className — funksiya
- 5.3 O'quv modeli: holat → className va data-*
- 6. DaisyUI: faqat CSS sinflari
- 7. Bir xil ekran: o'lchov
- 8. Qaysi biri qachon
- 9. Biz sinab ko'rdik: nega vazifalar da bular yo'q
- 10. Ko'p uchraydigan xatolar
- 11. Mashqlar
- 1-mashq (oson): kim ustida qurilgan?
- 2-mashq (o'rta): useToggle
- 3-mashq (qiyin): data-* holatlari bilan tugma
- 12. Real ishda
- Xulosa
- Manbalar
Mantine, Chakra, HeroUI va React Aria: boshqa React UI kitlar
Qisqacha: MUI va Ant Design'dan tashqari to'rtta kit tez-tez uchraydi. Mantine — 120 ga yaqin komponent, 81 ta hook va o'z formasi, uslubi tayyor CSS faylda. Chakra UI v3 — Ark UI (holat mashinalari) ustida, tema
createSystembilan, uslub Emotion orqali. HeroUI — React Aria + Tailwind v4 ustidagi chiroyli komponentlar. React Aria Components — Adobe'ning xulq kutubxonasi: ko'rinish sizniki, a11y eng chuqur. Bir xil ekranda o'lchadik: React Aria 95.1 KB va CSP 1, Mantine ochilmadi (Trusted Types), Chakra va HeroUI — 151–155 KB.
Bu darsda
- To'rt kitning har birini "qanday qurilgan" (uslub dvigateli, xulq qatlami) bo'yicha farqlaysiz.
- Mantine hooklarini (
useDisclosure) va React Aria'ningclassNamefunksiyasini o'quv modelida yozasiz. - Chakra v3 temasi (
createSystem) va snippet CLI'ni, Ark UI va Park UI'ni bilasiz. - HeroUI'da Esc nega tasdiq oynasini yopmasligini manba kodidan topasiz.
- DaisyUI — faqat CSS sinflari bo'lgan "kit"ni ko'rasiz.
- Kanon o'lchovi bilan qaysi vaziyatda qaysi kit to'g'ri ekanini aytasiz.
Oldin bilishingiz kerak: UI kutubxonalar xaritasi, MUI (Material UI), Ant Design, Headless komponentlar va prop getters.
1. Nega bu kerak?
Sardor vakansiyalarni ko'rib chiqdi. Birida "Mantine bilan ishlash tajribasi", ikkinchisida "Chakra UI", uchinchisida "HeroUI (NextUI)", to'rtinchisida "React Aria". Hammasini o'rganib chiqish uchun vaqt yo'q. Lekin har birining qanday qurilgani ni bilsangiz, yangi kitni bir kunda o'zlashtirasiz.
Har kitni uchta savol bilan tahlil qilamiz:
- Xulq qatlami — fokus, klaviatura, ARIA'ni kim qiladi (o'zimi, Radix'mi, React Aria'mi, Ark UI'mi)?
- Uslub dvigateli — CSS-in-JS (
<style>yasaydi), tayyor CSS fayl yoki Tailwind? - O'lchov — hajm, CSP, klaviatura (kanon tajribasidan).
Hayotiy o'xshatish: avtomobil sotib olganda rangiga emas, avval dvigateli va shassisiga qaraysiz. Kit ham shunday: ko'rinish — ustki qism, xulq va uslub dvigateli — ichki qism.
flowchart TB
subgraph X["Xulq qatlami"]
RA["React Aria"]
ARK["Ark UI (Zag.js)"]
OWN["o'zining"]
end
RA --> HERO["HeroUI<br/>+ Tailwind"]
RA --> RAC["React Aria<br/>Components"]
ARK --> CHAKRA["Chakra v3<br/>+ Emotion"]
ARK --> PARK["Park UI<br/>+ Panda/Tailwind"]
OWN --> MANTINE["Mantine<br/>+ CSS fayl"]Nimaga qarang: HeroUI va React Aria Components bir xil "shassi"da, Chakra va Park UI — boshqasida. Bitta xulq qatlamini bilsangiz, uning ustidagi kitlar tanish bo'ladi.
2. Mantine: hooklar, forma va tayyor CSS
2.1 Qanday qurilgan
Mantine — katta styled kit: @mantine/core 9.7.1 ning components papkasida 120 ta katalog (o'z kompyuterimizda sanadik), alohida hooklar va forma paketlari. Uslub dvigateli — CSS-in-JS emas: komponentlar uslubi tayyor CSS faylda keladi va siz uni import qilasiz (kanon tajribasidagidek):
import { MantineProvider, Button, Modal } from "@mantine/core";
import "@mantine/core/styles.css";
<MantineProvider>
<Button variant="default">O'chirish</Button>
</MantineProvider>Bu MUI va AntD'dan yaxshiroq ko'rinadi: CSS — oddiy fayl, style-src 'self' bilan chiqishishi kerak. Lekin o'lchovni eslang (UI kutubxonalar xaritasi): Mantine vazifalar CSP'si ostida umuman ochilmadi. Nega?
MantineProvider tema qiymatlarini CSS o'zgaruvchilari sifatida <style> tegiga yozadi. Manba kodida (@mantine/core 9.7.1, MantineCssVariables.mjs, o'z kompyuterimizda ochdik):
if (css) return jsx("style", {
"data-mantine-styles": true,
nonce: nonce?.(),
dangerouslySetInnerHTML: { __html: `${css}…` }
});dangerouslySetInnerHTML — React bu matnni innerHTML bilan yozadi. Trusted Types innerHTML ga oddiy satrni taqiqlaydi (Ant Design darsidagi bilan bir xil sabab) → istisno → oq ekran. Kanon yozuvida (kitlar-ishlat.txt):
{"v":"mantine","xato":"Waiting failed: 10000ms exceeded","csp":["require-trusted-types-for trusted-types-sink","require-trusted-types-for trusted-types-sink"],...}E'tibor bering: kodda nonce: nonce?.() bor — MantineProvider ning getStyleNonce prop'i. Server nonce bersa, style-src muammosi hal bo'ladi. Trusted Types esa baribir to'sadi.
Hajm: 139.8 KB, shundan CSS 35.9 KB — tayyor CSS fayl barcha komponentlar uslubini olib keladi, ekranda bitta tugma bo'lsa ham.
2.2 @mantine/hooks — eng foydali qism
Mantine'ning eng qadrli tomoni — hooklar. @mantine/hooks 9.7.1 da 81 ta hook bor (lib papkasida sanadik): useDisclosure, useDebouncedValue, useClickOutside, useLocalStorage, useMediaQuery, useHotkeys, useIntersection, useReducedMotion va boshqalar.
Muhim fakt: bu paketning dependencies ro'yxati bo'sh, faqat react peer. Ya'ni uni Mantine komponentlarisiz ham ishlatish mumkin — Radix yoki shadcn loyihasida ham. Uslub muammosi yo'q: hooklar CSS yozmaydi.
Eng ko'p ishlatiladigani — useDisclosure: ochiq/yopiq holat va uchta amal.
import { useDisclosure } from "@mantine/hooks";
const [opened, { open, close, toggle }] = useDisclosure(false);Bu custom hook darsidagi naqsh. Uni o'zimiz yozib ko'ramiz — o'quv modeli, Mantine'ning kodi emas:
import { useState } from "react";
function useDisclosure(initial = false) {
const [opened, setOpened] = useState(initial);
const handlers = {
open: () => setOpened(true),
close: () => setOpened(false),
toggle: () => setOpened((o) => !o),
};
return [opened, handlers];
}
export default function App() {
const [opened, { open, close, toggle }] = useDisclosure();
console.log("opened:", opened);
return (
<div>
<button onClick={open}>Menyuni ochish</button>{" "}
<button onClick={close}>Yopish</button>{" "}
<button onClick={toggle}>Almashtirish</button>
{opened && <p>Osh — 35 000 so'm</p>}
</div>
);
}Konsolda:
opened: false
opened: true
opened: false
opened: trueEkranda:
Menyuni ochish Yopish Almashtirish
Osh — 35 000 so'mMassiv qaytarish — useState dagi kabi: nomni o'zingiz tanlaysiz ([menuOpened, menu]). Ikkinchi element — funksiyalar obyekti, uni ham massiv va obyekt destructuring bilan ochdik. Haqiqiy useDisclosure da onOpen/onClose callback'lari ham bor.
2.3 @mantine/form
Mantine'ning o'z formasi — useForm:
import { useForm } from "@mantine/form";
const form = useForm({
mode: "uncontrolled",
initialValues: { ism: "", odam: 2 },
validate: {
ism: (v) => (v.trim() === "" ? "Ismni kiriting" : null),
odam: (v) => (v < 1 || v > 20 ? "1–20 oralig'ida" : null),
},
});
<form onSubmit={form.onSubmit((qiymatlar) => saqla(qiymatlar))}>
<TextInput label="Ism" {...form.getInputProps("ism")} />
</form>validate — har maydon uchun funksiya: xato matni yoki null. mode: "uncontrolled" — React Hook Form dagi kabi qiymatlar har harfda qayta chizilmaydi. getInputProps — prop getter naqshi: maydonga kerakli props'ni bitta obyektda beradi. Zod bilan ham ulanadi (zod4Resolver — alohida paketda).
3. Chakra UI v3: Ark UI ustida
3.1 Qanday qurilgan
Chakra UI 3-versiyada qayta yozildi. Endi uning xulq qatlami — Ark UI: o'sha jamoaning headless kutubxonasi. Ark UI esa Zag.js ustida: har komponent xulqi — holat mashinasi (Holat mashinalari darsidagi XState g'oyasi, kichikroq shaklda). npm'dagi tavsifi: "A minimal implementation of xstate fsm for UI machines".
@chakra-ui/react 3.37.0 ning bog'liqliklarini o'qidik: @ark-ui/react, @emotion/serialize, @emotion/utils, @emotion/use-insertion-effect-with-fallbacks… Ya'ni xulq — Ark UI, uslub — Emotion (MUI'dagi CSS-in-JS dvigateli). Natija oldindan ma'lum: <style> teglari va CSP buzilishi.
Kanon o'lchovi: 151.0 KB, CSP buzilishi 3, klaviatura (rol alertdialog, fokus «Bekor qilish» da, Esc'da qaytdi).
3.2 Tema: createSystem
Chakra v3 da tema — system:
import {
ChakraProvider, createSystem, defaultConfig, defineConfig,
} from "@chakra-ui/react";
const config = defineConfig({
theme: {
tokens: {
colors: { bahor: { 500: { value: "#0f7b3f" } } },
},
},
});
const system = createSystem(defaultConfig, config);
<ChakraProvider value={system}>…</ChakraProvider>Har token — { value: … } obyekt (W3C dizayn tokenlari formatiga yaqin). createSystem standart konfiguratsiyani siznikiga birlashtiradi. Komponentda: <Button colorPalette="red"> — rang palitrasi bitta prop bilan. Kanon tajribasidagi Chakra varianti defaultSystem ni ishlatgan.
3.3 Snippetlar: shadcn g'oyasi Chakra'da
Chakra v3 ning qiziq tomoni — ba'zi komponentlar paketdan emas, loyihangizga ko'chiriladi. CLI buyrug'i (@chakra-ui/cli 3.37.0 ning manba kodida snippet add [snippets...] buyrug'i bor):
npx @chakra-ui/cli@3.37.0 snippet addBu — shadcn/ui dagi copy-paste yondashuv: src/components/ui/ ga tayyor o'ramlar (provider.tsx, toaster.tsx…) yoziladi va ular sizniki bo'ladi. Ya'ni Chakra v3 — styled kit va copy-paste aralashmasi.
3.4 Ark UI va Park UI
- Ark UI — Chakra'siz ham ishlatiladigan headless kutubxona (
@ark-ui/react5.39.3). Uning xususiyati — bir xil xulq bir nechta framework uchun: React, Vue, Solid, Svelte. Radix va React Aria bilan bir qatorda (UI kutubxonalar xaritasi dagi headless yo'l). - Park UI — Ark UI ustiga tayyor ko'rinish (Panda CSS yoki Tailwind bilan), shadcn kabi CLI orqali ko'chiriladi (
@park-ui/cli). Ya'ni "shadcn, lekin Radix o'rniga Ark".
Bu ikkalasini kanon o'lchamagan — raqam aytmaymiz.
4. HeroUI: React Aria + Tailwind
4.1 Qanday qurilgan
HeroUI (avvalgi nomi NextUI) — ko'zga chiroyli, animatsiyali styled kit. @heroui/react 3.2.6 ning peer bog'liqliklari: react-aria-components, react-aria, tailwindcss >=4.0.0. Ya'ni xulq — React Aria (Adobe), ko'rinish — Tailwind v4 uslublari. Ulash kanon tajribasidagidek:
@import "tailwindcss" source(none);
@import "@heroui/styles";
@source "./heroui.tsx";Komponent — compound naqshda (Compound komponentlar):
<AlertDialog>
<Button variant="secondary">O'chirish</Button>
<AlertDialog.Backdrop>
<AlertDialog.Container>
<AlertDialog.Dialog>
<AlertDialog.Header>
<AlertDialog.Heading>{sarlavha}</AlertDialog.Heading>
</AlertDialog.Header>
<AlertDialog.Footer>
<Button slot="close" variant="tertiary">
Bekor qilish
</Button>
</AlertDialog.Footer>
</AlertDialog.Dialog>
</AlertDialog.Container>
</AlertDialog.Backdrop>
</AlertDialog>Kanon o'lchovi: 154.7 KB (CSS 39.1 KB — @heroui/styles ning tayyor uslublari), CSP buzilishi 1.
4.2 Esc tasdiq oynasini yopmadi — ataylab
O'lchovdagi eng qiziq qator:
{"v":"heroui",...,"escdanKeyin":{"oyna":true,"fokus":"Vazifa o'chirilsinmi"},...}Esc bosildi — oyna ochiq qoldi. UI kutubxonalar xaritasi darsida "ehtimol ataylab" degan edik. Endi manba kodida tekshirdik (@heroui/react 3.2.6, alert-dialog.d.ts):
/**
* Whether pressing the escape key to close the modal should
* be disabled.
* Alert dialogs typically require explicit action, so this
* defaults to true.
* @default true
*/
isKeyboardDismissDisabled?: boolean;Tarjimasi: "Esc bilan yopishni o'chirish. Ogohlantirish oynalari odatda aniq javob talab qiladi, shuning uchun standart qiymat — true". Xuddi shunday isDismissable (tashqariga bosish) — standart false. Ya'ni bu xato emas, dizayn qarori: xavfli amal tasodifan yopilmasin.
Lekin bu WAI-ARIA'ning alertdialog tavsiyasidan farq qiladi: unda Esc oynani yopishi kutiladi, faqat fokus odatda xavfsiz tugmada turadi. Bobur (faqat klaviatura) Esc bosib chiqolmay, "qotib qoldim" deb o'ylashi mumkin. Davosi bitta prop: <AlertDialog.Backdrop isKeyboardDismissDisabled={false}>. Saboq UI kutubxonalar xaritasi dagidek: standart xulqni o'z ssenariyingiz bilan sinang.
Tekshirib ko'ring: Radix AlertDialog va HeroUI AlertDialog — ikkalasida ham "tashqariga bosish oynani yopmaydi". Esc bo'yicha farq nima?
Javob
Radix AlertDialog'da (kanon tajribasidagi shadcn varianti) Esc oynani yopdi va fokus «O'chirish» ga qaytdi — o'lchovda escdanKeyin: oyna false. HeroUI'da standart holatda Esc o'chirilgan. Ikkalasi ham "ogohlantirish oynasi aniq javob talab qiladi" degan bir g'oyadan boshlangan, lekin chegarani har xil chizgan: Radix faqat tashqariga bosishni o'chiradi, HeroUI — Esc'ni ham. Kutubxona almashtirsangiz, testlaringiz aynan shu farqni ushlashi kerak.
5. React Aria Components: xulq — Adobe'dan
5.1 Qanday qurilgan
React Aria — Adobe'ning kutubxonasi. Ikki qavat:
- hooklar (
react-aria):useButton,useMenu,useDialog— faqat xulq va ARIA, siz DOM'ni o'zingiz yozasiz; - React Aria Components (
react-aria-components, kanonda 1.21.1): tayyor, lekin uslubsiz komponentlar —Button,DialogTrigger,Modal,Menu.
Bu headless yo'l (UI kutubxonalar xaritasi): ko'rinish to'liq sizniki. Kanon tajribasida o'z CSS'imiz — 533 bayt.
Kanon o'lchovi: 95.1 KB, CSP buzilishi 1, klaviatura . Fokus ochilganda tugmaga emas, oynaning o'ziga ("fokus":"Vazifa o'chirilsinmi" — oyna nomi): Malika avval savolni eshitadi, keyin Tab bilan tugmalarga o'tadi. Bu ham to'g'ri usul.
React Aria nonce'ni qayerdan oladi? Manba kodida (getNonce.mjs) — <meta name="csp-nonce"> tegi yoki __webpack_nonce__ dan. Ya'ni serverli ilovada sozlash bitta <meta> bilan.
5.2 className — funksiya
React Aria Components'ning o'ziga xos API'si: className (va style, children) funksiya bo'lishi mumkin. Funksiya komponent holatini oladi:
import { ToggleButton } from "react-aria-components";
<ToggleButton
className={({ isSelected, isFocusVisible }) =>
[
"tugma",
isSelected && "tanlangan",
isFocusVisible && "fokus-halqa",
].filter(Boolean).join(" ")
}
>
Faqat yetkazib berish
</ToggleButton>Bu — render props naqshi. Holat CSS'da ham ko'rinadi: data-selected, data-pressed, data-hovered, data-focus-visible atributlari (Radix chuqur dagi data-state g'oyasi, boshqa nomlar bilan).
isFocusVisible nega muhim? Sichqoncha bilan bosganda fokus halqasi kerak emas, klaviatura bilan kelganda — kerak. CSS'dagi :focus-visible bilan bir xil g'oya (Fokus boshqaruvi), lekin React Aria uni hamma brauzerda bir xil hisoblaydi.
5.3 O'quv modeli: holat → className va data-*
React Aria natija oynasida yo'q. G'oyani o'zimiz yozamiz — o'quv modeli:
import { useState } from "react";
function ToggleButton({ className, children }) {
const [isSelected, setSelected] = useState(false);
const cls =
typeof className === "function"
? className({ isSelected })
: className;
console.log("className:", cls);
return (
<button
aria-pressed={isSelected}
data-selected={isSelected || undefined}
className={cls}
onClick={() => setSelected((s) => !s)}
>
{children}
</button>
);
}
export default function App() {
return (
<ToggleButton
className={({ isSelected }) =>
isSelected ? "tugma tanlangan" : "tugma"
}
>
Faqat yetkazib berish
</ToggleButton>
);
}Konsolda:
className: tugma
className: tugma tanlangan
className: tugmaKomponent holatni o'zi saqlaydi, foydalanuvchi esa faqat "holatga qarab qaysi sinf" ni aytadi. aria-pressed — ekran o'quvchi uchun ("tugma, bosilgan"), data-selected — CSS uchun. || undefined — false bo'lganda atribut umuman yozilmasin (React undefined atributni tashlab yuboradi).
6. DaisyUI: faqat CSS sinflari
DaisyUI (5.7.50, "The Tailwind CSS Component Library") — umuman boshqa toifa: Tailwind plagini, JavaScript komponentlari yo'q. Faqat sinf nomlari:
<button class="btn btn-primary">Bron qilish</button>
<dialog id="tasdiq" class="modal">
<div class="modal-box">
<h3 class="text-lg font-bold">Vazifa o'chirilsinmi?</h3>
<form method="dialog" class="modal-action">
<button class="btn">Bekor qilish</button>
</form>
</div>
</dialog>Tailwind'da bg-green-700 px-4 py-2 rounded… deb yozish o'rniga — bitta btn btn-primary. Modal esa brauzerning o'z <dialog> i: fokus, Esc, fon — native dialog qiladi.
Kuchli tomoni: JS yo'q — React, Vue yoki oddiy HTML'da bir xil; uslub — build paytidagi oddiy CSS, ya'ni style-src 'self' bilan muammo bo'lmasligi kerak. Zaif tomoni: xulq yo'q. Dropdown menyu, combobox, toast — klaviatura va ARIA'ni siz yozasiz (yoki Radix/React Aria qo'shasiz). Kanon DaisyUI'ni o'lchamagan.
7. Bir xil ekran: o'lchov
Kanon tajribasi (tajriba/kitlar/, Chrome 155, vazifalar CSP'si ostida, faqat klaviatura):
- native <dialog> (kanon)CSP 066,8 KB
- React Aria 1.21.1CSP 195,1 KB
- Mantine 9.7.1ochilmadi139,8 KB
- Chakra UI 3.37.0CSP 3151 KB
- HeroUI 3.2.6CSP 1154,7 KB
Manba: O'lchandi: tajriba/kitlar, Vite 8.3.3, React 19.3.0, Chrome 155, natijalar/tajriba/kitlar-hajm.txt va kitlar-ishlat.txt, 2026-10-14
| Kit | Xulq / uslub | CSP | Klaviatura |
|---|---|---|---|
| React Aria | o'zi / sizniki | 1 | fokus oynada |
| Mantine | o'zi / CSS fayl + <style> |
Trusted Types — ochilmadi | — |
| Chakra v3 | Ark UI / Emotion | 3 | |
| HeroUI | React Aria / Tailwind | 1 | Esc yopmadi (standart) |
Kod qatorlari: Mantine 33, HeroUI 41, Chakra 41, React Aria 48 (kitlar-hajm.txt). Yana o'sha qonuniyat: styled kitlar — kamroq kod, ko'proq bayt; headless — aksincha.
8. Qaysi biri qachon
| Vaziyat | Mos keladi |
|---|---|
| Ko'p hook kerak, CSP'siz ichki panel | Mantine (yoki faqat @mantine/hooks) |
| Chakra'ni biladigan jamoa, moslashuvchan tema | Chakra v3 |
| Tailwind loyiha, tez chiroyli UI | HeroUI (Esc xulqini tekshiring) |
| A11y — eng muhim talab, o'z dizayn tizimi | React Aria Components |
| Bir nechta framework (React + Vue) | Ark UI / Park UI |
| JS'siz, faqat Tailwind sinflari | DaisyUI (+ xulq uchun headless) |
Kamsitish yo'q: har biri o'z vaziyatida eng yaxshi. Masalan, Mantine hooklari Radix loyihasida ham foydali, React Aria esa davlat xizmatlari kabi a11y talabi qattiq joyda kuchli.
Tekshirib ko'ring: Qattiq CSP va Trusted Types'li bank ilovasi, o'z dizayn tizimi bor. To'rt kitdan qaysi biri eng yaqin, va nima qo'shimcha qilish kerak?
Javob
React Aria Components. U uslub yozmaydi (dizayn tizimi sizniki), o'lchovda — 1 CSP buzilishi, Trusted Types'da ishladi. Qolgan bitta buzilish uchun serverda nonce va <meta name="csp-nonce"> — React Aria uni o'zi o'qiydi. Mantine Trusted Types'da ochilmaydi, Chakra — Emotion (3 buzilish), HeroUI — React Aria ustida, lekin o'z Tailwind uslublari bilan, dizayn tizimingizni almashtiradi. Baribir qaror — o'z ekraningizda o'lchovdan keyin.
9. Biz sinab ko'rdik: nega vazifalar da bular yo'q
Bu darsda vazifalar kodi o'zgarmaydi. Kanon qaydi (#05–#07): "CSS-in-JS (MUI, Chakra) va Mantine/AntD style-src 'self' / Trusted Types bilan ziddiyatda; o'lcham +46…+108 KB". vazifalar da Radix (menyu, tooltip) va native <dialog> qoldi.
React Aria esa jiddiy nomzod edi: 95.1 KB, 1 buzilish. Nega Radix? Radix chuqur darsida aytilgan: menyu modal={false} bilan CSP 0, mavjud loyihalarning ko'pi Radix'da, shadcn ekotizimi Radix (yoki Base UI) ustida. Agar vazifalar noldan boshlansa va a11y eng birinchi talab bo'lsa — React Aria yoki Base UI ni o'lchab tanlash mantiqli bo'lardi.
10. Ko'p uchraydigan xatolar
| Belgi | Sabab | Davosi |
|---|---|---|
Mantine: oq ekran, TrustedHTML |
MantineCssVariables — dangerouslySetInnerHTML |
Trusted Types'siz yoki boshqa kit |
| Mantine: komponentlar uslubsiz | @mantine/core/styles.css import qilinmagan |
CSS'ni ildizda import qiling |
Chakra: style-src xatolari |
Emotion <style> |
server nonce |
| HeroUI: Esc tasdiq oynasini yopmaydi | isKeyboardDismissDisabled standarti true |
prop'ni false qiling |
React Aria: className dagi shart ishlamaydi |
satr o'rniga funksiya kerak | className={({ isSelected }) => …} |
| ikki kit aralash — ikki xil fokus xulqi | har kit o'z fokus boshqaruvi | bitta xulq qatlami tanlang |
11. Mashqlar
Mashqlar kurs/mashqlar/20/07-boshqa-kitlar/ da.
1-mashq (oson): kim ustida qurilgan?
To'ldiring:
- HeroUI'ning xulq qatlami:
- Chakra UI v3 ning xulq qatlami:
- Chakra va MUI'ning umumiy uslub dvigateli:
- JS komponentlari yo'q, faqat Tailwind sinflari bo'lgan kit:
Yechim
- HeroUI — React Aria (peer:
react-aria-components) + Tailwind v4. - Chakra v3 — Ark UI (u esa Zag.js holat mashinalari ustida).
- Emotion — CSS-in-JS; shuning uchun ikkalasi ham CSP'da
<style>buzilishini beradi. - DaisyUI — Tailwind plagini; modal uchun native
<dialog>.
2-mashq (o'rta): useToggle
Mantine'dagi useToggle ning o'quv modelini yozing: useToggle(["light", "dark"]) — [qiymat, toggle] qaytaradi. toggle() keyingi qiymatga o'tadi (oxiridan boshiga qaytadi), toggle("dark") esa aniq qiymatni o'rnatadi.
Ishora: indeks — useState, keyingi indeks — (i + 1) % length (qoldiq operatori), aniq qiymat — indexOf.
import { useState } from "react";
function useToggle(options) {
// yozing
}
export default function App() {
const [size, toggle] = useToggle(["kichik", "o'rta", "katta"]);
const [mode, setMode] = useToggle(["yorug'", "qorong'i"]);
return (
<div>
<button onClick={() => toggle()}>Keyingi</button>{" "}
<button onClick={() => setMode("qorong'i")}>Qorong'i</button>
<p>O'lcham: {size}, rejim: {mode}</p>
</div>
);
}Uch marta «Keyingi» va bir marta «Qorong'i» bosilgandan keyin:
Keyingi Qorong'i
O'lcham: kichik, rejim: qorong'iYechim
import { useState } from "react";
function useToggle(options) {
const [index, setIndex] = useState(0);
function toggle(value) {
if (value !== undefined) {
setIndex(options.indexOf(value));
} else {
setIndex((i) => (i + 1) % options.length);
}
}
return [options[index], toggle];
}
export default function App() {
const [size, toggle] = useToggle(["kichik", "o'rta", "katta"]);
const [mode, setMode] = useToggle(["yorug'", "qorong'i"]);
return (
<div>
<button onClick={() => toggle()}>Keyingi</button>{" "}
<button onClick={() => setMode("qorong'i")}>Qorong'i</button>
<p>O'lcham: {size}, rejim: {mode}</p>
</div>
);
}Ekranda:
Keyingi Qorong'i
O'lcham: kichik, rejim: qorong'iUch bosishda: kichik → o'rta → katta → kichik (% 3 boshiga qaytardi). onClick={() => toggle()} — toggle ni to'g'ridan onClick={toggle} qilib bermadik: aks holda unga hodisa obyekti value bo'lib kelardi va indexOf -1 qaytarardi. Holatda qiymatning o'zi emas, indeksi — variantlar ro'yxati har renderda yangi massiv bo'lsa ham to'g'ri ishlaydi.
3-mashq (qiyin): data-* holatlari bilan tugma
«O'quv modeli: holat → className va data-*» bo'limidagi ToggleButton ni kengaytiring:
isPressedholati:onPointerDowndatrue,onPointerUpdafalse.data-pressedatributi faqat bosilib turganda.classNamefunksiyasi{ isSelected, isPressed }ni oladi.Appda tugma bosilgandan keyindocument.querySelector("button")ningaria-pressed,data-selectedvadata-pressedatributlarini konsolga chiqaring (tugma bosish bilan ishga tushadigansetTimeout(…, 50)ichida).
Bitta bosishdan keyin konsol oxiri:
aria-pressed: true | data-selected: true | data-pressed: nullIshora: getAttribute yo'q atributga null qaytaradi (Radix chuqur dagi kabi). Hodisalar tartibi: pointerdown → pointerup → click.
Yechim
import { useState } from "react";
function ToggleButton({ className, children, onChange }) {
const [isSelected, setSelected] = useState(false);
const [isPressed, setPressed] = useState(false);
const cls = className({ isSelected, isPressed });
return (
<button
aria-pressed={isSelected}
data-selected={isSelected || undefined}
data-pressed={isPressed || undefined}
className={cls}
onPointerDown={() => setPressed(true)}
onPointerUp={() => setPressed(false)}
onClick={() => {
setSelected((s) => !s);
onChange?.();
}}
>
{children}
</button>
);
}
function report() {
setTimeout(() => {
const b = document.querySelector("button");
console.log(
"aria-pressed:", b.getAttribute("aria-pressed"),
"| data-selected:", b.getAttribute("data-selected"),
"| data-pressed:", b.getAttribute("data-pressed"),
);
}, 50);
}
export default function App() {
return (
<ToggleButton
onChange={report}
className={({ isSelected, isPressed }) =>
[
"tugma",
isSelected && "tanlangan",
isPressed && "bosilgan",
].filter(Boolean).join(" ")
}
>
Faqat yetkazib berish
</ToggleButton>
);
}Konsolda:
aria-pressed: true | data-selected: true | data-pressed: nullclick kelganda pointerup allaqachon isPressed ni false qilgan — shuning uchun 50 ms dan keyin data-pressed yo'q (null), data-selected esa "true". filter(Boolean) — false qiymatlarni tashlab, faqat sinf nomlarini qoldiradi (cn() ning qo'lda yozilgan shakli, shadcn/ui I). React Aria'da shu ishning hammasini — sensorli ekran, klaviatura (Space/Enter) va sichqonchani bir xil "press" ga birlashtirishni — kutubxona qiladi.
12. Real ishda
- Vakansiyalar — kit nomi ko'pincha "talab" emas, "afzallik": bitta kitni chuqur bilsangiz, boshqasining xulq qatlamini va uslub dvigatelini aniqlab, tez o'tasiz.
- Aralash loyihalar — Mantine hooklari shadcn loyihasida, React Aria hooklari o'z dizayn tizimida — bu normal. Ikki styled kitni aralashtirish esa — yo'q (UI kutubxonalar xaritasi).
- Intervyu savollari: "headless va styled kit farqi?", "CSS-in-JS'siz styled kit bormi?", "React Aria nimasi bilan Radix'dan farq qiladi?", "kutubxonaning standart xulqi siz kutgandan farq qilsa nima qilasiz?".
Xulosa
- Kitni uch savol bilan tahlil qiling: xulq qatlami, uslub dvigateli, o'lchov.
- Mantine — CSS fayl, lekin
<style dangerouslySetInnerHTML>tufayli Trusted Types'da ochilmaydi;@mantine/hooksesa bog'liqliksiz va har loyihada foydali. - Chakra v3 — Ark UI (Zag.js) + Emotion + snippet CLI; Park UI — Ark ustidagi copy-paste.
- HeroUI — React Aria + Tailwind; AlertDialog'da Esc standart bo'yicha o'chirilgan (manbada yozilgan qaror).
- React Aria Components — uslubsiz,
classNamefunksiya vadata-*holatlari; o'lchovda 95.1 KB, CSP 1. - DaisyUI — faqat CSS sinflari; xulqni boshqa joydan olasiz.
Keyingi dars: Ikonkalar — lucide-react bilan vazifalar tugmalariga ikonka qo'shamiz. Nomli import nega +2.0 KB, icons[nom] esa +161 KB; ikonka qachon aria-hidden bo'ladi.
Manbalar
- Mantine: Getting started,
@mantine/hooks,@mantine/form, Styles (CSS files, nonce) — mantine.dev (9.7.1) - Chakra UI v3: Theming (
createSystem), CLI (snippet add) — chakra-ui.com (3.37.0); Ark UI — ark-ui.com; Zag.js — zagjs.com - HeroUI v3: AlertDialog — heroui.com (3.2.6)
- React Aria Components: Styling (render props, data attributes) — react-spectrum.adobe.com/react-aria
- Park UI — park-ui.com; DaisyUI — daisyui.com (5.7.50)
- WAI-ARIA APG: Alert and Message Dialogs Pattern — w3.org/WAI/ARIA/apg/patterns/alertdialog
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!