टेबल
पंक्तियों और कॉलम वाला डेटा दिखाती है, नाम वाले कॉलम, वैकल्पिक पंक्ति हेडर, कैप्शन और फ़ुटर पंक्तियों के साथ। जब वह अपनी जगह में नहीं समाती तो अपने ही बॉक्स में स्क्रॉल होती है। कॉलम का हेडर पंक्तियों को अपने क्रम में माँग सकता है और पंक्तियाँ चुनी जा सकती हैं; टेबल ख़ुद कभी सॉर्ट नहीं करती।
- श्रेणी
- कंटेनमेंट
- टोकन
comp.table- स्तर
- आधार
- Web
tanrei-tableschedule - SwiftUI
TanreiTableradio_button_unchecked - Jetpack Compose
TanreiTableradio_button_unchecked - Flutter
TanreiTableradio_button_unchecked - React Native
Tableradio_button_unchecked
इससे जनरेट किया गया: docs/status/status.json, specs/table.spec.json
पंक्ति हेडर, अंत की ओर संख्याएँ, एक फ़ुटर पंक्ति
| स्थिति | Web | SwiftUI | Compose | Flutter |
|---|---|---|---|---|
| नियोजित | 2 | 6 | 6 | 6 |
| Alpha | 31 | 30 | 30 | 29 |
| Beta | 4 | 1 | 1 | 2 |
| कुल | 37 | 37 | 37 | 37 |
टेबल उस डेटा के लिए है जिसके दो आयाम हैं: क़ीमतों की सूची, प्लान की तुलना, सेटिंग की सूची जिसमें उनके टाइप और डिफ़ॉल्ट हों, कई प्लैटफ़ॉर्म पर कई चीज़ों की स्थिति, वे रिकॉर्ड जिन पर व्यक्ति काम करता है। कॉलम का हेडर पंक्तियों को अपने क्रम में माँग सकता है, बिना पंक्तियों की टेबल आपका ख़ाली स्टेट दिखाती है, और पंक्तियों के नीचे की स्थिति पंक्ति में आपका वाक्य और आपका पेजिनेशन रहता है। पंक्तियाँ चुनी जा सकती हैं, हर पंक्ति अपने चेकबॉक्स से, या रेडियो बटन से सिर्फ़ एक पंक्ति, और जो टेबल अपनी पंक्तियों का इंतज़ार कर रही है, वह बताती है कि वह व्यस्त है। टेबल ख़ुद कभी सॉर्ट नहीं करती, फ़िल्टर नहीं करती, डेटा नहीं लाती और पेज में नहीं बँटती: वह वही पंक्तियाँ बनाती है जो उसे दी जाती हैं, उसी क्रम में जिसमें वे दी जाती हैं। वह कॉलम का साइज़ नहीं बदलती।
वेब पर यह आपकी अपनी नेटिव <table> के चारों ओर <tanrei-table> है। एलिमेंट में कोई शैडो रूट नहीं है और टेबल को कभी कोई दूसरा display नहीं दिया जाता, इसलिए क्रॉलर, स्प्रेडशीट में कॉपी और पेस्ट, और स्क्रीन रीडर का टेबल नेविगेशन, सबको एक साधारण HTML टेबल ही मिलती है। बाक़ी प्लैटफ़ॉर्म ने इसे अभी इम्प्लीमेंट नहीं किया है।
<link rel="stylesheet" href="@tanrei/web/table.css" />
<tanrei-table row-headers>
<table>
<caption>क्षेत्र के अनुसार विज़िट</caption>
<thead>
<tr>
<th scope="col">क्षेत्र</th>
<th scope="col" data-align="end" data-wrap="false">जनवरी</th>
</tr>
</thead>
<tbody>
<tr><th scope="row">द्वीप</th><td data-align="end">212</td></tr>
</tbody>
<tfoot>
<tr><th scope="row">सभी क्षेत्र</th><td data-align="end">6,846</td></tr>
</tfoot>
</table>
</tanrei-table>
<script type="module">
import '@tanrei/web/components/table';
</script>import { Table } from '@tanrei/react';
import '@tanrei/web/table.css';
<Table density="compact" striped label="टेबल के टोकन">
<table>
<thead>
<tr><th scope="col">टोकन</th><th scope="col">टाइप</th></tr>
</thead>
<tbody>
{tokens.map((token) => (
<tr key={token.name}><td data-wrap="false">{token.name}</td><td>{token.type}</td></tr>
))}
</tbody>
</table>
</Table>@tanrei/web/table.css किसी भी स्क्रिप्ट के चलने से पहले पूरी टेबल बना देती है। एलिमेंट वही स्टाइलशीट पेज में ख़ुद जोड़ता है, इसलिए जो पेज सिर्फ़ स्क्रिप्ट लोड करता है, उसे भी बनी हुई टेबल मिलती है, एक पल बाद।
| भाग | वेब पर |
|---|---|
| कॉलम | <thead> की अकेली पंक्ति में एक <th scope="col">। उसका टेक्स्ट हेडर है। |
| कॉलम का अलाइनमेंट | हेडर सेल पर data-align="start", "center" या "end"। end उन संख्याओं के लिए है जिनकी तुलना की जाती है। |
| ऐसा कॉलम जिसका टेक्स्ट रैप नहीं होता | हेडर सेल पर data-wrap="false", आइडेंटिफ़ायर, तारीख़ों और संख्याओं के लिए। |
| पंक्ति | <tbody> में एक <tr>। फ़ुटर पंक्ति <tfoot> में एक <tr> है। |
| सेल | एक <td>। उसमें टेक्स्ट होता है, कोई कंपोनेंट, या कुछ नहीं। |
| पंक्ति हेडर | पहले सेल के रूप में एक <th scope="row">, एलिमेंट पर row-headers के साथ। |
| नाम | एक <caption>, या जहाँ टेबल के ऊपर की हेडिंग उसे पहले से नाम देती है, वहाँ एलिमेंट पर label। |
| सॉर्ट करने लायक़ कॉलम | हेडर सेल पर aria-sort="none", "ascending" या "descending", और उसके टेक्स्ट के चारों ओर एक <button type="button">। सेल पर data-value वह नाम है जो sort इवेंट के साथ आता है। |
| कोई पंक्ति नहीं | <tbody> में एक <td colspan> वाली एक <tr data-part="empty">, जिसमें आपका ख़ाली स्टेट रहता है। |
| स्थिति पंक्ति | टेबल के बाद एक <div data-part="status">, जिसमें एक <p role="status"> और आपका पेजिनेशन रहता है। जहाँ आप कोई पैराग्राफ़ नहीं लिखते, वहाँ एलिमेंट पर status उसे लिख देता है। |
| चुनी जा सकने वाली पंक्तियाँ | एलिमेंट पर selection="multiple", या जहाँ ज़्यादा से ज़्यादा एक पंक्ति चुनी जाती है वहाँ selection="single", और हर पंक्ति में पहले सेल के रूप में एक <td data-part="selection">। |
| चुनी जा सकने वाली एक पंक्ति | <tr> पर data-value, और उसके चयन सेल में एक <tanrei-checkbox label-hidden>, या single में एक <tanrei-radio-button label-hidden>। <tr> पर data-selected बताता है कि वह चुनी गई है। |
| सभी पंक्तियों का चेकबॉक्स | हेडर पंक्ति के चयन सेल में एक <tanrei-checkbox label-hidden>। एलिमेंट पर select-all-label उसे नाम देता है। single में यह सेल ख़ाली रहता है। |
| लोड होती टेबल | एलिमेंट पर loading। |
| प्लेसहोल्डर पंक्ति, उस पंक्ति के लिए जो अभी आई नहीं है | एक <tr data-placeholder aria-hidden="true">, जिसके सेल ख़ाली हैं या जिनमें स्केलेटन का प्लेसहोल्डर है। |
एलिमेंट कॉलम का अलाइनमेंट और रैप होना उसके हेडर सेल से लेकर कॉलम के हर सेल को देता है। इन्हें स्क्रिप्ट के चलने से पहले ही बनवाने के लिए data-align और data-wrap को हर सेल पर दोहराएँ, जैसा इस पेज के डेमो करते हैं।
कोई हेडर दबाएँ: टेबल माँगती है, और यह पेज पंक्तियों को क्रम में रखता है
| नोट | |||
|---|---|---|---|
| केतली | 15 | 3,800 | इंडक्शन और गैस |
| तराज़ू | 0 | 2,950 | |
| फ़िल्टर पेपर | 120 | 450 | सौ के पैक में बिकता है |
| हैंड ग्राइंडर | 8 | 6,400 |
सॉर्ट करने लायक़ कॉलम एक हेडर सेल है जो बताता है कि पंक्तियाँ किस क्रम में हैं, और जिसके टेक्स्ट के चारों ओर आपका अपना बटन है:
<th scope="col" aria-sort="ascending" data-value="name"><button type="button">नाम</button></th>
<th scope="col" aria-sort="none" data-value="price" data-align="end"><button type="button">क़ीमत</button></th>स्टाइलशीट पूरे हेडर सेल को बटन बना देती है और aria-sort से निशान बनाती है: जब तक पंक्तियाँ उस कॉलम के क्रम में नहीं हैं तब तक दोतरफ़ा तीर, जब तक वे उसके बढ़ते क्रम में हैं तब तक ऊपर का तीर, और जब तक घटते क्रम में हैं तब तक नीचे का तीर। आप कोई आइकन नहीं लिखते। @tanrei/web/icons.css और आइकन फ़ॉन्ट लोड करें, क्योंकि ये निशान आइकन सेट के ग्लिफ़ हैं।
टेबल कभी सॉर्ट नहीं करती। दबाने पर sort एमिट होता है और स्क्रीन पर कुछ नहीं बदलता; अपनी पंक्तियों को क्रम में आप रखते हैं और नया aria-sort आप लिखते हैं:
table.addEventListener('sort', (event) => {
const { column, index, direction } = event.detail; // 'price', 2, 'ascending' | 'descending'
showRows(sortedBy(column, direction)); // आपका डेटा, आपकी तुलना, या आपका सर्वर
for (const th of headerCells) th.setAttribute('aria-sort', th.dataset.value === column ? direction : 'none');
});direction वह है जो व्यक्ति ने माँगा: ascending, या जहाँ पंक्तियाँ पहले से उस कॉलम के बढ़ते क्रम में हैं वहाँ descending। तीसरी बार दबाने जैसा कुछ नहीं है जो क्रम हटा दे। ज़रूरी नहीं कि आप वही क्रम दें जो माँगा गया: आप पंक्तियों को किसी दूसरे क्रम में रख सकते हैं, या उन्हें बिना किसी क्रम के छोड़ सकते हैं।
जिस टेबल को सर्वर क्रम में रखता है, उसके लिए बटन की जगह लिंक रखें: <a href="?sort=price&order=asc">क़ीमत</a>, जो दूसरे क्रम वाली उसी टेबल पर ले जाता है। यह स्क्रिप्ट के बिना काम करता है। तब sort ब्राउज़र के लिंक खोलने से पहले एमिट होता है, और event.preventDefault() पेज को वहीं रखता है।
कोई पंक्ति नहीं: हेडर पंक्ति के नीचे आपका ख़ाली स्टेट
| नाम | स्टॉक | क़ीमत |
|---|---|---|
एक सेल वाली एक पंक्ति लिखें जो सारे कॉलम में फैलती है, और उसमें अपना ख़ाली स्टेट रखें:
<tbody>
<tr data-part="empty">
<td colspan="3"><tanrei-empty-state headline="इन फ़िल्टर से कोई प्रॉडक्ट मेल नहीं खाता">…</tanrei-empty-state></td>
</tr>
</tbody>टेबल उसे ऊपर और नीचे जगह और अपने बॉक्स की चौड़ाई देती है, और कॉलम के आड़े स्क्रॉल होते समय उसे नज़र में रखती है। वह अपना कोई शब्द नहीं जोड़ती। ऐसी पंक्ति न हो तो बिना पंक्तियों की टेबल सिर्फ़ अपना हेडर है।
पंक्तियों के नीचे आपका वाक्य और आपका पेजिनेशन
| वर्शन | रिलीज़ की तारीख़ | बदलाव |
|---|---|---|
| 2.4.0 | 12 मई | टेबल अपना हेडर नज़र में रखती हैं। |
| 2.3.2 | 28 अप्रैल | दो अंकों वाले साल के साथ टाइप की गई तारीख़ों का सुधार। |
| 2.3.1 | 20 अप्रैल | स्क्रीन के बाहर खुलने वाले मेन्यू का सुधार। |
| 2.3.0 | 2 अप्रैल | साइड शीट, और ज़्यादा हल्की फ़ोकस रिंग। |
| 2.2.1 | 18 मार्च | खुले रह जाने वाले टूलटिप का सुधार। |
| 2.2.0 | 4 मार्च | दाएँ से बाएँ वाले लेआउट। |
42 में से 1–6 रिलीज़
टेबल के बाद, एलिमेंट के भीतर, स्थिति पंक्ति लिखें: आपका वाक्य, एक ऐसे पैराग्राफ़ में जो status है, और आपका पेजिनेशन।
<tanrei-table>
<table>…</table>
<div data-part="status">
<p role="status">132 में से 1–20</p>
<tanrei-pagination label="प्रॉडक्ट के पेज" variant="compact" size="small" page="1" count="7" previous-label="पिछला पेज" next-label="अगला पेज" count-text="{count} में से पेज {page}"></tanrei-pagination>
</div>
</tanrei-table>वाक्य शुरुआती किनारे पर रहता है और पेजिनेशन अंतिम किनारे पर; जहाँ दोनों अगल-बगल नहीं समाते, वहाँ पेजिनेशन वाक्य के नीचे चला जाता है। स्थिति पंक्ति कॉलम के साथ आड़ी स्क्रॉल नहीं होती, और जिस टेबल की पंक्तियाँ उसके अपने बॉक्स में स्क्रॉल होती हैं, उसमें यह सबसे नीचे रहती है। टेबल कुछ नहीं गिनती और कोई शब्द नहीं लिखती: “132 में से 1–20” आपका है, आपकी भाषा में। जब आप पैराग्राफ़ का टेक्स्ट बदलते हैं, तो सहायक तकनीक को बिना टोके (polite) बताया जाता है। जहाँ आपके मार्कअप में वह पैराग्राफ़ नहीं है, वहाँ एलिमेंट का status ऐट्रिब्यूट उसे आपके लिए लिख देता है। जो पैराग्राफ़ आपने ख़ुद लिखा है, वही पढ़ा जाता है, और तब यह ऐट्रिब्यूट कुछ नहीं बदलता।
अंतिम किनारे पर small साइज़ का पेजिनेशन रहता है: यहाँ की तरह कॉम्पैक्ट, या नंबर वाला, जहाँ लोग किसी पेज पर उसके नंबर से जाते हैं। जहाँ लोग चुनते हैं कि एक पेज में कितनी पंक्तियाँ हों, वहाँ पेजिनेशन से पहले उसके लिए एक सिलेक्ट रखें, और दोनों को एक ऐसे एलिमेंट में रखें जिसका लेआउट आप तय करते हैं; दिखाई जा रही पंक्तियों की रेंज आपका वाक्य है, पेजिनेशन का हिस्सा नहीं। पिछला और अगला लिंक यहाँ नहीं आते: वे शीर्षक वाले पेजों तक ले जाते हैं, एक ही सूची की पंक्तियों तक नहीं। टेबल बस वही रखती है जो आप उसे देते हैं: पेज बदलने पर पंक्तियाँ और वाक्य आप बदलें।
पंक्तियाँ चुनें: चयन टेबल के पास रहता है, और यह पेज उसे गिनता है
| नाम | स्टॉक | क़ीमत | |
|---|---|---|---|
| फ़िल्टर पेपर | 120 | 450 | |
| हैंड ग्राइंडर | 8 | 6,400 | |
| केतली | 15 | 3,800 | |
| तराज़ू | 0 | 2,950 |
4 में से 2 चयनित
एलिमेंट पर selection="multiple" सेट करें और हर पंक्ति को एक चयन सेल से शुरू करें। हेडर पंक्ति में इस सेल में सभी पंक्तियों का चेकबॉक्स रहता है। बॉडी की पंक्ति में इसमें उस पंक्ति का चेकबॉक्स रहता है, और पंक्ति data-value में वह नाम रखती है जिससे आप उस रिकॉर्ड को जानते हैं:
<tanrei-table selection="multiple" row-headers select-all-label="सभी प्रॉडक्ट चुनें">
<table>
<caption>दोबारा मँगाए जाने वाले प्रॉडक्ट</caption>
<thead>
<tr>
<td data-part="selection"><tanrei-checkbox label-hidden></tanrei-checkbox></td>
<th scope="col">नाम</th>
<th scope="col" data-align="end">क़ीमत</th>
</tr>
</thead>
<tbody>
<tr data-value="grinder" data-selected>
<td data-part="selection"><tanrei-checkbox label-hidden checked></tanrei-checkbox></td>
<th scope="row">हैंड ग्राइंडर</th>
<td data-align="end">6,400</td>
</tr>
</tbody>
</table>
<div data-part="status"><p role="status">4 में से 1 चयनित</p></div>
</tanrei-table>चयन टेबल के पास रहता है। जब व्यक्ति कोई चेकबॉक्स बदलता है, तो एलिमेंट उस पंक्ति पर data-selected लिखता है, हेडर के चेकबॉक्स को सिंक में रखता है, और selectionchange एक बार एमिट करता है, जिसके साथ चुनी गई हर पंक्ति का मान आता है, पंक्तियों के क्रम में:
table.addEventListener('selectionchange', (event) => {
if (!(event instanceof CustomEvent)) return; // नीचे का नोट देखें
const { values } = event.detail; // ['grinder', 'scale']
// आपका वाक्य, आपकी भाषा में, उस पैराग्राफ़ में जो आपने लिखा है
table.querySelector('[role="status"]').textContent = `${total} में से ${values.length} चयनित`;
});- किसी पंक्ति को ख़ुद चुनने के लिए उसके
<tr>परdata-selectedलिखें; यह ऐट्रिब्यूट हटा दें तो पंक्ति चुनी हुई नहीं रहती। एलिमेंट उस पंक्ति का चेकबॉक्स चेक करता है या उसका चेक हटाता है, और कुछ एमिट नहीं करता। - कोई पंक्ति चुनी गई है या नहीं, यह उसी पंक्ति पर लिखा होता है (
data-selected)। जो पंक्तियाँ आप किसी दूसरे क्रम में फिर से देते हैं, वे चुनी हुई या बिना चुनी वैसी ही रहती हैं, और जो पंक्ति टेबल को पहली बार दी जाती है, वह तभी चुनी हुई होती है जब वह ख़ुद ऐसा कहती है। - बिना
data-valueकी पंक्ति चुनी नहीं जा सकती। उसका चयन सेल ख़ाली छोड़ें, जैसे फ़ुटर पंक्ति में। - हेडर का चेकबॉक्स तब तक चेक किया हुआ रहता है जब तक हर पंक्ति चुनी हुई है, तब तक अनिश्चित जब तक कुछ चुनी हुई हैं, और तब तक अक्षम जब तक चुनने को कोई पंक्ति नहीं है। वह उन पंक्तियों के लिए है जो टेबल को दी गई हैं, दूसरे पेजों की पंक्तियों के लिए कभी नहीं।
- चयन कॉलम डेटा का कॉलम नहीं है।
row-headersऔरsticky-first-columnका मतलब उसके बाद वाला कॉलम है, औरsortइवेंट काindexउसे नहीं गिनता। - चुनी जा सकने वाली पंक्ति पर कहीं भी दबाने से उसका चेकबॉक्स बदल जाता है, ठीक वैसे ही जैसे चेकबॉक्स दबाने से। उसके सेलों में रखे लिंक, बटन और फ़ील्ड अपना दबाना ख़ुद सँभालते हैं, और खींचने, टेक्स्ट चुनने, डबल क्लिक के दूसरे क्लिक या मॉडिफ़ायर कुंजी दबाकर किए गए क्लिक से कुछ नहीं बदलता। पंक्ति होवर और दबाने में एक इकाई की तरह दिखती है; कीबोर्ड चेकबॉक्स पर ही रहता है।
ब्राउज़र का selectionchange नाम का अपना इवेंट है, जो टेक्स्ट के चयन के बदलने पर फ़ायर होता है, और सेल में रखा टेक्स्ट फ़ील्ड उसे टेबल से होकर भेजता है। टेबल का इवेंट एक CustomEvent है जिसके साथ detail.values आता है; ब्राउज़र का इवेंट ऐसा नहीं है। इसकी जाँच करें, जैसा उदाहरण करता है।
जिस पेज को स्क्रिप्ट के बिना काम करना है, उसके लिए नेटिव चेकबॉक्स इस्तेमाल करें। जिस पंक्ति का चेकबॉक्स checked है, उसे अकेली स्टाइलशीट ही चुनी हुई के रूप में बना देती है, और चेकबॉक्स आपके फ़ॉर्म के साथ सबमिट होते हैं:
<tr data-value="grinder">
<td data-part="selection"><input type="checkbox" name="product" value="grinder" checked aria-label="हैंड ग्राइंडर चुनें" /></td>
<th scope="row">हैंड ग्राइंडर</th>
</tr>एक पंक्ति चुनें: हर पंक्ति में एक रेडियो बटन, हेडर में कोई नहीं
| प्लान | सीटें | प्रति माह | |
|---|---|---|---|
| स्टार्टर | 3 | 0.00 | |
| टीम | 20 | 48.00 | |
| बिज़नेस | 100 | 180.00 |
जहाँ व्यक्ति एक रिकॉर्ड चुनता है (बदलने के लिए प्लान, भेजने का पता, तुलना के लिए बिल्ड), वहाँ selection="single" सेट करें। हर बॉडी पंक्ति के चयन सेल में चेकबॉक्स की जगह एक रेडियो बटन रहता है, और हेडर पंक्ति का चयन सेल ख़ाली रहता है, क्योंकि कोई कंट्रोल सभी पंक्तियों का प्रतिनिधि नहीं है:
<tanrei-table selection="single" row-headers>
<table>
<caption>बदलने के लिए प्लान</caption>
<thead>
<tr><td data-part="selection"></td><th scope="col">प्लान</th><th scope="col" data-align="end">सीटें</th></tr>
</thead>
<tbody>
<tr data-value="team" data-selected>
<td data-part="selection"><tanrei-radio-button label-hidden name="plan" checked></tanrei-radio-button></td>
<th scope="row">टीम</th>
<td data-align="end">20</td>
</tr>
</tbody>
</table>
</tanrei-table>- एक पंक्ति चुनने पर पहले चुनी गई पंक्ति छूट जाती है।
selectionchangeएक ही मान लाता है:{ values: ['team'] }। - चुनी गई पंक्ति या उसके रेडियो बटन को दबाने से कुछ नहीं बदलता। रेडियो बटन दोबारा दबाने से नहीं छूटता। जहाँ व्यक्ति फिर से किसी पंक्ति को न चुनी हुई हालत में लौट सकता है, वहाँ उसके लिए अपना कंट्रोल दें, और पंक्ति से
data-selectedहटा दें। - एक टेबल के रेडियो बटन एक ही नाम साझा करते हैं, इसलिए वे एक समूह हैं: फ़ोकस के क्रम में एक पड़ाव, और ऐरो कुंजियाँ चयन को एक पंक्ति से दूसरी पर ले जाती हैं। उन्हें अपना नाम दें, जिसे फ़ॉर्म भेजता है; जिनका कोई नाम नहीं है, उन्हें एलिमेंट एक नाम देता है।
- अगर आप एक से ज़्यादा पंक्तियों पर
data-selectedलिखते हैं, तो आख़िर में लिखी गई पंक्ति चुनी जाती है, और एक साथ लिखी गई पंक्तियों में से पहली। एक साथ लिखी गई पंक्तियाँ डीबग बिल्ड में रिपोर्ट की जाती हैं। - बाक़ी सब चेकबॉक्स जैसा ही है: पंक्ति पर कहीं भी दबाने से वह चुनी जाती है,
data-selectedआप लिखते हैं, और नेटिव<input type="radio" name="…">स्क्रिप्ट के बिना काम करता है।
लोड होना: प्लेसहोल्डर पंक्तियाँ, और स्थिति पंक्ति यही बताती है
| ग्राहक | ऑर्डर की तारीख़ | कुल |
|---|
लोड हो रहा है
जब तक आप पंक्तियाँ ला रहे हैं, loading सेट करें। टेबल सहायक तकनीक को व्यस्त के रूप में मिलती है, और इस बीच आप उसे जो देते हैं, वह उसे बनाती है। वह कुछ नहीं लाती और किसी चीज़ का इंतज़ार नहीं करती: वह तब तक लोड हो रही है जब तक आप ऐसा कहते हैं।
<tanrei-table loading>
<table>
<thead>…</thead>
<tbody>
<tr data-placeholder aria-hidden="true">
<td><span class="tanrei-skeleton-placeholder"></span></td>
<td data-align="end"><span class="tanrei-skeleton-placeholder" style="inline-size: 3rem; margin-inline-start: auto"></span></td>
</tr>
</tbody>
</table>
<div data-part="status"><p role="status">लोड हो रहा है</p></div>
</tanrei-table>- पहली बार लोड होते समय प्लेसहोल्डर पंक्तियाँ दें:
<tr data-placeholder aria-hidden="true">। प्लेसहोल्डर पंक्ति कम से कम टेक्स्ट की एक लाइन जितनी ऊँची होती है, उसमें कोई चेकबॉक्स नहीं होता, और वह सहायक तकनीक से छिपी रहती है। - प्लेसहोल्डर पंक्ति के सेल ख़ाली छोड़ें, या हर सेल में स्केलेटन का प्लेसहोल्डर रखें (
class="tanrei-skeleton-placeholder",@tanrei/web/skeleton.cssसे)। प्लेसहोल्डर सेल के टेक्स्ट की एक लाइन जितना ऊँचा होता है, इसलिए पंक्ति उतनी ही ऊँची होती है जितनी उसकी जगह लेने वाली पंक्ति। यहाँ अकेली क्लास काफ़ी है: टेबल पहले से बता रही है कि वह व्यस्त है। - किसी दूसरे पेज या दूसरे क्रम के लिए वे पंक्तियाँ रहने दें जो टेबल में थीं, और
loadingसेट करें। जो पंक्तियाँ व्यक्ति पढ़ रहा था, वे पढ़ने लायक़ बनी रहती हैं। - कुछ भी धुँधला नहीं किया जाता और कुछ भी अक्षम नहीं किया जाता। टेबल के लोड होते समय हेडर और चेकबॉक्स काम करते हैं।
- जब तक
loadingसेट है, ख़ाली स्टेट की पंक्ति नहीं बनती, तब भी नहीं जब कोई और पंक्ति न हो।
Markdown रेंडरर एक सादी <table> लिखता है। उसे बिल्ड के समय लपेटें; Tanrei रन टाइम पर आपका कॉन्टेंट इधर-उधर नहीं करता। rehype के साथ यह एक छोटा-सा क़दम है:
import { visit, SKIP } from 'unist-util-visit';
/** दस्तावेज़ की हर टेबल को <tanrei-table> में लपेटता है। */
export function rehypeTanreiTable() {
return (tree) =>
visit(tree, 'element', (node, index, parent) => {
if (node.tagName !== 'table' || parent?.tagName === 'tanrei-table') return;
parent.children[index] = { type: 'element', tagName: 'tanrei-table', properties: {}, children: [node] };
return SKIP;
});
}सेल पर रेंडरर का अपना align="right" end के रूप में पढ़ा जाता है, और align="left" start के रूप में, इसलिए दाएँ से बाएँ वाले पेज पर “संख्याएँ दाईं ओर” का मतलब “संख्याएँ अंत की ओर” हो जाता है।
Compact और धारीदार, उस टेबल के लिए जिस पर व्यक्ति नज़र दौड़ाता है
| टोकन | एलियास | टाइप |
|---|---|---|
| comp.table.separation | sys.behavior.separation | number |
| comp.table.divider.color | sys.color.outline-variant | color |
| comp.table.divider.thickness | sys.border.hairline | dimension |
| comp.table.row.gap | sys.space.space50 | dimension |
| comp.table.stripe.container.color | sys.color.surface-container-low | color |
| comp.table.caption.gap | sys.space.space100 | dimension |
अपने बॉक्स से चौड़ी: वह वहीं स्क्रॉल होती है, और पहला कॉलम अपनी जगह रहता है
| क्षेत्र | जनवरी | फ़रवरी | मार्च | अप्रैल | मई | जून | जुलाई |
|---|---|---|---|---|---|---|---|
| उत्तरी क्षेत्र | 1,204 | 1,310 | 1,288 | 1,402 | 1,396 | 1,450 | 1,512 |
| मध्य क्षेत्र | 3,020 | 2,985 | 3,110 | 3,204 | 3,190 | 3,275 | 3,301 |
| दक्षिणी क्षेत्र | 870 | 902 | 915 | 899 | 940 | 968 | 1,002 |
| द्वीप | 212 | 220 | 198 | 240 | 251 | 263 | 270 |
लेआउट से मिली ऊँचाई: पंक्तियाँ स्क्रॉल होती हैं, और हेडर अपनी जगह रहता है
| वर्शन | रिलीज़ की तारीख़ | बदलाव |
|---|---|---|
| 2.4.0 | 12 मई | टेबल अपना हेडर नज़र में रखती हैं। |
| 2.3.2 | 28 अप्रैल | दो अंकों वाले साल के साथ टाइप की गई तारीख़ों का सुधार। |
| 2.3.1 | 20 अप्रैल | स्क्रीन के बाहर खुलने वाले मेन्यू का सुधार। |
| 2.3.0 | 2 अप्रैल | साइड शीट, और ज़्यादा हल्की फ़ोकस रिंग। |
| 2.2.1 | 18 मार्च | खुले रह जाने वाले टूलटिप का सुधार। |
| 2.2.0 | 4 मार्च | दाएँ से बाएँ वाले लेआउट। |
| 2.1.0 | 11 फ़रवरी | तारीख़ और समय पिकर। |
संरचना
| भाग | विवरण |
|---|---|
1 container | The table's box: as wide as its layout gives it, as tall as its rows unless the layout limits it. It has no fill, edge or corner of its own. When the columns or the rows do not fit, it is the box they scroll in, and then the one part of the table that takes focus. |
2 caption · वैकल्पिक | The name of the table, drawn above its first row at the start edge. It does not scroll sideways with the columns. |
3 header-row · वैकल्पिक | The first row: one header cell for each column. It can stay in view while the rows scroll under it. |
4 header-cell · वैकल्पिक | The name of a column, in a label style and a quieter color than the data. |
5 sort-button · वैकल्पिक | The whole header cell of a column that can be sorted, as one button: the column's name and its mark. It carries hover, focus and press, and asks the product for the rows in the column's order. |
6 sort-mark · वैकल्पिक | The glyph beside the name of a column that can be sorted: a two-way arrow while the rows are not in its order, an arrow up while they ascend by it, an arrow down while they descend. |
7 row | One record: a cell for each column, as tall as its tallest cell. A row that can be chosen is, for a pointer, one target that presses its checkbox or radio button, with its own hover and press (TBL-58, TBL-59). |
8 row-header · वैकल्पिक | The first cell of a row where the first column names its rows: the cell style at its emphasized weight. The first column can stay in view while the others scroll under it. |
9 selection-cell · वैकल्पिक | The cell before the first column of a table whose rows can be chosen: in a body row the row's checkbox, or its radio button where one row at most is chosen; in the header row the checkbox for every row, or nothing where one row at most is chosen; in a footer row nothing. |
10 cell | One value: text that wraps inside its column, or a component of the product's (a tag, a link, inline code). It may be empty. |
11 divider · वैकल्पिक | The one hairline between two rows, under the header row and above the footer rows, where rows are told apart by a line; also the line along the inner edge of a first column that stays in view, and along an edge of the box beyond which there is more to scroll to. |
12 stripe · वैकल्पिक | A quiet fill on every second body row. |
13 selected-row · वैकल्पिक | The fill of a body row that is chosen, across its whole width, in place of a stripe. |
14 placeholder-row · वैकल्पिक | A body row that stands for a record that has not arrived: as tall as a row of one line, holding what the product puts in its cells (a Skeleton), and no checkbox or radio button. |
15 empty · वैकल्पिक | What stands in the place of the body rows of a table that has none: the product's own content (an Empty state), as wide as the table's box, under the header row. |
16 footer-row · वैकल्पिक | A row after every body row that sums the columns up or notes something about them: the cell style at its emphasized weight. |
17 status · वैकल्पिक | One line under the last row, outside the columns: the product's sentence about what the table shows now (the range of rows shown, how many are chosen) at the start edge, and its pagination at the end edge. It does not scroll sideways with the columns. |
प्रॉपर्टी
| प्रॉपर्टी | टाइप | डिफ़ॉल्ट | विवरण |
|---|---|---|---|
caption | string | "" | The name of the table, drawn above it ("Response times by region"). It is also what assistive technology calls the table and its scroll region. Prefer it to label wherever the page does not already name the table in sight. |
label | string | "" | The table's accessible name where no caption is drawn, because a heading just above it already says what it is. Not drawn. Ignored where caption is given. |
density | regular | compact | "regular" | How close the rows are. Regular (a 46 row in the default system) is for a table a person reads: a few rows, cells that wrap. Compact (a 32 row, smaller text) is for a table a person scans: hundreds of rows, identifiers and values. A design system may add values. |
separation | auto | divider | gap | "auto" | How a row is told from the row next to it. divider: one hairline between them. gap: empty space and no line. Auto takes comp.table.separation, the design system's answer (divider in the default system). |
striped | boolean | false | Fills every second body row with a quiet color, for a wide table of many similar rows where the eye loses its row on the way across. It can be combined with either separation. |
rowHeaders | boolean | false | Says that the first column names its rows (a component, a region, a plan), so its cells are drawn and exposed as row headers. False for a table whose rows are named by no single column. |
stickyHeader | boolean | false | Keeps the header row at the top of the table's box while its rows scroll under it. It has an effect only where the layout limits the table's height, so that the rows scroll in the table's own box. |
stickyFirstColumn | boolean | false | Keeps the first column at the start edge while the other columns scroll sideways under it, for a wide table whose first column says what each row is. Released by itself where the column would take more than half of the box. |
selection | none | single | multiple | "none" | Whether rows can be chosen, and how many. multiple puts a checkbox before the first column of every body row that has a value, and one in the header row that stands for all of them. single puts a radio button there instead and nothing in the header row: one row at most is chosen, and a person moves the choice from row to row but does not take it back (TBL-60). none draws no such column and ignores a row's selected. |
selectAllLabel | string | "" | The accessible name of the checkbox in the header row that chooses every row ("Select all rows"). Not drawn; read only while selection is multiple. From the product's words where the instance gives none. |
sortedAscendingLabel | string | "" | What a platform that has no sort state of its own says after the name of the column the rows ascend by ("sorted ascending"). Not drawn. A platform that exposes the direction itself (the web) does not read it. |
sortedDescendingLabel | string | "" | What a platform that has no sort state of its own says after the name of the column the rows descend by ("sorted descending"). Not drawn. A platform that exposes the direction itself (the web) does not read it. |
loading | boolean | false | Says that the product is fetching the rows — the first ones, another page of them, or the same ones in another order. The table is exposed as busy and draws the rows it is given meanwhile: the ones it had, or placeholder rows. It fetches nothing itself. |
status | string | "" | The product's sentence about what the table shows now ("1–20 of 132", "3 of 132 selected", "Loading"), drawn under the last row and told politely to assistive technology when it changes. The table counts nothing and writes no word of its own. Empty draws no status text. |
स्लॉट
| स्लॉट | विवरण |
|---|---|
empty | What the table draws in the place of its body rows while it has none and is not loading: the product's Empty state, or its own sentence. The table gives it the box's width and room above and below, and does nothing else to it. A fixture's string is drawn as plain text in its place. |
pagination | What stands at the end edge of the status line: one element, the product's Pagination — at size small, and compact where the product does not page by number — or a group the product lays out of a Select for the rows per page and that Pagination, as the table paginations of Carbon and MUI are. The range of rows shown ("1–20 of 132") is the status text, not the slot's. It is never Previous and next links, which lead to titled pages and not to the rows of one list. The table places it and does nothing else to it. A fixture's string is drawn as plain text in its place. |
इवेंट
| इवेंट | विवरण |
|---|---|
sort | The user pressed the header of a sortable column; carries column (the column's value), index (its place among the columns of data, from 0) and direction (ascending or descending: the one asked for, TBL-34). The table changes nothing: the product orders its rows and sets the column's sort. |
selectionChange | The user changed which rows are chosen — by a row's checkbox or radio button, by a press on the row, by the checkbox for every row, or by an arrow key on a radio button; carries values: the values of the chosen rows after the change, in row order. While selection is single it holds the one chosen row's value. |
आइटम
वे आइटम के प्रकार जिन्हें कंपोनेंट दोहराता है। फ़िक्स्चर अपने आइटम क्रम से सूचीबद्ध करता है; हर प्लैटफ़ॉर्म हर प्रकार को अपने तरीक़े से नाम देता है।
column
One column of the table: the text of its header cell, how its cells are aligned and wrapped, and whether its header asks for the rows in its order.
| प्रॉपर्टी | टाइप | डिफ़ॉल्ट | विवरण |
|---|---|---|---|
header | string | "" | The text of the column's header cell ("Price"). Empty only where the table has no header row at all, and then for every column. |
align | start | center | end | "start" | Where the content of the column's cells sits, header and footer cells included. start for text. end for numbers that are compared, so that their digits line up. center for a mark or a single word that is the same kind of answer in every row. |
wrap | boolean | true | Whether the text of the column's cells may wrap. False keeps every cell on one line, for identifiers, dates, numbers and short values; the column is then as wide as its widest cell. |
sortable | boolean | false | Says that the rows can be put in this column's order: its header cell is a button that asks for it. The table never orders rows itself. It needs a header: a sortable column without one is drawn as a plain column. |
sort | none | ascending | descending | "none" | The order the rows are in by this column, as the product has put them: the header draws it and exposes it. The product sets it after it has ordered its rows; one column at a time is not none. |
value | string | "" | The name the product knows the column by ("price"), carried by the sort event. Not drawn. Empty: the event carries the column's index alone. |
| स्पेक | Web | SwiftUI | Jetpack Compose | Flutter | React Native |
|---|---|---|---|---|---|
| आइटम | th | TanreiTableColumn | TanreiTableColumn | TanreiTableColumn | TableColumn |
header · प्रॉपर्टी | scope | header | header | header | header |
align · प्रॉपर्टी | data-align | alignment | align | align | align |
wrap · प्रॉपर्टी | data-wrap | wraps | wrap | wrap | wrap |
sortable · प्रॉपर्टी | button | isSortable | sortable | sortable | sortable |
sort · प्रॉपर्टी | aria-sort | sort | sort | sort | sort |
value · प्रॉपर्टी | data-value | value | value | value | value |
| टिप्पणियाँ | A <th scope="col"> in the <thead> row; its text is the header. data-align="end" and data-wrap="false" on that <th> reach every cell of the column: the element writes the positions of such columns on the wrapper (data-columns-end, data-columns-center, data-columns-nowrap) and one rule per position places the cells, so no cell is written to; without script, and from a Markdown renderer, the same attributes (or the renderer's own align attribute, where left and right are read as start and end) sit on each cell. A sortable column: the <th> holds the product's own <button type="button"> (or, for a table ordered by the server, an <a href> to the same table in the other order) around the header's text, and carries aria-sort="none", "ascending" or "descending"; the stylesheet draws the mark from that attribute, so the product writes no glyph. data-value on the <th> is the column's value. | An entry of the columns prop. |
row · ग्रुप — इसमें आइटम होते हैं
One row of the table: a cell for each column, in the order of the columns; a record that can be chosen where the table's selection says so.
| प्रॉपर्टी | टाइप | डिफ़ॉल्ट | विवरण |
|---|---|---|---|
footer | boolean | false | Says that the row is a footer row: drawn after every body row, in the emphasized weight, never striped. For sums, averages and notes about the columns. |
value | string | "" | The name the product knows the record by, carried by selectionChange. Not drawn. A body row without a value cannot be chosen: it has no checkbox or radio button. |
selected | boolean | false | Whether the row is chosen. Read only while the table's selection is single or multiple and the row has a value; while it is single, one row at most is chosen (TBL-60). |
selectLabel | string | "" | The accessible name of the row's checkbox or radio button ("Select Islands"): words about this one record, so the instance's. Not drawn. Empty: it is named by the row's header cell where rowHeaders is true. |
placeholder | boolean | false | Says that the row stands for a record that has not arrived. It is drawn as a body row at least one line tall, holds what the product puts in its cells (a Skeleton) or nothing, has no checkbox or radio button and is hidden from assistive technology. |
| स्पेक | Web | SwiftUI | Jetpack Compose | Flutter | React Native |
|---|---|---|---|---|---|
| आइटम | tr | TanreiTableRow | row | TanreiTableRow | Table.Row |
footer · प्रॉपर्टी | tfoot | isFooter | footer | footer | footer |
value · प्रॉपर्टी | data-value | value | value | value | value |
selected · प्रॉपर्टी | data-selected | isSelected | selected | selected | selected |
selectLabel · प्रॉपर्टी | aria-label | selectLabel | selectLabel | selectLabel | selectLabel |
placeholder · प्रॉपर्टी | data-placeholder | isPlaceholder | placeholder | placeholder | placeholder |
| टिप्पणियाँ | A <tr>; a footer row is a <tr> inside <tfoot>. A row that can be chosen has data-value and a first cell <td data-part="selection"> holding the product's checkbox — <tanrei-checkbox label-hidden label="…">, or a native <input type="checkbox" aria-label="…"> that also works in a form without script; selectLabel is that checkbox's own name. data-selected on the <tr> draws the row as chosen; the element keeps it in step with the checkbox, and the stylesheet also reads a native checkbox that is checked, so a row is drawn chosen before and without script. While selection="single" the selection cell holds a radio button instead — <tanrei-radio-button label-hidden name="…" label="…">, or a native <input type="radio" name="…" aria-label="…"> — the radio buttons of one table share one name (the element gives one to those that have none, so that they form one group), and the header row's selection cell is empty. A placeholder row is <tr data-placeholder aria-hidden="true">. | A call in the table's scope: row(footer = false) { cell("…") }. |
cell · ग्रुप — इसमें आइटम होते हैं
One value of a row: plain text, a component of the product's, or nothing.
| स्लॉट | विवरण |
|---|---|
content | What the cell holds in place of plain text: a tag, a link, inline code, a button, a picture, any view of the product's. The table places it and styles nothing inside it (TBL-15). |
| स्पेक | Web | SwiftUI | Jetpack Compose | Flutter | React Native |
|---|---|---|---|---|---|
| आइटम | td | TanreiTableCell | cell | TanreiTableCell | Table.Cell |
| टिप्पणियाँ | A <td>, or a <th scope="row"> for a row header; its children are the content. | A cell takes a string or a view builder. | cell(text) or cell { content } in a row's scope. | TanreiTableCell.text("…") or TanreiTableCell(child: …). | Its children are a string or elements. |
tag
A tag placed in a cell: the Tag component, as it is drawn anywhere else.
| प्रॉपर्टी | टाइप | डिफ़ॉल्ट | विवरण |
|---|---|---|---|
label | string | "" | The tag's text. |
variant | tonal | outlined | filled | "tonal" | The tag's look. |
status | default | info | warning | error | success | "default" | What the tag reports. |
size | small | medium | "medium" | The tag's size; small in a table cell, so that it does not make its row taller. |
| स्पेक | Web | SwiftUI | Jetpack Compose | Flutter | React Native |
|---|---|---|---|---|---|
| आइटम | tanrei-tag | TanreiTag | TanreiTag | TanreiTag | Tag |
label · प्रॉपर्टी | label | title | label | label | label |
variant · प्रॉपर्टी | variant | variant | variant | variant | variant |
status · प्रॉपर्टी | status | status | status | status | status |
size · प्रॉपर्टी | size | size | size | size | size |
स्टेट
व्यवहार
EARS रूप में लिखी गई आवश्यकताएँ। हर प्लैटफ़ॉर्म के इम्प्लीमेंटेशन को इन ID के आधार पर टेस्ट किया जाता है। आवश्यकताओं का पाठ स्पेक फ़ाइल से ज्यों का त्यों, अंग्रेज़ी में दिखाया गया है।
| ID | आवश्यकता |
|---|---|
TBL-1 | THE table SHALL draw, from top to bottom, its caption where it has one, one header row holding one header cell for each column, its body rows in the order given, and its footer rows after every body row, each row holding one cell for each column in the order of the columns; THE table SHALL be at least as wide as the layout gives it, SHALL draw no fill, no edge, no corner and no elevation of its own around its rows, and SHALL bring no outer space of its own, so that it is spaced by what holds it. |
TBL-2 | THE table SHALL size every column from its content: a column SHALL never be narrower than the widest thing in it that cannot break — a word, a number, a cell of a column whose wrap is false, a component — with the cell's inline paddings; WHILE the columns at those least widths fit the table's box THE table SHALL share the box's width among them in proportion to their content, so that the table fills its box and a column of long text takes what the short columns leave; THE table SHALL NOT give a column a width in a unit of its own, and a width the product gives a column SHALL replace what the content would give it. |
TBL-3 | THE table SHALL wrap the text of a cell inside its column, breaking lines by the rules of the text's language, and SHALL never cut it or end it with an ellipsis; a run with no break opportunity (an identifier, an address) SHALL NOT be broken inside and widens its column instead (TBL-2, TBL-17); WHERE a column's wrap is false THE table SHALL keep every cell of that column, its header cell included, on one line. |
TBL-4 | THE table SHALL pad every cell at the top and bottom by comp.table.cell.padding-block.regular and at the start and end by comp.table.cell.padding-inline.regular while density is regular, and by comp.table.cell.padding-block.compact and comp.table.cell.padding-inline.compact while density is compact, the first and the last cell of a row included; SHALL set a cell's text in comp.table.cell.text.typescale.regular or comp.table.cell.text.typescale.compact by density, in comp.table.cell.text.color, with digits in figures of equal width so that the numbers of a column line up; SHALL make a row as tall as its tallest cell and no taller, with no height of its own; and SHALL align the cells of a row to the top, so that the first lines of a row share a baseline. |
TBL-5 | THE table SHALL set a column's header cell in comp.table.header.text.typescale.regular or comp.table.header.text.typescale.compact by density, in comp.table.header.text.color, with the paddings of a cell (TBL-4), and SHALL fill the header row with comp.table.header.container.color; the header cells of a row SHALL align to the bottom, so that the last line of each sits next to the data it names. IF every column's header is empty THE table SHALL draw no header row and no line for it, and the table then relies on its row headers (TBL-6). |
TBL-6 | WHILE rowHeaders is true THE table SHALL treat the first cell of every body row and of every footer row as the header of its row: it SHALL draw that cell in the cell's text style at its emphasized weight — the style's weight plus sys.typescale.emphasis.body — in comp.table.cell.text.color, with a cell's paddings and no fill of its own, and SHALL expose it as a row header (TBL-24); WHILE rowHeaders is false THE table SHALL draw and expose the first column as cells, except that a first cell the product's own content already marks as the header of its row (on the web a th whose scope is row) SHALL be drawn and exposed as one whatever rowHeaders says: rowHeaders adds row headers and takes none away. WHILE selection is multiple or single the first column is the first column of data, after the selection column (TBL-42). |
TBL-7 | THE table SHALL align the content of every cell of a column, its header cell and its footer cells included, as the column's align names — start: at the start edge of the cell; end: at the end edge, for numbers that are compared digit by digit; center: in the middle, for a mark or a single word that is the same kind of answer in every row — and SHALL align every line of a wrapped cell the same way; a value of align the table does not define SHALL be treated as start. |
TBL-8 | WHILE the table's separation is divider (TBL-9) THE table SHALL draw one line of comp.table.divider.thickness in comp.table.divider.color across its whole width under the header row, between every two rows that follow each other, and between the last body row and the first footer row, without adding to a row's height or moving its content; it SHALL draw no line above the first row or below the last, and no line between columns. |
TBL-9 | THE table SHALL tell a row from the row next to it as its separation names: WHILE separation is auto, as comp.table.separation names, which follows sys.behavior.separation unless a design system sets it apart; WHILE separation is divider or gap, as that value names, whatever the tokens say; divider draws the lines of TBL-8 and gap leaves the space of TBL-10. WHEN separation, or the token it follows, changes THE table SHALL draw the other form at once, without animation, keeping its scroll position; WHEN separation names a value the table does not define THE table SHALL treat it as auto and in debug builds report the unknown value. A platform that cannot draw a choice SHALL fall back to the first value, divider, and state that in its README. |
TBL-10 | WHILE the table's separation is gap (TBL-9) THE table SHALL leave comp.table.row.gap of empty space under the header row, between every two rows that follow each other, and between the last body row and the first footer row, SHALL draw none of the lines of TBL-8, and SHALL leave no such space above the first row or below the last; the rows SHALL stay exposed as rows (TBL-24). |
TBL-11 | WHILE striped is true THE table SHALL fill every second body row — the second, the fourth and so on, counted among the body rows as they are shown — with comp.table.stripe.container.color across the row's whole width, paddings included, and SHALL fill neither the header row nor a footer row with it; the fill SHALL change nothing else about the row, and the row separation of TBL-9 SHALL be drawn as without it. |
TBL-12 | WHERE caption is not empty THE table SHALL draw it above the header row, at the start edge of the table's box, in comp.table.caption.text.typescale and comp.table.caption.text.color, wrapping inside the box's width, comp.table.caption.gap above the first row; the caption SHALL stay where it is while the columns scroll sideways (TBL-17) and SHALL be the table's accessible name (TBL-23). |
TBL-13 | WHERE a row's footer is true THE table SHALL draw it after every body row, in the order given, as a footer row: its cells in the cell's text style at its emphasized weight — the style's weight plus sys.typescale.emphasis.body — in comp.table.cell.text.color, aligned as their columns are, never striped, and exposed as rows of the table that follow its body; IF a row whose footer is false is given after a footer row THE table SHALL still draw every body row before every footer row and in debug builds report the order. |
TBL-14 | WHERE a cell has no content THE table SHALL draw nothing in it, keep its place and its paddings so that the cells after it stay in their columns, and expose it as an empty cell; THE table SHALL NOT put a dash, a word or any other mark of its own in it. IF a row holds fewer cells than the table has columns THE table SHALL keep the row's place and its height and leave the places of the missing cells empty at the row's end: a platform that builds its rows SHALL draw them as empty cells, and a platform that draws the product's own rows (the web) SHALL write no cell into them, so that there the row's line and a stripe end at its last cell, and in debug builds SHALL report the row; IF it holds more THE table SHALL draw only as many as it has columns and in debug builds report the row. |
TBL-15 | WHERE a cell holds a component or any content of the product's that is not plain text — a tag, a link, inline code, a button, a picture — THE table SHALL place it by the column's alignment (TBL-7) on the cell's first line, SHALL add nothing to it and style nothing inside it, and SHALL let pointer, touch and keyboard input reach it as it would outside the table, in the reading order of the cells. |
TBL-16 | THE table and its cells SHALL NOT take pointer, touch or keyboard input of their own and SHALL NOT change anything they draw under a pointer, a press or focus, and a row SHALL NOT either except as TBL-58 and TBL-59 say: no row has a focused state, is a stop in the focus order or takes a key; a row that cannot be chosen — every row of a table whose selection is none, the header row, a footer row, a placeholder row and a body row without a value — has no hovered or pressed state and is not pressed as a whole; and a cell is not a stop in the focus order. Four parts of the table take input, each by its own sentences: the header cell of a sortable column, which is a button (TBL-32 to TBL-41); the checkboxes of a table whose selection is multiple, which are the Checkbox component, and the radio buttons of a table whose selection is single, which are the Radio button component (TBL-42 to TBL-47, TBL-60, TBL-61); a body row that can be chosen, which a pointer presses as its checkbox or radio button (TBL-58, TBL-59); and the scroll region while the table scrolls (TBL-22). WHILE no column is sortable and selection is none THE table SHALL emit no event. |
TBL-17 | WHEN the columns at their least widths (TBL-2) are wider than the table's box THE table SHALL keep its box at the width the layout gives it and scroll its columns sideways inside that box, header row, body rows and footer rows together, beginning at the start edge; it SHALL never be wider than its layout and SHALL never make what holds it scroll sideways; a wheel, a trackpad, a drag on a touch screen and the keys of TBL-22 SHALL scroll it. |
TBL-18 | WHERE the layout gives the table less height than its rows need THE table SHALL scroll its rows up and down inside its own box, the caption above them as the first thing in the box, where it MAY scroll away with the rows on a platform whose caption is part of what scrolls (the web's native caption), and the status line staying at the bottom of the box (TBL-51); WHERE the layout sets no such limit THE table SHALL be exactly as tall as its caption and its rows, and SHALL set no height and no number of rows of its own. |
TBL-19 | WHILE stickyHeader is true and the table scrolls its rows in its own box (TBL-18) THE table SHALL keep the header row at the top of that box while the rows pass under it, filled with comp.table.sticky.container.color under comp.table.header.container.color so that nothing shows through it, and SHALL draw a line of comp.table.divider.thickness in comp.table.divider.color under it whatever the separation is while a row is under it; WHILE stickyHeader is false, or the table does not scroll its rows in its own box, THE header row SHALL scroll with the rows. |
TBL-20 | WHILE stickyFirstColumn is true and the table scrolls sideways (TBL-17) THE table SHALL keep the first column — its header cell, its cells and its footer cells — at the start edge of the box while the other columns pass under it, each of its cells filled with comp.table.sticky.container.color under the fill its row gives it (comp.table.header.container.color in the header row, comp.table.stripe.container.color in a striped row), and SHALL draw a line of comp.table.divider.thickness in comp.table.divider.color along its inner edge for the table's whole height while a column is under it; WHILE both stickyHeader and stickyFirstColumn hold THE first header cell SHALL stay above both. IF the first column is wider than half of the table's box THE table SHALL let it scroll with the other columns, so that a narrow window is never filled by the column that stays. |
TBL-21 | WHILE the table scrolls sideways and columns lie beyond an inline edge of its box THE table SHALL draw a line of comp.table.divider.thickness in comp.table.divider.color along that edge of the box for the table's whole height, and SHALL remove it when the scroll reaches that edge; at the start edge of a table whose first column is kept in view the line of TBL-20 is that line. THE table SHALL show that there is more with these lines alone: no shadow, no fade and no color that is not the divider's. |
TBL-22 | WHILE the table scrolls in its own box, sideways or up and down, THE table SHALL make that box one stop in the focus order, before anything in its cells that takes focus, exposed as a region that carries the table's name (TBL-23); WHILE it has keyboard focus the box SHALL draw the system's focus indicator inside its edge — sys.focus.outer-width wide in the color role focus-ring, set in from the edge by sys.focus.offset so that nothing clips it, and never animated — and the arrow keys, Page Up, Page Down, Home and End SHALL scroll it as the platform scrolls a region, the left and right arrow keys moving the view left and right in either layout direction; WHILE the table does not scroll THE table SHALL NOT be a stop in the focus order and SHALL expose no region. |
TBL-23 | THE table SHALL take its accessible name from caption where caption is not empty, and from label otherwise, and SHALL NOT draw label; IF both are empty THE table SHALL be exposed without a name and in debug builds report that a table has no name, and WHILE such a table scrolls in its own box that box SHALL still be a stop in the focus order (TBL-22), exposed as a region without a name, because the keyboard must be able to scroll it; IF both are given THE caption SHALL be the name and label SHALL be ignored. |
TBL-24 | THE table SHALL be exposed to assistive technology as a table with its number of rows and columns, its header cells as column headers, its first cells as row headers while rowHeaders is true, and every cell associated with the header of its column and, where there is one, of its row, so that a person moving cell by cell hears what each value belongs to; a platform that has no table semantics SHALL expose each row as one group in reading order and each cell with its column header before its own content. Keeping a header row or a first column in view, striping, the density and scrolling SHALL change nothing that is exposed. |
TBL-25 | WHEN the table's rows, columns or cells change THE table SHALL draw the new content at once, without a motion, keeping its scroll position where the content it showed still exists, and SHALL NOT announce the change by itself. The one place where the table tells a change is its status line, and what that says is the product's (TBL-52); WHEN rows are replaced because the product ordered or fetched them THE table SHALL keep keyboard focus on the sort button, the checkbox or the radio button that had it, where that control still exists. |
TBL-26 | THE table SHALL take its layout direction from where it is used — the direction of the nearest ancestor that sets one, and the platform's own where none does — and SHALL have no direction setting of its own; WHEN that direction changes while the table is shown THE table SHALL draw itself for the new direction at once, without a motion of its own, keeping its content and the column a person was looking at in view. |
TBL-27 | WHERE the layout direction is right-to-left THE table SHALL lay its columns out from the right, the first column at the right edge; SHALL apply paddings and the alignments start and end by the layout direction; SHALL begin its sideways scroll at the right edge; SHALL keep a first column that stays in view (TBL-20) at the right edge with its line on its left; and SHALL draw the lines of TBL-21 at the edges beyond which columns lie. Top and bottom SHALL NOT change: the header row is the first row and the footer rows the last in either direction. |
TBL-28 | THE table SHALL lay out the text of each cell, of each header cell and of the caption as text of its own direction, isolated from the cells beside it: it takes the base direction of its first strong character, or the layout direction where it has none, so that a left-to-right name, an identifier, a number with its sign, unit or currency, a version and a date keep their own order in a right-to-left layout; THE table SHALL place that text by the column's alignment in the layout direction, not by the text's own, and SHALL NOT reverse the digits of a number: a column of numbers whose align is end is at the left edge of its cells in a right-to-left layout, with its digits written left to right. |
TBL-29 | WHILE the text size is enlarged THE table SHALL grow every text style with it, give up none of its paddings and none of its lines (they MAY grow with the text where the design system's units follow the text size), size its columns again from the larger content (TBL-2), wrap what can wrap and scroll in its own box where the columns no longer fit (TBL-17); it SHALL cut no content, SHALL set no fixed height on a row or a cell, SHALL lose no content when the reader raises line height, paragraph spacing, letter spacing or word spacing, and SHALL need no sideways scrolling of what holds it at a width of 320 points. |
TBL-30 | WHERE the platform draws with a person's own forced colors (the web's forced-colors mode, and a platform's equivalent where it has one) THE table SHALL draw every line of TBL-8, TBL-19, TBL-20 and TBL-21 in the platform's text color and its text in that color, SHALL keep header cells, row headers and footer cells told apart by their text styles, and, because the mode removes fills, SHALL draw the lines of TBL-8 in a striped table whatever its separation is, so that its rows are still told apart. |
TBL-31 | WHEN density names a value that the active design system does not have THE table SHALL render with the default value's tokens, and in debug builds report the unknown value. |
TBL-32 | WHERE a column's sortable is true and its header is not empty THE table SHALL draw that column's header cell as one button, the sort button: its container is the whole box of the header cell, paddings included, with square corners; it holds the column's header as its label, in the header's text style (TBL-5), and the sort mark — one glyph of the system's icon set in a box of comp.table.header.icon.size, drawn through the icon helper with sys.icon.family.unselected, sys.icon.fill.unselected, the weight comp.table.header.icon.weight and an optical size clamped between sys.icon.optical-size.min and sys.icon.optical-size.max — comp.table.header.gap after the label's box, at the height of the label's last line, so that a header that wraps keeps its mark at the edge of its label rather than after the last word; in a column whose align is end the mark SHALL stand before the label, so that the end of the label stays on the edge its numbers end at. The mark's box SHALL be kept whatever the column's sort is, so that a change of order moves no label and changes no column's width. IF sortable is true and header is empty THE table SHALL draw the column as one that is not sortable and in debug builds report it. |
TBL-33 | THE table SHALL draw the order the product sets and never make one: WHILE a sortable column's sort is none its sort button is the part sort — the label in comp.table.sort.label.color, the glyph swap_vert in comp.table.sort.icon.color, the container in comp.table.sort.container.color; WHILE its sort is ascending or descending it is the part sorted — the label in comp.table.sorted.label.color, the glyph arrow_upward for ascending and arrow_downward for descending in comp.table.sorted.icon.color, the container in comp.table.sorted.container.color. THE table SHALL NOT reorder, compare, filter or hide a row, SHALL NOT change a column's sort itself, and SHALL draw its rows in the order it is given whatever any sort says. WHEN a column's sort changes THE table SHALL draw the other glyph and colors at once, with no motion but that of a state change (TBL-35). IF more than one column's sort is not none THE table SHALL draw each as it is given and in debug builds report it: the rows have one order. A sort on a column whose sortable is false SHALL be ignored. |
TBL-34 | WHEN the user activates a sort button by pointer, touch, Enter or Space THE table SHALL emit sort exactly once, carrying the column's value, its index among the columns of data and the direction asked for — ascending WHILE the column's sort is none or descending, descending WHILE it is ascending — and SHALL change nothing it draws but the answer to the press: the mark, the colors and the rows stay as they are until the product sets sort and gives the rows in their new order. The direction is what the person asked; the product MAY set another, or none. THE table SHALL keep keyboard focus on the sort button through the press and through the change of rows that follows it. WHERE the product gave the control a destination in place of an action (on the web an anchor in the header cell, whose address is the same table in the other order) THE table SHALL emit sort once and then let the platform follow the destination unless the product cancelled the event, and Space SHALL NOT activate it, as it activates no link. |
TBL-35 | WHILE a sort button is hovered, keyboard-focused or pressed THE table SHALL render its container, its label, its mark and its opacity from the component tokens of its part (sort or sorted) in the highest-precedence active state, with precedence pressed over focused over hovered; focus gained by pointer or touch SHALL NOT select the focused state. A change between states SHALL take comp.table.motion.state-duration with comp.table.motion.state-easing and SHALL be immediate where motion is reduced. The state layer SHALL cover the header cell and nothing beside it, and WHILE the header row or the column is kept in view (TBL-19, TBL-20) SHALL be drawn over comp.table.sticky.container.color, so that nothing shows through it. |
TBL-36 | WHEN a sort button receives keyboard focus THE table SHALL show the system's focus indicator inside the edge of its header cell without animation — sys.focus.outer-width wide in the color role focus-ring, set in from the edge by sys.focus.offset so that neither the next cell, the box's edge nor a header kept in view clips it, with the inner stroke of sys.focus.inner-width where the system has one; focus gained by pointer or touch SHALL NOT show it. WHEN keyboard focus moves to a sort button, a checkbox or a radio button that is under a header row, a first column or a status line kept in view, or outside the box, THE table SHALL scroll its box so that the whole control is in view beside them. |
TBL-37 | WHEN a sort button is pressed by pointer, touch, Enter or Space THE table SHALL show the pressed state without delay and SHALL keep it visible for at least sys.motion.duration.press-hold, even when the press ends sooner. |
TBL-38 | WHILE a sort button is pressed THE table SHALL answer as sys.behavior.pressed-feedback names: overlay applies the pressed tokens to the whole container at once; ripple grows the pressed state layer from the point of contact (from the center for keyboard activation); dim applies the pressed opacity to the whole control and draws no state layer; none draws no answer to the press. Under ripple and dim only the container color stays with the state under the press; label, mark and opacity still come from the pressed tokens. Under none every part stays with the state under the press. The ripple grows over comp.table.motion.feedback-duration with comp.table.motion.state-easing, fades over comp.table.motion.state-duration with comp.table.motion.state-easing once the press has ended and press-hold has passed, and appears whole where motion is reduced. |
TBL-39 | THE table SHALL show the keyboard focus of a sort button as sys.behavior.focus-style names (ring or glow); a platform that cannot draw a choice SHALL fall back to the first value and state that in its README. A sort button's container has square corners, the header cell's, so sys.shape.corner-smoothing has nothing to ease on it. |
TBL-40 | THE table SHALL make a sort button's hit area its whole header cell, with no gap to the hit area of the header cell beside it. WHERE input is touch, or the platform cannot tell the input type, a header row that holds a sort button SHALL be at least sys.target.touch high, drawn so, at both densities, because a header cell cannot extend a hit area over the row under it; for a fine pointer it SHALL be at least sys.target.pointer high WHILE density is regular, and WHILE density is compact as high as its density gives. A header cell narrower than the target SHALL extend its hit area along the row no further than halfway into the paddings between it and the cell beside it. |
TBL-41 | THE table SHALL expose a sortable column's header cell as the column header it is (TBL-24) with the order its sort names — ascending, descending, or none for a column that can be sorted and is not — and the sort button inside it as a button named by the column's header; the sort mark SHALL be hidden from assistive technology. On the web these are aria-sort on the header cell and the product's own button in it. WHERE a platform has no sort state THE table SHALL say the order after the button's name with sortedAscendingLabel or sortedDescendingLabel, which come from the instance or from the product's words under the keys of the same names and from nowhere else; IF such a platform is given neither, THE table SHALL expose the button by its name alone and in debug builds report the missing word once. THE table SHALL NOT announce an order itself when it changes: the header cell's state says it, and a product that wants it spoken writes it in status (TBL-52). |
TBL-42 | WHILE selection is multiple or single THE table SHALL draw a selection column before its first column: in the header row a cell holding the checkbox for every row WHILE selection is multiple (TBL-45) and nothing WHILE it is single (TBL-60), in each body row that has a value a cell holding that row's control — a checkbox WHILE selection is multiple, a radio button WHILE it is single — and an empty cell in a body row without a value, in a placeholder row and in a footer row. Each checkbox is the Checkbox component and each radio button the Radio button component, as their own specs draw them, with no label drawn, placed on the cell's first line (TBL-15) with the edge of its box or ring, not of its round container, at the cell's padding, so that the boxes and rings stand on the line the text of the other cells starts at: the selection cell's paddings are a cell's paddings less half of what the control's container exceeds its box by — comp.checkbox.container.size over comp.checkbox.box.size, comp.radio-button.container.size over comp.radio-button.ring.size — (never less than 0), the round container reaching into them, and the column is as wide as the control's container and those paddings. The selection column is not a column of data: it has no header text, the first column of rowHeaders and of stickyFirstColumn is the one after it, and a sort event's index does not count it. WHILE stickyFirstColumn is true the selection column SHALL stay in view with the first column (TBL-20), and the two together are what is released when they would take more than half of the box. WHILE selection is none THE table SHALL draw no such column and no checkbox or radio button, SHALL ignore every row's selected, and SHALL emit no selectionChange. |
TBL-43 | WHILE selection is multiple or single and a body row's selected is true THE table SHALL draw that row as chosen: comp.table.row.selected.container.color across its whole width, paddings and the selection cell included, in place of the stripe of TBL-11 where the row would have one; the text of its cells and of its row header in comp.table.row.selected.text.color; and its checkbox or radio button checked. What a cell holds that is not plain text SHALL keep its own colors (TBL-15). In a column kept in view the fill SHALL lie over comp.table.sticky.container.color. The lines and the gap between rows (TBL-8, TBL-10) SHALL be drawn as without it. The fill SHALL change at once, without a motion of the table's own. A footer row and a placeholder row are never chosen. |
TBL-44 | WHEN the user changes a row's checkbox or radio button — by a press, by Space while it has focus, or, for a radio button, by an arrow key (TBL-61) — THE table SHALL set that row's selected to the control's new state, WHILE selection is single let the row that was chosen go (TBL-60), and emit selectionChange exactly once, carrying the values of every chosen row after the change in row order. A press on the row outside its selection cell presses its control where TBL-58 says so, and this sentence holds for that change as for any other. WHEN the product sets a row's selected THE table SHALL draw it and SHALL NOT emit. THE table SHALL keep which rows are chosen by their values: WHEN rows are given again in another order (TBL-33) each row SHALL be drawn chosen or not by its own selected, and the table SHALL carry no selection over to a row it is not given. |
TBL-45 | WHILE selection is multiple THE table SHALL keep the checkbox for every row in step with the body rows it holds that have a value: checked WHILE each of them is chosen, in its mixed (indeterminate) state WHILE some are and some are not, unchecked WHILE none is, and disabled WHILE there is no such row. WHEN the user activates it while it is unchecked or mixed THE table SHALL choose every such row, and while it is checked SHALL clear every one, and SHALL emit selectionChange exactly once with the values after the change. "Every row" is every row the table has been given: it SHALL NOT claim to choose records the product has not given it (the rows of other pages), and a product that offers that says so with a control of its own. WHILE selection is single there is no such checkbox (TBL-60). |
TBL-46 | THE table SHALL name each row's checkbox or radio button by that row's selectLabel; WHERE selectLabel is empty and rowHeaders is true the control SHALL be named by the text of the row's header cell; IF it has neither THE table SHALL expose the control without a name and in debug builds report the row once per table. WHILE selection is multiple THE table SHALL name the checkbox for every row by selectAllLabel, from the instance or from the product's words under the key selectAllLabel and from nowhere else; IF neither gives it THE table SHALL still draw the checkbox, expose it without a name and in debug builds report the missing word. A table whose selection is multiple or single SHALL still be exposed as a table (TBL-24), its rows as rows and its selection cells as cells: which rows are chosen is said by the checked state of their checkboxes or radio buttons, the header checkbox says checked, mixed or not checked, and the table SHALL add no selected state to a row and no role of a grid. |
TBL-47 | THE table SHALL make each sort button and each checkbox its own stop in the focus order, and the radio buttons of a table whose selection is single one stop together (TBL-61), in reading order — the scroll region first while the table scrolls (TBL-22), then the header row's controls from the start, then each row's checkbox, or the one radio button that is the stop, followed by whatever in that row's cells takes focus — and SHALL handle no key that moves focus from cell to cell: the arrow keys scroll the region or do what the focused control does with them, which for a radio button is TBL-61. A checkbox's or radio button's hit area SHALL be its whole selection cell, in width and in height; for a pointer the rest of its row answers too (TBL-58). WHERE input is touch, or the platform cannot tell the input type, a row that holds a checkbox or a radio button SHALL be at least sys.target.touch high, drawn so, at both densities, and its selection cell at least sys.target.touch wide; for a fine pointer the row SHALL be at least sys.target.pointer high WHILE density is regular, and WHILE density is compact as high as its density gives. |
TBL-48 | WHILE the table has no body row, loading is false and the empty slot has content THE table SHALL draw that content in the place of the body rows: under the header row and its line, before any footer row, as wide as the table's box and staying in view while the columns scroll sideways, with comp.table.empty.padding-block above and below it and a cell's inline padding at its sides (TBL-4), with no line, no stripe and no fill of the table's through it. THE table SHALL expose it as one row holding one cell that spans every column, SHALL add no word, glyph or role of its own to it, and SHALL NOT announce it (TBL-25): where a search or a filter emptied the table, the product's Empty state is the live one. WHILE the table has no body row and the empty slot has no content THE table SHALL draw its caption, its header row and its footer rows and nothing between them. WHILE the table has a body row THE table SHALL NOT draw the empty slot's content. |
TBL-49 | WHILE loading is true THE table SHALL be exposed as busy; SHALL draw the rows it is given as they are — the rows it had, or placeholder rows (TBL-50) — and SHALL NOT draw the empty slot's content, even with no body row; SHALL keep its header row, its sort buttons, its checkboxes, its radio buttons and its status line working as without it; SHALL change no color, no opacity and no size of its own because of it; and SHALL announce nothing itself when loading begins or ends: the product says it in status (TBL-52). THE table SHALL fetch nothing, wait for nothing and time nothing: loading is true for as long as the product says so. |
TBL-50 | WHERE a row's placeholder is true THE table SHALL draw it as a body row — counted for stripes, parted from its neighbours as TBL-9 says, with a cell's paddings — at least as tall as a body row holding one line of text at the table's density, however little its cells hold; SHALL place in each cell what the product gives it there (a Skeleton, by TBL-15) or nothing; SHALL draw no checkbox or radio button in its selection cell and count it neither as a body row for the header checkbox (TBL-45) nor as a row for the empty slot (TBL-48); and SHALL hide the row from assistive technology, so that a person hears that the table is busy and not a row of nothing. IF a row's placeholder is true while loading is false THE table SHALL draw it all the same and in debug builds report it. |
TBL-51 | WHERE status is not empty or the pagination slot has content THE table SHALL draw a status line under its last row: the status text at the start edge in comp.table.status.text.typescale and comp.table.status.text.color, the pagination slot's content at the end edge, both centered on the line's height, with comp.table.status.padding-block above and below, a cell's inline padding at its sides (TBL-4) and at least comp.table.status.gap between the two; WHERE the two do not fit on one line THE table SHALL put the status text above the pagination, comp.table.status.gap apart, each at the start edge, and the text SHALL wrap and never be cut. The status line SHALL be as wide as the table's box and SHALL stay where it is while the columns scroll sideways (TBL-17). WHILE separation is divider THE table SHALL draw one line of comp.table.divider.thickness in comp.table.divider.color above it. WHILE the table scrolls its rows in its own box (TBL-18) the status line SHALL stay at the bottom of that box while the rows pass under it, filled with comp.table.sticky.container.color, with that line above it whatever the separation is while a row is under it. WHERE status is empty and the slot has no content THE table SHALL draw no status line and leave no room for one. |
TBL-52 | THE table SHALL expose the status text as a status that assistive technology is told of politely WHEN it changes, without moving focus, and SHALL tell it nothing when the text is first drawn with the table. THE table SHALL write no word into it and SHALL count nothing for it: how many rows there are, which of them are shown and how many are chosen are the product's to say, in its own language. THE table SHALL place the content of the pagination slot and SHALL NOT style it, give it keys or listen to it: the table shows the rows it is given, emits nothing about pages, and holds no page number and no page size. |
TBL-53 | WHERE the layout direction is right-to-left THE table SHALL draw the selection column at the right edge, before the first column; SHALL place a sort mark after its label on the left, and before it — on the right — in a column whose align is end; SHALL draw the status text at the right edge of the status line and the pagination at the left; and SHALL keep the selection column and a first column that stay in view at the right (TBL-27). The glyphs swap_vert, arrow_upward and arrow_downward show an order and not a direction of reading, and SHALL NOT be mirrored. The status text SHALL be laid out as text of its own direction (TBL-28). |
TBL-54 | WHERE the platform draws with a person's own forced colors THE table SHALL draw a sort button's label and mark in the platform's button-text color and its focus indicator in the platform's highlight color, SHALL keep the sorted column told from the others by its glyph alone, and, because the mode removes the fill of a chosen row, SHALL rely on the row's control — its checkbox, which the Checkbox draws checked in that mode, or its radio button, which the Radio button draws selected there — to say that the row is chosen; it SHALL draw the line above a status line kept in view in the platform's text color (TBL-30). |
TBL-55 | WHILE the text size is enlarged THE table SHALL grow a sort button's label and its mark's box with it, wrap the label inside its column where the column's wrap allows it and keep the mark on the label's last line, grow the status text and wrap it, keep the selection column as wide as its checkbox or radio button and paddings, and lay the status line out in two lines where one no longer fits (TBL-51); nothing of these SHALL be cut, and TBL-29 holds for a table with every one of them at a width of 320 points. |
TBL-56 | WHILE the system's icon set cannot yet draw a sort mark (its font is still loading) THE table SHALL draw nothing in the mark's box, never the glyph's name as text, SHALL keep the box, and SHALL draw the glyph once the set can; the sort button SHALL work all the same. |
TBL-57 | WHERE the platform draws the product's own elements and script does not run (the web) THE table SHALL still draw, from the product's markup alone, everything of TBL-32, TBL-33, TBL-42, TBL-43, TBL-48, TBL-50 and TBL-51 that is drawing: a sort button and the mark of the order the header cell names, the hover, focus and press of the button, the selection column, a chosen row, the empty content, placeholder rows and the status line; a sort button that is an anchor, and checkboxes and radio buttons that are the platform's own inside the product's form, SHALL work as the platform makes them work — radio buttons of one name exclude each other and share one stop without script (TBL-60, TBL-61). What needs script and is then absent: the events, a press on a row outside its checkbox or radio button and the row's hover and press (TBL-58, TBL-59), which are then not drawn, the header checkbox kept in step and choosing every row (TBL-45), the busy state where the product did not write it, keeping focus through a change of rows, and what TBL-22 already loses. Nothing SHALL be hidden that script would have to reveal. |
TBL-58 | WHILE selection is multiple or single, WHEN a body row that can be chosen (it has a value and a checkbox or radio button, TBL-42) is pressed and released outside its selection cell with the primary mouse button, a touch or a pen, without the pointer moving further than the platform's touch slop between the two, THE table SHALL press that row's control exactly as a press on the control does: a checkbox's row is chosen or let go, a radio button's row is chosen where it was not and stays chosen where it was (TBL-60), and selectionChange is emitted once where the choice changed (TBL-44). For a pointer the whole row is the control's hit area, the way a whole card answers a press while the controls inside it keep their own. THE table SHALL NOT press the control IF the press lands on or inside something in a cell that answers a press itself — a link, a button, a field, a select, a label, a summary, an editable element, an element with a tab index, an element with a widget role, a custom element that takes focus, or an element to which the product gave the pointer cursor where the row's own is not (the pointer the row shows for itself does not count) — which keeps its own behaviour; IF the release ends a text selection, that is, the selection is not empty and lies in the row once the press is released; IF the pointer moved further than the slop (a drag, a scroll); IF a modifier key (Control, Command, Shift, Alt or Option) is held or a button other than the primary is used; IF the press is the second or a later press of a multiple click; IF the product cancelled the click; or IF the press lands inside a table nested in a cell, whose rows are its own. A press in the selection cell is the control's (TBL-47). The header row, whose checkbox stands for every row, a footer row, a placeholder row and a body row without a value SHALL take no such press. The row SHALL get no role, no name, no focus stop, no selected state and no announcement of its own: the checkbox or radio button stays the one control of the row, which the keyboard and assistive technology reach as TBL-46, TBL-47 and TBL-61 say, and a press on the row is a larger target for the same action. WHERE the platform's row answers no press (on the web, without the element's script) the row SHALL show neither the pointer cursor nor a state, and a press there SHALL choose nothing. |
TBL-59 | WHILE selection is multiple or single and a fine pointer is over a body row that can be chosen where a press would be its control's — its selection cell, or its cells outside anything that answers a press itself (TBL-58) — THE table SHALL draw that row hovered, as one target — the chosen row of a table whose selection is single too, whose press is its radio button's even though it changes nothing, as the radio button itself answers a hover and a press while it is selected — across its whole width, paddings and the selection cell included: its fill in the hovered container color of the row's condition — selected WHILE the row is chosen, unselected otherwise; the default system mixes comp.table.row.selected.state-layer.color or comp.table.row.unselected.state-layer.color into that condition's resting fill — laid over what the row is filled with at rest (its stripe, the chosen fill, comp.table.sticky.container.color in a column kept in view) and short of the gap of TBL-10; the text of its cells in the hovered text color of its condition; and the pointer cursor. WHILE the pointer is over something in a cell that answers a press itself, that thing SHALL keep its own cursor, hover and press, and the row SHALL be drawn at rest. WHEN such a row is pressed by pointer, touch or pen where TBL-58 or TBL-47 makes the press its control's THE table SHALL draw the row pressed without delay and keep it so for at least sys.motion.duration.press-hold, even when the press ends sooner, answering as sys.behavior.pressed-feedback names: overlay draws the pressed container and text colors of the row's condition across the row; dim applies the table's pressed opacity to the whole row while its fill and text stay with the state under the press; none draws no answer; and ripple, which has no one box to grow in across the cells of a row, answers as overlay. The press SHALL end when the pointer leaves the row, moves further than the slop or is cancelled. The fills SHALL change at once, without a motion of the table's own, as the chosen fill does (TBL-43). The checkbox or radio button SHALL keep its own hover, focus and press; a key that presses it or moves to it SHALL NOT draw the row pressed, and its keyboard focus is shown by the control alone. Under forced colors the row's state fills are gone with the other fills (TBL-54). |
TBL-60 | WHILE selection is single THE table SHALL let one row at most be chosen: each body row that can be chosen holds a radio button in its selection cell (TBL-42), and the header row's selection cell SHALL hold nothing, because no control stands for every row; IF the product puts a control there THE table SHALL NOT draw it and in debug builds report it. The radio buttons of one table SHALL be one group whose options exclude each other (RAD-3): on the web the radio buttons of one name, the name the product gave them or, for those it gave none, one the table gives them. WHEN the user chooses a row that is not chosen — by a press on its radio button or on the row (TBL-58), by Space, or by an arrow key (TBL-61) — THE table SHALL set that row's selected, let the row that was chosen go, and emit selectionChange exactly once, carrying the value of the chosen row alone. WHEN the user activates the radio button of the chosen row, or presses that row, THE table SHALL keep the row chosen and SHALL NOT emit: a radio button is never cleared by its own activation (RAD-2), and a product that lets a person go back to no row chosen offers a control of its own for that, which clears selected. WHEN the product sets selected THE table SHALL draw it and SHALL NOT emit (TBL-44); IF more than one row says it is chosen THE table SHALL draw chosen the one whose selected the product set last — of several set at once, the first in row order — and let the others go without emitting, and in debug builds report several set at once. IF a body row's selection cell holds a checkbox WHILE selection is single, or a radio button WHILE it is multiple, THE table SHALL treat the row as one that cannot be chosen, SHALL NOT draw that control, and in debug builds report it. |
TBL-61 | WHILE selection is single THE table SHALL expose each row's radio button as a radio, checked or not, named as TBL-46 says, with its position among the table's radio buttons and their number, and SHALL wrap them in no radio group, give a row no selected state and add no role of a grid: a radio group cannot hold the rows of a table, and the table's name and the column the radio buttons stand in say what they choose. THE radio buttons SHALL be one stop in the focus order — the chosen row's, or, while no row is chosen, the first row's that can be chosen — at the place of that row's control in the reading order of TBL-47, and Tab SHALL leave them rather than move between them (RAD-5). WHILE one of them has keyboard focus, Down Arrow and Right Arrow SHALL move focus to the radio button of the next row that can be chosen and Up Arrow and Left Arrow to the previous one's, wrapping from the last to the first, and choose that row as TBL-60 says, with one selectionChange for each key; in a right-to-left layout Left Arrow and Right Arrow SHALL exchange what they do. THE table SHALL scroll its box so that a radio button that receives keyboard focus is in view beside a header row or a status line kept in view (TBL-36), and WHEN rows are given again focus SHALL stay with the radio button of the row of the same value (TBL-25). |
प्लैटफ़ॉर्म के अनुसार नामों का मिलान
पैरिटी का मतलब एक जैसे API नहीं है। हर प्लैटफ़ॉर्म एक ही कॉन्ट्रैक्ट को अपने तरीक़े से व्यक्त करता है।
| स्पेक | Web | SwiftUI | Jetpack Compose | Flutter | React Native |
|---|---|---|---|---|---|
| कंपोनेंट | tanrei-table | TanreiTable | TanreiTable | TanreiTable | Table |
caption · प्रॉपर्टी | caption | caption | caption | caption | caption |
label · प्रॉपर्टी | label | accessibilityLabel | contentDescription | semanticLabel | accessibilityLabel |
density · प्रॉपर्टी | density | density | density | density | density |
separation · प्रॉपर्टी | separation | separation | separation | separation | separation |
striped · प्रॉपर्टी | striped | striped | striped | striped | striped |
rowHeaders · प्रॉपर्टी | rowHeaders | rowHeaders | rowHeaders | rowHeaders | rowHeaders |
stickyHeader · प्रॉपर्टी | stickyHeader | stickyHeader | stickyHeader | stickyHeader | stickyHeader |
stickyFirstColumn · प्रॉपर्टी | stickyFirstColumn | stickyFirstColumn | stickyFirstColumn | stickyFirstColumn | stickyFirstColumn |
selection · प्रॉपर्टी | selection | selection | selection | selection | selection |
selectAllLabel · प्रॉपर्टी | select-all-label | selectAllLabel | selectAllLabel | selectAllLabel | selectAllLabel |
sortedAscendingLabel · प्रॉपर्टी | sorted-ascending-label | sortedAscendingLabel | sortedAscendingLabel | sortedAscendingLabel | sortedAscendingLabel |
sortedDescendingLabel · प्रॉपर्टी | sorted-descending-label | sortedDescendingLabel | sortedDescendingLabel | sortedDescendingLabel | sortedDescendingLabel |
loading · प्रॉपर्टी | loading | isLoading | loading | loading | loading |
status · प्रॉपर्टी | status | status | status | status | status |
sort · इवेंट | sort | onSort | onSort | onSort | onSort |
selectionChange · इवेंट | selectionchange | selection | onSelectionChange | onSelectionChanged | onSelectionChange |
| टिप्पणियाँ | Form: <tanrei-table> is a custom element with **no shadow root**, wrapped around a native <table> that stays in the light DOM — <tanrei-table><table><caption>…</caption><thead>…</thead><tbody>…</tbody><tfoot>…</tfoot></table></tanrei-table>. The native table is never given another display, so its semantics, a crawler's reading, copy and paste as a table and a screen reader's table navigation are the browser's own. The wrapper is the scroll box (display: block; overflow: auto; max-inline-size: 100%; the product limits its height with max-block-size). Everything drawn comes from one stylesheet, @tanrei/web/table.css, whose selectors start at tanrei-table and are wrapped in :where(); it styles the page without script (an element that is not yet defined is still an element), and the element adopts the same sheet into the root it is connected to, so it also works inside another component's shadow root. Props are attributes of the wrapper: density, separation, striped, row-headers, sticky-header, sticky-first-column, label. caption is the native <caption>; the caption attribute is a convenience that writes one. label becomes aria-label on the table. Script adds only what CSS cannot: while the wrapper overflows it sets tabindex="0", role="region" and aria-labelledby (the caption) or aria-label (TBL-22), and removes them when it does not; it sets data-more-start and data-more-end for the lines of TBL-21, writes the positions of the columns whose header names data-align or data-wrap on the wrapper (data-columns-end, -center, -nowrap; one rule per position places the cells and no cell is written to), gives first cells role="rowheader" where row-headers is set on a table whose body cells are <td> (Markdown), and releases a first column wider than half of the box (TBL-20). Without script the table is fully drawn, scrolls in its box, and keeps its sticky parts; it lacks the two edge lines and, in a browser that does not focus scrollers by itself, the focus stop. Sticky parts are position: sticky on the cells (inset-block-start: 0 on thead th, inset-inline-start: 0 on the first cell of each row) with border-collapse: separate and the lines drawn as cell borders, because collapsed borders do not travel with a sticky cell. The caption stays in place sideways with position: sticky; inset-inline-start: 0 and a width of the wrapper (100cqi). font-variant-numeric: tabular-nums on cells (TBL-4); unicode-bidi: plaintext per cell (TBL-28). Markdown: a renderer emits a bare <table>; the product wraps it at build time (a rehype step of a few lines, shown in the README) — Tanrei does not transform content. Inside .tanrei-prose the element is an island by its tag name (PRS-16). A cell that spans (colspan, rowspan) and a second header row keep working as HTML and are drawn with the same cell styles, but no fixture covers them. As built: the wrapper is a grid of one cell, not display: block, so that the two "there is more" lines are as tall as the table; the attributes the element writes are data-more-start, data-more-end, data-more-above, data-first-column-released, data-columns and the three positions above, and data-separation on the table; the region's aria-labelledby or aria-label is copied from the table's own name where the product named it natively. **Sorting, selection, empty, loading and status: proposed form, for the platform's agent to settle.** Everything new is the product's own markup inside the same <table>, drawn by table.css without script (TBL-57). Sorting: the stylesheet makes the control in a th[aria-sort] fill the cell (the cell's paddings move onto the control) and draws the mark as a generated glyph from the attribute; the element listens for the control's activation and emits sort (cancelable where the control is an anchor) with detail: { column, index, direction }; it never writes aria-sort. Selection: selection="multiple" on the wrapper; the header row's first cell is <td data-part="selection"> (a cell and not a header cell: a header without text is announced as an empty one) holding the checkbox for every row, which the element keeps checked, indeterminate or unchecked and disables with no row to choose, and names from select-all-label or the product's words (setWords({ selectAllLabel })); the element listens to change from the row checkboxes, writes data-selected, and emits selectionchange with detail: { values }. Neither checkbox is moved, wrapped or replaced. sorted-ascending-label and sorted-descending-label are accepted and not read: aria-sort is the browser's. Empty: the product writes <tbody><tr data-part="empty"><td colspan="…">…</td></tr></tbody> with its <tanrei-empty-state> inside; the stylesheet keeps the cell's content as wide as the box (100cqi) and in view sideways, as it does the caption, and the element corrects a colspan that is not the number of columns. Loading: the loading attribute; the element writes aria-busy on the table (a server may write it itself). Status: after the <table>, inside the wrapper, <div data-part="status"><p role="status">…</p> <nav class="tanrei-pagination">…</nav></div>; it is sticky at the inline start with the box's width, and at the block end, with the sticky fill; the status attribute is a convenience that writes the paragraph, as caption writes a caption. Coarse pointers get the taller header row and rows by @media (pointer: coarse). | Proposed spelling, for the platform's agent to settle. TanreiTable(caption:, columns: [TanreiTableColumn], density:, …) { TanreiTableRow { TanreiTableCell("…"); TanreiTableCell { TanreiTag("Beta", size: .small) } } }. Built on Grid and GridRow (columns sized from content, which is TBL-2) inside a ScrollView whose axes are the ones that overflow; a table of several hundred rows uses a LazyVStack of rows with column widths measured once from the header and a sample of rows. The platform's own Table is not used: it is a data table of its own look, with selection and sorting, and it collapses to its first column in a compact width. Sticky parts are pinned section headers (pinnedViews) for the header row and an overlaid first column whose offset follows the scroll. Accessibility: SwiftUI has no table container for custom views, so TBL-24's fallback applies — each row is an accessibility container in reading order, each cell's label is its column header followed by its content, header cells carry the header trait, and the scroll view is named by the caption. Sorting, selection, empty, loading and status: TanreiTableColumn(header:, value:, isSortable:, sort:), TanreiTable(selection: $values, onSort: { column, index, direction in … }) where selection is a binding to the set of chosen values, and rows take value:, selectLabel:, isPlaceholder:. A sortable header is a Button whose accessibility value is sortedAscendingLabel or sortedDescendingLabel (SwiftUI has no sort trait); the row's checkbox is TanreiCheckbox. The empty slot and the pagination slot are view builders (empty:, pagination:); the status text is posted as an announcement when it changes; isLoading sets nothing SwiftUI has a trait for, so placeholder rows are hidden and the status says it. Single selection (selection single, TBL-60, TBL-61): the row's control is the platform's Tanrei radio button in place of the checkbox, the header row holds none, and the product's selection holds one value at most. | Proposed spelling, for the platform's agent to settle. TanreiTable(columns = listOf(TanreiTableColumn("Price", align = End)), caption = …) { row { cell("…"); cell { TanreiTag("Beta", size = Small) } } }. Compose has no table layout: a custom Layout measures each column's least and preferred widths (intrinsics) and shares the width as TBL-2 says, inside horizontalScroll; a long table is a LazyColumn of rows with the widths measured from the header and the rows composed so far, and stickyHeader for the header row. Semantics: the container sets collectionInfo(rowCount, columnCount) and each cell collectionItemInfo(rowIndex, columnIndex), header cells are heading(), and each cell's content description is preceded by its column header, so TalkBack announces position and header. The scroll container is focusable and named by the caption. Sorting, selection, empty, loading and status: TanreiTableColumn(header, value = "price", sortable = true, sort = TanreiTableSort.Ascending), onSort = { column, index, direction -> }, selection = TanreiTableSelection.Multiple, rows as row(value = "a1", selected = …, selectLabel = …) with onSelectionChange = { values -> }; the product holds both states. A sortable header is Modifier.clickable(role = Role.Button) with stateDescription from sortedAscendingLabel or sortedDescendingLabel; the checkboxes are TanreiCheckbox (ToggleableState.Indeterminate for the header's); empty and pagination are composable slots; the status text is a polite liveRegion. Single selection (selection single, TBL-60, TBL-61): the row's control is the platform's Tanrei radio button in place of the checkbox, the header row holds none, and the product's selection holds one value at most. | Proposed spelling, for the platform's agent to settle. TanreiTable(caption: …, columns: [TanreiTableColumn(header: "Price", align: TanreiTableAlign.end)], rows: [TanreiTableRow(cells: [...])]). Built on the framework's Table widget with IntrinsicColumnWidth (flex for a column that wraps), inside a horizontal SingleChildScrollView in a Scrollbar; a long table uses a two-dimensional scroll view with pinned rows and columns for the sticky parts. The Material library's DataTable is not used: it brings its own look, sorting and selection, and reads a Material theme. Semantics: the table, row, cell and column-header roles where the framework version has them, and otherwise one Semantics per cell whose label is the column header followed by the content; the scroll view is a focusable region named by the caption. Sorting and selection: TanreiTableColumn(header:, value:, sortable:, sort:), onSort: (column, index, direction) {}, selection: TanreiTableSelection.multiple, TanreiTableRow(value:, selected:, selectLabel:, placeholder:) and onSelectionChanged: (values) {}; the product holds both states. A sortable header is an InkWell in Semantics(button: true, value: sortedAscendingLabel); the checkboxes are TanreiCheckbox with tristate for the header's; empty and pagination are widgets; the status text is Semantics(liveRegion: true); placeholder rows are in ExcludeSemantics. Single selection (selection single, TBL-60, TBL-61): the row's control is the platform's Tanrei radio button in place of the checkbox, the header row holds none, and the product's selection holds one value at most. | Proposed spelling, for the platform's agent to settle. <Table caption="…" columns={[{ header: "Price", align: "end" }]}><Table.Row><Table.Cell>…</Table.Cell></Table.Row></Table>. React Native has no table layout: rows are Views in a horizontal ScrollView (inside a vertical one, or a FlatList with stickyHeaderIndices for a long table), and column widths are measured in a first pass with onLayout and applied in a second, so the first frame of a large table is drawn after measuring. A first column that stays in view is a second column of cells drawn over the scroll view and kept in step with its vertical offset. There is no table role on either native platform: TBL-24's fallback applies — a row is one accessible group and each cell's accessibilityLabel is its column header followed by its content; header cells have accessibilityRole="header". Follows the app's direction where an ancestor's is not known. Sorting and selection: columns { header, value, sortable, sort }, onSort={({ column, index, direction }) => …}, selection="multiple", <Table.Row value selected selectLabel placeholder> and onSelectionChange={(values) => …}; the product holds both states. A sortable header is a Pressable with accessibilityRole="button" and accessibilityValue={{ text: sortedAscendingLabel }}; the checkboxes are Checkbox (accessibilityState={{ checked: "mixed" }} for the header's); empty and pagination are elements; the status text has accessibilityLiveRegion="polite" on Android and is posted with AccessibilityInfo.announceForAccessibility on iOS; accessibilityState={{ busy: true }} while loading. Single selection (selection single, TBL-60, TBL-61): the row's control is the platform's Tanrei radio button in place of the checkbox, the header row holds none, and the product's selection holds one value at most. |
टोकन
| टोकन | किसका एलियास | रिज़ॉल्व किया गया मान (लाइट) |
|---|---|---|
--tanrei-comp-table-caption-gap | sys.space.space100 | 8px |
--tanrei-comp-table-caption-text-color | sys.color.on-surface-variant | |
--tanrei-comp-table-cell-padding-block-compact | — | 6px |
--tanrei-comp-table-cell-padding-block-regular | — | 12px |
--tanrei-comp-table-cell-padding-inline-compact | sys.space.space150 | 12px |
--tanrei-comp-table-cell-padding-inline-regular | sys.space.space200 | 16px |
--tanrei-comp-table-cell-text-color | sys.color.on-surface | |
--tanrei-comp-table-divider-color | sys.color.outline-variant | |
--tanrei-comp-table-divider-thickness | sys.border.hairline | 1px |
--tanrei-comp-table-empty-padding-block | sys.space.space400 | 32px |
--tanrei-comp-table-focused-opacity | — | 1 |
--tanrei-comp-table-header-container-color | — | |
--tanrei-comp-table-header-gap | sys.space.space50 | 4px |
--tanrei-comp-table-header-icon-size | sys.icon.extra-small | 16px |
--tanrei-comp-table-header-icon-weight | sys.icon.mark.weight | 500 |
--tanrei-comp-table-header-text-color | sys.color.on-surface-variant | |
--tanrei-comp-table-hovered-opacity | — | 1 |
--tanrei-comp-table-motion-feedback-duration | sys.motion.role.feedback | 450ms |
--tanrei-comp-table-motion-state-duration | sys.motion.role.state.large | 250ms |
--tanrei-comp-table-motion-state-easing | sys.motion.easing.state | cubic-bezier(0.2, 0, 0, 1) |
--tanrei-comp-table-pressed-opacity | — | 1 |
--tanrei-comp-table-row-gap | sys.space.space50 | 4px |
--tanrei-comp-table-row-selected-container-color | sys.color.secondary-container | |
--tanrei-comp-table-row-selected-hovered-container-color | — | |
--tanrei-comp-table-row-selected-hovered-text-color | — | |
--tanrei-comp-table-row-selected-pressed-container-color | — | |
--tanrei-comp-table-row-selected-pressed-text-color | — | |
--tanrei-comp-table-row-selected-state-layer-color | comp.table.row.selected.text.color | |
--tanrei-comp-table-row-selected-text-color | sys.color.on-secondary-container | |
--tanrei-comp-table-row-unselected-container-color | — | |
--tanrei-comp-table-row-unselected-hovered-container-color | — | |
--tanrei-comp-table-row-unselected-hovered-text-color | — | |
--tanrei-comp-table-row-unselected-pressed-container-color | — | |
--tanrei-comp-table-row-unselected-pressed-text-color | — | |
--tanrei-comp-table-row-unselected-state-layer-color | comp.table.cell.text.color | |
--tanrei-comp-table-row-unselected-text-color | comp.table.cell.text.color | |
--tanrei-comp-table-separation | sys.behavior.separation | 0 |
--tanrei-comp-table-sort-container-color | — | |
--tanrei-comp-table-sort-focused-container-color | — | |
--tanrei-comp-table-sort-focused-icon-color | — | |
--tanrei-comp-table-sort-focused-label-color | — | |
--tanrei-comp-table-sort-focused-state-layer-color | — | |
--tanrei-comp-table-sort-hovered-container-color | — | |
--tanrei-comp-table-sort-hovered-icon-color | — | |
--tanrei-comp-table-sort-hovered-label-color | — | |
--tanrei-comp-table-sort-hovered-state-layer-color | — | |
--tanrei-comp-table-sort-icon-color | sys.color.on-surface-variant | |
--tanrei-comp-table-sort-label-color | comp.table.header.text.color | |
--tanrei-comp-table-sort-pressed-container-color | — | |
--tanrei-comp-table-sort-pressed-icon-color | — | |
--tanrei-comp-table-sort-pressed-label-color | — | |
--tanrei-comp-table-sort-pressed-state-layer-color | — | |
--tanrei-comp-table-sort-state-layer-color | comp.table.sort.label.color | |
--tanrei-comp-table-sorted-container-color | — | |
--tanrei-comp-table-sorted-focused-container-color | — | |
--tanrei-comp-table-sorted-focused-icon-color | — | |
--tanrei-comp-table-sorted-focused-label-color | — | |
--tanrei-comp-table-sorted-focused-state-layer-color | — | |
--tanrei-comp-table-sorted-hovered-container-color | — | |
--tanrei-comp-table-sorted-hovered-icon-color | — | |
--tanrei-comp-table-sorted-hovered-label-color | — | |
--tanrei-comp-table-sorted-hovered-state-layer-color | — | |
--tanrei-comp-table-sorted-icon-color | sys.color.on-surface | |
--tanrei-comp-table-sorted-label-color | sys.color.on-surface | |
--tanrei-comp-table-sorted-pressed-container-color | — | |
--tanrei-comp-table-sorted-pressed-icon-color | — | |
--tanrei-comp-table-sorted-pressed-label-color | — | |
--tanrei-comp-table-sorted-pressed-state-layer-color | — | |
--tanrei-comp-table-sorted-state-layer-color | comp.table.sorted.label.color | |
--tanrei-comp-table-status-gap | sys.space.space200 | 16px |
--tanrei-comp-table-status-padding-block | sys.space.space100 | 8px |
--tanrei-comp-table-status-text-color | sys.color.on-surface-variant | |
--tanrei-comp-table-sticky-container-color | sys.color.surface | |
--tanrei-comp-table-stripe-container-color | sys.color.surface-container-low | |
--tanrei-comp-table-caption-text-typescale | sys.typescale.body-small | 400 13px/1.5385 |
--tanrei-comp-table-cell-text-typescale-compact | sys.typescale.body-small | 400 13px/1.5385 |
--tanrei-comp-table-cell-text-typescale-regular | sys.typescale.body | 400 14px/1.5714 |
--tanrei-comp-table-header-text-typescale-compact | sys.typescale.label-small | 500 12px/1.3333 |
--tanrei-comp-table-header-text-typescale-regular | sys.typescale.label | 500 14px/1.4286 |
--tanrei-comp-table-status-text-typescale | sys.typescale.body-small | 400 13px/1.5385 |
फ़िक्स्चर
मानक रेंडरिंग। हर प्लैटफ़ॉर्म हर फ़िक्स्चर का स्नैपशॉट एक ही ID से लेता है, ताकि नतीजों की तुलना की जा सके।
density: regular (42)
basic
caption: Button sizes items: 6 label-only
label: Button sizes items: 6 long-cells
label: Properties of the button items: 7 requirements
label: Requirements of the checkout items: 5 totals
caption: Components by status and platform rowHeaders: true items: 11 no-header
label: Accessibility of the button rowHeaders: true items: 5 empty-cells
caption: Orders this week items: 8 tags
caption: Status by platform rowHeaders: true items: 10 centered
caption: What each plan includes rowHeaders: true items: 7 mapping
label: Names on each platform rowHeaders: true items: 10 striped
caption: Visits by region striped: true rowHeaders: true items: 10 separation-divider
caption: Button sizes separation: divider items: 6 separation-gap
caption: Button sizes separation: gap items: 6 separation-gap-striped
caption: Orders this week separation: gap striped: true items: 8 wide
caption: Visits by region items: 15 wide-sticky-column
caption: Visits by region rowHeaders: true stickyFirstColumn: true items: 15 sticky-header
caption: Releases stickyHeader: true items: 15 japanese
caption: 表の設定 items: 6 rtl
caption: الطلب direction: rtl items: 8 rtl-wide-sticky-column
caption: الزيارات حسب المنطقة rowHeaders: true stickyFirstColumn: true direction: rtl items: 13 ltr-cells-rtl
label: Names on each platform rowHeaders: true direction: rtl items: 10 sortable
caption: Products sortedAscendingLabel: sorted ascending sortedDescendingLabel: sorted descending items: 7 sorted-end
caption: Products by price sortedAscendingLabel: sorted ascending sortedDescendingLabel: sorted descending items: 7 sortable-mixed
caption: Products sortedAscendingLabel: sorted ascending sortedDescendingLabel: sorted descending items: 6 sortable-long-headers
caption: Response times sortedAscendingLabel: sorted ascending sortedDescendingLabel: sorted descending items: 6 selection
caption: Products rowHeaders: true selection: multiple selectAllLabel: Select all products items: 8 selection-all
caption: Products rowHeaders: true selection: multiple selectAllLabel: Select all products items: 7 selection-striped
caption: Products separation: gap striped: true selection: multiple selectAllLabel: Select all products items: 7 selection-sticky-column
caption: Visits by region rowHeaders: true stickyFirstColumn: true selection: multiple selectAllLabel: Select all regions items: 13 selection-single
caption: Featured product rowHeaders: true selection: single items: 8 sortable-selection
caption: Products rowHeaders: true selection: multiple selectAllLabel: Select all products sortedAscendingLabel: sorted ascending sortedDescendingLabel: sorted descending status: 2 of 4 selected items: 7 empty
caption: Products items: 3 slots: empty empty-selection
caption: Products selection: multiple selectAllLabel: Select all products sortedAscendingLabel: sorted ascending sortedDescendingLabel: sorted descending status: 0 of 0 items: 3 slots: empty header-alone
label: Keyboard items: 2 loading
caption: Products rowHeaders: true selection: multiple selectAllLabel: Select all products loading: true status: Loading items: 7 loading-placeholders
caption: Products selection: multiple selectAllLabel: Select all products loading: true status: Loading items: 8 status
caption: Products status: 4 products items: 7 status-pagination
caption: Products status: 1–4 of 132 items: 7 slots: pagination status-long
label: Products status: Showing products 1 to 4 of the 132 that… items: 7 slots: pagination japanese-data
caption: 商品 rowHeaders: true selection: multiple selectAllLabel: すべての商品を選択 sortedAscendingLabel: 昇順で並べ替え済み sortedDescendingLabel: 降順で並べ替え済み status: 4 件中 1 件を選択中 items: 7 rtl-sortable-selection
caption: المنتجات rowHeaders: true selection: multiple selectAllLabel: تحديد كل المنتجات sortedAscendingLabel: مرتب تصاعديًا sortedDescendingLabel: مرتب تنازليًا status: تم تحديد 1 من 3 direction: rtl items: 6 slots: pagination rtl-empty
caption: المنتجات status: 0 منتج direction: rtl items: 3 slots: empty density: compact (7)
compact
caption: Button sizes density: compact items: 6 compact-tokens
label: Tokens of the table density: compact items: 16 striped-compact-tokens
label: Tokens of the table density: compact striped: true items: 16 wide-sticky-column-striped
caption: Visits by region density: compact striped: true rowHeaders: true stickyFirstColumn: true items: 14 sortable-compact
label: Products density: compact sortedAscendingLabel: sorted ascending sortedDescendingLabel: sorted descending items: 7 selection-compact
label: Products density: compact selection: multiple selectAllLabel: Select all products items: 7 data
caption: Products density: compact rowHeaders: true stickyHeader: true selection: multiple selectAllLabel: Select all products sortedAscendingLabel: sorted ascending sortedDescendingLabel: sorted descending status: 1–4 of 132 · 1 selected items: 7 slots: pagination इससे जनरेट किया गया: specs/table.spec.json, tokens/comp/table.tokens.json, design/tokens/
टेबल उस डेटा के लिए इस्तेमाल करें जिसमें पंक्तियाँ और कॉलम हैं। चीज़ों को अगल-बग़ल रखने के लिए इसे इस्तेमाल न करें: सहायक तकनीक हर सेल के लिए पंक्तियाँ, कॉलम और हेडर पढ़कर सुनाती है, जो उस कॉन्टेंट के आसपास शोर है जो टेबल जैसा नहीं है। उसके लिए लेआउट इस्तेमाल करें।
कुंजियों और मानों की वह सूची जिसका कोई दूसरा आयाम नहीं है, टेबल से ज़्यादा डिस्क्रिप्शन लिस्ट के क़रीब है।
density |
टेक्स्ट की एक लाइन वाली पंक्ति | किसके लिए |
|---|---|---|
regular (डिफ़ॉल्ट) |
46 | वह टेबल जिसे व्यक्ति पढ़ता है: कुछ पंक्तियाँ, रैप होने वाले सेल। |
compact |
32 | वह टेबल जिस पर व्यक्ति नज़र दौड़ाता है: सैकड़ों पंक्तियाँ, आइडेंटिफ़ायर और मान। |
पंक्ति की अपनी कोई ऊँचाई नहीं होती। वह अपने सबसे ऊँचे सेल जितनी ऊँची होती है।
separation |
क्या बनाता है |
|---|---|
auto (डिफ़ॉल्ट) |
जो डिज़ाइन सिस्टम ने चुना है: डिफ़ॉल्ट सिस्टम में एक बारीक रेखा। |
divider |
पंक्तियों के बीच, हेडर पंक्ति के नीचे और फ़ुटर पंक्तियों के ऊपर एक बारीक रेखा। |
gap |
ख़ाली जगह, और कोई रेखा नहीं। |
striped बॉडी की हर दूसरी पंक्ति को एक हल्के रंग से भरता है। इसे एक जैसी बहुत-सी पंक्तियों वाली चौड़ी टेबल के लिए इस्तेमाल करें, जहाँ एक सिरे से दूसरे सिरे तक जाते हुए आँख अपनी पंक्ति खो देती है। इसे दोनों में से किसी भी separation के साथ मिलाया जा सकता है।
- कॉलम अपना साइज़ अपने कॉन्टेंट से लेते हैं। कॉलम कभी उस चीज़ से सँकरा नहीं होता जो उसमें टूट नहीं सकती, और लंबे टेक्स्ट वाला कॉलम वह जगह लेता है जो छोटे कॉलम छोड़ते हैं।
- टेक्स्ट रैप होता है और कभी काटा नहीं जाता। आइडेंटिफ़ायर बीच में नहीं टूटता; वह अपने कॉलम को चौड़ा कर देता है।
- संख्याओं वाले कॉलम को अंत की ओर सीध में रखें, ताकि अंक एक के नीचे एक आएँ। टेक्स्ट को शुरू की ओर रहने दें। बीच में सिर्फ़ उस निशान या अकेले शब्द को रखें जो हर पंक्ति में एक ही तरह का जवाब है।
- कॉलम को चौड़ाई ख़ुद तभी दें जब देनी ही पड़े (उसके हेडर सेल पर
style="width: …")। यह उस चौड़ाई की जगह ले लेती है जो कॉन्टेंट से मिलती।
- टेबल अपने ही बॉक्स में स्क्रॉल होती है, पेज कभी नहीं। बॉक्स के किनारे के साथ बनी एक बारीक रेखा बताती है कि उसके आगे और कॉलम हैं। उसके चारों ओर स्क्रॉल एरिया की ज़रूरत नहीं: वह अपने किनारे ख़ुद दिखाती है।
sticky-first-columnपहले कॉलम को नज़र में रखता है, जबकि बाक़ी उसके नीचे से स्क्रॉल होते हैं। जहाँ वह बॉक्स के आधे से ज़्यादा हिस्से को घेर लेता, वहाँ वह अपने आप छूट जाता है, इसलिए फ़ोन की स्क्रीन कभी उस कॉलम से नहीं भरती जो अपनी जगह रहता है।sticky-headerपंक्तियों के स्क्रॉल होते समय हेडर पंक्ति को नज़र में रखता है। यह वहाँ काम करता है जहाँ आपका लेआउट टेबल की ऊँचाई सीमित करता है (एलिमेंट परmax-block-size); यह पेज के साथ नहीं चलता।- जो टेबल पेज की सरफ़ेस के अलावा किसी सरफ़ेस पर है (कार्ड, डायलॉग) और अपनी हेडर पंक्ति या पहला कॉलम नज़र में रखती है, या जिसमें स्थिति पंक्ति है, वह
--tanrei-comp-table-sticky-container-colorको उस सरफ़ेस के रंग पर सेट करती है। ये भाग उसी रंग से भरे जाते हैं, ताकि उनके नीचे से गुज़रने वाली पंक्तियाँ और कॉलम उनके आर-पार न दिखें।
- कॉलम को वहाँ सॉर्ट करने लायक़ बनाएँ जहाँ व्यक्ति उसके सहारे कोई पंक्ति ढूँढेगा: कोई नाम, कोई तारीख़, कोई रक़म, कोई कैटेगरी। नोट का कॉलम ऐसा नहीं है।
- निशान सॉर्ट करने लायक़ हर कॉलम पर बनता है, सामान्य हालत में भी, ताकि टच स्क्रीन दिखाए कि कौन-से हेडर दबाए जा सकते हैं।
- एक समय में एक ही कॉलम सॉर्ट होता है। सॉर्ट की दूसरी कुंजी आपका अपना कंट्रोल है।
- जहाँ आप चाहते हैं कि नया क्रम बोला जाए, वहाँ उसे स्थिति पंक्ति में कहें (“क़ीमत के अनुसार सॉर्ट किया गया, सबसे ज़्यादा पहले”)। टेबल ख़ुद कुछ पढ़कर नहीं सुनाती।
- सॉर्ट करने लायक़ कॉलम वाली टेबल की हेडर पंक्ति regular डेंसिटी में कम से कम 44 ऊँची होती है, और टच के लिए दोनों डेंसिटी में 48।
- लोगों को पंक्तियाँ वहाँ चुनने दें जहाँ वे एक साथ कई रिकॉर्ड पर काम करते हैं: हटाना, एक्सपोर्ट करना, दूसरी जगह ले जाना। एक रिकॉर्ड के लिए क्रिया को उसकी पंक्ति में रखें।
- जहाँ जवाब एक रिकॉर्ड है (एक प्लान, एक पता, तुलना के लिए एक वर्ज़न), वहाँ एक पंक्ति का चयन (
single) इस्तेमाल करें। रिकॉर्ड खोलने के लिए इसका इस्तेमाल न करें। - पंक्ति पर कहीं भी दबाने से वह चुनी जाती है। अगर पंक्ति से उसका रिकॉर्ड भी खुलना हो, तो उसके लिए पंक्ति के हेडर में एक लिंक रखें, पूरी पंक्ति को दबाना नहीं।
- कितनी पंक्तियाँ चुनी गई हैं, यह स्थिति पंक्ति में बताएँ (“132 में से 3 चयनित”)। टेबल कुछ नहीं गिनती।
- चुनी गई पंक्तियों पर काम करने वाले बटन टेबल के ऊपर रखें। वे आपके हैं; टेबल आपको बताती है कि क्या चुना गया है।
- “सभी 132” अपने किसी कंट्रोल से दें। हेडर का चेकबॉक्स वे पंक्तियाँ चुनता है जो टेबल को दी गई हैं, दूसरे पेजों की पंक्तियाँ कभी नहीं।
- हर चेकबॉक्स फ़ोकस के क्रम में एक पड़ाव है। एक पेज में उतनी ही पंक्तियाँ रखें जितनी से व्यक्ति Tab कुंजी दबाते हुए गुज़र सके, और बाक़ी को पेजों में बाँटें। एक टेबल के रेडियो बटन मिलकर एक ही पड़ाव हैं।
- जिस पंक्ति में चेकबॉक्स या रेडियो बटन है, वह regular डेंसिटी में कम से कम 44 ऊँची होती है, और टच के लिए दोनों डेंसिटी में 48। compact पंक्ति पॉइंटर के लिए compact ही रहती है।
- टैग और इनलाइन कोड तब तक tonal रहते हैं जब तक आप कोई दूसरा वेरिएंट न चुनें, और डिफ़ॉल्ट सिस्टम में tonal फ़िल क़रीब-क़रीब चुनी गई पंक्ति के फ़िल जैसा है, इसलिए चुनी गई पंक्ति पर उनका आकार खो जाता है। उनका टेक्स्ट पढ़ने लायक़ रहता है। जिस टेबल की पंक्तियाँ चुनी जाती हैं, उसमें outlined टैग इस्तेमाल करें।
- पहली बार लोड होते समय प्लेसहोल्डर पंक्तियाँ इस्तेमाल करें, क़रीब उतनी जितनी पंक्तियों की आपको उम्मीद है।
- क्रम या पेज बदलते समय पंक्तियाँ रहने दें। जो पंक्तियाँ व्यक्ति पढ़ रहा है, उनकी जगह प्लेसहोल्डर पंक्तियाँ या लोडिंग इंडिकेटर न रखें।
- स्थिति पंक्ति में “लोड हो रहा है” कहें, और जब लोड होना पूरा हो जाए तो बताएँ कि क्या आया (“132 में से 1–20”)।
loadingहटाते समय प्लेसहोल्डर पंक्तियाँ भी हटा दें। जो रह जाती है, वह फिर भी बनती है, और डीबग बिल्ड में रिपोर्ट की जाती है।
- बिना पंक्तियों की टेबल के लिए ख़ाली स्टेट इस्तेमाल करें, और बताएँ कि पंक्तियाँ क्यों नहीं हैं और आगे क्या करना है। जो ख़ाली स्टेट किसी खोज या फ़िल्टर का जवाब है, वह
liveहोता है, ताकि नतीजा बताया जाए। - स्थिति पंक्ति को उसके लिए रखें जो टेबल अभी दिखा रही है: कितनी पंक्तियाँ हैं और उनमें से कौन-सी दिखाई गई हैं। पंक्तियों पर काम करने वाले बटन टेबल के ऊपर रहते हैं।
- हर टेबल को नाम दें: एक कैप्शन जो सबको दिखता है, या जहाँ उसके ऊपर की हेडिंग पहले से बताती है कि वह क्या है, वहाँ
label। - जब भी पहला कॉलम बताता हो कि हर पंक्ति क्या है, उसे पंक्ति हेडर के रूप में लिखें (
<th scope="row">औरrow-headers)। - जहाँ कहने को कुछ नहीं है, वहाँ सेल ख़ाली छोड़ें। जहाँ न होना ही अपने आप में जानकारी है (“उपलब्ध नहीं”), वहाँ उसे लिखें।
- स्क्रीन का लेआउट बनाने के लिए टेबल इस्तेमाल न करें।
- अर्थ बताने के लिए धारियों या रंग पर निर्भर न रहें। सेल में स्थिति एक शब्द है, या ऐसा टैग जिसका लेबल उसे बताता है।
- ख़ाली सेल को भरने के लिए उसमें डैश न रखें।
- पंक्ति को दबाने लायक़ न बनाएँ, और हेडर में सॉर्ट का अपना निशान या अपना क्रम न लिखें। हेडर ऊपर दिए मार्कअप से ही दबाने लायक़ बनता है, और किसी चीज़ से नहीं। पंक्ति अपने चेकबॉक्स या रेडियो बटन से चुनी जाती है, और खुलने वाली पंक्तियाँ टेबल का हिस्सा नहीं हैं।
- टेबल के लोड होते समय उसे धुँधला या अक्षम न करें।
- रोल
table- लेबलिंग
- The table is named by its caption, or by label where no caption is drawn (TBL-23). Header cells name their columns and, while rowHeaders is true, first cells name their rows; every cell is associated with both (TBL-24). While the table scrolls in its own box, that box is a region with the same name, so that a person who reaches it by keyboard hears what scrolls. A sortable column's button is named by the column's header, and the header cell carries the order (TBL-41). A row's checkbox or radio button is named by selectLabel, or by the row's header; the header row's checkbox by selectAllLabel (TBL-46). The radio buttons of a table are not wrapped in a radio group: each is exposed with its position among them (TBL-61). The status line is the product's sentence, told politely when it changes (TBL-52).
- न्यूनतम टार्गेट
- दिखने वाला आकार छोटा होने पर भी हिट एरिया न्यूनतम टार्गेट साइज़ को पूरा करता है। minimum 32px · pointer 44px · spacing 8px · touch 48px
कीबोर्ड
| कुंजियाँ | क्रिया |
|---|---|
| Tab | Moves focus to the table's box while the table scrolls in it; then to each sortable column's header button, in reading order; then, row by row, to the row's checkbox where rows can be chosen — where one row at most is chosen, once to the chosen row's radio button, or the first row's while none is — and to whatever in its cells takes focus. A table that does not scroll, sorts nothing and selects nothing is not a stop. |
| Enter / Space | On a sortable column's header: asks for the rows in that column's order — ascending, or descending where they already ascend by it. Where the header is a link, Enter alone. |
| Space | On a row's checkbox: chooses the row or lets it go. On the header row's checkbox: chooses every row, or lets every row go where all are chosen. On a row's radio button: chooses the row where it is not chosen; on the chosen row's, nothing. |
| Arrow keys | On a row's radio button: move to the next row's radio button (Down, and Right in a left-to-right layout) or the previous one's, wrapping, and choose that row. While the box has focus: scroll it. Left and right move the view left and right in either layout direction. |
| Page Up / Page Down, Home / End | While the box has focus: scroll it by a page, or to its beginning or end, as the platform scrolls a region. |
टिप्पणियाँ
- The table, its cells and every row that cannot be chosen take no input (TBL-16). What does — a sortable column's header, the checkboxes, a row that can be chosen (for a pointer), the scroll box — is a control, a larger target for one, or a region: a header's hit area is its whole cell and a checkbox's its whole selection cell, each at least the touch target high for touch at both densities (TBL-40, TBL-47); the compact density is lower than the pointer target, as a compact tree row is. What is pressable inside a cell (a link, a button) meets the minimum target by its own spec.
- A table is for data that has rows and columns. Do not use it to place things side by side: assistive technology announces rows, columns and headers for every cell, which is noise around content that is not tabular. Use the layout.
- Give every table a name (WCAG 1.3.1, 4.1.2): a caption that everyone sees is best; label is for a table whose heading already names it. A table that scrolls and has no name is a focus stop a person cannot tell from any other, so debug builds report it (TBL-23).
- Header cells are structure, not style (WCAG 1.3.1). Every column has a header cell unless the table has no header row at all; rowHeaders is true whenever the first column says what each row is. A table with two levels of column headers, or cells that span columns or rows, is outside this spec: split it.
- A scrolling box must be reachable and operable by keyboard (WCAG 2.1.1) and its focus must be visible (2.4.7): TBL-22. It is a stop only while it scrolls, so short tables add nothing to the focus order.
- Reflow (WCAG 1.4.10) exempts data tables from two-dimensional scrolling, and the table uses that exemption carefully: only its own box scrolls sideways, never the page (TBL-17, TBL-29), and a first column that stays in view is released on a narrow window (TBL-20).
- Meaning never rests on color: stripes are an aid to the eye and say nothing; a status in a cell is a word, or a tag whose label says it. An empty cell is exposed as empty (TBL-14); where the absence itself is information ("not available", "none"), write it in the cell.
- Contrast in the default system: cell text is on-surface and header text on-surface-variant, each held to 4.5:1 on every surface and container step by the token invariants, the stripe included. The lines are decorative: rows, headers and the region are exposed without them.
- Alignment end for numbers is for sighted comparison only; it changes nothing that is exposed. Text is never justified and never centred except in a column the product sets to center.
- A table with checkboxes stays a table (TBL-46). The grid pattern — one stop for the whole table, arrow keys from cell to cell — is for a sheet whose cells are edited or acted on; it takes over the keys a screen reader uses to read a table, it would replace the roles of the product's own table on the web, and it cannot work without script. The price of staying a table is one Tab stop for each row's checkbox, which pagination keeps to a page of rows.
- Where a person chooses one record — the plan to change to, the address to ship to, the build to compare against — selection is single, and the selection column holds a radio button, as the single selection of Carbon's data table and of Ant Design's table does: a radio says that the choices exclude each other, and that one is answered once it is (TBL-60). A radio is never cleared by its own activation (HTML, WAI-ARIA APG radio group), so the table offers no way back to none: a product that needs it gives a control of its own. The radio buttons share one name and so behave as one radio group — one Tab stop, the arrow keys move the choice (TBL-61) — which also keeps a page of rows to one stop where checkboxes would be one each. They are not wrapped in an element of the radio group role, which cannot hold the rows of a table; each radio is heard with its row's name, its state and its position ("Select Kettle, radio button, checked, 3 of 4"), inside the table's name. The grid alternative, rows that carry aria-selected (React Aria's table, single selection mode), is declined for the reasons above.
- A press anywhere on a row that can be chosen presses its checkbox or radio button (TBL-58), as a press on a card or on a list item that can be chosen does: a larger target for a pointer (WCAG 2.5.8), not a second control. The row gets no role, no tab index and no selected state — ARIA allows aria-selected on a row only inside a grid or a treegrid — so that the keyboard and assistive technology meet the one control the row has, its named checkbox or radio button, and lose nothing. What a cell holds that answers a press (a link, a button, a field) keeps it, and a drag that selects text chooses nothing, so the text of a table can still be selected and copied.
- Sorting is asked for and shown, never done, by the table (TBL-33, TBL-34): the header cell says the order (WCAG 1.3.1, 4.1.2) and the mark repeats it to the eye without relying on color (1.4.1). One column is sorted at a time.
- A chosen row is said by its checkbox or radio button, checked; the fill is the same fact for the eye and is not relied on (WCAG 1.4.1), which is also what is left in forced colors (TBL-54). In the default system the text of a chosen row is on-secondary-container on a layer of that color over the surface, the pair a selected list item and a selected tree row are drawn in, held to 4.5:1 by the token invariants, and the fill stands 1.1:1 at least from a hovered row; the contrast of what a cell holds beside plain text on that fill is its own component's.
- Status messages (WCAG 4.1.3): the table announces nothing itself (TBL-25) and gives the product one polite place to say what changed — rows found, rows chosen, loading and loaded (TBL-52). An Empty state in the empty slot that answers a search or a filter is live by its own spec.
- While loading, the table is busy and placeholder rows are hidden (TBL-49, TBL-50), so that a person does not walk through rows of nothing. Do not take the rows a person was reading away for a spinner where they can stay.
- Focus is never lost to a change of rows (TBL-25) and a focused control is never left under a part kept in view (TBL-36; WCAG 2.4.11).
इससे जनरेट किया गया: specs/table.spec.json, tokens/sys/measure.tokens.json
- नेटिव टेबल एक टेबल ही रहती है: पंक्तियाँ, कॉलम हेडर, पंक्ति हेडर और सेल ब्राउज़र के अपने हैं, धारियों के साथ या उनके बिना, दोनों डेंसिटी में, स्क्रॉल होते समय, और तब भी जब कोई कॉलम या हेडर नज़र में रखा गया हो।
- कैप्शन टेबल को नाम देता है। उसके बिना
labelटेबल काaria-labelबन जाता है और दिखाया नहीं जाता। दोनों हों तो कैप्शन ही नाम है। - जब तक टेबल अपने बॉक्स में स्क्रॉल होती है, वह बॉक्स फ़ोकस के क्रम में एक पड़ाव है, अपने सेल की किसी भी चीज़ से पहले, और टेबल के नाम वाला एक रीजन। ऐरो कुंजियाँ, Page Up, Page Down, Home और End उसे स्क्रॉल करती हैं। जो टेबल स्क्रॉल नहीं होती, वह कोई पड़ाव नहीं जोड़ती।
- फ़ोकस रिंग बॉक्स के किनारे के भीतर बनती है, इसलिए कुछ भी उसे नहीं काटता।
- जहाँ टेबल के पहले सेल सादे
<td>हैं (रेंडर किया गया Markdown) औरrow-headersसेट है, वहाँ एलिमेंट उन्हें पंक्ति हेडर का रोल देता है। - दाएँ से बाएँ वाले लेआउट में कॉलम दाईं ओर से चलते हैं, स्क्रॉल दाईं ओर से शुरू होता है, अपनी जगह रहने वाला पहला कॉलम दाईं ओर होता है, और हर सेल का टेक्स्ट अपनी दिशा बनाए रखता है: कोई संख्या कभी उलटी नहीं होती।
- 200% टेक्स्ट पर कॉलम का साइज़ फिर से तय होता है, और जहाँ वे अब नहीं समाते, वहाँ टेबल अपने बॉक्स में स्क्रॉल होती है।
- फ़ोर्स्ड कलर्स में हर रेखा टेक्स्ट के रंग की होती है, और धारीदार टेबल अपनी पंक्तियों की रेखाएँ बनाती है, उसका separation जो भी हो, क्योंकि यह मोड फ़िल हटा देता है।
- सॉर्ट करने लायक़ कॉलम का हेडर सेल एक कॉलम हेडर है जो क्रम बताता है (
aria-sort), और उसमें आपके बटन का नाम हेडर के टेक्स्ट से आता है। निशान सहायक तकनीक से छिपा रहता है। - सॉर्ट बटन फ़ोकस के क्रम में एक पड़ाव है। Enter और Space उसे दबाती हैं; जहाँ वह लिंक है, वहाँ सिर्फ़ Enter। दबाने के बाद भी फ़ोकस उसी पर होता है। जहाँ आप पंक्तियों के साथ हेडर पंक्ति भी बदल देते हैं, वहाँ फ़ोकस उसी कॉलम के नए बटन पर जाता है।
- सॉर्ट बटन का फ़ोकस इंडिकेटर उसके हेडर सेल के भीतर बनता है, और कीबोर्ड से फ़ोकस किया गया बटन नज़र में रखे गए पहले कॉलम या स्थिति पंक्ति के नीचे से बाहर लाया जाता है।
- ख़ाली स्टेट की पंक्ति एक सेल वाली एक पंक्ति है। टेबल उसमें कोई रोल और कोई शब्द नहीं जोड़ती।
- स्थिति पंक्ति का पैराग्राफ़ एक status है: उसके टेक्स्ट का बदलना बिना टोके (polite) बताया जाता है, फ़ोकस हटाए बिना, और जब वह पहली बार बनता है तब कुछ नहीं बताया जाता।
- फ़ोर्स्ड कलर्स में सॉर्ट बटन का लेबल और निशान बटन के टेक्स्ट का रंग लेते हैं, और सॉर्ट किया गया कॉलम सिर्फ़ अपने तीर से पहचाना जाता है।
- स्क्रिप्ट के बिना भी सॉर्ट बटन, उनके निशान, ख़ाली स्टेट की पंक्ति और स्थिति पंक्ति वैसे ही बनते हैं, और सॉर्ट का लिंक काम करता है।
sortइवेंट को स्क्रिप्ट चाहिए। - जिस टेबल की पंक्तियाँ चुनी जा सकती हैं, वह फिर भी एक टेबल है। उसे grid का रोल नहीं मिलता, पंक्ति को चुने जाने का कोई स्टेट नहीं मिलता, और कोई कुंजी फ़ोकस को एक सेल से दूसरे सेल पर नहीं ले जाती। पंक्ति के चेकबॉक्स या रेडियो बटन का चेक किया हुआ स्टेट बताता है कि पंक्ति चुनी गई है।
- हेडर का चेकबॉक्स बताता है कि वह चेक किया हुआ है, चेक नहीं किया हुआ है, या अनिश्चित रहने पर मिला-जुला है, और तब तक अक्षम रहता है जब तक चुनने को कोई पंक्ति नहीं है।
- हर चेकबॉक्स फ़ोकस के क्रम में अपना अलग पड़ाव है: पहले हेडर पंक्ति का चेकबॉक्स और सॉर्ट बटन, फिर हर पंक्ति का चेकबॉक्स। Space उसे चेक करती है या उसका चेक हटाती है।
- पंक्ति के जिस चेकबॉक्स या रेडियो बटन का अपना कोई नाम नहीं है, उसका नाम उस पंक्ति के हेडर सेल से आता है।
singleमें रेडियो बटन मिलकर एक पड़ाव हैं: Tab चुनी गई पंक्ति के रेडियो बटन पर रुकता है (कोई पंक्ति चुनी न हो तो पहली पंक्ति के रेडियो बटन पर), और अगला Tab टेबल से बाहर ले जाता है। ऐरो कुंजियाँ अगली या पिछली पंक्ति के रेडियो बटन पर जाकर उस पंक्ति को चुनती हैं, और आख़िर पर पहुँचकर दूसरे सिरे से शुरू करती हैं। हर रेडियो बटन अपनी पंक्ति के नाम, अपने स्टेट और उनमें अपनी जगह के साथ सुनाई देता है, जैसे “टीम चुनें, रेडियो बटन, चेक किया हुआ, 3 में से 2”। वे किसी रेडियो ग्रुप में नहीं लपेटे जाते, क्योंकि रेडियो ग्रुप टेबल की पंक्तियों को नहीं समा सकता।- चयन सेल में कहीं भी दबाना उसके चेकबॉक्स को दबाता है। जब किसी चेकबॉक्स पर फ़ोकस रहते आप पंक्तियाँ बदलते हैं या उनका क्रम बदलते हैं, तो फ़ोकस उसी
data-valueवाली पंक्ति के चेकबॉक्स पर जाता है। - पॉइंटर के लिए चुनी जा सकने वाली पंक्ति उसके चेकबॉक्स का बड़ा लक्ष्य है। पंक्ति को न कोई रोल मिलता है, न फ़ोकस का पड़ाव, न चुनी हुई अवस्था, इसलिए कीबोर्ड और स्क्रीन रीडर पहले की तरह नाम वाले चेकबॉक्स तक पहुँचते हैं, और पंक्ति का टेक्स्ट अब भी चुना और कॉपी किया जा सकता है।
- फ़ोर्स्ड कलर्स में चुनी गई पंक्ति का फ़िल नहीं रहता, और चेकबॉक्स या रेडियो बटन फिर भी बताता है कि पंक्ति चुनी गई है।
- जब तक
loadingसेट है, टेबल सहायक तकनीक को व्यस्त के रूप में मिलती है (aria-busy)। प्लेसहोल्डर पंक्तियाँ सहायक तकनीक से छिपी रहती हैं, इसलिए व्यक्ति यह सुनता है कि टेबल व्यस्त है, ख़ाली पंक्तियाँ नहीं। लोड होना शुरू या ख़त्म होने पर टेबल ख़ुद कुछ पढ़कर नहीं सुनाती। - स्क्रिप्ट के बिना भी चयन कॉलम, चुनी गई पंक्ति (
data-selected, या चेक किया हुआ नेटिव चेकबॉक्स) और प्लेसहोल्डर पंक्तियाँ वैसे ही बनती हैं, और नेटिव चेकबॉक्स आपके फ़ॉर्म में काम करते हैं। हेडर के चेकबॉक्स को सिंक में रखने औरselectionchangeइवेंट को स्क्रिप्ट चाहिए। स्क्रिप्ट के बिना पंक्ति न होवर दिखाती है न पॉइंटर कर्सर, और चेकबॉक्स के बगल में दबाने से कुछ नहीं बदलता। - बिना नाम की टेबल, अनजान density, separation या selection, बॉडी से पहले दी गई फ़ुटर पंक्ति, कॉलम से ज़्यादा या कम सेल वाली पंक्ति, बिना हेडर का सॉर्ट करने लायक़ कॉलम, एक साथ सॉर्ट किए गए दो कॉलम, पंक्ति का बिना नाम का चेकबॉक्स, एक साथ चुनी हुई बताई गई कई पंक्तियाँ,
singleमें ग़लत तरह का कंट्रोल, और लोड न हो रही टेबल में प्लेसहोल्डर पंक्ति डीबग बिल्ड में रिपोर्ट किए जाते हैं।
- टेबल को नाम दें। जो टेबल स्क्रॉल होती है और जिसका कोई नाम नहीं है, वह फ़ोकस का ऐसा पड़ाव है जिसे व्यक्ति किसी दूसरे से अलग नहीं पहचान सकता।
- हर कॉलम को एक हेडर सेल दें, और पंक्ति हेडर को पंक्ति हेडर के रूप में चिह्नित करें। हेडर ढाँचा हैं, स्टाइल नहीं।
- जिस टेबल को कॉलम हेडर के दो स्तर चाहिए, या ऐसे सेल जो कई कॉलम या पंक्तियों में फैलते हैं, उसे जितना हो सके उतना सरल रखें। वे वैसे ही काम करते हैं जैसे HTML में, पर इस कंपोनेंट का कोई हिस्सा उन्हें ध्यान में रखकर डिज़ाइन नहीं किया गया है; टेबल को बाँट देना आम तौर पर ज़्यादा साफ़ रहता है।
- सेल के भीतर जो चीज़ दबाई जा सकती है (लिंक, बटन), वह अपना नाम, फ़ोकस और टार्गेट का साइज़ बनाए रखती है। उसे जगह दें।
- पंक्तियों को क्रम में रखने के बाद हेडर सेल पर नया
aria-sortलिखें: एक परascendingयाdescending, और सॉर्ट करने लायक़ बाक़ी परnone। जिस हेडर में कोई बटन नहीं है, उस पर यह ऐट्रिब्यूट न छोड़ें। - स्थिति पंक्ति के पैराग्राफ़ को तब भी पेज में रखें जब उसमें कोई टेक्स्ट न हो, ताकि आप उसे जो अगला टेक्स्ट दें, वह बताया जाए।
- हेडर के चेकबॉक्स को
select-all-labelसे नाम दें, और जहाँ टेबल में पंक्ति हेडर नहीं हैं, वहाँ हर पंक्ति के चेकबॉक्स को उसकेlabelसे। - लोड होना कब शुरू होता है और कब ख़त्म, यह स्थिति पंक्ति में बताएँ। यही वह अकेली जगह है जहाँ यह बदलाव बताया जाता है।
Tanrei अपना कोई शब्द साथ नहीं देता। टेबल आपसे एक शब्द माँगती है, हेडर के चेकबॉक्स का नाम: एलिमेंट पर select-all-label, या setWords() से selectAllLabel। बाक़ी दो आप अपने मार्कअप में लिखते हैं।
| शब्द | आप उसे कहाँ देते हैं |
|---|---|
| हेडर के चेकबॉक्स का नाम (“सभी प्रॉडक्ट चुनें”) | एलिमेंट पर select-all-label, या हर टेबल के लिए एक ही बार setWords({ selectAllLabel: 'सभी पंक्तियाँ चुनें' }) से। |
| पंक्ति के चेकबॉक्स या रेडियो बटन का नाम (“हैंड ग्राइंडर चुनें”) | पंक्ति के <tanrei-checkbox> या <tanrei-radio-button> पर label, या नेटिव कंट्रोल पर aria-label। पंक्ति हेडर हों तो आप इसे छोड़ सकते हैं: पंक्ति का हेडर चेकबॉक्स को नाम देता है। |
| स्थिति पंक्ति का वाक्य (“4 में से 2 चयनित”, “लोड हो रहा है”) | स्थिति पंक्ति का पैराग्राफ़, या जहाँ आप कोई पैराग्राफ़ नहीं लिखते, वहाँ एलिमेंट पर status। |
हेडर के चेकबॉक्स का नाम न हो, तो भी चेकबॉक्स बनता है और काम करता है, उसका कोई सुलभ नाम नहीं होता, और डीबग बिल्ड छूटे हुए शब्द की रिपोर्ट करता है।