सीधे मुख्य कॉन्टेंट पर जाएँ
menumenu tanreiexpand_morecontrasttranslate
tanreiexpand_more
शुरुआत करेंWebReactSwiftUIJetpack ComposeFlutterReact Nativeप्रीसेटआपका अपना डिज़ाइन सिस्टमAI एजेंट के साथ Tanrei का इस्तेमालब्रांडडिज़ाइन टोकनडिज़ाइन सिस्टम और कस्टमाइज़ेशनTheme Studioरंगटाइपोग्राफ़ीआइकनशेपएलिवेशनमोशनइंटरैक्शन स्टेटव्यवहारलेआउटसुलभताशब्दकलर टोकनटाइप स्केल टोकनशेप टोकनएलिवेशन टोकनमोशन टोकनस्टेट टोकनस्पेस और माप के टोकनकंपोनेंटबटनमुख्य ऐक्शन बटनसेगमेंटेड बटनबटन ग्रुपमेन्यू वाला बटनटूलबारकॉपी बटनचेकबॉक्सरेडियो बटनस्विचचिपमेन्यूस्लाइडरस्लाइडर फ़ील्डकैलेंडरDateTimePickerफ़ील्ड ग्रुपरेडियो ग्रुपचेकबॉक्स ग्रुपसिलेक्टसिलेक्ट फ़ील्डमेन्यू बारफ़ाइल अपलोडफ़ाइल पिकर उन्नतड्रॉप ज़ोनटेक्स्ट इनपुट उन्नतटेक्स्ट फ़ील्डचिप फ़ील्डफ़ील्डकॉम्बोबॉक्स उन्नतकॉम्बोबॉक्स फ़ील्डनंबर इनपुट उन्नतनंबर फ़ील्डकलर इनपुट उन्नतकलर फ़ील्डवन-टाइम कोड इनपुट उन्नतवन-टाइम कोड फ़ील्डएम्बेडेड टेक्स्ट इनपुट उन्नतचैट कंपोज़रकार्डडिवाइडरमोडल लेयर उन्नतडायलॉगलिस्टलिस्ट पंक्तिबॉटम शीटसाइड शीटकैरसेलकोड ब्लॉकटेबलपॉपओवरचरणअकॉर्डियनडिस्क्रिप्शन लिस्टफ़िगरऐप शेलपेज हेडरट्री व्यूटाइमलाइनइमेज प्रीव्यूसाइज़ हैंडलसाइज़ बदलने वाला फ़्रेमस्क्रॉल एरियाबैजप्रोग्रेस इंडिकेटरमीटरनंबर टिकरलोडिंग इंडिकेटरस्नैकबारटूलटिपकीबोर्ड शॉर्टकटटैगइनलाइन कोडकॉलआउटअवतारख़ाली स्टेटटैग ग्रुपस्केलेटनफ़ाइल आइटमस्वॉचमार्की टेक्स्टटैबटैब व्यूऐप बारनेविगेशन बारनेविगेशन ड्रॉअरखोजलिंकपेजिनेशनपिछला और अगला लिंकस्टेपरब्रेडक्रंबविषय सूचीलिंक कार्डFAB मेन्यूस्थितिTanrei कैसे बनता हैयोगदानलाइसेंस और श्रेय
होमशुरू करेंWeb

Web

किसी भी वेब प्रोजेक्ट में Tanrei के CSS टोकन और Web Components इस्तेमाल करें।

content_copyMarkdown में देखें

@tanrei/web में दो चीज़ें हैं: डिज़ाइन टोकन की एक स्टाइलशीट, जिसमें टोकन CSS कस्टम प्रॉपर्टी के रूप में हैं, और Lit से बने, वेब मानकों पर आधारित कस्टम एलिमेंट। इसके लिए किसी फ़्रेमवर्क की ज़रूरत नहीं है।

प्री-रिलीज़

0.1.0-next.0 npm पर dist-tag next के साथ प्रकाशित है: 0.1.0 तक @tanrei/web@next इंस्टॉल करें। 0.x प्री-रिलीज़ के दौरान पुराने वर्शन के साथ संगतता नहीं रखी जाती: कोई भी प्री-रिलीज़ पहले से अप्रचलित घोषित किए बिना कुछ भी तोड़ सकती है, और क्या टूटा, यह उसका changeset बताता है।

इंस्टॉल करें

npm से

npm install @tanrei/web

सोर्स से

main पर मौजूद सोर्स को उसके प्रकाशित होने से पहले इस्तेमाल करने के लिए आपको Git, Node 22.22 या उसके बाद का वर्शन और pnpm 12 चाहिए (corepack enable से आपको वही वर्शन मिलता है जो रिपॉज़िटरी में तय है)। रिपॉज़िटरी के क्लोन में पैकेज बिल्ड करें, उसे पैक करें, और पैक की गई फ़ाइल अपने प्रोजेक्ट में इंस्टॉल करें:

git clone https://github.com/chnotchy/tanrei.git
cd tanrei
pnpm install
pnpm --filter @tanrei/web build
pnpm --filter @tanrei/web pack --pack-destination ../tanrei-packages
# अपने प्रोजेक्ट में: उस फ़ोल्डर का पाथ जिसमें पैकेज लिखे गए
npm install path/to/tanrei-packages/tanrei-web-*.tgz

पैक की गई फ़ाइल में वही है जो कोई रिलीज़ प्रकाशित करती है, इसलिए नीचे का सब कुछ उसी तरह काम करता है। सोर्स की नई स्थिति लेने के लिए pull करें, फिर से बिल्ड और पैक करें, और नई फ़ाइल इंस्टॉल करें।

इस्तेमाल

  1. स्टाइलशीट एक बार लोड करें, जितना पहले हो सके। वे कैस्केड लेयर (tanrei.*) में लिपटी हैं, इसलिए आपकी अपनी स्टाइल हमेशा उन पर भारी पड़ती हैं।

    import '@tanrei/web/tanrei.css';

    tanrei.css में सब कुछ एक फ़ाइल में है: पेज का बेस, टोकन, और उन भागों की स्टाइलशीट जो बिना एलिमेंट के बनते हैं (टेक्स्ट स्टाइल, टेबल, अकॉर्डियन और बाक़ी)। सिर्फ़ वही लोड करना हो जो आप इस्तेमाल करते हैं, तो टोकन लें, चाहें तो बेस भी, और उन स्टाइलशीट में से हर एक तभी लें जब उसकी ज़रूरत हो:

    import '@tanrei/web/tokens.css';
    import '@tanrei/web/base.css'; // पेज सिस्टम की सरफ़ेस, टेक्स्ट के रंग और बॉडी फ़ॉन्ट में, और body पर कोई मार्जिन नहीं

    बेस पेज को सरफ़ेस का रंग देता है, आपके अपने टेक्स्ट को on-surface रंग और बॉडी फ़ॉन्ट देता है, और ब्राउज़र का body पर लगाया मार्जिन हटा देता है। इसके बिना पेज ब्राउज़र के डिफ़ॉल्ट पर रहता है।

  2. अपने डिज़ाइन सिस्टम के कंपोनेंट रजिस्टर करें, या सिर्फ़ वे एलिमेंट जो आप इस्तेमाल करते हैं।

    import '@tanrei/web';
    // प्रीसेट पर, उसकी एंट्री इसकी जगह: m3-like, m3-expressive-like या cupertino
    import '@tanrei/web/m3-like';
    // या, एक-एक एलिमेंट:
    import '@tanrei/web/components/button';

    @tanrei/web सिर्फ़ वे कंपोनेंट रजिस्टर करता है जो डिफ़ॉल्ट सिस्टम में हैं, इसलिए उस पर बना प्रोडक्ट ऐसे कंपोनेंट तक नहीं पहुँच सकता जो उसके सिस्टम में नहीं है। प्रीसेट की एंट्री, @tanrei/web/<id>, वह रजिस्टर करती है जो उस प्रीसेट में है, और @tanrei/web/all पैकेज के सारे कंपोनेंट। जो कंपोनेंट सिर्फ़ किसी प्रीसेट में है, जैसे सेगमेंटेड बटन, उसे फिर भी जान-बूझकर लिया जा सकता है: उसे अपने सिस्टम की लेयर में शामिल करें और उसका अपना मॉड्यूल इंपोर्ट करें।

    @tanrei/web/… वाले स्पेसिफ़ायर पैकेज के एक्सपोर्ट हैं: इन्हें कोई बंडलर (Vite, webpack, esbuild) रिज़ॉल्व करता है। बंडलर के बिना ब्राउज़र <link> या <script src> में बेयर स्पेसिफ़ायर रिज़ॉल्व नहीं कर सकता, इसलिए पैकेज का dist/ सर्व करें और सीधे फ़ाइलों की ओर इशारा करें — स्टाइलशीट जैसी हैं वैसी ही, और tanrei.bundle.js, जिसमें Lit और हर एलिमेंट शामिल है:

    <link rel="stylesheet" href="/node_modules/@tanrei/web/dist/tanrei.css" />
    <script type="module" src="/node_modules/@tanrei/web/dist/tanrei.bundle.js"></script>
  3. एलिमेंट को किसी भी दूसरे HTML की तरह इस्तेमाल करें।

    <tanrei-button variant="filled">डिप्लॉय करें</tanrei-button>
    <tanrei-button variant="outlined" size="small" disabled>रद्द करें</tanrei-button>
  4. अपने प्रॉडक्ट के शब्द दें। किसी कंपोनेंट के अपने कोई शब्द नहीं होते: ज़रूरी या वैकल्पिक के टैग का टेक्स्ट, बंद करने वाले बटन का नाम और ऐसे दूसरे शब्द आपके प्रॉडक्ट के हैं। शुरुआत में इन सबके लिए सादी अंग्रेज़ी चाहिए, तो अंग्रेज़ी शब्दों का पैक एक बार import करें:

    import '@tanrei/web/words/en';

    इनमें से कोई भी बदलने के लिए, या किसी दूसरी भाषा के शब्द देने के लिए, उसके बाद setWords() कॉल करें। आपका दिया शब्द पैक से ऊपर है, और एलिमेंट पर दिया शब्द इन दोनों से ऊपर।

    import { setWords } from '@tanrei/web';
    
    setWords({ requiredText: 'Mandatory' });
    setWords({ requiredText: 'ज़रूरी', optionalText: 'वैकल्पिक', closeLabel: 'बंद करें' }, { lang: 'hi' });

    पैक और आपके शब्दों के बिना भी कंपोनेंट काम करता है, और कंसोल में बताता है कि कौन-सा शब्द नहीं मिला। देखें शब्द।

लाइव

डिप्लॉय करेंरद्द करें

एलिमेंट का मैनिफ़ेस्ट

एडिटर और कोडिंग एजेंट पैकेज के एलिमेंट उसके custom elements manifest, @tanrei/web/custom-elements.json, से पढ़ते हैं: हर एलिमेंट अपने ऐट्रिब्यूट, प्रॉपर्टी, इवेंट, स्लॉट और पार्ट के साथ, और ऐसा कुछ नहीं जिस तक प्रोडक्ट नहीं पहुँच सकता। @tanrei/web/custom-elements/<id>.json में सिर्फ़ वे एलिमेंट हैं जो सिस्टम <id> में हैं, इसलिए एक सिस्टम में काम करने वाला टूल और कुछ नहीं सुझाता।

थीम और कंट्रास्ट

टोकन के मान light-dark() इस्तेमाल करते हैं, इसलिए वे उस एलिमेंट की color-scheme के अनुसार चलते हैं जिस पर उनका इस्तेमाल हुआ है। बिना कुछ किए इसका मतलब है ऑपरेटिंग सिस्टम की सेटिंग, और prefers-contrast: more होने पर उच्च कंट्रास्ट वाली स्कीम लागू हो जाती है।

नियंत्रण अपने हाथ में लेने के लिए ऐट्रिब्यूट सेट करें:

<!-- पूरे पेज या किसी भी सबट्री के लिए थीम तय करें -->
<html data-tanrei-theme="dark">

<!-- पूरे पेज के लिए कंट्रास्ट का स्तर तय करें: "medium" या "high" -->
<html data-tanrei-contrast="high">

टिप्पणी

दोनों ऐट्रिब्यूट <html> पर या किसी भी सबट्री पर काम करते हैं। जनरेट की गई स्टाइलशीट पूरा टोकन सेट :root, [data-tanrei-contrast] पर घोषित करती है, इसलिए किसी नेस्टेड एलिमेंट पर लगा data-tanrei-contrast उसके भीतर सिर्फ़ सिस्टम के रंग ही नहीं, कंपोनेंट टोकन भी उसी कंट्रास्ट स्तर के हिसाब से दोबारा रिज़ॉल्व करता है।

किसी व्यक्ति की चुनी हुई थीम बनाए रखें

अगर आपके प्रॉडक्ट में लोग थीम चुन सकते हैं, तो उनकी पसंद सहेजें और पेज के पहली बार बनने से पहले उसे <html> पर लगाएँ: बाद में चलने वाली स्क्रिप्ट से लगाने पर पेज पहले एक फ़्रेम के लिए सिस्टम की थीम दिखाता है। @tanrei/web/theme-script दोनों काम करता है। themeScript() एक छोटी स्क्रिप्ट है जिसे <head> में, स्टाइलशीट से पहले, इनलाइन लिखा जाता है, और saveTheme() पसंद सहेजता है और उसे तुरंत लागू करता है।

import { loadTheme, saveTheme } from '@tanrei/web/theme-script';

saveTheme('dark'); // 'light', 'dark', या फिर से ऑपरेटिंग सिस्टम के हिसाब से चलने के लिए 'system'
loadTheme();       // जो सहेजा गया है: 'light', 'dark' या 'system'

Next.js (App Router) में इसे रूट लेआउट में इनलाइन लिखें। suppressHydrationWarning इसलिए है कि React के हाइड्रेट करने से पहले स्क्रिप्ट <html> का एक ऐट्रिब्यूट बदल देती है।

// app/layout.tsx
import { themeScript } from '@tanrei/web/theme-script';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en" suppressHydrationWarning>
      <head>
        <script dangerouslySetInnerHTML={{ __html: themeScript() }} />
      </head>
      <body>{children}</body>
    </html>
  );
}

Astro में इसे लेआउट में इनलाइन लिखें:

---
// src/layouts/Layout.astro
import { themeScript } from '@tanrei/web/theme-script';
---
<html lang="en">
  <head>
    <script is:inline set:html={themeScript()} />
  </head>
  <body><slot /></body>
</html>

अपनी CSS में टोकन

हर टोकन एक कस्टम प्रॉपर्टी है, जिसका नाम उसके पाथ से बनता है: tanrei.sys.color.primary का नाम --tanrei-sys-color-primary बन जाता है।

.panel {
  background: var(--tanrei-sys-color-surface-container-low);
  border-radius: var(--tanrei-sys-shape-corner-medium);
  box-shadow: var(--tanrei-sys-elevation-level1);
  font: var(--tanrei-sys-typescale-body-font);
}

स्क्रिप्ट से टोकन सेट करने के लिए @tanrei/web का setTokens() इस्तेमाल करें: रूट पर setTokens({ '--tanrei-sys-color-primary': '#0b57d0' }), या पेज के किसी एक हिस्से के लिए { on: element } के साथ। रूट पर style.setProperty() से अकेला एक टोकन सेट करने पर Safari कई सेकंड तक पूरे पेज की स्टाइल फिर से निकालता है; setTokens() उसे इस तरह लिखता है कि ऐसा न हो।

टेक्स्ट स्टाइल

टेक्स्ट स्टाइल के नाम उनके स्तर पर रखे गए हैं (heading-2 एक h2 है, body एक p, और label किसी कंट्रोल पर लिखा टेक्स्ट), और हर स्टाइल कस्टम प्रॉपर्टी का एक सेट है: शॉर्टहैंड के रूप में --tanrei-sys-typescale-<role>-font, और साथ में -font-family, -font-size, -font-weight, -line-height, -letter-spacing और -font-weight-emphasized। दो वैकल्पिक स्टाइलशीट इन्हें आपके लिए एलिमेंट पर लगा देती हैं:

import '@tanrei/web/text.css';   // .tanrei-text-<role>, .tanrei-text-emphasized
import '@tanrei/web/prose.css';  // .tanrei-prose के भीतर h1–h6, p, small, code, pre
<h2 class="tanrei-text-heading-2">सेक्शन</h2>
<p class="tanrei-text-body">चलता टेक्स्ट, जिसमें <strong class="tanrei-text-emphasized">ज़ोर</strong> भी है।</p>
<article class="tanrei-prose"><!-- रेंडर किया गया Markdown --></article>

.tanrei-text-emphasized जिस रोल के भीतर है, उसी रोल को उसके वेट में फ़ैमिली का एम्फ़ेसिस स्टेप जोड़कर दिखाता है; यह एक वेट है, कोई अलग रोल नहीं। सोलह रोल और एलिमेंट से उनका मिलान टाइपोग्राफ़ी पेज पर है।

फ़ॉन्ट

टाइप स्केल Inter, Noto Sans JP, Noto Sans और Roboto Mono माँगता है (tokens.css में --tanrei-ref-typeface-{brand,plain,mono}; tanrei build किसी भी सिस्टम के लिए यह सूची छापता है), आइकन Material Symbols Rounded माँगते हैं, और हर चीज़ का फ़ॉलबैक सिस्टम फ़ॉन्ट है। Tanrei फ़ॉन्ट फ़ाइलें साथ में नहीं देता; इन्हें ठीक इन्हीं फ़ैमिली नामों से ख़ुद लोड करें — Google Fonts से, या @fontsource-variable/* पैकेजों से (ये Inter Variable जैसे नाम रजिस्टर करते हैं: सादे नाम के साथ अपना @font-face घोषित करें जो उनकी फ़ाइलों की ओर इशारा करे, जैसा यह साइट करती है)।

आइकन

import '@tanrei/web/icons.css';
<tanrei-button><span slot="icon" class="tanrei-icon" aria-hidden="true">add</span>जोड़ें</tanrei-button>

.tanrei-icon किसी Material Symbols नाम को सिस्टम के आइकन वेट के साथ बनाता है और अपना साइज़ उस जगह से लेता है जहाँ वह रखा गया है। आउटलाइन वाला या भरा हुआ, यह आप कभी नहीं चुनते: आइकन देखें।

पूरी Material Symbols Rounded फ़ाइल में हर ग्लिफ़ हर वेट, फ़िल, ग्रेड और ऑप्टिकल साइज़ पर मौजूद है: 5.4 MB, जिसके लिए धीमे कनेक्शन पर कोई पेज आधा मिनट तक रुक सकता है। सिर्फ़ वही ग्लिफ़ लोड करें जो आपका प्रोडक्ट बनाता है। tanrei build उन ग्लिफ़ के नाम छापता है जिन्हें Tanrei के कंपोनेंट ख़ुद बना सकते हैं (शेवरॉन, चेक का निशान, बंद करने वाले बटन का क्रॉस…), और वे ऐक्सिस मान भी जिन पर आपका सिस्टम आइकन बनाता है; इस सूची में अपने नाम जोड़ें। Google Fonts से लोड करते समय नामों को वर्णक्रम में लगाकर icon_names= में दें और ऐक्सिस को family= में रेंज के रूप में लिखें (डिफ़ॉल्ट सिस्टम के लिए Material+Symbols+Rounded:opsz,wght,FILL,[email protected],300..500,0..1,0)। फ़ाइल ख़ुद सर्व करते हैं तो उसे ऐसे सबसेटर से छोटा करें जो फ़ॉन्ट के लिगेचर फ़ीचर (rlig, rclt) और दोनों फ़िल रखे; यह साइट अपने आइकन ऐसी ही फ़ाइल से बनाती है। दोनों ही तरीक़ों में आइकन फ़ेस को font-display: block के साथ रजिस्टर करें: फ़ाइल आने तक आइकन अदृश्य रहता है, उसका नाम अक्षरों में कभी नहीं दिखता।

ब्राउज़र सपोर्ट

Tanrei इन वर्शन और इनके बाद के वर्शन में काम करता है:

ब्राउज़र वर्शन
Chrome और Edge 125
Firefox 126
Safari, macOS और iOS पर 17.5

हर संख्या उन फ़ीचर में सबसे नए फ़ीचर से आती है जिनके बिना Tanrei बन ही नहीं सकता, और इनमें से किसी का कोई विकल्प नहीं है:

  • CSS. हर रंग light-dark() की एक जोड़ी है (Chrome और Edge 123, Firefox 120, Safari 17.5)। साइज़ और फ़ॉन्ट साइज़ CSS के round() से राउंड किए जाते हैं (Chrome और Edge 125, Firefox 118, Safari 15.4)। कंपोनेंट कस्टम स्टेट, :state(), के हिसाब से अपनी स्टाइल बदलते हैं (Chrome और Edge 125, Firefox 126, Safari 17.4)। मेन्यू, टूलटिप और स्नैकबार Popover API से टॉप लेयर में खुलते हैं (Chrome और Edge 114, Firefox 125, Safari 17)। स्टाइलशीट जिन कैस्केड लेयर में लिपटी हैं, वे इनसे पहले से उपलब्ध हैं (Chrome और Edge 99, Firefox 97, Safari 15.4)।
  • JavaScript. पैकेज ES2022 में है, और अगर उसकी पब्लिश होने वाली कोई भी फ़ाइल इससे आगे जाती है तो उसका बिल्ड फ़ेल हो जाता है। इसका सबसे नया सिंटैक्स, क्लास के static ब्लॉक, Chrome और Edge 94, Firefox 93 और Safari 16.4 से चलता है। पैकेज को किसी पुराने टारगेट के लिए ट्रांसपाइल करने से न्यूनतम वर्शन नीचे नहीं आता: ऊपर वाली CSS जैसी है वैसी ही रहती है।

कुछ नए फ़ीचर सिर्फ़ वहीं इस्तेमाल होते हैं जहाँ उनके बिना भी ब्राउज़र ठीक से काम करता है: @starting-style न हो तो खुलने का एनिमेशन नहीं चलता, और corner-shape न हो तो कोना सामान्य गोल ही रहता है।

विज़िटर को बताना कि उसका ब्राउज़र बहुत पुराना है

Tanrei यह ख़ुद नहीं करता: यह आपके प्रोडक्ट के एंट्री पॉइंट का काम है। पहले फ़ीचर जाँचें, और ऐप को, उसके साथ Tanrei को, तभी लोड करें जब वे मौजूद हों:

<p id="unsupported" hidden>इस साइट के लिए Chrome या Edge 125, Firefox 126 या Safari 17.5, या इनसे नया वर्शन चाहिए।</p>
<script type="module">
  // Safari का न्यूनतम वर्शन light-dark() से, Chrome और Edge का round() से, और Firefox का :state() से तय होता है
  const supported =
    CSS.supports('color', 'light-dark(red, red)') &&
    CSS.supports('width', 'round(1px, 1px)') &&
    CSS.supports('selector(:state(open))');
  if (supported) import('./app.js'); // आपका ऐप, जो @tanrei/web को इंपोर्ट करता है
  else document.getElementById('unsupported').hidden = false;
</script>

इस स्क्रिप्ट को छोटा और सीधा रखें: हर विज़िटर का ब्राउज़र इसे चलाता है, पुराने ब्राउज़र भी। स्टैटिक import के साथ ब्राउज़र इस स्क्रिप्ट के चलने से पहले ही ऐप लोड कर लेता है, और जो पुराना ब्राउज़र ऐप को पार्स नहीं कर पाता वह जाँच तक पहुँचता ही नहीं; import() ऐप को जाँच के बाद ही लोड करता है।

टेस्टिंग

ब्राउज़र में

Tanrei के एलिमेंट उन चीज़ों पर बने हैं जिन्हें ब्राउज़र लागू करते हैं: शैडो रूट, ElementInternals (फ़ॉर्म कंट्रोल का मान और वैलिडिटी, कस्टम स्टेट), Popover API, <dialog> और लेआउट। jsdom और happy-dom इनका सिर्फ़ एक हिस्सा लागू करते हैं (happy-dom में न attachInternals() है, न Popover API), इसलिए कोई एलिमेंट रेंडर होते ही एरर फेंक सकता है, कोई रिजेक्ट हुआ Promise छोड़ सकता है, या उन साइज़, फ़ोकस क्रम और टॉप लेयर के बिना रेंडर हो सकता है जिन पर वह निर्भर है। Tanrei इन एनवायरनमेंट को सपोर्ट नहीं करता, और इनमें जो कमी है उसकी जगह कोई विकल्प भी नहीं देता: जो विकल्प एलिमेंट को एरर फेंकने से रोक दे, वह टेस्ट को ऐसे बर्ताव पर पास करा देगा जो किसी ब्राउज़र में नहीं होता।

जो कुछ भी Tanrei का एलिमेंट रेंडर करता है, उसे असली ब्राउज़र में टेस्ट करें:

  • Vitest का ब्राउज़र मोड, Playwright प्रोवाइडर के साथ, आपके कंपोनेंट टेस्ट को Vitest में ही रखता है और उन्हें Chromium, Firefox या WebKit में चलाता है।
  • Playwright Test पेज और पूरे फ़्लो चलाता है।

आपके अपने लॉजिक के टेस्ट, जो Tanrei का कोई एलिमेंट रेंडर नहीं करते, Node, jsdom या happy-dom में ही रह सकते हैं। Tanrei के अपने टेस्ट Chromium, Firefox और WebKit में, Playwright के साथ axe-core से चलते हैं।

एलिमेंट ढूँढना

ज़्यादातर एलिमेंट अपना रोल ख़ुद पर नहीं, बल्कि अपने शैडो रूट के अंदर के किसी नेटिव एलिमेंट (<button>, <input>, <dialog>) पर रखते हैं, ताकि ब्राउज़र और टेस्टिंग टूल असली सिमैंटिक्स देखें; कुछ एलिमेंट, जैसे टैब या खुला मेन्यू, रोल ख़ुद रखते हैं। Playwright के लोकेटर खुले शैडो रूट के अंदर तक देखते हैं, इसलिए किसी कंट्रोल को उसके रोल और नाम से ढूँढें, जैसे कोई व्यक्ति ढूँढता:

await page.getByRole('button', { name: 'सेव करें' }).click();
await expect(page.getByRole('switch', { name: 'Wi-Fi' })).toBeChecked();

उस बटन पर क्लिक <tanrei-button> पर लगे लिसनर तक भी पहुँचता है। Testing Library की क्वेरी शैडो रूट के अंदर नहीं देखतीं, इसलिए वे ये कंट्रोल नहीं ढूँढ पातीं।

जब रोल और उसका कंटेंट अलग-अलग ट्री में हों

कुछ एलिमेंट रोल को अपने शैडो रूट में रखते हैं, जबकि उससे जुड़ा कंटेंट आपका अपना मार्कअप होता है, जो स्लॉट के ज़रिए उसमें रखा जाता है: <tanrei-tabs> की टैब सूची और उसके <tanrei-tab> चाइल्ड, <tanrei-dialog> का <dialog> और उसके ऐक्शन। DOM में टैब, टैब सूची के अंदर नहीं होते, इसलिए रोल से जोड़ा गया लोकेटर कुछ नहीं ढूँढता:

// कुछ नहीं मिलता: टैब <tanrei-tabs> के चाइल्ड हैं, उसकी टैब सूची के नहीं।
page.getByRole('tablist', { name: 'सेक्शन' }).getByRole('tab', { name: 'बिलिंग' });

पहले वह एलिमेंट ढूँढें जिसमें नाम वाला रोल है, फिर उसके अंदर खोजें:

const sections = page.locator('tanrei-tabs', { has: page.getByRole('tablist', { name: 'सेक्शन' }) });
await sections.getByRole('tab', { name: 'बिलिंग' }).click();

const confirm = page.locator('tanrei-dialog', { has: page.getByRole('dialog', { name: 'फ़ाइल हटाएँ?' }) });
await confirm.getByRole('button', { name: 'हटाएँ' }).click();

टॉप लेयर में मेन्यू

खुला रहने तक <tanrei-menu> ही मेन्यू है, जिसका नाम उसके ऐंकर से आता है, पर वह पेज में कोई जगह नहीं लेता: उसकी सतह टॉप लेयर में बनती है। इसलिए मेन्यू के दिखने की जाँच खुले होने पर भी फ़ेल होती है। पहले जाँचें कि मेन्यू मौजूद है, फिर उसके आइटम जाँचें:

await page.getByRole('button', { name: 'और' }).click();
const menu = page.getByRole('menu', { name: 'और' });
await expect(menu).toBeAttached();
await expect(menu.getByRole('menuitem', { name: 'नाम बदलें' })).toBeVisible();

बंद होने पर एलिमेंट मेन्यू नहीं रहता, और await expect(menu).toHaveCount(0) पास होता है।

चेतावनियाँ

डेवलपमेंट बिल्ड में, जब किसी एलिमेंट का इस्तेमाल उस तरह होता है जिसकी उसका स्पेक इजाज़त नहीं देता, तो वह कंसोल में यह बताता है। संदेश [tanrei] से शुरू होता है और बर्ताव की ID पर ख़त्म होता है। ब्राउज़र टेस्ट इनमें से किसी के भी आने पर फ़ेल हो सकता है: Playwright का उदाहरण AI एजेंट के लिए गाइड में है।