cssVars — المتغيرات
ليها 3 مفاتيح:
theme: متغيرات Tailwind v4 العامة، زي الخطوط والـ spacing والـ animations.light: قيم الـ light mode.dark: قيم الـ dark mode.
registry-item.json
{ "cssVars": { "theme": { "font-heading": "Cairo, sans-serif" }, "light": { "brand": "oklch(0.55 0.17 160)", "brand-accent": "oklch(0.8 0.1 90)" }, "dark": { "brand": "oklch(0.7 0.15 160)", "brand-accent": "oklch(0.6 0.1 90)" } }}- الـ CLI بيعدّل ملف الـ CSS بتاع المشروع ويحط القيم.
- لون جديد: حطه في
lightوdark، وبعدها تقدر تستخدمbg-brandوtext-brand-accentعلى طول. - تغيّر متغير Tailwind موجود: حطه في
themeبنفس اسمه، زي"spacing": "0.2rem"أو"breakpoint-md": "800px"أو"ease-in-out": "cubic-bezier(...)".
css — قواعد CSS جديدة
كل key هو at-rule أو selector، والقيمة object:
registry-item.json
{ "css": { "@layer base": { "h1": { "font-size": "var(--text-2xl)" } }, "@layer components": { "price-tag": { "background-color": "var(--color-brand)", "padding": "var(--spacing-2)" } }, "@utility content-auto": { "content-visibility": "auto" }, "@utility no-scrollbar": { "&::-webkit-scrollbar": { "display": "none" } }, "@utility tab-*": { "tab-size": "var(--tab-size-*)" } }}@layer base: للـ styles العامة زي الـ headings والـ body.@layer components: لـ classes الـ components.@utility: utility بسيطة، أو معقدة فيها nested selectors، أو functional بالنجمةtab-*.
@import و@plugin
registry-item.json
{ "dependencies": ["@tailwindcss/typography", "tw-animate-css"], "css": { "@import \"tailwindcss\"": {}, "@import url(\"https://fonts.googleapis.com/css2?family=Cairo&display=swap\")": {}, "@import \"print.css\" print": {}, "@plugin \"@tailwindcss/typography\"": {}, "@plugin \"tw-animate-css\"": {}, "@plugin \"./my-plugin.js\"": {}, "@layer base": { "body": { "font-family": "Cairo, sans-serif" } } }}- الـ
@importبيتحط في أول ملف الـ CSS. وبيقبل string عادي أوurl()أو media query. - الـ
@pluginبيتحط بعد الـ imports وقبل باقي الـ CSS. ولو كذا plugin، بيتجمعوا مع بعض ويتشال المكرر. - الترتيب النهائي: imports، وبعدها plugins، وبعدها أي CSS تاني.
- plugin من npm: لازم يتكتب في
dependenciesكمان، وإلا هيتضاف للـ CSS من غير ما يتسطب.
الـ animations محتاجة حاجتين
registry-item.json
{ "cssVars": { "theme": { "--animate-wiggle": "wiggle 1s ease-in-out infinite" } }, "css": { "@keyframes wiggle": { "0%, 100%": { "transform": "rotate(-3deg)" }, "50%": { "transform": "rotate(3deg)" } } }}لازم الـ @keyframes في css، والـ --animate-* في cssVars.theme. واحدة من غير التانية مش هتشتغل.
registry:font — الخطوط
font-cairo.json
{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "font-cairo", "type": "registry:font", "font": { "family": "'Cairo Variable', sans-serif", "provider": "google", "import": "Cairo", "variable": "--font-sans", "weight": ["400", "700"], "subsets": ["arabic", "latin"], "dependency": "@fontsource-variable/cairo" }}family(إجباري): قيمةfont-familyفي الـ CSS.provider(إجباري): حاليًاgoogleبس.import(إجباري): اسم الـ import منnext/font/google. والأسماء اللي فيها مسافة بتتكتب بـ_، زيJetBrains_Mono.variable(إجباري): اسم الـ CSS variable، زي--font-sansأو--font-monoأو--font-heading.weightو**subsets**: اختياريين.dependency: الـ npm package اللي يتسطب في المشاريع اللي مش Next.selector: اختياري، والـ default بتاعهhtml.
selector بيغيّر إيه؟
- من غيره: الـ font class بتتحط على
html، فالخط بيبقى على الصفحة كلها. - معاه: زي
"selector": "h1, h2, h3"، الـ class (مثلًاfont-heading) بتتحط بـ@applyعلى الـ selector ده جوه@layer base. - الـ variable نفسه بيفضل متحط على
htmlفي الحالتين، فتقدر تستخدمه في أي حتة.
registry:theme وregistry:style
registry:theme: ألوان بس فيcssVars، زيbackgroundوprimaryوringوsidebar-*، لـ light ولـ dark.registry:style: style كامل بيتطبق وقتshadcn init، وممكن يكون فيهdependenciesوregistryDependenciesوcssVarsوcss.
nile-style.json
{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "nile-style", "type": "registry:style", "dependencies": ["@tabler/icons-react"], "registryDependencies": ["login-01", "calendar", "https://nile.dev/r/money-input.json"], "cssVars": { "theme": { "font-sans": "Cairo, sans-serif" }, "light": { "brand": "oklch(0.55 0.17 160)" }, "dark": { "brand": "oklch(0.7 0.15 160)" } }}extends: "none" — من الصفر
- من غيره: الـ style بيبني على shadcn، يعني بياخد الـ defaults بتاعته ويزوّد عليها.
- معاه: الـ style مش بيورث أي حاجة من shadcn، وإنت مسؤول عن كل الـ components والـ vars والـ dependencies.
nile-from-scratch.json
{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "extends": "none", "name": "nile-scratch", "type": "registry:style", "dependencies": ["cn"], "registryDependencies": ["utils", "https://nile.dev/r/button.json", "https://nile.dev/r/input.json"], "cssVars": { "light": { "main": "#0e7c66", "bg": "#f4f1ea", "text": "#111" }, "dark": { "main": "#3fd1ac", "bg": "#14161a", "text": "#eee" } }}registry:base — design system كامل
الـ base هو أكبر نوع: dependencies وvars وCSS، ومعاهم إعداد المشروع في حقل config، وده حقل خاص بالـ base بس. كل حاجة فيه اختيارية:
style: اسم الـ style.iconLibrary: مكتبة الأيقونات، زيlucide.rsc: React Server Components، والـ defaultfalse.tsx: TypeScript، والـ defaulttrue.rtl: دعم right-to-left، والـ defaultfalse. وده مهم لينا.menuColor:defaultأوinvertedأوdefault-translucentأوinverted-translucent.menuAccent:subtleأوbold.tailwind.baseColorو**tailwind.css** و**tailwind.prefix**.aliases.componentsو**utils** و**ui** و**lib** و**hooks**.registries: registries تانية تتضاف لمشروع المستخدم، والـ keys لازم تبدأ بـ@.
nile-base.json
{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "nile-base", "type": "registry:base", "config": { "style": "nile-base", "iconLibrary": "lucide", "rtl": true, "tailwind": { "baseColor": "stone" }, "registries": { "@nile": "https://nile.dev/r/{name}.json" } }, "dependencies": ["class-variance-authority", "tw-animate-css", "lucide-react"], "registryDependencies": ["utils", "font-cairo"], "cssVars": { "light": { "background": "oklch(1 0 0)", "primary": "oklch(0.55 0.17 160)" }, "dark": { "background": "oklch(0.15 0 0)", "primary": "oklch(0.7 0.15 160)" } }, "css": { "@import \"tw-animate-css\"": {}, "@layer base": { "body": { "@apply bg-background text-foreground": {} } } }}والـ base كمان ينفع يتعمل extends: "none" عشان يبقى design system من الصفر.
Block بيغيّر الـ primitives
ممكن تاخد block من shadcn وتبدّل الـ primitives اللي جواه بتوعك، من غير ولا ملف:
nile-login.json
{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "nile-login", "type": "registry:block", "registryDependencies": [ "login-01", "https://nile.dev/r/button.json", "https://nile.dev/r/input.json" ]}الـ login-01 بيتسطب الأول، وبعده الـ button والـ input بتوعك بيتكتبوا فوق بتوع shadcn، لأنهم نفس الـ target والأخير بيكسب. وده هيتشرح بالتفصيل في فصل الـ namespaces.
خلّصت الفصل لما
🧠 اختبر نفسك
١) ضفت @plugin @tailwindcss/typography في css بس. إيه الناقص؟
تحطه في dependencies عشان يتسطب.
٢) font فيها selector: h1. الـ variable هيتحط فين؟
على html زي العادي. الـ class بس اللي بتتطبق على h1.
٣) عايز design system مش وارث أي حاجة من shadcn. تعمل إيه؟
extends: none في registry:style أو registry:base.
٤) إيه الحقل اللي موجود في registry:base بس؟
config، وهو إعداد المشروع زي iconLibrary وrtl وaliases وregistries.