नेविगेशन बार
कॉम्पैक्ट स्क्रीन के निचले किनारे से तीन से पाँच सबसे ऊपरी स्तर के गंतव्यों के बीच ले जाता है, और दिखाता है कि मौजूदा गंतव्य कौन-सा है।
- श्रेणी
- नेविगेशन
- टोकन
comp.navigation-bar- स्तर
- आधार
- Web
tanrei-navigation-barschedule - SwiftUI
TanreiNavigationBarschedule - Jetpack Compose
TanreiNavigationBarschedule - Flutter
TanreiNavigationBarschedule - React Native
NavigationBarschedule
- वे वेरिएंट जो इनमें शामिल नहीं
- cupertino: filled · m3-expressive-like: filled · m3-like: filled
इससे जनरेट किया गया: docs/status/status.json, specs/navigation-bar.spec.json
संशोधित स्पेक, जो अभी हर प्लैटफ़ॉर्म पर नहीं है
यह पेज नेविगेशन बार को वैसा बताता है जैसा स्पेक में वह अभी है, टैब की तर्ज़ पर। सक्रिय इंडिकेटर मौजूदा गंतव्य का बार में पूरा बराबर हिस्सा है, जो बार के किनारों से भीतर रखा गया है, न कि आइकन और लेबल से सटा हुआ कोई पिल। चयन बदलने पर वह अपने पूरे साइज़ में नए गंतव्य तक खिसकता है, और बार पर किया गया ड्रैग उसे पॉइंटर के साथ ले चलता है। होवर, दबाना और फ़ोकस उसी बॉक्स में बनाए जाते हैं। variant tonal (डिफ़ॉल्ट) और filled के बीच चुनता है। बाक़ी हर प्रॉपर्टी और इवेंट दोनों संशोधनों में एक जैसा है। ऊपर जिन प्लैटफ़ॉर्म पर “पीछे” लिखा है, वे बराबरी पर आने तक पहला संशोधन देते हैं: न variant, न ड्रैग, और सिर्फ़ आइकन के पीछे का इंडिकेटर जो अपने केंद्र से बढ़ता हुआ आता है, और उनके उदाहरण वही संशोधन दिखाते हैं। इस पेज के डेमो में वही वेब कंपोनेंट है जो आज दिया जाता है।
चार गंतव्य, जिनमें से एक पर गिनती है
filled वेरिएंट: इंडिकेटर को साथ ले चलने के लिए बार पर दबाएँ और ड्रैग करें
लिंक का बार: पेज अपने पते से मौजूदा गंतव्य का नाम लेता है, और सहायता नया टैब खोलती है
नेविगेशन बार में एक ही तरह का आइटम होता है, destination: एक आइकन, उसके नीचे एक लेबल, और आइकन पर एक वैकल्पिक बैज। हर प्लैटफ़ॉर्म गंतव्यों को वैसे ही लेता है जैसे वह दोहराए जाने वाले किसी भी चाइल्ड को लेता है: वेब पर <tanrei-navigation-bar-item> चाइल्ड एलिमेंट, SwiftUI के व्यू बिल्डर में TanreiNavigationBarItem व्यू, Compose के कॉन्टेंट लैम्ब्डा में TanreiNavigationBarItem कॉल, Flutter की destinations: लिस्ट में TanreiNavigationDestination ऑब्जेक्ट, और React Native पर सादे ऑब्जेक्ट का destinations ऐरे।
चयन बार का होता है, गंतव्य के मान से। value मौजूदा गंतव्य का नाम बताता है, change वह गंतव्य लाता है जो व्यक्ति ने चुना, और reselect तब फ़ायर होता है जब वह मौजूदा गंतव्य को दोबारा चुनता है, ताकि आप उस स्क्रीन को वापस सबसे ऊपर तक स्क्रॉल कर सकें। ख़ाली मान किसी को नहीं चुनता, उस स्क्रीन के लिए जो बार के गंतव्यों में से नहीं है। SwiftUI नया मान selection बाइंडिंग में लिखता है। दो प्लैटफ़ॉर्म अपना तरीक़ा रखते हैं, जैसा उनके अपने नेविगेशन बार करते हैं। Compose में बार के स्तर का कोई मान नहीं है: आप मौजूदा आइटम को selected चिह्नित करते हैं, और उसका onClick change और reselect दोनों का काम करता है। Flutter इंडेक्स से चुनता है: selectedIndex, और onDestinationSelected, जिसे वह मौजूदा गंतव्य के लिए भी कॉल करता है।
variant तय करता है कि मौजूदा गंतव्य कितना उभारकर दिखाया जाए: tonal (डिफ़ॉल्ट) उसके इंडिकेटर को हल्के से भरता है, और filled उसे गहरे रंग से भरता है, जिस पर आइकन और लेबल उलटे रंग में होते हैं। यह आज वेब पर है।
href वाला गंतव्य एक लिंक है: प्लैटफ़ॉर्म का अपना लिंक, जो ठीक बटन वाले गंतव्य की तरह बनता है। Enter उसे सक्रिय करती है और Space नहीं करती। बार दबाने पर लिंक को नहीं चुनता: वह गंतव्य के मान और उसके href के साथ change एमिट करता है, और फिर लिंक खोला जाता है। जो पेज खुलता है वही value के ज़रिए मौजूदा गंतव्य का नाम लेता है, जैसे नेविगेशन ड्रॉअर में, और बिना value वाला लिंक अपने href को अपना मान बना लेता है। target और targetLabel Button वाले ही हैं। लिंक वाले गंतव्य वेब पर बने हैं; SwiftUI, Compose, Flutter और React Native में वे अभी नहीं हैं।
गंतव्य का icon डिज़ाइन सिस्टम के आइकन फ़ॉन्ट के किसी ग्लिफ़ का नाम है। बार उसे अचयनित रहते आउटलाइन वाला और चयनित रहते भरा हुआ बनाता है। badge, badgeCount और badgeLabel आइकन पर Tanrei का बैज बनाते हैं: गिनती न हो तो एक बिंदु, वरना संख्या। SwiftUI, Compose और Flutter इन्हें एक TanreiNavigationBadge मान के रूप में लेते हैं, और React Native एक badge ऑब्जेक्ट के रूप में।
बार एक लेआउट रीजन है, ओवरले नहीं। उसका रंग अपने नीचे के होम इंडिकेटर या जेस्चर बार के नीचे तक पहुँचता है, और उसके गंतव्य उनके ऊपर और बग़ल के इनसेट के भीतर रहते हैं। React Native पर इनसेट सिर्फ़ प्रॉपर्टी से आते हैं, सेफ़ एरिया की किसी डिपेंडेंसी के बिना: TanreiProvider के insets, या बार के अपने insets, जिनकी ओर के मान प्रोवाइडर के मानों की जगह लेते हैं।
<!-- होस्ट एक नेविगेशन लैंडमार्क है जिसका नाम label से आता है। -->
<!-- variant="filled" मौजूदा गंतव्य को उलटे रंग में दिखाता है, भरी-भरी स्क्रीन के ऊपर के बार के लिए। Tonal डिफ़ॉल्ट है। -->
<tanrei-navigation-bar label="मुख्य" value="inbox">
<tanrei-navigation-bar-item value="inbox" label="इनबॉक्स" icon="inbox"
badge badge-count="3" badge-label="3 अपठित"></tanrei-navigation-bar-item>
<tanrei-navigation-bar-item value="chat" label="चैट" icon="chat"
badge badge-label="नए संदेश"></tanrei-navigation-bar-item>
<tanrei-navigation-bar-item value="starred" label="तारांकित" icon="star"></tanrei-navigation-bar-item>
<tanrei-navigation-bar-item value="settings" label="सेटिंग" icon="settings" disabled></tanrei-navigation-bar-item>
</tanrei-navigation-bar>
<script type="module">
import '@tanrei/web/components/navigation-bar';
const bar = document.querySelector('tanrei-navigation-bar');
// बार change फ़ायर करने से पहले अपना value ख़ुद सेट करता है, और change उसे साथ लाता है।
bar.addEventListener('change', (e) => showScreen(e.detail.value));
bar.addEventListener('reselect', () => scrollTo({ top: 0 }));
</script>
<!-- लिंक का बार: हर पेज value को अपने पते पर सेट करता है। बिना value वाला लिंक अपना href लेता है। -->
<tanrei-navigation-bar label="मुख्य" value="/search/">
<tanrei-navigation-bar-item href="/" label="होम" icon="home"></tanrei-navigation-bar-item>
<tanrei-navigation-bar-item href="/search/" label="खोज" icon="search"></tanrei-navigation-bar-item>
<tanrei-navigation-bar-item href="/library/" label="लाइब्रेरी" icon="video_library"></tanrei-navigation-bar-item>
<tanrei-navigation-bar-item href="https://example.com/help" label="सहायता" icon="help"
target="new" target-label="नए टैब में खुलता है"></tanrei-navigation-bar-item>
</tanrei-navigation-bar>
<script type="module">
// राउटर नेविगेशन अपने हाथ में लेता है: change रद्द करें, detail.href पर जाएँ, और बताएँ कि प्रॉडक्ट अब कहाँ है।
bar.addEventListener('change', (e) => {
if (!e.detail.href) return;
e.preventDefault();
router.push(e.detail.href);
bar.value = e.detail.value;
});
</script>import { NavigationBar, NavigationBarItem } from '@tanrei/react';
// भरी-भरी स्क्रीन के ऊपर के बार के लिए variant="filled"; tonal डिफ़ॉल्ट है।
<NavigationBar label="मुख्य" value={screen} onChange={(e) => setScreen(e.detail.value)} onReselect={scrollToTop}>
<NavigationBarItem value="inbox" label="इनबॉक्स" icon="inbox" badge badgeCount={3} badgeLabel="3 अपठित" />
<NavigationBarItem value="chat" label="चैट" icon="chat" />
<NavigationBarItem value="starred" label="तारांकित" icon="star" />
</NavigationBar>import Tanrei
// निचले सेफ़ एरिया इनसेट में अपना अलग बार। गंतव्य चुनने पर बाइंडिंग में लिखा जाता है (change)।
ScreenView(screen)
.safeAreaInset(edge: .bottom, spacing: 0) {
TanreiNavigationBar(selection: $screen, accessibilityLabel: "मुख्य", onReselect: { _ in scrollToTop() }) {
TanreiNavigationBarItem("इनबॉक्स", icon: "inbox", value: "inbox",
badge: TanreiNavigationBadge(count: 3, label: "3 अपठित"))
TanreiNavigationBarItem("चैट", icon: "chat", value: "chat")
TanreiNavigationBarItem("तारांकित", icon: "star", value: "starred")
// disabled SwiftUI का अपना मॉडिफ़ायर है।
TanreiNavigationBarItem("सेटिंग", icon: "settings", value: "settings").disabled(true)
}
}import io.github.chnotchy.tanrei.components.TanreiNavigationBadge
import io.github.chnotchy.tanrei.components.TanreiNavigationBar
import io.github.chnotchy.tanrei.components.TanreiNavigationBarItem
// Material के NavigationBar की तरह: बार के स्तर का कोई मान नहीं। आप मौजूदा आइटम को selected चिह्नित करते हैं,
// और एक ही onClick change और reselect दोनों है।
var screen by rememberSaveable { mutableStateOf("inbox") }
TanreiNavigationBar(contentDescription = "मुख्य") {
TanreiNavigationBarItem(
selected = screen == "inbox",
onClick = { if (screen == "inbox") { scrollToTop() } else { screen = "inbox" } },
icon = "inbox",
label = "इनबॉक्स",
badge = TanreiNavigationBadge(count = 3, contentDescription = "3 अपठित"),
)
TanreiNavigationBarItem(selected = screen == "chat", onClick = { screen = "chat" }, icon = "chat", label = "चैट")
// enabled स्पेक के disabled का उलटा है।
TanreiNavigationBarItem(selected = screen == "settings", onClick = { screen = "settings" }, icon = "settings", label = "सेटिंग", enabled = false)
}import 'package:tanrei/tanrei.dart';
// NavigationBar की तरह: गंतव्य का मान उसका इंडेक्स है। बार अपना कोई चयन नहीं रखता।
TanreiNavigationBar(
selectedIndex: current, // null किसी को नहीं चुनता
onDestinationSelected: (int index) {
if (index == current) {
scrollToTop(); // reselect
} else {
setState(() => current = index); // change
}
},
semanticLabel: 'मुख्य',
destinations: const <TanreiNavigationDestination>[
TanreiNavigationDestination(icon: 'inbox', label: 'इनबॉक्स', badge: TanreiNavigationBadge(count: 3, semanticLabel: '3 अपठित')),
TanreiNavigationDestination(icon: 'chat', label: 'चैट'),
TanreiNavigationDestination(icon: 'settings', label: 'सेटिंग', enabled: false),
],
),import { useState } from 'react';
import { NavigationBar } from '@tanrei/react-native';
const [screen, setScreen] = useState('inbox');
// कंट्रोल्ड: value को onValueChange से बदलें।
<NavigationBar
accessibilityLabel="मुख्य"
value={screen}
onValueChange={setScreen}
onReselect={scrollToTop}
destinations={[
{ value: 'inbox', label: 'इनबॉक्स', icon: 'inbox', badge: { count: 3, label: '3 अपठित' } },
{ value: 'chat', label: 'चैट', icon: 'chat', badge: { label: 'नए संदेश' } },
{ value: 'settings', label: 'सेटिंग', icon: 'settings', disabled: true },
]}
/>सिर्फ़ चयनित का लेबल, और कोई लेबल नहीं
संरचना
प्रॉपर्टी
| प्रॉपर्टी | टाइप | डिफ़ॉल्ट | विवरण |
|---|---|---|---|
value | string | "" | The value of the selected destination (selection is the bar's, by a destination's value). Empty selects none (the current screen is not one of the bar's destinations). |
variant | tonal | filled | "tonal" | How the active indicator is filled. Tonal: a soft container with the content in that container's own color. Filled: the strong color, with the content inverted on it, for a bar that must stand out from a busy screen. Tonal destinations are drawn from the unselected and selected conditions, filled ones from filled-unselected and filled-selected. The indicator's size and place are the same in both. |
labelVisibility | always | selected | never | "always" | Which destinations draw their label: all of them, only the selected one, or none. A label that is not drawn is still the destination's accessible name, and no item container changes size with it. |
label | string | "" | Names the bar itself for assistive technology ("Main"); on the web it names the navigation landmark. |
इवेंट
| इवेंट | विवरण |
|---|---|
change | The user activated a destination that is not the selected one, or released a drag of the active indicator on one; carries its value and, for a link, its href. For a link it comes before the link is followed, only for an activation that follows it in place (NVB-31), and a product that cancels it follows the link itself. |
reselect | The user activated the destination that is already selected (a product may scroll that screen to its top); carries its value and, for a link, its href, as change does. A drag that returns the indicator to it does not emit it. |
आइटम
वे आइटम के प्रकार जिन्हें कंपोनेंट दोहराता है। फ़िक्स्चर अपने आइटम क्रम से सूचीबद्ध करता है; हर प्लैटफ़ॉर्म हर प्रकार को अपने तरीक़े से नाम देता है।
destination
One top-level destination of the bar: an icon, a label under the icon, and optionally a badge on the icon.
| प्रॉपर्टी | टाइप | डिफ़ॉल्ट | विवरण |
|---|---|---|---|
value | string | "" | What identifies the destination. The bar's value selects the destination whose value equals it; change and reselect carry it. Unique within the bar. Empty on a link, its href stands as its value. |
href | string | "" | The address the destination leads to. Not empty, the destination is a link and not a button (NVB-30): it is followed as the platform follows a link, and the bar does not select it by itself (NVB-31). Empty, the destination is a button and the product moves on change. As the Button's href (a control with a destination is a link). |
target | same | new | "same" | Where a link opens, as the Button's target. same: where the person is. new: a new context — a new tab or window on the web, outside the current screen elsewhere — which a bar's cell has no place to mark and says through targetLabel (NVB-32). A link that opens elsewhere is never selected by a press (NVB-31). Ignored without href. |
targetLabel | string | "" | What assistive technology reads after the link's name while target is new ("opens in a new tab"), as the Button's targetLabel: Tanrei ships no words of its own. Required while target is new; ignored otherwise. |
label | string | "" | Its name, drawn under the icon (see the bar's labelVisibility) and always its accessible name. Required. |
icon | string | "" | The name of its glyph in the system's icon set, drawn in the destination's own icon style: outlined while unselected, filled while selected. Required. |
disabled | boolean | false | Makes it unavailable. It keeps its place, draws its disabled look, cannot be activated and leaves the focus order. |
badge | boolean | false | Draws a Tanrei badge (the badge component) on the icon, from badgeCount and badgeLabel. |
badgeCount | number | null | The badge's count, as the badge component's count: null draws the dot, 0 draws nothing, above 0 the number (above 999 as 999+). Ignored while badge is false. |
badgeLabel | string | "" | The badge's label, as the badge component's: what assistive technology reads after the destination's name and state ("3 unread"). A dot needs one. Ignored while badge is false. |
| स्पेक | Web | SwiftUI | Jetpack Compose | Flutter | React Native |
|---|---|---|---|---|---|
| आइटम | tanrei-navigation-bar-item | TanreiNavigationBarItem | TanreiNavigationBarItem | TanreiNavigationDestination | NavigationBarDestination |
value · प्रॉपर्टी | value | value | selected | destinations | value |
href · प्रॉपर्टी | href | destination | href | href | href |
target · प्रॉपर्टी | target | target | target | target | target |
targetLabel · प्रॉपर्टी | targetLabel | targetLabel | targetLabel | targetSemanticLabel | targetLabel |
label · प्रॉपर्टी | label | title | label | label | label |
icon · प्रॉपर्टी | icon | icon | icon | icon | icon |
disabled · प्रॉपर्टी | disabled | disabled | enabled | enabled | disabled |
badge · प्रॉपर्टी | badge | badge | badge | badge | badge |
badgeCount · प्रॉपर्टी | badgeCount | count | count | count | count |
badgeLabel · प्रॉपर्टी | badgeLabel | label | contentDescription | semanticLabel | label |
| टिप्पणियाँ | icon is the glyph's name, as <tanrei-tab>'s. badgeCount and badgeLabel are the badge-count and badge-label attributes; the element draws a <tanrei-badge> around the glyph from them. href is the spec's own prop: the cell is an <a href> in the item's shadow root. target is the target attribute with the values same and new (the HTML spellings _self and _blank are read as those two), targetLabel the target-label attribute, and rel (to which new adds noopener) and download are web-only and forwarded to the anchor, all as <tanrei-button>'s. Space is not handled on it. With no value attribute the item's value property reads its href attribute as written (not the resolved URL). | TanreiNavigationBarItem(_ title: String, icon: String, value: Value, badge: TanreiNavigationBadge? = nil), where icon is the glyph's name and TanreiNavigationBadge(count: Int? = nil, label: String = "") is drawn with .tanreiBadge(…) on the glyph (no badge is nil). disabled follows .disabled(_:) on the item. destination: URL? = nil makes it a link (the link trait beside the item's selected trait), opened by the environment's openURL after the selection callback, which an app that routes addresses itself answers with its own OpenURLAction; the binding is not written for it. target: TanreiLinkTarget = .same and targetLabel (the accessibility hint), as the Button's. | TanreiNavigationBarItem(selected, onClick, icon = "inbox", label = "…", enabled = true, badge = null) in the bar's RowScope content lambda. enabled is the inverse flag. badge: TanreiNavigationBadge? with TanreiNavigationBadge(count: Int? = null, contentDescription: String = ""); the item draws a TanreiBadge around its icon from it. icon is the glyph's name; the item draws it in the selection's icon style. href: String? = null makes it a link: opened through LocalUriHandler.current after onClick (an app that routes addresses itself provides its own UriHandler); the item keeps Role.Tab, which Compose cannot join with a link role. target: TanreiLinkTarget = TanreiLinkTarget.Same, and targetLabel is appended to the state description, as the Button's. | TanreiNavigationDestination(icon:, label:, enabled: true, badge: null) in the bar's destinations: list; its value is its index there. icon is the glyph's name. badge: TanreiNavigationBadge(count:, semanticLabel:), drawn as a TanreiBadge around the icon. enabled: false disables it. href: Uri? = null makes it a link (Semantics(link: true) with the address as its linkUrl, beside the tab semantics), opened by the nearest TanreiLinkOpener after onDestinationSelected; target is a TanreiLinkTarget and targetSemanticLabel the semantics hint, as the Button's. | An entry of destinations: NavigationBarDestination[]: { value, label, icon, disabled?, badge? }, where icon is the glyph's name and badge?: { count?: number | null; label?: string } (absent is no badge) is drawn as a Badge around the icon. href?: string makes it a link: the destination keeps the tab role (React Native gives an element one role), onValueChange receives the value and the href, and Linking.openURL(href) follows it unless the product handles it; target is "same" | "new" and targetLabel the accessibilityHint, as the Button's. |
स्टेट
व्यवहार
EARS रूप में लिखी गई आवश्यकताएँ। हर प्लैटफ़ॉर्म के इम्प्लीमेंटेशन को इन ID के आधार पर टेस्ट किया जाता है। आवश्यकताओं का पाठ स्पेक फ़ाइल से ज्यों का त्यों, अंग्रेज़ी में दिखाया गया है।
| ID | आवश्यकता |
|---|---|
NVB-1 | WHEN the user activates a destination by pointer, touch, Enter or Space (Enter only for a destination that is a link, and for a link only an activation that NVB-31 counts) THE navigation bar SHALL emit change exactly once with the destination's value WHILE it is not the selected destination, and reselect exactly once with its value WHILE it is. |
NVB-2 | WHILE a destination's disabled is true THE navigation bar SHALL NOT emit change or reselect for it, SHALL NOT make it focusable and SHALL expose it as disabled to assistive technology. |
NVB-3 | THE navigation bar SHALL draw the destination whose value equals the bar's value from its variant's selected condition and every other destination from its variant's unselected condition: WHILE variant is tonal the selected condition is selected (comp.navigation-bar.selected.item.container.color, comp.navigation-bar.selected.item.icon-indicator.color, comp.navigation-bar.selected.item.icon.color, comp.navigation-bar.selected.item.label.color, comp.navigation-bar.selected.item.covered-icon.color, comp.navigation-bar.selected.item.covered-label.color) and the unselected condition is unselected; WHILE variant is filled they are filled-selected (comp.navigation-bar.filled-selected.item.container.color and the same parts) and filled-unselected. IF no destination's value equals a value that is not empty THE navigation bar SHALL draw every destination from its variant's unselected condition, and in debug builds report the value. |
NVB-4 | WHILE a destination is hovered, keyboard-focused or pressed THE navigation bar SHALL render its item container, icon indicator, icon, label, covered icon and label, and opacity from the component tokens of its condition 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. |
NVB-5 | WHEN a destination receives keyboard focus THE navigation bar SHALL show the focus indicator (the ring or the glow, NVB-10) around its item container (NVB-12), concentric with it and in its shape, with its inner edge sys.focus.offset outside the container's edge, and SHALL hold it inside the bar: WHERE the space between the item container and the bar's edges (comp.navigation-bar.container.padding) is less than the indicator reaches, it SHALL be drawn further in by the difference, on every side alike, keeping the container's shape. THE indicator SHALL be drawn above the neighbouring destinations and the active indicator, without animation; focus gained by pointer or touch SHALL NOT show it. |
NVB-6 | THE navigation bar SHALL make each destination's hit area its whole cell, the bar's full height above the system inset and its share of the bar's width (NVB-11), the first and the last cell reaching the bar's start and end edges, and SHALL NOT let a cell's hit area fall below sys.target.touch in either direction; hover and press over any part of the cell SHALL answer on the item container. WHERE an equal share of the bar's width is narrower than sys.target.touch (more destinations than the width holds), the cells SHALL still share the bar's width and narrow below the target rather than make the bar wider than the space it is given. |
NVB-7 | WHILE a destination's disabled is true THE navigation bar SHALL render its item container, icon indicator, icon, label, covered icon and label, and opacity from the disabled component tokens of its condition. |
NVB-8 | WHEN a destination is pressed by pointer, touch, Enter or Space THE navigation bar SHALL show its pressed state without delay and SHALL keep it visible for at least sys.motion.duration.press-hold, even when the press ends sooner. |
NVB-9 | WHILE a destination is pressed THE navigation bar SHALL answer as sys.behavior.pressed-feedback names: overlay applies the pressed tokens to the whole item container at once; ripple grows the pressed state layer, clipped to the item container, from the point of contact (from the center for keyboard activation); dim applies the pressed opacity to the whole destination and draws no state layer; none draws no answer to the press. Under ripple and dim only the item container color stays with the state under the press; icon indicator, icon, label, covered icon and label, and opacity still come from the pressed tokens. Under none every part stays with the state under the press. The ripple grows over comp.navigation-bar.motion.feedback-duration with comp.navigation-bar.motion.state-easing, fades over comp.navigation-bar.motion.state-duration with comp.navigation-bar.motion.state-easing once the press has ended and press-hold has passed, and appears whole where motion is reduced. |
NVB-10 | THE navigation bar SHALL ease its item container and icon indicator corners by sys.shape.corner-smoothing (0 is a quarter circle, 0.6 the iOS continuous corner; a platform with only the OS curve draws it for any amount above 0) and show its keyboard focus 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. |
NVB-11 | THE navigation bar SHALL span the full width of its parent, at least comp.navigation-bar.container.height high above the system inset, filled with comp.navigation-bar.container.color, raised by comp.navigation-bar.container.elevation and edged at the top by comp.navigation-bar.outline.width of comp.navigation-bar.outline.color, and SHALL divide its width, less comp.navigation-bar.container.padding at its start and at its end, into equal cells, one per destination, in reading order from the start edge; right-to-left layouts SHALL mirror the order. THE bar's container SHALL be the same whichever destination is selected, whatever state a destination is in and while the active indicator moves: only the active indicator marks the selection. |
NVB-12 | THE navigation bar SHALL draw each destination's item container as wide as its cell and as tall as the bar above the system inset less comp.navigation-bar.container.padding above and below, the same size for every destination of the bar whatever each holds, with its four corners rounded by comp.navigation-bar.item.container.shape, each at most half its height, and SHALL NOT size it to the destination's content. Inside it THE navigation bar SHALL lay out the destination as a column centered in the item container: the icon indicator, comp.navigation-bar.item.icon-indicator.width wide and comp.navigation-bar.item.icon-indicator.height high with corners comp.navigation-bar.item.icon-indicator.shape, its icon centered in it; and WHILE the label is drawn, the label below it, comp.navigation-bar.item.gap away, centered, on one line in comp.navigation-bar.item.label.typescale. THE column SHALL keep comp.navigation-bar.item.container.padding-block between itself and the item container's top and bottom edges, the bar growing in height to keep it (NVB-21), and a label wider than the item container less comp.navigation-bar.item.container.padding-inline on each side SHALL be truncated at its end with an ellipsis. THE navigation bar SHALL NOT draw hover, focus or press on the part of the cell outside the item container. Every part is laid out in every system; a transparent color hides a part without changing the layout. |
NVB-13 | WHILE labelVisibility is always THE navigation bar SHALL draw every destination's label; WHILE it is selected it SHALL draw only the selected destination's label; WHILE it is never it SHALL draw none. A destination that draws no label SHALL center its icon indicator in its item container, whose size does not change with the label, and every destination's label SHALL remain its accessible name. |
NVB-14 | THE navigation bar SHALL draw each icon at comp.navigation-bar.item.icon.size with the family and fill of its condition (selected for the selected destination, unselected for every other), sys.icon.weight, and an optical size clamped between sys.icon.optical-size.min and sys.icon.optical-size.max. |
NVB-15 | WHEN the selected destination changes while no drag is followed (NVB-27) THE navigation bar SHALL slide the active indicator (the fill of the selected condition's item container) from the previous destination's item container to the new one's, at its full size throughout and drawn in the new destination's colors, every frame of the slide being the in-between look of NVB-27 (the indicator as a drag would draw it at that place, each icon and label in its covered color exactly where it is covered); SHALL grow the new destination's icon indicator in width from its center to its full width, at its full height throughout, and fade the previous one out; and SHALL change icon and label colors and icon fill; all over comp.navigation-bar.motion.selection-duration with comp.navigation-bar.motion.selection-easing. WHERE no destination was selected before, the active indicator SHALL fade in on the new item container at its full size, and WHERE none is selected after, it SHALL fade out, over the same time; it SHALL NOT grow or shrink in width to appear or disappear. WHILE labelVisibility is selected the labels SHALL appear and disappear over the same time, without resizing or moving any item container. WHERE motion is reduced it SHALL show the new selection at once. WHEN the bar first appears, or the selected destination changes size or place without a new selection (a font arriving, the text size changing, the bar resizing), THE navigation bar SHALL put the active indicator on it at once, without a slide. |
NVB-16 | WHILE a destination's badge is true THE navigation bar SHALL draw a Tanrei badge anchored to its icon as the badge component draws one whose count is the destination's badgeCount and whose label is its badgeLabel, SHALL keep it while the destination is disabled, and SHALL expose the badge's description (badgeLabel, or the displayed count when it is empty) as part of the destination's own description, after its name and state. |
NVB-17 | IF the navigation bar holds fewer than three or more than five destinations THE navigation bar SHALL still render them, and in debug builds report the count. |
NVB-18 | THE navigation bar SHALL extend its container under the bottom system inset (home indicator, gesture bar, taskbar) and SHALL place its destinations above that inset and inside the left and right insets. |
NVB-19 | THE navigation bar SHALL expose each destination as one element named by its label, with its selected state and its position in the set (for example 2 of 4), and its icon hidden: a link WHILE its href is not empty (NVB-30) and a button otherwise. On the web it is an anchor or a button inside a navigation landmark named by the bar's label, the selected destination carrying aria-current="page"; on Apple platforms, Android, Flutter and React Native a tab of a tab bar, with the selected state, a link destination included: there the tab is what carries the position and the selection a bar is read by, and a link destination adds the link trait to it where the platform lets one element carry both. The selected destination is the place the product is showing, in a product of one screen and in a site of many pages alike: THE navigation bar SHALL have no second state and no second mark for a current page, and SHALL expose exactly one destination, or none, as current. |
NVB-20 | WHILE a destination's label is not empty THE navigation bar SHALL expose it as the destination's accessible name, over a name the product gives the destination on the element (aria-label or aria-labelledby); WHILE a destination's label is empty and the product gives the destination a name of its own on the element — aria-label, or aria-labelledby naming an element — THE navigation bar SHALL expose that name as its accessible name; WHILE a destination's label is empty and the product gives it none THE navigation bar SHALL still render it, and in debug builds report that it has no accessible name. |
NVB-21 | WHILE the text size is enlarged THE navigation bar SHALL grow its height to hold its labels on one line inside their item containers (NVB-12), every item container growing with the bar alike, and SHALL NOT scale its icon indicators or icons; WHERE the platform offers a large-content viewer for bar items (iOS) a long press SHALL show the destination's icon and label enlarged. |
NVB-22 | IF two destinations have the same value THE navigation bar SHALL treat the first of them as the one the bar's value selects, and in debug builds report the repeated value. |
NVB-23 | THE navigation bar SHALL draw each destination's icon and label a second time, over the first, in the covered colors of its condition (comp.navigation-bar.unselected.item.covered-icon.color and comp.navigation-bar.unselected.item.covered-label.color for a tonal destination that is not selected, comp.navigation-bar.selected.item.covered-icon.color and comp.navigation-bar.selected.item.covered-label.color for the tonal selected one, comp.navigation-bar.filled-unselected.item.covered-icon.color, comp.navigation-bar.filled-unselected.item.covered-label.color, comp.navigation-bar.filled-selected.item.covered-icon.color and comp.navigation-bar.filled-selected.item.covered-label.color for a filled bar), clipped to the active indicator's current shape, its corners included, wherever the indicator is drawn; WHILE the indicator slides (NVB-15) or follows a drag (NVB-27) the clip SHALL move with it in the same frame, so that a destination it passes over changes where it is covered and the newly selected destination's icon and label are wholly in their covered colors when it lands, neither before nor after. THE navigation bar SHALL NOT approximate the covered colors with a blend mode, SHALL draw the badge above both copies, and SHALL expose each destination to assistive technology once. |
NVB-24 | THE navigation bar 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 navigation bar is shown THE navigation bar SHALL draw itself for the new direction at once, without a motion of its own, keeping the selected destination and its focus; a drag (NVB-27) SHALL carry the active indicator to where the pointer is in either direction. |
NVB-25 | WHERE the layout direction is right-to-left THE navigation bar SHALL draw a destination's icon, in both of its copies (NVB-23) mirrored left to right exactly when the system's icon set marks that glyph's name as mirrored or the product forces mirroring for that use, and unmirrored when the product forbids it: the icon helper mirrors the glyph inside its own box, about the box's vertical centre line, changing neither its place, size, color and fill nor the order NVB-11 gives. THE navigation bar SHALL NOT mirror a glyph itself, and SHALL NOT mirror content the product gives as an image or a view of its own rather than by a glyph's name. |
NVB-26 | THE navigation bar SHALL lay out a destination's label, in both of its copies (NVB-23) as text of its own direction, isolated from the text around it: each takes the base direction of its first strong character, or the layout direction where it has none, so that a left-to-right word, a number with its sign or unit, a telephone number and an address keep their own order in a right-to-left layout and reorder nothing beside them; THE navigation bar SHALL still place each label and align its lines by the layout direction, not by the text's own, and SHALL cut a label that does not fit (NVB-12) at the end of its own direction, so that a left-to-right label in a right-to-left layout loses its right end and never its beginning. |
NVB-27 | WHEN the user presses the bar with touch, a pen or a mouse and drags past the platform's touch slop (8 points where the platform names none), further sideways than up or down, WHILE a destination is selected, THE navigation bar SHALL take the drag: the press SHALL activate no destination when it ends (NVB-1), the destination under it SHALL leave its pressed state as it does when a press ends (NVB-8), and from then until the drag ends THE navigation bar SHALL draw the active indicator where the pointer is along the bar — on an enabled destination's item container while the pointer is at that cell's center, halfway between two neighbouring enabled destinations while the pointer is where their cells meet (the middle of any disabled destinations between them), at the linear interpolation in between, and on the first or last enabled destination while the pointer is before or beyond its center — at its full size, in the selected destination's colors. Everything that differs between the indicator on the one destination and on the other SHALL change continuously with the pointer, with no threshold: its place, and the color of each icon and label, which is its covered color exactly where the indicator covers it and its own color elsewhere, the clip of NVB-23 moving with the indicator in the same frame. The icon indicator, each icon's fill and, WHILE labelVisibility is selected, the label that is drawn SHALL stay with the selected destination until the release (NVB-28). THE navigation bar SHALL place the indicator in the frame the pointer moves, without a motion of its own; WHEN the drag is taken with the pointer away from where the indicator rests THE navigation bar SHALL bring it to the pointer's place over comp.navigation-bar.motion.state-duration with comp.navigation-bar.motion.state-easing instead of at once, following the pointer meanwhile. A drag that is further up or down than sideways when it passes the slop SHALL be left to the page and to the system's gestures at the bottom edge for its whole length, a wheel or a trackpad SHALL move nothing, and WHILE no destination is selected THE navigation bar SHALL take no drag. |
NVB-28 | WHEN the user releases a drag the navigation bar has taken THE navigation bar SHALL choose one enabled destination: the one the active indicator is nearer to of the two it lies between (the one after it from halfway on), or, WHEN the release is a fling along the bar, the one of those two that the fling is toward; a fling is a release faster than the platform's minimum fling velocity (Android's ViewConfiguration.getScaledMinimumFlingVelocity, Flutter's kMinFlingVelocity) or, where the platform names none (the web, SwiftUI, React Native), 0.5 points per millisecond. A release's velocity is the pointer's over its last moves: WHERE the pointer has not moved for longer than the time after which the platform's velocity tracker takes a pointer as stopped (40 milliseconds in Android's VelocityTracker, Jetpack Compose's VelocityTracker and Flutter's VelocityTracker) or, where the platform names none (the web, SwiftUI, React Native), 40 milliseconds before the release THE navigation bar SHALL take the release as having no velocity, so that a drag that stops where it is wanted and is let go there is no fling, however fast it moved before it stopped. WHERE the chosen destination is not the selected one and is not a link THE navigation bar SHALL activate it as NVB-1 does — emit change exactly once with its value — and SHALL slide the active indicator from where the release left it onto that destination over comp.navigation-bar.motion.selection-duration with comp.navigation-bar.motion.selection-easing, as NVB-15 does from a destination; WHERE the chosen destination is not the selected one and is a link THE navigation bar SHALL treat the release as a plain press on that link — emitting change and following the link as NVB-31 says, or only opening it where NVB-31 does not count it — SHALL NOT write value, and SHALL return the active indicator to the destination that value selects as NVB-29 returns it, the indicator going on to the chosen destination when the product sets value (NVB-15); WHERE it is the selected destination THE navigation bar SHALL return the indicator to it over the same motion and SHALL emit neither change nor reselect. The place where two cells meet decides only what a release chooses; nothing drawn changes at it. The release SHALL NOT also activate the destination under the pointer. |
NVB-29 | WHEN a drag the navigation bar has taken is cancelled — the platform cancels the pointer (a system gesture, a lost capture), Escape is pressed while it lasts, or the product sets value or removes or disables a destination the indicator lies between — THE navigation bar SHALL return the active indicator to the selected destination (the one the product has just set, where it set one) over comp.navigation-bar.motion.selection-duration with comp.navigation-bar.motion.selection-easing and emit nothing. WHILE a drag lasts THE navigation bar SHALL NOT change value, keyboard focus, or the selected state that each destination exposes to assistive technology, whatever the indicator covers, and SHALL announce nothing: the selection is made, and announced, by the release alone (NVB-28). WHERE motion is reduced THE navigation bar SHALL still draw the active indicator where the pointer is, which the person's own finger moves, taking the drag without the catch-up motion of NVB-27, and SHALL put it on its destination at once when the drag is released or cancelled. |
NVB-30 | WHILE a destination's href is not empty THE navigation bar SHALL make it a link to that address and not a button. On the web it SHALL be an anchor element with that address, whose behaviours are the browser's own — following it on a plain click, a touch or Enter; opening it in another tab or window by a modified click or a middle click; the link's context menu; copying its address; showing its address on hover — and THE navigation bar SHALL NOT prevent, replace or imitate any of them, with one exception: a sideways drag that begins on a link destination moves the active indicator (NVB-27) and does not drag the link's address, because one gesture cannot do both and the drag is the bar's own way of moving its selection; Space SHALL NOT activate a link. On other platforms it SHALL be the platform's own link (SwiftUI's Link; on Compose, Flutter and React Native an element with the platform's link semantics whose address is opened by the platform's opener), as BTN-22 says for a link button. THE navigation bar SHALL draw a link exactly as it draws a button destination, from the same tokens in every state and both variants (NVB-3, NVB-4, NVB-7 to NVB-9, NVB-12, NVB-23), SHALL draw no look of its own for a link the user has visited, and SHALL give its hit area (NVB-6) to the link. WHILE a link's value is empty THE navigation bar SHALL take its href as its value, for value, change, reselect and NVB-22. WHILE a link's disabled is true it SHALL keep the link role with the disabled state and no destination, and SHALL open nothing by any means the platform gives a link (NVB-2; on the web the anchor carries no address). |
NVB-31 | WHEN the user activates a link destination THE navigation bar SHALL count it as an activation (NVB-1) only WHILE it follows the link in the place where the product is shown: a click with the primary button and no modifier key, a touch, Enter, or the default action of assistive technology, on a link whose target is same and that asks for no download. It SHALL then emit change or reselect exactly once, carrying the destination's value and its href, before the link is followed, and SHALL NOT hold the link back for sys.motion.duration.press-hold; SHALL NOT write value itself on any platform, because where the product is, is the product's to say, and the page or the route shown next sets value; SHALL keep the active indicator on the destination that value selects, moving it as NVB-15 says only when value changes; and SHALL let the link be followed unless the product cancels the event (preventDefault on the web), as a product does that moves between its pages without loading a document. For every other activation of a link — a modified or a middle click, a link whose target is new, a download — THE navigation bar SHALL emit neither change nor reselect, and SHALL keep value and the drawn selection as they are. |
NVB-32 | WHILE a destination is a link and its target is new THE navigation bar SHALL open its href in a new context, as BTN-24 says for a link button (on the web a new tab or window that is given no handle to the page that opened it), and SHALL draw no mark for it: a destination's cell is an icon over a label and has no trailing glyph place for a mark to stand in, as an icon-only button has none, and a second glyph beside the icon would be read as its badge. It SHALL expose targetLabel as part of the destination's description, after its badge's description (NVB-16), and WHILE targetLabel is empty SHALL still render and in debug builds report that a link that opens a new context does not say so. WHILE target is same THE navigation bar SHALL ignore targetLabel. |
NVB-33 | WHEN a destination's target names a value the navigation bar does not define THE navigation bar SHALL treat it as same, and in debug builds report the unknown value. IF a destination's href is only white space, or names a script to run rather than a place to go (the web's javascript: scheme), or cannot be read as an address by the platform, THE navigation bar SHALL make the destination a button without a destination, and in the last two cases report it in debug builds, as BTN-26 says for a button. WHILE a destination's href is empty THE navigation bar SHALL ignore its target and targetLabel. |
NVB-34 | WHERE the platform has ARIA attributes (the web), WHEN the product sets an aria- attribute on a destination's host, by the attribute or by the ARIA property that reflects it, THE navigation bar SHALL move it to the data-aria- attribute of the same name, so that the host is no second node with its name, description or state, and SHALL expose it on the element that carries the destination's role (its link or its button) — an id reference by the elements it names in the host's tree or a tree around it, an error message as part of the description while the destination is invalid — except those a destination owns (aria-current, aria-disabled), which it SHALL move and not expose. WHEN the product removes the aria- attribute or its data-aria- twin, or sets the ARIA property that reflects it (ariaLabel, ariaDescribedByElements…) to null, THE navigation bar SHALL take it off that element. WHEN the product sets an aria- attribute a destination owns THE navigation bar SHALL report it in debug builds. The bar's host carries its navigation landmark itself (NVB-19), so what the product writes on it is not moved, but for a name: WHILE the bar's label is not empty THE navigation bar SHALL hold the product's aria-label and aria-labelledby on that host as their data-aria- twins, so that label is the landmark's whole name although the platform gives aria-labelledby the precedence, and WHEN label is emptied SHALL give them back as they were written, so that a name the product gives names the landmark; WHEN the product removes one, or its data-aria- twin, or sets the ARIA property that reflects it to null, THE navigation bar SHALL take it away. |
प्लैटफ़ॉर्म के अनुसार नामों का मिलान
पैरिटी का मतलब एक जैसे API नहीं है। हर प्लैटफ़ॉर्म एक ही कॉन्ट्रैक्ट को अपने तरीक़े से व्यक्त करता है।
| स्पेक | Web | SwiftUI | Jetpack Compose | Flutter | React Native |
|---|---|---|---|---|---|
| कंपोनेंट | tanrei-navigation-bar | TanreiNavigationBar | TanreiNavigationBar | TanreiNavigationBar | NavigationBar |
value · प्रॉपर्टी | value | selection | selected | selectedIndex | value |
variant · प्रॉपर्टी | variant | variant | variant | variant | variant |
labelVisibility · प्रॉपर्टी | labelVisibility | labelVisibility | labelVisibility | labelBehavior | labelVisibility |
label · प्रॉपर्टी | label | accessibilityLabel | contentDescription | semanticLabel | accessibilityLabel |
change · इवेंट | change | selection | onClick | onDestinationSelected | onValueChange |
reselect · इवेंट | reselect | onReselect | onClick | onDestinationSelected | onReselect |
| टिप्पणियाँ | Destinations are <tanrei-navigation-bar-item> children, in order. The bar selects the activated destination itself (sets value) before firing change, as a native control does, unless the destination is a link. For a link destination change and reselect are cancelable, carry detail.href beside detail.value, and are fired from the anchor's click only when event.button is 0, no modifier key is down, the click was not already cancelled, and the item's target is same and it has no download; cancelling one calls preventDefault() on that click. The bar does not set value for a link. variant is the variant attribute (tonal, filled) and labelVisibility the label-visibility attribute. The host is a navigation landmark (role="navigation", aria-label from label); the selected destination has aria-current="page". The active indicator is one layer of the bar that slides between the destinations' item containers; the covered copy of every icon and label (NVB-23) is an aria-hidden layer clipped with clip-path to the indicator's box, animated with it. A drag (NVB-27 to NVB-29) is followed with Pointer Events, as tanrei-tabs follows its own: pointerdown on the bar, setPointerCapture once the drag is taken, pointermove placing the indicator through the same custom properties a slide transitions, pointerup choosing the destination, and pointercancel, lostpointercapture or Escape cancelling; the click that follows a taken drag is swallowed, aria-current is written only on the release, a destination that is a link is not draggable as a link (draggable="false", the one behaviour of a link the bar takes, NVB-30) and is followed with its own click() when a release chooses it, the indicator then returning to the destination value selects (NVB-28), and touch-action: pan-y leaves vertical drags to the page. The bottom inset is env(safe-area-inset-bottom). It does not yet follow NVB-30 to NVB-33, nor the parts of NVB-1, NVB-19 and NVB-28 that concern links: a pressed link destination is selected like a button, change is not cancelable and carries no href, and the destination writes the link rules itself instead of using the shared link primitive (packages/web/src/primitives/link.ts). | TanreiNavigationBar(selection: Binding<Value>, variant:, labelVisibility:, onReselect:) { TanreiNavigationBarItem(…) … }, placed with .safeAreaInset(edge: .bottom). A bar of its own rather than a restyled TabView, whose bar the tokens cannot reach (indicator, geometry, colors). Activation writes the binding (change); activating the selected item calls onReselect. The bar is exposed as a tab bar and each item as a button with the selected trait; each item supports the large-content viewer. It lags the spec: it has no variant, and draws the active indicator behind the icon alone (the item container at its least size), growing in from its center instead of sliding, with the label outside it. Not built on this platform yet: the item container as wide as the destination's cell and held in by container.padding, hover, focus and press drawn in that box, and the drag of the active indicator (NVB-27 to NVB-29): a DragGesture(minimumDistance:) beside each item's tap, predictedEndTranslation for the fling, the binding written in onEnded. Link destinations are not built yet either (NVB-30 to NVB-33 and the parts of NVB-1, NVB-19 and NVB-28 that concern links, with the fixtures links, links-rtl and links-disabled). | Compose idiom (as NavigationBar): TanreiNavigationBar(variant, labelVisibility, contentDescription) { TanreiNavigationBarItem(…) … }. There is no bar-level value: the caller marks the selected item with selected = (current == value), so the bar's value and a destination's value both map to the item's selected, and one onClick per item covers change and reselect (the caller knows which item is selected). The bar draws the sliding active indicator behind its items, from the bounds of the selected item. Insets follow WindowInsets.navigationBars plus the horizontal display cutout, as a windowInsets parameter. Items have Role.Tab in a selectableGroup(). It lags the spec: it has no variant, and draws the active indicator behind the icon alone (the item container at its least size), growing in from its center instead of sliding, with the label outside it. Not built on this platform yet: the item container as wide as the destination's cell and held in by container.padding, hover, focus and press drawn in that box, and the drag of the active indicator (NVB-27 to NVB-29): pointerInput with detectHorizontalDragGestures on the bar and a VelocityTracker for the fling; the release calls the chosen item's onClick. Link destinations are not built yet either (NVB-30 to NVB-33 and the parts of NVB-1, NVB-19 and NVB-28 that concern links, with the fixtures links, links-rtl and links-disabled). | Flutter idiom (as NavigationBar): TanreiNavigationBar(selectedIndex:, onDestinationSelected:, variant:, labelBehavior:, destinations: [TanreiNavigationDestination(…), …]). A destination's value is its index in destinations; a selectedIndex of null selects none. onDestinationSelected is called for the selected destination too (reselect); the caller compares. variant is TanreiNavigationBarVariant.tonal or .filled; labelBehavior is alwaysShow, onlyShowSelected or alwaysHide. Bottom inset from MediaQuery.padding via SafeArea. It lags the spec: it has no variant, and draws the active indicator behind the icon alone (the item container at its least size), growing in from its center instead of sliding, with the label outside it. Not built on this platform yet: the item container as wide as the destination's cell and held in by container.padding, hover, focus and press drawn in that box, and the drag of the active indicator (NVB-27 to NVB-29): a GestureDetector's horizontal drag callbacks on the bar, DragEndDetails.primaryVelocity for the fling; the release calls onDestinationSelected. Link destinations are not built yet either (NVB-30 to NVB-33 and the parts of NVB-1, NVB-19 and NVB-28 that concern links, with the fixtures links, links-rtl and links-disabled). | Controlled, in React Native's value / onValueChange idiom, with a destinations data array; variant is 'tonal' or 'filled'. The bar has the tablist role and each destination the tab role with accessibilityState.selected; the covered copy is hidden with importantForAccessibility="no-hide-descendants" and accessibilityElementsHidden. Insets come from the bar's own insets prop, side by side, falling back to TanreiProvider's insets; the package takes no safe-area dependency, and a product that uses react-native-safe-area-context passes its useSafeAreaInsets() to either. It lags the spec: it has no variant, and draws the active indicator behind the icon alone (the item container at its least size), growing in from its center instead of sliding, with the label outside it. Not built on this platform yet: the item container as wide as the destination's cell and held in by container.padding, hover, focus and press drawn in that box, and the drag of the active indicator (NVB-27 to NVB-29): a PanResponder on the bar (or React Native Gesture Handler's Gesture.Pan() where the product has it), the release's vx for the fling; the release calls onValueChange. Link destinations are not built yet either (NVB-30 to NVB-33 and the parts of NVB-1, NVB-19 and NVB-28 that concern links, with the fixtures links, links-rtl and links-disabled). |
टोकन
| टोकन | किसका एलियास | रिज़ॉल्व किया गया मान (लाइट) |
|---|---|---|
--tanrei-comp-navigation-bar-container-color | sys.color.surface | |
--tanrei-comp-navigation-bar-container-elevation | sys.elevation.level0 | |
--tanrei-comp-navigation-bar-container-height | — | 64px |
--tanrei-comp-navigation-bar-container-padding | sys.space.space50 | 4px |
--tanrei-comp-navigation-bar-disabled-opacity | — | 1 |
--tanrei-comp-navigation-bar-filled-selected-disabled-item-container-color | — | |
--tanrei-comp-navigation-bar-filled-selected-disabled-item-covered-icon-color | — | |
--tanrei-comp-navigation-bar-filled-selected-disabled-item-covered-label-color | — | |
--tanrei-comp-navigation-bar-filled-selected-disabled-item-icon-indicator-color | — | |
--tanrei-comp-navigation-bar-filled-selected-disabled-item-icon-color | — | |
--tanrei-comp-navigation-bar-filled-selected-disabled-item-label-color | — | |
--tanrei-comp-navigation-bar-filled-selected-disabled-item-state-layer-color | — | |
--tanrei-comp-navigation-bar-filled-selected-focused-item-container-color | — | |
--tanrei-comp-navigation-bar-filled-selected-focused-item-covered-icon-color | — | |
--tanrei-comp-navigation-bar-filled-selected-focused-item-covered-label-color | — | |
--tanrei-comp-navigation-bar-filled-selected-focused-item-icon-indicator-color | — | |
--tanrei-comp-navigation-bar-filled-selected-focused-item-icon-color | — | |
--tanrei-comp-navigation-bar-filled-selected-focused-item-label-color | — | |
--tanrei-comp-navigation-bar-filled-selected-focused-item-state-layer-color | — | |
--tanrei-comp-navigation-bar-filled-selected-hovered-item-container-color | — | |
--tanrei-comp-navigation-bar-filled-selected-hovered-item-covered-icon-color | — | |
--tanrei-comp-navigation-bar-filled-selected-hovered-item-covered-label-color | — | |
--tanrei-comp-navigation-bar-filled-selected-hovered-item-icon-indicator-color | — | |
--tanrei-comp-navigation-bar-filled-selected-hovered-item-icon-color | — | |
--tanrei-comp-navigation-bar-filled-selected-hovered-item-label-color | — | |
--tanrei-comp-navigation-bar-filled-selected-hovered-item-state-layer-color | — | |
--tanrei-comp-navigation-bar-filled-selected-item-container-color | sys.color.primary | |
--tanrei-comp-navigation-bar-filled-selected-item-covered-icon-color | sys.color.on-primary | |
--tanrei-comp-navigation-bar-filled-selected-item-covered-label-color | sys.color.on-primary | |
--tanrei-comp-navigation-bar-filled-selected-item-icon-indicator-color | comp.navigation-bar.selected.item.icon-indicator.color | |
--tanrei-comp-navigation-bar-filled-selected-item-icon-color | comp.navigation-bar.selected.item.icon.color | |
--tanrei-comp-navigation-bar-filled-selected-item-label-color | comp.navigation-bar.selected.item.label.color | |
--tanrei-comp-navigation-bar-filled-selected-item-state-layer-color | comp.navigation-bar.filled-selected.item.covered-icon.color | |
--tanrei-comp-navigation-bar-filled-selected-pressed-item-container-color | — | |
--tanrei-comp-navigation-bar-filled-selected-pressed-item-covered-icon-color | — | |
--tanrei-comp-navigation-bar-filled-selected-pressed-item-covered-label-color | — | |
--tanrei-comp-navigation-bar-filled-selected-pressed-item-icon-indicator-color | — | |
--tanrei-comp-navigation-bar-filled-selected-pressed-item-icon-color | — | |
--tanrei-comp-navigation-bar-filled-selected-pressed-item-label-color | — | |
--tanrei-comp-navigation-bar-filled-selected-pressed-item-state-layer-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-disabled-item-container-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-disabled-item-covered-icon-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-disabled-item-covered-label-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-disabled-item-icon-indicator-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-disabled-item-icon-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-disabled-item-label-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-disabled-item-state-layer-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-focused-item-container-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-focused-item-covered-icon-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-focused-item-covered-label-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-focused-item-icon-indicator-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-focused-item-icon-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-focused-item-label-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-focused-item-state-layer-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-hovered-item-container-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-hovered-item-covered-icon-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-hovered-item-covered-label-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-hovered-item-icon-indicator-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-hovered-item-icon-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-hovered-item-label-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-hovered-item-state-layer-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-item-container-color | comp.navigation-bar.unselected.item.container.color | |
--tanrei-comp-navigation-bar-filled-unselected-item-covered-icon-color | sys.color.on-primary | |
--tanrei-comp-navigation-bar-filled-unselected-item-covered-label-color | sys.color.on-primary | |
--tanrei-comp-navigation-bar-filled-unselected-item-icon-indicator-color | comp.navigation-bar.unselected.item.icon-indicator.color | |
--tanrei-comp-navigation-bar-filled-unselected-item-icon-color | comp.navigation-bar.unselected.item.icon.color | |
--tanrei-comp-navigation-bar-filled-unselected-item-label-color | comp.navigation-bar.unselected.item.label.color | |
--tanrei-comp-navigation-bar-filled-unselected-item-state-layer-color | comp.navigation-bar.filled-unselected.item.icon.color | |
--tanrei-comp-navigation-bar-filled-unselected-pressed-item-container-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-pressed-item-covered-icon-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-pressed-item-covered-label-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-pressed-item-icon-indicator-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-pressed-item-icon-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-pressed-item-label-color | — | |
--tanrei-comp-navigation-bar-filled-unselected-pressed-item-state-layer-color | — | |
--tanrei-comp-navigation-bar-focused-opacity | — | 1 |
--tanrei-comp-navigation-bar-hovered-opacity | — | 1 |
--tanrei-comp-navigation-bar-item-container-padding-block | sys.space.space50 | 4px |
--tanrei-comp-navigation-bar-item-container-padding-inline | sys.space.space150 | 12px |
--tanrei-comp-navigation-bar-item-container-shape | sys.shape.corner.full | 9999px |
--tanrei-comp-navigation-bar-item-gap | sys.space.space50 | 4px |
--tanrei-comp-navigation-bar-item-icon-indicator-height | comp.navigation-bar.item.icon.size | 24px |
--tanrei-comp-navigation-bar-item-icon-indicator-shape | sys.shape.corner.full | 9999px |
--tanrei-comp-navigation-bar-item-icon-indicator-width | comp.navigation-bar.item.icon.size | 24px |
--tanrei-comp-navigation-bar-item-icon-size | sys.icon.medium | 24px |
--tanrei-comp-navigation-bar-motion-feedback-duration | sys.motion.role.feedback | 450ms |
--tanrei-comp-navigation-bar-motion-selection-duration | sys.motion.role.selection.travel | 250ms |
--tanrei-comp-navigation-bar-motion-selection-easing | sys.motion.easing.spatial | cubic-bezier(0.2, 0, 0, 1) |
--tanrei-comp-navigation-bar-motion-state-duration | sys.motion.role.state.large | 250ms |
--tanrei-comp-navigation-bar-motion-state-easing | sys.motion.easing.state | cubic-bezier(0.2, 0, 0, 1) |
--tanrei-comp-navigation-bar-outline-color | sys.color.outline-variant | |
--tanrei-comp-navigation-bar-outline-width | sys.border.hairline | 1px |
--tanrei-comp-navigation-bar-pressed-opacity | — | 1 |
--tanrei-comp-navigation-bar-selected-disabled-item-container-color | — | |
--tanrei-comp-navigation-bar-selected-disabled-item-covered-icon-color | — | |
--tanrei-comp-navigation-bar-selected-disabled-item-covered-label-color | — | |
--tanrei-comp-navigation-bar-selected-disabled-item-icon-indicator-color | — | |
--tanrei-comp-navigation-bar-selected-disabled-item-icon-color | — | |
--tanrei-comp-navigation-bar-selected-disabled-item-label-color | — | |
--tanrei-comp-navigation-bar-selected-disabled-item-state-layer-color | — | |
--tanrei-comp-navigation-bar-selected-focused-item-container-color | — | |
--tanrei-comp-navigation-bar-selected-focused-item-covered-icon-color | — | |
--tanrei-comp-navigation-bar-selected-focused-item-covered-label-color | — | |
--tanrei-comp-navigation-bar-selected-focused-item-icon-indicator-color | — | |
--tanrei-comp-navigation-bar-selected-focused-item-icon-color | — | |
--tanrei-comp-navigation-bar-selected-focused-item-label-color | — | |
--tanrei-comp-navigation-bar-selected-focused-item-state-layer-color | — | |
--tanrei-comp-navigation-bar-selected-hovered-item-container-color | — | |
--tanrei-comp-navigation-bar-selected-hovered-item-covered-icon-color | — | |
--tanrei-comp-navigation-bar-selected-hovered-item-covered-label-color | — | |
--tanrei-comp-navigation-bar-selected-hovered-item-icon-indicator-color | — | |
--tanrei-comp-navigation-bar-selected-hovered-item-icon-color | — | |
--tanrei-comp-navigation-bar-selected-hovered-item-label-color | — | |
--tanrei-comp-navigation-bar-selected-hovered-item-state-layer-color | — | |
--tanrei-comp-navigation-bar-selected-item-container-color | sys.color.secondary-container | |
--tanrei-comp-navigation-bar-selected-item-covered-icon-color | sys.color.on-secondary-container | |
--tanrei-comp-navigation-bar-selected-item-covered-label-color | sys.color.on-secondary-container | |
--tanrei-comp-navigation-bar-selected-item-icon-indicator-color | — | |
--tanrei-comp-navigation-bar-selected-item-icon-color | sys.color.on-secondary-container | |
--tanrei-comp-navigation-bar-selected-item-label-color | sys.color.on-surface | |
--tanrei-comp-navigation-bar-selected-item-state-layer-color | comp.navigation-bar.selected.item.icon.color | |
--tanrei-comp-navigation-bar-selected-pressed-item-container-color | — | |
--tanrei-comp-navigation-bar-selected-pressed-item-covered-icon-color | — | |
--tanrei-comp-navigation-bar-selected-pressed-item-covered-label-color | — | |
--tanrei-comp-navigation-bar-selected-pressed-item-icon-indicator-color | — | |
--tanrei-comp-navigation-bar-selected-pressed-item-icon-color | — | |
--tanrei-comp-navigation-bar-selected-pressed-item-label-color | — | |
--tanrei-comp-navigation-bar-selected-pressed-item-state-layer-color | — | |
--tanrei-comp-navigation-bar-unselected-disabled-item-container-color | — | |
--tanrei-comp-navigation-bar-unselected-disabled-item-covered-icon-color | — | |
--tanrei-comp-navigation-bar-unselected-disabled-item-covered-label-color | — | |
--tanrei-comp-navigation-bar-unselected-disabled-item-icon-indicator-color | — | |
--tanrei-comp-navigation-bar-unselected-disabled-item-icon-color | — | |
--tanrei-comp-navigation-bar-unselected-disabled-item-label-color | — | |
--tanrei-comp-navigation-bar-unselected-disabled-item-state-layer-color | — | |
--tanrei-comp-navigation-bar-unselected-focused-item-container-color | — | |
--tanrei-comp-navigation-bar-unselected-focused-item-covered-icon-color | — | |
--tanrei-comp-navigation-bar-unselected-focused-item-covered-label-color | — | |
--tanrei-comp-navigation-bar-unselected-focused-item-icon-indicator-color | — | |
--tanrei-comp-navigation-bar-unselected-focused-item-icon-color | — | |
--tanrei-comp-navigation-bar-unselected-focused-item-label-color | — | |
--tanrei-comp-navigation-bar-unselected-focused-item-state-layer-color | — | |
--tanrei-comp-navigation-bar-unselected-hovered-item-container-color | — | |
--tanrei-comp-navigation-bar-unselected-hovered-item-covered-icon-color | — | |
--tanrei-comp-navigation-bar-unselected-hovered-item-covered-label-color | — | |
--tanrei-comp-navigation-bar-unselected-hovered-item-icon-indicator-color | — | |
--tanrei-comp-navigation-bar-unselected-hovered-item-icon-color | — | |
--tanrei-comp-navigation-bar-unselected-hovered-item-label-color | — | |
--tanrei-comp-navigation-bar-unselected-hovered-item-state-layer-color | — | |
--tanrei-comp-navigation-bar-unselected-item-container-color | — | |
--tanrei-comp-navigation-bar-unselected-item-covered-icon-color | sys.color.on-secondary-container | |
--tanrei-comp-navigation-bar-unselected-item-covered-label-color | sys.color.on-secondary-container | |
--tanrei-comp-navigation-bar-unselected-item-icon-indicator-color | — | |
--tanrei-comp-navigation-bar-unselected-item-icon-color | sys.color.on-surface-variant | |
--tanrei-comp-navigation-bar-unselected-item-label-color | sys.color.on-surface-variant | |
--tanrei-comp-navigation-bar-unselected-item-state-layer-color | comp.navigation-bar.unselected.item.icon.color | |
--tanrei-comp-navigation-bar-unselected-pressed-item-container-color | — | |
--tanrei-comp-navigation-bar-unselected-pressed-item-covered-icon-color | — | |
--tanrei-comp-navigation-bar-unselected-pressed-item-covered-label-color | — | |
--tanrei-comp-navigation-bar-unselected-pressed-item-icon-indicator-color | — | |
--tanrei-comp-navigation-bar-unselected-pressed-item-icon-color | — | |
--tanrei-comp-navigation-bar-unselected-pressed-item-label-color | — | |
--tanrei-comp-navigation-bar-unselected-pressed-item-state-layer-color | — | |
--tanrei-comp-navigation-bar-item-label-typescale | sys.typescale.label-small | 500 12px/1.3333 |
फ़िक्स्चर
मानक रेंडरिंग। हर प्लैटफ़ॉर्म हर फ़िक्स्चर का स्नैपशॉट एक ही ID से लेता है, ताकि नतीजों की तुलना की जा सके।
four-destinations
value: inbox label: Main items: 4 three-destinations
value: search label: Main items: 3 five-destinations
value: library label: Main items: 5 labels-selected
value: sent labelVisibility: selected label: Main items: 4 labels-never
value: inbox labelVisibility: never label: Main items: 4 badges
value: inbox label: Main items: 4 disabled
value: inbox label: Main items: 4 none-selected
label: Main items: 4 selected-disabled
value: starred label: Main items: 4 long-labels
value: subscriptions label: Main items: 5 filled
value: sent variant: filled label: Main items: 4 filled-labels-selected
value: starred variant: filled labelVisibility: selected label: Main items: 4 filled-badges
value: inbox variant: filled label: Main items: 4 filled-selected-disabled
value: starred variant: filled label: Main items: 4 links
value: /search/ label: Main items: 4 links-rtl
value: /search/ label: Main direction: rtl items: 4 links-disabled
value: / label: Main items: 3 इससे जनरेट किया गया: specs/navigation-bar.spec.json, tokens/comp/navigation-bar.tokens.json, design/tokens/
नेविगेशन बार को कॉम्पैक्ट स्क्रीन पर, जैसे सीधा पकड़ा हुआ फ़ोन, तीन से पाँच सबसे ऊपरी स्तर के गंतव्यों के बीच जाने के लिए इस्तेमाल करें: वे जगहें जहाँ व्यक्ति दिन भर लौटता है, जैसे इनबॉक्स, खोज और प्रोफ़ाइल। बार सबसे ऊपरी स्तर की हर स्क्रीन पर रहता है और दिखाता है कि व्यक्ति कहाँ है।
एक स्क्रीन के भीतर एक ही विषय के व्यू के बीच बदलने के लिए टैब इस्तेमाल करें। जिस स्क्रीन पर व्यक्ति किसी दूसरी स्क्रीन से पहुँचा, उससे निकलने के लिए ऐप बार का “पीछे” बटन इस्तेमाल करें: ब्योरे वाली स्क्रीन आम तौर पर नेविगेशन बार को छिपा देती हैं।
| पहलू | नेविगेशन बार | नेविगेशन ड्रॉअर, सिमटा हुआ | नेविगेशन ड्रॉअर, फैला हुआ |
|---|---|---|---|
| कहाँ रहता है | निचले किनारे के साथ | शुरुआती किनारे के साथ आइकन का एक कॉलम | शुरुआती किनारे पर एक पैनल में |
| विंडो | कॉम्पैक्ट | मीडियम और उससे चौड़ी | एक्सपैंडेड और उससे चौड़ी (standard), या कॉम्पैक्ट (modal) |
| गंतव्य | तीन से पाँच | उसके सबसे ऊपरी स्तर के गंतव्य और ग्रुप, हर एक के लिए एक सेल | जितने प्रॉडक्ट में हैं, सेक्शन और ग्रुप में |
| एक गंतव्य | एक पंक्ति के लेबल के ऊपर एक आइकन, आइकन पर बैज के साथ | आइकन के बाद काटी गई पंक्ति: अकेला आइकन, जिस पर बैज है और जिसका नाम टूलटिप में है | एक पंक्ति: एक वैकल्पिक आइकन, अगली पंक्ति में जाने वाला लेबल, और अंत में अंतिम टेक्स्ट या कॉन्टेंट |
| इसमें और क्या है | और कुछ नहीं | एक हेडर: मेन्यू बटन और मुख्य क्रिया, अपने आइकन तक सिमटी हुई | एक हेडर: मेन्यू बटन, एक शीर्षक या खाता बदलने वाला कंट्रोल, और मुख्य क्रिया |
| नेटिव प्लैटफ़ॉर्म पर गंतव्य है | टैब बार का एक टैब | चयनित स्टेट वाला एक बटन | चयनित स्टेट वाला एक बटन |
| यह क्या है | एक लेआउट रीजन | एक लेआउट रीजन, या लेआउट का वह कॉलम जिससे मोडल ड्रॉअर चौड़ा होता है | Standard: एक लेआउट रीजन। Modal: एक मोडल ओवरले |
- सिमटा हुआ ड्रॉअर ही नेविगेशन रेल है। समेटा जा सकने वाला ड्रॉअर वहाँ आइकन के एक कॉलम तक सँकरा हो जाता है जहाँ कॉन्टेंट को चौड़ाई चाहिए, और उसका मेन्यू बटन उसे फिर चौड़ा करता है; हर आइकन अपनी जगह रहता है। Tanrei की अलग नेविगेशन रेल हटाकर इसी रूप में मिला दी गई है।
- बार और ड्रॉअर दो जगहों पर गंतव्यों का एक ही सेट हैं। वे वही गंतव्य और वही चयन लेते हैं, इसलिए जो प्रॉडक्ट विंडो के हिसाब से ढलता है, वह एक ब्रेकपॉइंट पर बार की जगह ड्रॉअर रख देता है और अपने गंतव्यों को छूता तक नहीं। एक समय में इनमें से एक ही दिखाएँ, दोनों कभी नहीं।
- ड्रॉअर में ज़्यादा समाता है। उसे फैला हुआ तब इस्तेमाल करें जब प्रॉडक्ट में बार में समा सकने से ज़्यादा गंतव्य हों, या जब वे ग्रुप में बँटते हों, जैसे किसी मेल ऐप के फ़ोल्डर और लेबल। बड़ी विंडो में standard ड्रॉअर कॉन्टेंट के बग़ल में रहता है। कॉम्पैक्ट विंडो में मोडल ड्रॉअर मेन्यू बटन से उसके ऊपर खिसककर आता है।
- समेटा जा सकने वाला मोडल ड्रॉअर अपने आइकन का कॉलम लेआउट में रखता है और, जब उसका मेन्यू बटन उसे खोलता है, स्क्रिम के ऊपर कॉन्टेंट पर चौड़ा होता है।
- हर प्लैटफ़ॉर्म पर दोनों गंतव्य के मान से चुनते हैं (Compose हर आइटम के फ़्लैग से, Flutter इंडेक्स से) और
changeऔरreselectएमिट करते हैं।
labelVisibility |
क्या करता है | किसके लिए |
|---|---|---|
always (डिफ़ॉल्ट) |
हर गंतव्य अपना लेबल बनाता है। | ज़्यादातर बार। लेबल गंतव्यों को एक नज़र में पहचानने लायक़ बनाते हैं। |
selected |
सिर्फ़ मौजूदा गंतव्य अपना लेबल बनाता है। बिना लेबल का आइकन अपने गंतव्य के बीच में रहता है। चयन के साथ कोई गंतव्य अपना साइज़ या जगह नहीं बदलता। | वे बार जहाँ जगह कम है और आइकन जाने-पहचाने हैं। |
never |
कोई गंतव्य अपना लेबल नहीं बनाता। | मीडिया और सोशल प्रॉडक्ट, जिनके चार या पाँच आइकन हर कोई जानता है। |
जो लेबल दिखाया नहीं जाता, वह अब भी गंतव्य का एक्सेसिबल नाम है, इसलिए हर गंतव्य को एक लेबल चाहिए।
- सक्रिय इंडिकेटर। हर गंतव्य का एक बॉक्स होता है: बार की चौड़ाई में उसका बराबर हिस्सा, जो बार के किनारों से, ऊपर और नीचे और दोनों सिरों पर, एक ही इनसेट (डिफ़ॉल्ट सिस्टम में 4) से भीतर रखा जाता है। 360 चौड़े और 64 ऊँचे बार में चार गंतव्यों में से हर एक का बॉक्स 88 × 56 का है, जो डिफ़ॉल्ट सिस्टम में एक कैप्सूल है। बार के हर गंतव्य के लिए बॉक्स एक जैसा होता है, चाहे उसमें कुछ भी हो, और वह कभी अपने आइकन और लेबल के साइज़ का नहीं बनाया जाता। मौजूदा गंतव्य का बॉक्स भरा होता है, जो उसे सक्रिय इंडिकेटर बनाता है, और उसका आइकन भरा हुआ होता है। होवर, फ़ोकस और दबाना हर गंतव्य के लिए उसी बॉक्स में बनाए जाते हैं।
- खिसकना। चयन बदलने पर इंडिकेटर पुराने गंतव्य से नए तक अपने पूरे साइज़ में खिसकता है। आइकन और लेबल सिर्फ़ वहीं उलटे रंग में होते हैं जहाँ इंडिकेटर उन्हें ढकता है, इसलिए जिस गंतव्य के ऊपर से वह गुज़रता है वह एक पल के लिए उसके नीचे रंग बदलता है, और इंडिकेटर के पहुँचते ही नया गंतव्य पूरी तरह उलटे रंग में होता है। जब पहले कोई चयन न हो, तो इंडिकेटर नए गंतव्य पर फ़ेड होकर आता है; जब चयन हटकर कोई चयन न रहे, तो वह फ़ेड होकर चला जाता है। वह कभी बढ़ता या सिकुड़ता नहीं। जब बार पहली बार दिखता है, या मौजूदा गंतव्य नए चयन के बिना साइज़ बदलता है (कोई फ़ॉन्ट आ गया, टेक्स्ट का साइज़ बदल गया), तो इंडिकेटर तुरंत अपनी जगह रख दिया जाता है। जहाँ मोशन कम किया गया है, वहाँ बदलाव तुरंत होता है।
- ड्रैग। जब कोई गंतव्य चयनित हो, तब बार पर टच, पेन या माउस से ऐसा दबाना जो बग़ल की ओर चलता है, इंडिकेटर को पॉइंटर के साथ ले चलता है। छोड़ने तक कुछ नहीं चुना जाता:
value, फ़ोकस, हर आइकन का फ़िल और जो पढ़कर सुनाया जाता है, सब मौजूदा गंतव्य के साथ रहते हैं। छोड़ने पर उन दो गंतव्यों में से पास वाला चुना जाता है जिनके बीच इंडिकेटर है, या वह जिसकी ओर फ़्लिंग है, औरchangeएक बार फ़ायर होता है। वापस मौजूदा गंतव्य पर छोड़ने पर कुछ फ़ायर नहीं होता,reselectभी नहीं। Escape ड्रैग को रद्द करती है। ड्रैग कभी अकेला तरीक़ा नहीं है: टैप, क्लिक, Enter और Space पहले की तरह चुनते हैं। - दोबारा चुनना। मौजूदा गंतव्य को फिर चुनने पर
reselectफ़ायर होता है,changeनहीं। इसका आम जवाब उस स्क्रीन को सबसे ऊपर तक स्क्रॉल करना है, या उसके पहले पेज पर लौटना। - बैज। गिनती वाला बैज संख्या दिखाता है (999 से ऊपर 999+), और बिना गिनती वाला एक बिंदु।
badgeLabelवह है जो स्क्रीन रीडर गंतव्य के नाम के बाद कहता है, जैसे “3 अपठित”। बिंदु में पढ़ने के लिए कोई संख्या नहीं होती, इसलिए उसे यह हमेशा चाहिए। गंतव्य के अक्षम रहते भी बैज बना रहता है।
अलग-अलग पेजों वाली साइट में हर गंतव्य को href दें और बार के value को पेज के अपने पते पर सेट करें। तब मौजूदा गंतव्य और मौजूदा पेज एक ही चीज़ हैं, एक ही निशान के साथ।
- खोला जाता है, चुना नहीं जाता। लिंक को सादे ढंग से सक्रिय करने पर
changeएमिट होता है, या मौजूदा लिंक परreselect, गंतव्य के मान और उसकेhrefके साथ, और फिर लिंक खोला जाता है। बारvalueनहीं लिखता: सक्रिय इंडिकेटर उसी गंतव्य पर रहता है जिसका नामvalueलेता है, औरvalueबदलने पर खिसकता है। - राउटर। नेविगेशन अपने हाथ में लेने के लिए इवेंट रद्द करें,
detail.hrefपर जाएँ औरvalueसेट करें। तब इंडिकेटर नए गंतव्य तक खिसकता है। - दूसरे टैब। मॉडिफ़ायर कुंजी के साथ क्लिक या Enter, मिडिल क्लिक, वह लिंक जिसका
targetnewहै, और डाउनलोड, ब्राउज़र के हैं। बार न कुछ एमिट करता है, न कुछ चुनता है। - नया संदर्भ।
target: newएक नया टैब या विंडो खोलता है। गंतव्य लेबल के ऊपर एक आइकन है, जिसमें निशान के लिए कोई जगह नहीं है, इसलिए कोई निशान नहीं बनता:targetLabelयह बात सहायक तकनीक को बताता है, बैज के विवरण के बाद। - ड्रैग। बग़ल की ओर का जो ड्रैग किसी लिंक पर शुरू होता है, वह सक्रिय इंडिकेटर को चलाता है और लिंक के पते को ड्रैग नहीं करता। किसी लिंक पर छोड़ा जाए, तो वह उस लिंक पर सादा दबाना है:
valueबदलने तक इंडिकेटर मौजूदा गंतव्य पर लौट आता है। - अक्षम। अक्षम लिंक किसी भी तरीक़े से खोला नहीं जा सकता और फ़ोकस के क्रम से बाहर हो जाता है।
variant |
मौजूदा गंतव्य | किसके लिए |
|---|---|---|
tonal (डिफ़ॉल्ट) |
secondary container रंग का एक हल्का इंडिकेटर, जिसके आइकन और लेबल उस कंटेनर के कॉन्टेंट रंग में होते हैं। | ज़्यादातर बार। |
filled |
primary रंग का एक गहरा इंडिकेटर, जिस पर उसके आइकन और लेबल उलटे रंग में होते हैं। | वह बार जिसे भरी-भरी स्क्रीन से अलग दिखना है: नक़्शा, फ़ोटो ग्रिड, प्लेयर। |
जिन गंतव्यों को इंडिकेटर नहीं ढकता, वे दोनों में एक जैसे दिखते हैं। वेरिएंट यह बदलता है कि चयन कितना उभारकर बनाया जाता है, यह नहीं कि क्या पढ़कर सुनाया जाता है: tonal और filled बार वही नाम, रोल और स्टेट देते हैं। अक्षम मौजूदा गंतव्य अपना tonal इंडिकेटर रखता है, जिस पर अक्षम कॉन्टेंट होता है; filled इंडिकेटर वैसे ही फीका पड़ता है जैसे अक्षम filled बटन, क्योंकि primary रंग पर अक्षम कॉन्टेंट पढ़ना मुश्किल होता।
m3-like और cupertino प्रीसेट filled को छोड़ देते हैं, क्योंकि Material के नेविगेशन बार और Apple के टैब बार की एक ही स्टाइल है। m3-like Material का बॉक्स सिर्फ़ आइकन के पीछे रखता है, लेबल उसके नीचे और गंतव्य के चारों ओर कोई बॉक्स नहीं, और cupertino मौजूदा टैब को सिर्फ़ अपने टिंट से चिह्नित करता है। दोनों में ड्रैग के दौरान कुछ चलता हुआ नहीं दिखता, और छोड़ने पर चुनाव फिर भी होता है।
- लेबल को एक छोटे शब्द तक रखें: “इनबॉक्स”, “खोज”, “प्रोफ़ाइल”। जो लेबल अपने गंतव्य में नहीं समाता, वह अपने अंत पर एलिप्सिस के साथ काटा जाता है, और कुछ भी अगली पंक्ति में नहीं जाता।
filledसिर्फ़ वहाँ इस्तेमाल करें जहाँ tonal इंडिकेटर बार के पीछे की स्क्रीन में खो जाएगा।- गंतव्य और उनका क्रम सबसे ऊपरी स्तर की हर स्क्रीन पर एक जैसा रखें।
- हर गंतव्य के लिए एक ही आइकन स्टाइल इस्तेमाल करें, और मौजूदा गंतव्य के लिए भरा हुआ रूप बार को बनाने दें।
- बार को “बनाएँ” या “शेयर करें” जैसी क्रियाओं के लिए इस्तेमाल न करें। मुख्य ऐक्शन बटन या ऐप बार इस्तेमाल करें।
- इसमें तीन से कम या पाँच से ज़्यादा गंतव्य न रखें। गिनती डीबग बिल्ड में रिपोर्ट की जाती है। बाक़ी को नेविगेशन ड्रॉअर में ले जाएँ।
- जो गंतव्य कभी-कभी उपलब्ध नहीं होता, उसे न छिपाएँ। उसे अक्षम करें, ताकि बार का रूप बना रहे।
- एक साथ हर गंतव्य पर बैज न दिखाएँ।
- रोल
navigation- लेबलिंग
- Each destination is named by its label, drawn or not; its icon is decorative, and so is the covered copy of its icon and label. A badge adds its description (badgeLabel, or the displayed count) after the name, and a link that opens a new context its targetLabel after that. The bar's label names the bar itself.
- न्यूनतम टार्गेट
- दिखने वाला आकार छोटा होने पर भी हिट एरिया न्यूनतम टार्गेट साइज़ को पूरा करता है। minimum 32px · pointer 44px · spacing 8px · touch 48px
कीबोर्ड
| कुंजियाँ | क्रिया |
|---|---|
| Tab | Moves focus to the next destination that is not disabled: each destination is a tab stop, as the links of a navigation region are. |
| Enter / Space | Activates the focused destination (Enter only for a destination that is a link: it follows the link, and Space is left to the platform). |
| Enter with a modifier key, on a link (the web) | What the browser does with a link: another tab or window, a download. The bar emits nothing and selects nothing (NVB-31). |
| Escape | Cancels a pointer drag of the active indicator in progress: the indicator returns and nothing is selected. Otherwise it does nothing. |
टिप्पणियाँ
- The semantics follow each platform's idiom for a bar of top-level destinations. On the web it is a navigation landmark whose destinations are links (or buttons in an app that does not change the URL) with aria-current="page" on the current one: that is how a web user recognises site navigation, and the tablist pattern would promise tab panels and arrow-key movement that a switch of whole screens does not have. On iOS, Android, Flutter and React Native the same bar is the platform's tab bar (UITabBar, BottomNavigationView and Material's NavigationBar all expose their items as tabs), so each destination is announced as a tab with its selected state and position.
- Selected and the current page are one thing. The bar lists the product's top-level places and the selected one is the place being shown, which the web exposes as aria-current="page" on a button and on a link alike. A site of separate pages changes who says which it is — the page, through value, not a press — and nothing else: a link destination is followed, the bar never selects it by itself, and no destination is ever selected and another current.
- Screen readers announce, for example, "Inbox, tab, 1 of 4, selected, 3 unread": name, role, position, state, then the badge's description.
- Labels do not wrap: a bar's height is part of the screen's layout. A label longer than its item container allows is truncated, and stays whole as the destination's name. At 200% text size the bar and its item containers grow, and iOS shows the large-content viewer on a long press, as its own tab bar does.
- The variant changes how strongly the selection is drawn, not what is announced: a tonal and a filled bar expose the same names, roles and states.
- The drag is never the only way to choose (WCAG 2.5.7): a tap, a click, Enter and Space remain, and the keyboard is unchanged. While a drag lasts nothing a destination exposes changes and nothing is announced; the release announces once, as an activation does. With a screen reader running a one-finger drag is the reader's, and activation works as before.
- How a state looks is a value decision of the active design system; components read the state's tokens and never compute the effect themselves.
इससे जनरेट किया गया: specs/navigation-bar.spec.json, tokens/sys/measure.tokens.json
- वेब पर बार एक नेविगेशन लैंडमार्क है जिसका नाम
labelसे आता है। हर गंतव्य एक लिंक (hrefके साथ) या एक बटन है, और मौजूदा गंतव्य परaria-current="page"होता है, लिंक पर भी और बटन पर भी: मौजूदा पेज के लिए कोई दूसरा स्टेट नहीं है। यह टैब लिस्ट नहीं है: पूरी स्क्रीन के बीच बदलने में न टैब पैनल होते हैं, न ऐरो कुंजियों से चलना। - iOS, Android, Flutter और React Native पर बार प्लैटफ़ॉर्म का टैब बार है, जैसे उनके अपने बॉटम बार हैं। हर गंतव्य टैब रोल वाला एक एलिमेंट है (SwiftUI पर selected ट्रेट वाला एक बटन), अपने चयनित स्टेट और सेट में अपनी जगह के साथ, जिसका नाम उसका लेबल है, चाहे लेबल दिखाया गया हो या नहीं। स्क्रीन रीडर, उदाहरण के लिए, कहता है: “इनबॉक्स, टैब, 4 में से 1, चयनित, 3 अपठित”।
- आइकन सहायक तकनीक से छिपा रहता है। बैज अपना विवरण (
badgeLabel, या वह संख्या जो वह दिखाता है) नाम और स्टेट के बाद जोड़ता है, और नया संदर्भ खोलने वाला लिंक उसके बाद अपनाtargetLabelजोड़ता है। - हर गंतव्य जो अक्षम नहीं है, अपना अलग Tab स्टॉप है, जैसे किसी नेविगेशन रीजन के लिंक होते हैं। Enter और Space फ़ोकस वाले गंतव्य को सक्रिय करती हैं (वेब पर लिंक के लिए सिर्फ़ Enter)। अक्षम गंतव्य फ़ोकस नहीं लेते और अक्षम के रूप में पढ़कर सुनाए जाते हैं।
- फ़ोकस रिंग गंतव्य के बॉक्स के चारों ओर बनती है और बार के भीतर रखी जाती है, सिर्फ़ कीबोर्ड फ़ोकस के लिए।
- इंडिकेटर का ड्रैग छोड़े जाने तक पढ़कर सुनाई जाने वाली कोई चीज़ नहीं बदलता, और फ़ोकस को कभी नहीं हटाता।
- हर आइकन और लेबल की वह उलटे रंग वाली प्रति जिसे इंडिकेटर ढकता है, सजावटी है: सहायक तकनीक को हर गंतव्य एक ही बार मिलता है, और
variantयह नहीं बदलता कि क्या पढ़कर सुनाया जाता है। - पूरा सेल हिट एरिया है: बार की पूरी ऊँचाई और उसकी चौड़ाई का बराबर हिस्सा, कम से कम न्यूनतम टार्गेट जितना। जो बार अपने गंतव्यों के लिए बहुत सँकरा है, वह भी अपनी चौड़ाई बराबर बाँटता है: सेल टार्गेट से नीचे तक सँकरे हो जाते हैं, बजाय इसके कि बार अपनी जगह से चौड़ा हो।
- बड़ा टेक्स्ट बार को, और उसके साथ हर गंतव्य के बॉक्स को, बढ़ाता है, ताकि लेबल अब भी एक पंक्ति में समाएँ। आइकन स्केल नहीं किए जाते। जो लेबल काटा गया है, वह गंतव्य के नाम के रूप में पूरा रहता है। जहाँ iOS large-content viewer देता है, वहाँ देर तक दबाने पर गंतव्य का आइकन और लेबल बड़े करके दिखाए जाते हैं।
- तीन से कम या पाँच से ज़्यादा गंतव्य, बिना लेबल का गंतव्य, ऐसा मान जो किसी गंतव्य का नाम नहीं है, और दो बार इस्तेमाल हुआ मान, डीबग बिल्ड में रिपोर्ट किए जाते हैं। इनकी भी रिपोर्ट की जाती है: ऐसा लिंक जो
targetLabelके बिना नया संदर्भ खोलता है, ऐसाhrefजो किसी स्क्रिप्ट का नाम लेता है या पढ़ा नहीं जा सकता, और ऐसाtargetजिसे बार परिभाषित नहीं करता।
प्लैटफ़ॉर्म की ज्ञात कमियाँ:
- SwiftUI, Compose, Flutter और React Native में लिंक वाले गंतव्य नहीं हैं: वहाँ गंतव्य अभी
hrefनहीं लेता। - Web: हर साइज़
remके अनुसार चलता है, इसलिए ब्राउज़र का बड़ा टेक्स्ट साइज़ आइटम के कंटेनर और आइकन को भी बढ़ाता है। अकेले Tanrei के टाइप को बड़ा करने से ऐसा नहीं होता। - SwiftUI: सेल का न्यूनतम साइज़ प्लैटफ़ॉर्म का अपना टार्गेट है, macOS पर 44 पॉइंट, जबकि स्पेक 48 पॉइंट का टच टार्गेट बताता है।
- SwiftUI: iOS के बाहर गंतव्य सेट में अपनी जगह को अपने मान टेक्स्ट के रूप में रखता है (“2 of 4”), सिर्फ़ अंग्रेज़ी में। इमेज आइकन, जैसे कोई SF Symbol, चयन के अनुसार नहीं बदलता: चयनित गंतव्य के लिए भरा हुआ सिंबल ख़ुद दें। large-content viewer बना हुआ है, पर अभी किसी टेस्ट ने उसे चलाकर नहीं देखा है।
- Compose में बार के स्तर का कोई मान नहीं है, इसलिए ऐसे मान के बारे में रिपोर्ट करने को कुछ नहीं है जो किसी गंतव्य का नाम नहीं है: किसी को न चुनने के लिए किसी आइटम को selected चिह्नित न करें।
- Flutter के सिमैंटिक्स में सेट के भीतर की जगह नहीं है, इसलिए “4 में से 1” पढ़कर नहीं सुनाया जाता।
- SwiftUI, Flutter और React Native आइकन की फ़ैमिली और फ़िल को चयन के मोशन के दौरान बदलने के बजाय तुरंत बदल देते हैं।
- React Native में large-content viewer नहीं है। गंतव्य सेट में अपनी जगह को अपने मान टेक्स्ट के रूप में रखता है (“1 of 4”), अंग्रेज़ी में, जब तक आप
positionTextन दें। - React Native: चयन का मोशन, इनसेट और TalkBack और VoiceOver जो पढ़कर सुनाते हैं, ये अभी किसी डिवाइस पर जाँचे नहीं गए हैं।
- हर प्लैटफ़ॉर्म, डिफ़ॉल्ट सिस्टम: tonal इंडिकेटर का बार के मुक़ाबले कंट्रास्ट क़रीब 1.15:1 है, और iOS का एक्सेसिबिलिटी ऑडिट इसे चिह्नित करता है। भरा हुआ आइकन और लेबल का रंग भी चयन को चिह्नित करते हैं, और जहाँ यह मायने रखता है वहाँ
filledकम से कम 3:1 का इंडिकेटर देता है।
- हर गंतव्य को एक लेबल दें, उस बार में भी जो कोई लेबल नहीं बनाता।
- बार को
labelसे नाम दें, जैसे “मुख्य”, ख़ासकर तब जब स्क्रीन में कोई दूसरा नेविगेशन रीजन हो। - हर बैज को ऐसा
badgeLabelदें जो बताए कि वह क्या गिनता है, और बिंदु के लिए हमेशा दें। - हर गंतव्य का मान अनोखा और स्थिर रखें।
- अलग-अलग पेजों वाली साइट में हर पेज पर
valueको उस पेज के गंतव्य पर सेट करें। बार किसी लिंक को अपने आप नहीं चुनता। - नया टैब खोलने वाले लिंक को अपने प्रॉडक्ट की भाषा में
targetLabelदें, जैसे “नए टैब में खुलता है”। Tanrei अपना कोई शब्द साथ नहीं देता। - Compose पर ठीक एक आइटम को
selectedचिह्नित करें, या किसी को नहीं। Flutter पर reselect और change में फ़र्क़ करने के लिए मिले हुए इंडेक्स की तुलनाselectedIndexसे करें। - React Native पर
positionTextअपने प्रॉडक्ट की भाषा में दें, औरTanreiProviderको विंडो के इनसेट दें।