---
title: "डिज़ाइन सिस्टम और कस्टमाइज़ेशन"
description: "एक शब्दावली, कई डिज़ाइन सिस्टम। कोई डायल बदलें, कोई पैलेट घोषित करें, किसी टोकन को दूसरी जगह मोड़ें — और हर प्लैटफ़ॉर्म एक ही कमिट में साथ चलता है।"
url: "https://tanrei.chnotchy.com/hi/foundations/design-systems/"
last_updated: 2026-10-23T06:11:40.000Z
---

# डिज़ाइन सिस्टम और कस्टमाइज़ेशन

> एक शब्दावली, कई डिज़ाइन सिस्टम। कोई डायल बदलें, कोई पैलेट घोषित करें, किसी टोकन को दूसरी जगह मोड़ें — और हर प्लैटफ़ॉर्म एक ही कमिट में साथ चलता है।

Tanrei इस तरह बना है कि वह किसी भी डिज़ाइन सिस्टम को दोबारा बना सके — लगभग नहीं, बिलकुल ठीक — और फिर भी उसकी अपनी शब्दावली छोटी रहे। दो नियम इसे संभव बनाते हैं: **डिज़ाइन सिस्टम सबसे पहले मानों में अलग होते हैं**, और **जो बात मान से नहीं कही जा सकती, उसे लेयर जोड़ती है।**

## कोर टोकन क्या है, और क्या नहीं

Tanrei की कोर शब्दावली में वह हर अवस्था है जो **एक डिज़ाइन सिस्टम एक प्रॉडक्ट के भीतर ले सकता है**। इससे हर प्रस्तावित टोकन के लिए एक कसौटी मिलती है — **“एक प्रॉडक्ट” कसौटी**:

- **वह टोकन है**, अगर किसी एक प्रॉडक्ट को वह भेद चाहिए हो सकता है, अर्थ के कारण या जगह के कारण। `focus-ring`, `primary` से अलग है, क्योंकि कोई प्रॉडक्ट गहरा ब्रैंड रंग और हल्की फ़ोकस रिंग चाह सकता है। डिफ़ॉल्ट सिस्टम इन्हें आपस में जुड़े मान देता है, यह संयोग है, इन्हें मिला देने का कारण नहीं। Button के साइज़ इसलिए हैं कि एक ही प्रॉडक्ट कई साइज़ इस्तेमाल करता है।
- **वह टोकन नहीं है**, अगर वह सिर्फ़ किसी एक डिज़ाइन सिस्टम में, या किसी एक असामान्य प्रॉडक्ट में है। Material Design 3 का `tertiary` उस प्रीसेट में घोषित पैलेट है जो उसे दोबारा बनाता है, और उसके `primary-fixed` रोल उसी प्रीसेट के विस्तार हैं — ऐसी जगहें नहीं जिन्हें हर कोई ढोए। किसी एक अनोखे प्रॉडक्ट के लिए बटन के बीस साइज़ भी कोर शब्दावली नहीं हैं; वह प्रॉडक्ट उन्हें अपनी लेयर में जोड़ता है।

अगर इसके बाद भी किसी डिज़ाइन सिस्टम की कोई ख़ासियत दोबारा नहीं बन पाती — कोई बैकड्रॉप मटीरियल, टेक्स्ट साइज़ की उसकी अपनी टेबल — तो वह Tanrei की कमी है, जो मिमिक्री-गैप रजिस्ट्री में दर्ज होती है (रिपॉज़िटरी में `docs/governance/mimicry-gaps.json`)।

## डायल: एक बदलाव, हर जगह

डिज़ाइन सिस्टम डिफ़ॉल्ट रूप से ठीक लगना चाहिए, और जब आप एक चीज़ बदलें तो आपके साथ चलना चाहिए। हर चीज़ के नीचे आठ संख्यात्मक **डायल** हैं:

| डायल | डिफ़ॉल्ट | क्या बदलता है |
| --- | --- | --- |
| `dial.type.base` | 16px | टेक्स्ट का हर साइज़ |
| `dial.type.contrast` | 1 | हेडिंग बॉडी टेक्स्ट से कितनी अलग दिखती हैं |
| `dial.space.unit` | 8px | हर दूरी |
| `dial.size.unit` | 4px | कंट्रोल की ऊँचाई, आइकन के साइज़, हिट टार्गेट |
| `dial.density` | 1 | कंट्रोल और पंक्तियों की ऊँचाई, और उनकी सामग्री के आसपास की जगह: 1 से कम पर पास-पास, 1 से ज़्यादा पर खुला-खुला |
| `dial.shape.unit` | 2px | हर कोना |
| `dial.stroke.unit` | 1px | बॉर्डर, रिंग, फ़ोकस इंडिकेटर |
| `dial.motion.unit` | 50ms | हर अवधि |

हर टोकन तीन में से किसी एक प्रकार का होता है:

- **व्युत्पन्न** — एक छोटा नियम, आम तौर पर किसी डायल पर एक गुणांक: `display` है `type.base × 3`, `space175` है `space.unit × 1.75`। असली टाइप रैंप ज्यामितीय नहीं होते, इसलिए हर टोकन का **अपना** गुणांक है;
- **स्थिर** — बताए गए कारण के साथ एक लिटरल, जो डायल से मुक्त है (`corner.full`, कोई ईज़िंग कर्व, क़ानूनन तय फ़ुटनोट साइज़);
- **एलियास** — एक रेफ़रेंस जिसे दूसरी जगह मोड़ा जा सकता है (`button.container.gap` → `space100`)।

वेब पर डायल लाइव भी काम करते हैं: व्युत्पन्न टोकन `calc()` एक्सप्रेशन के रूप में निकलते हैं, इसलिए किसी भी एलिमेंट पर `--tanrei-dial-type-base` सेट करने से उसके भीतर सब कुछ नए सिरे से स्केल हो जाता है। एक टेस्ट हर व्युत्पन्न टोकन को असली ब्राउज़र में कई डायल सेटिंग पर निकालकर देखता है और माँगता है कि वह बिल्ड के नतीजे के बराबर हो।

## डिज़ाइन सिस्टम एक लेयर है

डिज़ाइन सिस्टम एक छोटी JSON फ़ाइल है जो किसी दूसरे सिस्टम का **विस्तार** करती है। ज़्यादातर वह मान बदलती है; जहाँ ज़रूरी हो, वहाँ वह [शब्दावली में जोड़ती है](https://tanrei.chnotchy.com/hi/foundations/design-systems/#%E0%A4%B6%E0%A4%AC%E0%A5%8D%E0%A4%A6%E0%A4%BE%E0%A4%B5%E0%A4%B2%E0%A5%80-%E0%A4%AE%E0%A5%87%E0%A4%82-%E0%A4%9C%E0%A5%8B%E0%A4%A1%E0%A4%BC%E0%A4%A8%E0%A4%BE)।

```json
{
  "id": "acme",
  "extends": "tanrei",
  "palettes": {
    "brand":   { "description": "Acme का लाल रंग ब्रैंड दिशानिर्देशों से तय है।", "source": { "seed": "#e60012" }, "roles": "intent" },
    "correct": { "description": "क्विज़ सही जवाबों को चिह्नित करता है — यह न success है, न primary।", "source": { "seed": "#0f766e" }, "roles": "intent" }
  },
  "tokens": {
    "tanrei.dial.type.base": { "$value": { "value": 17, "unit": "px" }, "reason": "हमारे पाठक हाथ भर की दूरी से पढ़ते हैं।" },
    "tanrei.comp.button.container.padding-inline-start.medium": { "scale": 2 },
    "tanrei.comp.button.container.gap.medium": { "$value": "{tanrei.sys.space.space50}" },
    "tanrei.sys.typescale.label-small": { "$value": { "fontSize": { "value": 11, "unit": "px" } }, "reason": "क़ानूनी फ़ुटनोट का साइज़ अनुबंध से तय है।" }
  }
}
```

| आप चाहते हैं | आप लिखते हैं |
| --- | --- |
| सब कुछ थोड़ा बड़ा | एक डायल सेट करें |
| बटन की पैडिंग डिफ़ॉल्ट से दोगुनी — और फिर भी स्पेसिंग डायल के साथ चलती हुई | `"scale": 2` |
| यह टोकन कोई दूसरा स्टेप इस्तेमाल करे | एलियास को दूसरी जगह मोड़ें |
| डायल कुछ भी करें, यह एक मान अपनी जगह रहे | `$value` को एक `reason` के साथ पिन करें |
| ब्रैंड या डोमेन का रंग, अपने `on-` और `-container` रोल के साथ, कंट्रास्ट-जाँचा हुआ | `"roles": "intent"` के साथ पैलेट घोषित करें |

चूँकि हर प्लैटफ़ॉर्म का कोड उसी एक रिज़ॉल्व किए गए सिस्टम से जनरेट होता है, इसलिए एक पुल रिक्वेस्ट वेब, SwiftUI, Compose, Flutter और React Native को एक साथ बदलती है।

## शब्दावली में जोड़ना

मान हमेशा काफ़ी नहीं होते। किसी रेफ़रेंस सिस्टम में बटन के ऐसे साइज़ हैं जो कोर में नहीं हैं; आपके प्रॉडक्ट का अपना एक रेटिंग कंपोनेंट है। इसलिए लेयर शब्दावली का **विस्तार** भी कर सकती है — `vocabulary` के अंतर्गत, हमेशा एक `rationale` के साथ, और सिर्फ़ जोड़कर:

```json
"vocabulary": {
  "tanrei.sys.space.space1200":        { "$type": "dimension", "rationale": "हीरो सेक्शन को 96px का रिदम स्टेप चाहिए।",
                                          "derive": { "fn": "mul", "of": "{tanrei.dial.space.unit}", "by": 12 } },
  "tanrei.comp.button.size.3x":        { "from": "large", "scale": 1.5, "rationale": "लैंडिंग स्क्रीन पर हीरो कॉल-टू-ऐक्शन।" },
  "tanrei.comp.button.variant.danger": { "from": "filled", "rationale": "विनाशकारी क्रिया की पुष्टि यहाँ एक अलग एम्फ़ेसिस है।" },
  "acme.comp.rating.star.size":        { "$type": "dimension", "rationale": "रेटिंग कंपोनेंट का तारा।",
                                          "derive": { "fn": "mul", "of": "{tanrei.dial.size.unit}", "by": 5 } }
}
```

| आप जोड़ते हैं | क्या होता है |
| --- | --- |
| **किसी सीरीज़ में एक स्टेप** — स्पेसिंग का स्टेप, कोना, टेक्स्ट रोल, या ऐसा कलर रोल जिसके साथ उस पर बनने वाला रोल (`onRole`) भी हो | वह अपने पड़ोसियों के बग़ल में बैठता है, उसी डायल के साथ चलता है, और कोर जोड़ी की तरह कंट्रास्ट के लिए जाँचा जाता है |
| **कंपोनेंट के किसी अक्ष पर एक मान** — Button का साइज़ या वेरिएंट | एक पंक्ति काफ़ी है। साइज़ उस अक्ष के हर सदस्य (ऊँचाई, पैडिंग, लेबल स्टाइल, आइकन) को किसी दूसरे साइज़ से क्लोन करके स्केल करता है, और डायल के साथ चलता रहता है। वेरिएंट अपने सामान्य अवस्था के रंग क्लोन करता है; **उसके होवर, फ़ोकस, दबाए हुए और अक्षम स्टेट के टोकन के मान सिस्टम के पैटर्न नियम आपके लिए तय कर देते हैं** |
| **आपके अपने टोकन**, आपकी लेयर के नेमस्पेस में (`acme.…`) | आपके अपने कंपोनेंट के लिए। वे किसी भी `tanrei.*` टोकन का रेफ़रेंस ले सकते हैं, डायल और स्कीम के साथ चलते हैं, और वेब पर `--acme-…` और बाक़ी हर प्लैटफ़ॉर्म पर एक टाइप किया हुआ ऑब्जेक्ट बन जाते हैं |

`vocabulary` कहती है कि कोई चीज़ **मौजूद है**; `tokens` और `rules` उसे **मान** देते हैं, ठीक कोर टोकन की तरह — इसलिए चाइल्ड लेयर किसी विस्तार को किसी भी दूसरी चीज़ की तरह बदल सकती है। विस्तार इनहेरिट होते हैं, कोर से कभी कुछ हटाते या उसका टाइप नहीं बदलते, और इंटरैक्शन स्टेट नहीं जोड़ सकते (वे प्लैटफ़ॉर्म के हैं)। हर जनरेट किया गया बंडल इन्हें इस ब्योरे के साथ सूचीबद्ध करता है कि इन्हें किसने घोषित किया और क्यों।

आप जो जोड़ते हैं, कंपोनेंट उसे स्वीकार करते हैं। `<tanrei-button size="3x" variant="danger">` वेब पर काम करता है, और नेटिव पैकेज वही कुंजियाँ लेते हैं; जो मान सक्रिय डिज़ाइन सिस्टम में नहीं है, वह डिफ़ॉल्ट के रूप में रेंडर होता है। **जो सिस्टम कुछ नहीं जोड़ता, वह कोई क़ीमत नहीं चुकाता**: उसके जनरेट किए गए कोड में विस्तारों का ज़िक्र तक नहीं होता।

इसी तरह दो आदर्श एक साथ टिके रहते हैं: Tanrei की अपनी शब्दावली छोटी और सीधे-सादे नामों वाली रहती है, **और** किसी भी डिज़ाइन सिस्टम से ठीक-ठीक मेल बिठाया जा सकता है — क्योंकि किसी और की ख़ातिर कोर में कुछ जोड़ना नहीं पड़ता।

## स्टेट कैसा दिखता है, यह भी एक मान है

कंपोनेंट होवर या दबाए हुए स्टेट का रूप कभी ख़ुद नहीं निकालते। हर स्टेट के अपने टोकन हैं (`button.filled.hovered.container.color`, …), और सिस्टम के **पैटर्न नियम** उनके मान तय करते हैं:

```json
{ "match": "tanrei.comp.*.*.hovered.container.color",
  "derive": { "fn": "mix", "base": "{tanrei.comp.$1.$2.container.color}", "with": "{tanrei.comp.$1.$2.label.color}", "amount": "{tanrei.sys.state.hover-state-layer-opacity}" } }
```

यही Tanrei की स्टेट लेयर है। जिस सिस्टम में हर स्टेट के रंग स्पष्ट रूप से दिए हैं, वह इसकी जगह एलियास लिखता है; जिसमें होवर नहीं है, वह उस स्टेट को उसके सामान्य अवस्था के मान का एलियास बना देता है; जो दबाने पर धुँधला करता है, वह `pressed.opacity` सेट करता है। शब्दावली वही, मान अलग।

## प्रकार के चुनाव

कुछ अंतर मात्रा के होते ही नहीं: दबाने का जवाब रिपल से या कंट्रोल को धुँधला करके, कीबोर्ड फ़ोकस रिंग के रूप में या चमक के रूप में। ये `sys.behavior` के अंतर्गत दो टोकन हैं (`pressed-feedback`, `focus-style`), जिनमें हर एक के पास नामों की एक छोटी, बंद सूची है, और लेयर किसी भी दूसरे मान की तरह इनमें से एक चुनती है। कोना कैसे मुड़ता है, यह चुनाव नहीं, मात्रा है: [शेप](https://tanrei.chnotchy.com/hi/foundations/shape/#%E0%A4%95%E0%A5%89%E0%A4%B0%E0%A5%8D%E0%A4%A8%E0%A4%B0-%E0%A4%B8%E0%A5%8D%E0%A4%AE%E0%A5%82%E0%A4%A6%E0%A4%BF%E0%A4%82%E0%A4%97) पेज पर `sys.shape.corner-smoothing`। इनका वर्णन [व्यवहार](https://tanrei.chnotchy.com/hi/foundations/behaviour/) पेज पर है। आइकन सेट और टाइपफ़ेस भी लेयर बदल सकती है: देखें [आइकन](https://tanrei.chnotchy.com/hi/foundations/icons/#%E0%A4%B9%E0%A4%B0-%E0%A4%A1%E0%A4%BF%E0%A4%9C%E0%A4%BC%E0%A4%BE%E0%A4%87%E0%A4%A8-%E0%A4%B8%E0%A4%BF%E0%A4%B8%E0%A5%8D%E0%A4%9F%E0%A4%AE-%E0%A4%95%E0%A4%BE-%E0%A4%85%E0%A4%AA%E0%A4%A8%E0%A4%BE-%E0%A4%86%E0%A4%87%E0%A4%95%E0%A4%A8-%E0%A4%B8%E0%A5%87%E0%A4%9F) और [टाइपोग्राफ़ी](https://tanrei.chnotchy.com/hi/foundations/typography/#%E0%A4%B9%E0%A4%B0-%E0%A4%A1%E0%A4%BF%E0%A4%9C%E0%A4%BC%E0%A4%BE%E0%A4%87%E0%A4%A8-%E0%A4%B8%E0%A4%BF%E0%A4%B8%E0%A5%8D%E0%A4%9F%E0%A4%AE-%E0%A4%95%E0%A5%87-%E0%A4%85%E0%A4%AA%E0%A4%A8%E0%A5%87-%E0%A4%9F%E0%A4%BE%E0%A4%87%E0%A4%AA%E0%A4%AB%E0%A4%BC%E0%A5%87%E0%A4%B8)।

## साथ आने वाले सिस्टम

वही `<tanrei-button>`, वही मार्कअप। `m3-like` और `cupertino` इसलिए हैं कि यह व्यवस्था उलटे स्वभाव वाले दो सिस्टमों पर साबित हो, और इसलिए भी कि वे आपकी अपनी लेयर के शुरुआती बिंदु बनें।

**सटीकता मापी जाती है, उसका दावा नहीं किया जाता।** `m3-like` के साथ material-web (Apache-2.0) के प्रकाशित टोकन से एक फ़िडेलिटी मैप है: रेफ़रेंस का हर कलर रोल, हर टेक्स्ट स्टाइल और Button का हर टोकन या तो बराबर होना चाहिए, या किसी दूसरे टोकन से कवर होना चाहिए, या उस मिमिक्री गैप के साथ सूचीबद्ध होना चाहिए जो उसे समझाता है। यह संख्या नीचे प्रीसेट के साथ दिखाई गई है — जो टोकन किसी दूसरे टोकन से कवर नहीं हैं, उनमें से कितने बराबर हैं — और `tokens/generated/<id>/fidelity.json` से पढ़ी जाती है। इसे “-like” ट्रेडमार्क के कारणों से कहा जाता है — इसलिए नहीं कि यह लगभग वैसा है।

वेब पर प्रीसेट एक अतिरिक्त स्टाइलशीट है, जो एक ऐट्रिब्यूट तक सीमित रहती है, इसलिए सिस्टम अगल-बग़ल भी रह सकते हैं। प्रीसेट की एंट्री उसके सारे कॉम्पोनेंट रजिस्टर करती है, उनमें वे भी जो डिफ़ॉल्ट सिस्टम में नहीं हैं (`@tanrei/web` सिर्फ़ डिफ़ॉल्ट सिस्टम के कॉम्पोनेंट रजिस्टर करता है):

```js
import '@tanrei/web/tokens.css';
import '@tanrei/web/systems/cupertino.css';
import '@tanrei/web/cupertino'; // cupertino के कॉम्पोनेंट
```

```html
<body data-tanrei-system="cupertino">
```

जो बात अभी न मान कह सकते हैं, न प्रकार के चुनाव — बैकड्रॉप मटीरियल, स्टाइल के तौर पर अपरकेस लेबल — वह `docs/governance/mimicry-gaps.json` में Tanrei की कमी के रूप में दर्ज है, छिपाई नहीं गई।

## वह कॉम्पोनेंट जो आपके सिस्टम में नहीं है

कोई सिस्टम पूरा कॉम्पोनेंट छोड़ सकता है, या किसी कॉम्पोनेंट के `variant` का एक मान: डिफ़ॉल्ट सिस्टम में सेगमेंटेड बटन नहीं है, और filled या outlined टेक्स्ट फ़ील्ड भी नहीं। लेयर यह बात `components` में लिखती है, कारण के साथ और यह भी कि उसकी जगह क्या इस्तेमाल होता है:

```json
"components": {
  "omit": { "carousel": { "reason": "Acme shows one thing at a time.", "insteadUse": ["list"] } },
  "variants": { "tabs": { "omit": ["tonal"] } }
}
```

जो छोड़ा गया है, वह फिर भी दिखता है और काम करता है। डेवलपमेंट बिल्ड में, उसे इस्तेमाल करने वाला हर एलिमेंट कंसोल में एक बार चेतावनी देता है, जिसमें आपके सिस्टम का नाम और उसकी जगह इस्तेमाल होने वाली चीज़ होती है। चेतावनी उसी कॉम्पोनेंट का नाम लेती है जो आपने लिखा: `<tanrei-text-field variant="outlined">` की रिपोर्ट टेक्स्ट फ़ील्ड के `outlined` के रूप में होती है, उस टेक्स्ट इनपुट के रूप में नहीं जिसे वह अंदर बनाता है। किसी दूसरे सिस्टम की लेयर में रहने वाले कॉम्पोनेंट की, जैसे m3-like का FAB मेन्यू, रिपोर्ट भी इसी तरह होती है, उस लेयर के नाम के साथ जिसमें वह रहता है।

इस पर अपने टेस्ट फ़ेल करने के लिए, इसकी रिपोर्ट एरर के रूप में करवाएँ, और पूछें कि क्या इस्तेमाल हुआ:

```js
import { setAvailabilityMode, unavailableUses } from '@tanrei/web';

setAvailabilityMode('error'); // अपने टेस्ट सेटअप में, कुछ भी रेंडर होने से पहले

test('प्रॉडक्ट वही इस्तेमाल करता है जो उसके सिस्टम में है', async () => {
  // …प्रॉडक्ट की स्क्रीन रेंडर करें…
  expect(unavailableUses()).toEqual([]);
});
```

`unavailableUses()` दोनों में से किसी भी मोड में हर इस्तेमाल को एक बार, वर्णक्रम में सूचीबद्ध करता है (`segmented-button`, `text-field:outlined`)। प्रोडक्शन बिल्ड कुछ नहीं जाँचता, इसलिए वहाँ सूची खाली रहती है। `@tanrei/web/availability` में यही दो फ़ंक्शन हैं, बिना कोई एलिमेंट रजिस्टर किए।

## सिस्टम साझा करना

सिस्टम को बिल्ड करने पर एक स्वयंपूर्ण **DTCG 2025.10 बंडल** बनता है — सादी, पूरे मानों वाली टोकन फ़ाइलें और एक मानक रिज़ॉल्वर — इसलिए डिज़ाइन टोकन पढ़ने वाला कोई भी टूल इसे Tanrei के बिना इस्तेमाल कर सकता है। जिन लेयर फ़ाइलों से यह बना, वे बंडल के भीतर साथ चलती हैं, इसलिए Tanrei (या कोई AI एजेंट) इसे दोबारा बना या बदल सकता है।

> [!WARNING]
> **सुलभता**
>
> कंट्रास्ट के थ्रेशोल्ड कॉन्स्टेंट हैं, जिन्हें कोई नहीं बदल सकता। डिफ़ॉल्ट सिस्टम में उल्लंघन होने पर बिल्ड विफल हो जाता है। प्रॉडक्ट की लेयर में उल्लंघन एक **चेतावनी** होता है — जो बिल्ड के समय छपती है और जनरेट की गई फ़ाइलों में लिखी जाती है, कभी चुपचाप नहीं गुज़रती। किसी दूसरे सिस्टम की नक़ल करने वाले प्रीसेट को इसके बजाय उस सिस्टम के प्रति फ़िडेलिटी पर परखा जाता है: Tanrei के सुलभता मानदंड उस पर लागू नहीं होते, न स्टैंडर्ड कंट्रास्ट में, न मध्यम में, न उच्च में, और बिल्ड वहाँ जो कंट्रास्ट अनुपात मापता है, वे चेतावनी के रूप में नहीं, जानकारी के रूप में दर्ज होते हैं। कार्यात्मक विफलता — ऐसा कंट्रोल जिसे चलाया न जा सके, या नाम या स्टेट का न होना — हर सिस्टम में ख़ामी है, नक़ल करने वाले प्रीसेट में भी।
