التخطّي إلى المحتوى
menumenu tanreiexpand_morecontrasttranslate
tanreiexpand_more
البدءWebReactSwiftUIJetpack ComposeFlutterReact Nativeالإعدادات الجاهزةنظام التصميم الخاص بكاستخدام Tanrei مع وكلاء الذكاء الاصطناعيالعلامة التجاريةرموز التصميمأنظمة التصميم والتخصيصTheme Studioاللونالطباعةالأيقوناتالشكلالارتفاعالحركةحالات التفاعلالسلوكالتخطيطإمكانية الوصولالكلماترموز الألوانرموز السلّم الطباعيرموز الشكلرموز الارتفاعرموز الحركةرموز الحالةرموز التباعد والقياسالمكوّناتالزرزر الإجراء الرئيسيالزر المقسَّممجموعة الأزرارزر مع قائمةشريط الأدواتزر النسخخانة الاختيارزر الاختيارمفتاح التبديلالرقاقةقائمة الخياراتشريط التمريرحقل شريط التمريرالتقويمDateTimePickerمجموعة الحقولمجموعة أزرار الاختيارمجموعة خانات الاختيارعنصر الاختيارحقل الاختيارشريط القوائمرفع الملفاتمنتقي الملفات متقدّمساحة الإفلاتحقل إدخال النص متقدّمحقل النصحقل الرقاقاتالحقلمربع التحرير والسرد متقدّمحقل التحرير والسردحقل إدخال العدد متقدّمحقل العددحقل إدخال اللون متقدّمحقل اللونحقل إدخال الرمز لمرة واحدة متقدّمحقل الرمز لمرة واحدةحقل إدخال النص المدمج متقدّممربع كتابة الرسائلالبطاقةالفاصلالطبقة النمطية متقدّممربع الحوارالقائمة (list)صف القائمةاللوحة السفليةاللوحة الجانبيةالعرض الدوّاركتلة الشيفرةالجدولاللوحة المنبثقةالخطواتالأكورديونقائمة الوصفالشكل التوضيحيهيكل التطبيقرأس الصفحةالعرض الشجريالخط الزمنيمعاينة الصورمقبض تغيير الحجمالإطار القابل لتغيير الحجممنطقة التمريرالشارةمؤشر التقدمالعدّادعارض الأرقام المتحرّكمؤشر التحميلشريط الإشعار (Snackbar)التلميحاختصار لوحة المفاتيحالوسمالشيفرة المضمَّنةالتنويهالصورة الرمزيةالحالة الفارغةمجموعة الوسومهيكل التحميلعنصر الملفمربع اللونالنص المتحركعلامات التبويبعرض التبويباتشريط التطبيقشريط التنقلدرج التنقلالبحثالرابطالتنقل بين الصفحاتروابط السابق والتاليمؤشر الخطواتمسار التنقلجدول المحتوياتبطاقة الرابطقائمة FABالحالةكيف يُبنى Tanreiالمساهمةالترخيص والإسناد
الرئيسيةالمكوّناتشريط الأدوات

شريط الأدوات

يجمع مجموعة من عناصر التحكم المترابطة في موضع توقف واحد للمفتاح Tab، ضمن المحتوى حيث يحتاج إليه، أو راسيًا على امتداد الحافة السفلية، أو عائمًا فوق المحتوى. تنقل مفاتيح الأسهم بين عناصر التحكم فيه، وما لا تتسع له المساحة ينتقل إلى قائمة الفائض.

content_copyعرض بتنسيق Markdown
الفئة
الإجراءات
الرموز
comp.toolbar
المستوى
أساسي

نظرة عامة

Web
tanrei-toolbar
schedule
SwiftUI
TanreiToolbar
schedule
Jetpack Compose
TanreiToolbar
schedule
Flutter
TanreiToolbar
schedule
React Native
Toolbar
schedule

مولَّد من docs/status/status.json, specs/toolbar.spec.json

ضمن المحتوى، وراسٍ، وعائم

format_boldformat_italicformat_underlinedlinkimagearchivedeletemark_email_unreaddrive_file_moveeditink_highlighterink_erasercheck

الاستخدام

يجمع شريط الأدوات مجموعة من عناصر التحكم المترابطة: إجراءات، وأزرار تبديل، وزرًّا يفتح قائمة خيارات، وزرًّا مع قائمة. وعناصره هي أزرار Button وأزرار مع قائمة من Tanrei من عندك، لكل منها تسميته ونقرته وحالته. يرتّبها شريط الأدوات بترتيب القراءة، ويفصل المجموعات بعضها عن بعض، وينقل تركيز لوحة المفاتيح بينها، ويخفي ما لا تتسع له المساحة في قائمة الفائض. ولا يغيّر مظهرها أبدًا، فالزر Button بأيقونة فقط يبدو في شريط الأدوات ويتصرف كما في أي مكان آخر.

وله ستة أنواع من العناصر:

  • النوع action: زر Button بأيقونة فقط. وزر التبديل مثل «غامق» واحد منها ضُبطت فيه الخاصية toggle.
  • النوع button: زر Button له تسمية ظاهرة، وقد يكون زر تبديل أيضًا، مثل عامل تصفية يعمل أو لا يعمل.
  • النوع menu-button: زر Button رُبطت به قائمة خيارات من Tanrei، مثل «ترتيب» أو «إدراج». القائمة قائمتك وتقف بجانب زرها. ولا يتولى شريط الأدوات ترتيبها.
  • النوع button-with-menu: إجراء رئيسي مع قائمة بإجراءات مرتبطة به. وكل نصف منه موضع توقف خاص لمفاتيح الأسهم.
  • النوع group: سلسلة من العناصر المترابطة، مثل «غامق» و«مائل» و«تسطير». لا ترسم شيئًا من عندها. أعطها الخاصية label حين يكون للتجميع معنى عند الشخص، مثل «نمط النص».
  • النوع separator: خط بين عنصرين ليسا في مجموعات. وهو على الويب فاصل يرسمه شريط الأدوات كما يرسم الخط بين مجموعتين.

ضمن المحتوى (inline، الافتراضي). يقف شريط الأدوات ضمن المحتوى حيث يضعه تخطيطك، في المحتوى الذي يعمل عليه: فوق جدول، أو في أعلى محرِّر، أو بجانب قائمة صفًّا من عوامل التصفية. وطوله بقدر ما تحتاج إليه عناصره، ولا يزيد أبدًا على ما يسمح به التخطيط. وليس له في النظام الافتراضي سطح ولا ظل ولا حافة من عنده، ويصطف طرفاه مع المحتوى المحيط به.

الراسي (docked). يمتد شريط الأدوات الراسي على الحافة السفلية للشاشة. يصل لونه إلى ما تحت مؤشر الشاشة الرئيسية أو شريط الإيماءات، وتبقى عناصره فوقه وداخل الهوامش الجانبية (insets). يقرأ الويب env(safe-area-inset-bottom)، ويضع SwiftUI الشريط بواسطة .safeAreaInset(edge: .bottom)، ويأخذ Compose القيمة windowInsets (أشرطة التنقل افتراضيًّا)، ويقرأ Flutter الحشو السفلي من MediaQuery. ويأخذ React Native هوامشه من الخاصية insets على شريط الأدوات أو من TanreiProvider، لأن Tanrei لا يعتمد على أي حزمة للمنطقة الآمنة.

العائم (floating). شريط الأدوات العائم لا يحدد موضعه بنفسه، كما لا يفعل زر الإجراء الرئيسي. تخطيطك هو الذي يضعه، في الوسط فوق أسفل المحتوى عادةً، أو بجانب حافة النهاية للمحتوى حين يكون عموديًّا.

تعرض عيّنتا Web و React المواصفة الحالية. أما SwiftUI و Compose و Flutter و React Native فمتأخرة. ما زالت تقدّم المراجعة السابقة لشريط الأدوات وللزر، وفيها شريط الأدوات راسٍ ما لم تقل غير ذلك، ولا يحمل إلا أزرار Button، ويمرّر ما لا تتسع له المساحة، والإجراء بأيقونة فقط زر أيقونة مستقل. وتعرض عيّناتها تلك المراجعة إلى أن تلحق بالمواصفة.

<tanrei-toolbar label="التنسيق" overflow-label="خيارات تنسيق إضافية">
  <tanrei-toolbar-group label="نمط النص">
    <tanrei-button variant="text" toggle selected label="غامق"><span slot="icon">format_bold</span></tanrei-button>
    <tanrei-button variant="text" toggle label="مائل"><span slot="icon">format_italic</span></tanrei-button>
  </tanrei-toolbar-group>
  <tanrei-toolbar-group>
    <tanrei-button variant="text" label="إدراج رابط"><span slot="icon">link</span></tanrei-button>
    <tanrei-button variant="text" id="insert" label="إدراج"><span slot="icon">add</span></tanrei-button>
    <tanrei-menu anchor="insert">
      <tanrei-menu-item label="جدول"></tanrei-menu-item>
      <tanrei-menu-item label="خط أفقي"></tanrei-menu-item>
    </tanrei-menu>
  </tanrei-toolbar-group>
  <tanrei-divider></tanrei-divider>
  <tanrei-button variant="filled" toolbar-overflow="never">نشر</tanrei-button>
</tanrei-toolbar>

<!-- راسٍ على امتداد الحافة السفلية للشاشة. -->
<tanrei-toolbar variant="docked" label="إجراءات الرسالة">
  <tanrei-button variant="text" label="أرشفة"><span slot="icon">archive</span></tanrei-button>
  <tanrei-button variant="text" label="حذف"><span slot="icon">delete</span></tanrei-button>
  <tanrei-button variant="filled">رد</tanrei-button>
</tanrei-toolbar>

<script type="module">
  import '@tanrei/web/components/toolbar';
  import '@tanrei/web/components/button';
  import '@tanrei/web/components/divider';
  import '@tanrei/web/components/menu';
  // العناصر عناصرك: شريط الأدوات لا يضيف أحداثًا من عنده.
  document.querySelector('[label="إدراج رابط"]').addEventListener('click', insertLink);
  const insert = document.querySelector('tanrei-menu[anchor="insert"]');
  document.querySelector('#insert').addEventListener('click', () => (insert.open = !insert.open));
  insert.addEventListener('close', () => (insert.open = false));
</script>
import { Button, Divider, Toolbar, ToolbarGroup } from '@tanrei/react';

<Toolbar label="التنسيق" overflowLabel="خيارات تنسيق إضافية">
  <ToolbarGroup label="نمط النص">
    <Button variant="text" toggle selected={bold} label="غامق" onChange={(e) => setBold(e.detail.selected)}><span slot="icon">format_bold</span></Button>
    <Button variant="text" toggle selected={italic} label="مائل" onChange={(e) => setItalic(e.detail.selected)}><span slot="icon">format_italic</span></Button>
  </ToolbarGroup>
  <ToolbarGroup>
    <Button variant="text" label="إدراج رابط" onClick={insertLink}><span slot="icon">link</span></Button>
  </ToolbarGroup>
  <Divider />
  <Button variant="filled" toolbar-overflow="never" onClick={publish}>نشر</Button>
</Toolbar>

<Toolbar variant="docked" label="إجراءات الرسالة">
  <Button variant="text" label="أرشفة" onClick={archive}><span slot="icon">archive</span></Button>
  <Button variant="filled" onClick={reply}>رد</Button>
</Toolbar>
import Tanrei

// يقع شريط الأدوات الراسي في الهامش الآمن السفلي؛ وتمتد خلفيته تحته.
MessageView()
    .safeAreaInset(edge: .bottom, spacing: 0) {
        TanreiToolbar("إجراءات الرسالة") {
            TanreiIconButton("أرشفة", action: archive) { Image(systemName: "archivebox") }
            TanreiIconButton("حذف", action: delete) { Image(systemName: "trash") }
            TanreiButton("رد", action: reply)
        }
    }

TanreiToolbar("التنسيق", variant: .floating) {
    TanreiIconButton("غامق", isSelected: $bold) { Image(systemName: "bold") }
    TanreiIconButton("إدراج رابط", action: insertLink) { Image(systemName: "link") }
}
import androidx.compose.foundation.gestures.Orientation
import io.github.chnotchy.tanrei.components.TanreiButton
import io.github.chnotchy.tanrei.components.TanreiIconButton
import io.github.chnotchy.tanrei.components.TanreiToolbar
import io.github.chnotchy.tanrei.primitives.TanreiText
import io.github.chnotchy.tanrei.tokens.TanreiToolbarVariant

// شريط الأدوات الراسي يضيف إلى عناصره حشوًا بمقدار WindowInsets.navigationBars ما لم تمرِّر windowInsets.
TanreiToolbar(contentDescription = "إجراءات الرسالة") {
    TanreiIconButton(onClick = ::archive, contentDescription = "أرشفة") { TanreiText("archive") }
    TanreiIconButton(onClick = ::delete, contentDescription = "حذف") { TanreiText("delete") }
    TanreiButton(text = "رد", onClick = ::reply)
}

TanreiToolbar(contentDescription = "التنسيق", variant = TanreiToolbarVariant.Floating) {
    TanreiIconButton(onClick = {}, contentDescription = "غامق", checked = bold, onCheckedChange = { bold = it }) {
        TanreiText("format_bold")
    }
    TanreiIconButton(onClick = ::insertLink, contentDescription = "إدراج رابط") { TanreiText("link") }
}

// الاتجاه العمودي لشريط الأدوات العائم؛ وتخطيطك هو الذي يضعه.
TanreiToolbar(
    contentDescription = "عناصر تحكم الخريطة",
    variant = TanreiToolbarVariant.Floating,
    orientation = Orientation.Vertical,
) {
    TanreiIconButton(onClick = ::zoomIn, contentDescription = "تكبير") { TanreiText("add") }
    TanreiIconButton(onClick = ::zoomOut, contentDescription = "تصغير") { TanreiText("remove") }
}
import 'package:tanrei/tanrei.dart';

TanreiToolbar(
  semanticLabel: 'إجراءات الرسالة',
  children: <Widget>[
    TanreiIconButton(onPressed: archive, semanticLabel: 'أرشفة', icon: const Icon(AppSymbols.archive)),
    TanreiIconButton(onPressed: delete, semanticLabel: 'حذف', icon: const Icon(AppSymbols.delete)),
    TanreiButton(onPressed: reply, child: const Text('رد')),
  ],
);

TanreiToolbar(
  semanticLabel: 'عناصر تحكم الخريطة',
  variant: TanreiToolbarVariant.floating,
  orientation: Axis.vertical,
  children: <Widget>[
    TanreiIconButton(onPressed: zoomIn, semanticLabel: 'تكبير', icon: const Icon(AppSymbols.add)),
    TanreiIconButton(onPressed: zoomOut, semanticLabel: 'تصغير', icon: const Icon(AppSymbols.remove)),
  ],
);
import { Button, IconButton, Toolbar } from '@tanrei/react-native';

// تأتي الهوامش السفلية والجانبية من insets على TanreiProvider؛ وخاصية insets على شريط الأدوات نفسه تستبدل الجوانب التي تسمّيها.
<Toolbar accessibilityLabel="إجراءات الرسالة">
  <IconButton accessibilityLabel="أرشفة" onPress={archive}>archive</IconButton>
  <IconButton accessibilityLabel="حذف" onPress={remove}>delete</IconButton>
  <Button variant="filled" onPress={reply}>رد</Button>
</Toolbar>

<Toolbar variant="floating" accessibilityLabel="التنسيق">
  <IconButton accessibilityLabel="غامق" toggle selected={bold} onSelectedChange={setBold}>format_bold</IconButton>
  <IconButton accessibilityLabel="إدراج رابط" onPress={insertLink}>link</IconButton>
</Toolbar>

المواصفات

مجموعات وفاصل، وزر قائمة خيارات، وزر مع قائمة، وأزرار تبديل لها تسميات، وقائمة الفائض

undoredosortالمفتوحةالمسندة إليّذات المرفقاتarchivedeletemark_email_unreaddrive_file_movelabelflagsnoozeprintattach_fileimagelinkإرسالaddremovemy_locationlayers

البنية

الجزء الوصف
1 container The surface that holds the items: none of its own in the default system where the toolbar stands inline in the content; a bar across the bottom edge of the screen whose color reaches under the bottom system inset (docked); or a rounded, raised surface over the content (floating).
2 items The controls, in reading order: the product's own Tanrei Buttons, icon-only and labelled, toggles among them, Buttons that open a Menu, and Buttons with menu, alone or in groups. The toolbar lays them out and moves keyboard focus among them; it does not restyle them.
3 separator · اختياري A line across the toolbar between two groups, or where a separator item stands, or the empty space that takes its place, as the design system's separation says.
4 overflow-button · اختياري The icon-only Button at the end that opens a Menu of the items that do not fit, drawn only while some do not.
5 outline The docked toolbar's top edge, or the edge around a floating or an inline toolbar's whole shape (none in the default system for the last two).

الخصائص

الخاصية النوع القيمة الافتراضية الوصف
variant inline | docked | floating "inline" Inline stands in place where the layout puts it, as long as its items need and no longer than the layout allows, with no surface, shadow or edge of its own in the default system (an editor's formatting bar, a table's actions, a row of filters); docked is a full-width bar along the bottom edge of the screen, flush with it; floating is a rounded, raised surface over the content, as long as its items. One product places a toolbar inside its content on one screen, docks it on another and floats it on a third. A design system may add values.
orientation horizontal | vertical "horizontal" The direction the items run. Vertical is for an inline or a floating toolbar beside the content (a floating one on a large screen); a docked toolbar is always horizontal.
label string "" Names the toolbar for assistive technology ("Formatting", "Message actions"). Never drawn. Required.
overflow menu | scroll "menu" What happens when the items do not fit along the toolbar's axis: menu hides items from the end into an overflow menu at the end of the toolbar (TBR-18); scroll keeps every item and scrolls them (TBR-8).
overflowLabel string "" The overflow button's accessible name ("More actions"), in the product's language. Never drawn. Empty takes the product's words. Needed whenever the toolbar may be narrower than its items.
separation auto | divider | gap "auto" How two groups, or a separator item, set items apart: divider draws a line across the toolbar with space on each side, gap leaves empty space and no line. Auto takes comp.toolbar.separation, the design system's answer (divider in the default system).

المنافذ

المنفذ الوصف
default Holds the items, in reading order: Tanrei Buttons, icon-only and labelled, Buttons with a Tanrei Menu anchored to them (the Menu beside its Button), Buttons with menu, groups of them and separators.

العناصر

أنواع العناصر التي يكررها المكوّن. يسرد كل نموذج اختبار عناصره بالترتيب، وتسمّي كل منصة كل نوع بأسلوبها.

action

An icon action: a Button of the text variant and the medium size with an icon and no label, unless the product sets otherwise, laid out by the toolbar and not restyled; a toggle (bold, mute) is one with toggle set.

الخاصية النوع القيمة الافتراضية الوصف
label string "" Its accessible name ("Bold"), as the Button's label. Required.
variant filled | tonal | elevated | outlined | text "text" As the Button's variant: text for most actions, filled for the one the toolbar leads to (Done, Send).
toggle boolean false As the Button's toggle: the action switches something on and off.
selected boolean false As the Button's selected: whether a toggle is on.
disabled boolean false As the Button's disabled.
overflow auto | never "auto" Whether the toolbar may hide this item into its overflow menu when space runs out: never keeps it (Send, Done). Read by the toolbar to place the item.
المنفذ الوصف
icon Its glyph, as the Button's icon slot. A fixture item's content is this glyph.
الحدث الوصف
click The action was activated, as the Button's click.
change A toggle was switched, as the Button's change.
المواصفة Web SwiftUI Jetpack Compose Flutter React Native
العنصر tanrei-button TanreiButton TanreiButton TanreiButton Button
label · الخاصية label label contentDescription semanticLabel accessibilityLabel
variant · الخاصية variant variant variant variant variant
toggle · الخاصية toggle isSelected onCheckedChange isSelected toggle
selected · الخاصية selected isSelected checked isSelected selected
disabled · الخاصية disabled disabled enabled onPressed disabled
overflow · الخاصية toolbar-overflow toolbarOverflow Modifier.toolbarOverflow TanreiToolbarItem.overflow toolbarOverflow
click · الحدث click action onClick onPressed onPress
change · الحدث change isSelected onCheckedChange onPressed onSelectedChange
ملاحظات An icon-only <tanrei-button> child; the glyph is its content. An icon-only TanreiButton in the toolbar's view builder; a toggle is its isSelected: initializer. An icon-only TanreiButton called in the toolbar's content lambda. An icon-only TanreiButton in the toolbar's children. An icon-only Button element among the toolbar's children.

button

A labelled action: the button component, medium unless the product sets otherwise, laid out by the toolbar and not restyled.

الخاصية النوع القيمة الافتراضية الوصف
variant filled | tonal | elevated | outlined | text "filled" As the button's variant.
toggle boolean false As the button's toggle: a labelled toggle (a filter that is on or off).
selected boolean false As the button's selected: whether a toggle is on.
disabled boolean false As the button's disabled.
overflow auto | never "auto" Whether the toolbar may hide this item into its overflow menu when space runs out: never keeps it (Send, Done). Read by the toolbar to place the item.
المنفذ الوصف
default Its label, as the button's default slot. A fixture item's content is this label.
الحدث الوصف
click The button was activated, as the button's click.
change A toggle was switched, as the button's change.
المواصفة Web SwiftUI Jetpack Compose Flutter React Native
العنصر tanrei-button TanreiButton TanreiButton TanreiButton Button
variant · الخاصية variant variant variant variant variant
toggle · الخاصية toggle isSelected onCheckedChange isSelected toggle
selected · الخاصية selected isSelected checked isSelected selected
disabled · الخاصية disabled disabled enabled onPressed disabled
overflow · الخاصية toolbar-overflow toolbarOverflow Modifier.toolbarOverflow TanreiToolbarItem.overflow toolbarOverflow
click · الحدث click action onClick onPressed onPress
change · الحدث change isSelected onCheckedChange onPressed onSelectedChange
ملاحظات A <tanrei-button> child; the label is its content. A TanreiButton in the toolbar's view builder. A TanreiButton called in the toolbar's content lambda. A TanreiButton in the toolbar's children. A Button element among the toolbar's children.

menu-button

A Button that opens a Tanrei Menu anchored to it (Sort, Insert): icon-only unless the product sets otherwise, laid out by the toolbar as any other item and not restyled. The Menu is the product's, beside it in the toolbar; it is neither laid out nor an item.

الخاصية النوع القيمة الافتراضية الوصف
label string "" Its accessible name ("Sort"), as the Button's label. Required.
variant filled | tonal | elevated | outlined | text "text" As the Button's variant.
disabled boolean false As the Button's disabled.
overflow auto | never "auto" Whether the toolbar may hide this item into its overflow menu when space runs out: never keeps it (Send, Done). Read by the toolbar to place the item.
المنفذ الوصف
icon Its glyph, as the Button's icon slot. A fixture item's content is this glyph.
الحدث الوصف
click The button was activated, as the Button's click: the product opens its Menu.
المواصفة Web SwiftUI Jetpack Compose Flutter React Native
العنصر tanrei-button TanreiButton TanreiButton TanreiButton Button
label · الخاصية label label contentDescription semanticLabel accessibilityLabel
variant · الخاصية variant variant variant variant variant
disabled · الخاصية disabled disabled enabled onPressed disabled
overflow · الخاصية toolbar-overflow toolbarOverflow Modifier.toolbarOverflow TanreiToolbarItem.overflow toolbarOverflow
click · الحدث click action onClick onPressed onPress
ملاحظات A <tanrei-button id> child with a <tanrei-menu anchor="<its id>"> beside it, in the toolbar or in the same group. A TanreiButton with .tanreiMenu { … } attached, in the toolbar's view builder. A TanreiButton with a TanreiMenu anchored to it, called in the toolbar's content lambda. A TanreiButton that opens a TanreiMenu anchored to it, in the toolbar's children. A Button with a Menu anchored to it, among the toolbar's children.

button-with-menu

A Button with menu: a main action and a menu of related ones, each half a stop of the toolbar's arrow keys (TBR-25), laid out by the toolbar and not restyled.

الخاصية النوع القيمة الافتراضية الوصف
label string "" The leading half's label ("Save"), as the Button with menu's label.
menuLabel string "" The trailing half's accessible name ("More save options"), as the Button with menu's menuLabel.
variant filled | tonal | elevated | outlined "filled" As the Button with menu's variant.
disabled boolean false As the Button with menu's disabled.
overflow auto | never "auto" Whether the toolbar may hide this item into its overflow menu when space runs out: never keeps it (Send, Done). Read by the toolbar to place the item.
الحدث الوصف
click The main action was activated, as the Button with menu's click.
toggle The trailing half asks to open or close the menu, as the Button with menu's toggle.
المواصفة Web SwiftUI Jetpack Compose Flutter React Native
العنصر tanrei-button-with-menu TanreiButtonWithMenu TanreiButtonWithMenu TanreiButtonWithMenu ButtonWithMenu
label · الخاصية label title text label label
menuLabel · الخاصية menuLabel menuLabel menuContentDescription menuSemanticLabel menuAccessibilityLabel
variant · الخاصية variant variant variant variant variant
disabled · الخاصية disabled disabled enabled onPressed disabled
overflow · الخاصية toolbar-overflow toolbarOverflow Modifier.toolbarOverflow TanreiToolbarItem.overflow toolbarOverflow
click · الحدث click action onClick onPressed onPress
toggle · الحدث toggle isMenuPresented onMenuExpandedChange menuController onToggle
ملاحظات A <tanrei-button-with-menu> child, its menu items in slot="menu" as anywhere. A TanreiButtonWithMenu in the toolbar's view builder. A TanreiButtonWithMenu called in the toolbar's content lambda. A TanreiButtonWithMenu in the toolbar's children. A ButtonWithMenu among the toolbar's children.

group · مجموعة — تحتوي عناصر

A run of related items (Bold, Italic, Underline), optionally named; the toolbar sets it apart from what is next to it as separation says. It draws nothing of its own.

الخاصية النوع القيمة الافتراضية الوصف
label string "" Names the group for assistive technology ("Text style"); never drawn. Empty leaves the group unexposed: its items are the toolbar's.
المواصفة Web SwiftUI Jetpack Compose Flutter React Native
العنصر tanrei-toolbar-group TanreiToolbarGroup TanreiToolbarGroup TanreiToolbarGroup ToolbarGroup
label · الخاصية label label contentDescription semanticLabel accessibilityLabel
ملاحظات A <tanrei-toolbar-group> child holding items: display: contents, with role="group" and aria-label while its label is not empty. TanreiToolbarGroup(_ label:) { items } in the toolbar's view builder: an accessibility container named by its label, or none without one. TanreiToolbarGroup(contentDescription) { … } in the toolbar's content lambda: a traversal group named by its description, or none without one. TanreiToolbarGroup(semanticLabel:, children:) in the toolbar's children: a semantics container named by its label, or none without one. <ToolbarGroup accessibilityLabel>{items}</ToolbarGroup> among the toolbar's children: a view with role group while it has a label.

separator

A line across the toolbar between two items outside the groups: the toolbar draws it as it draws the line between two groups, and it is never a stop of the arrow keys.

المواصفة Web SwiftUI Jetpack Compose Flutter React Native
العنصر tanrei-divider TanreiDivider TanreiDivider TanreiDivider Divider
ملاحظات A <tanrei-divider> child: the toolbar draws the line itself, as between two groups (TBR-23), as an element of its own with role="separator", and leaves the divider unassigned. A TanreiDivider() in the toolbar's view builder; the toolbar draws the line from its own tokens. A TanreiDivider() called in the toolbar's content lambda; the toolbar draws the line from its own tokens. A TanreiDivider() in the toolbar's children; the toolbar draws the line from its own tokens. A Divider among the toolbar's children; the toolbar draws the line from its own tokens.

الحالات

السلوك

متطلبات بصيغة EARS. يُختبر تنفيذ كل منصة مقابل هذه المعرّفات. يُعرض نص المتطلبات كما ورد في ملف المواصفة، بالإنجليزية.

المعرّف المتطلب
TBR-1 WHILE variant is docked THE toolbar SHALL span the full width of its parent, be at least comp.toolbar.container.size.docked high above the bottom system inset, fill its container with comp.toolbar.container.color.docked, raise it by comp.toolbar.container.elevation.docked, round it by comp.toolbar.container.shape.docked, and draw its top edge comp.toolbar.outline.width thick in comp.toolbar.outline.color.docked.
TBR-2 WHILE variant is docked THE toolbar SHALL lay its items out in one row in reading order, the first comp.toolbar.container.padding-inline.docked from the start edge and the last as far from the end edge, with equal space between neighbours and never less than comp.toolbar.container.gap.docked, each item vertically centered in the row; a toolbar with one item SHALL center it.
TBR-3 WHILE variant is docked THE toolbar SHALL extend its container under the bottom system inset (home indicator, gesture bar, taskbar) and SHALL place its items above that inset and inside the left and right insets, so that its color reaches the screen's bottom edge while no item sits under a system bar.
TBR-4 WHILE variant is floating THE toolbar SHALL fill its container with comp.toolbar.container.color.floating, raise it by comp.toolbar.container.elevation.floating, round it by comp.toolbar.container.shape.floating eased by sys.shape.corner-smoothing, draw an edge comp.toolbar.outline.width thick in comp.toolbar.outline.color.floating around its whole shape, be as long along its axis as its items need — comp.toolbar.container.padding-inline.floating at each end and comp.toolbar.container.gap.floating between neighbours, or as much more as TBR-16 keeps for their targets — and at least comp.toolbar.container.size.floating across it, with every item centered across the axis.
TBR-5 WHILE variant is floating THE toolbar SHALL NOT position itself: it SHALL lay out at its own size where the layout that holds it places it (normally centered above the bottom edge of the content, clear of a navigation bar and of the system inset, or beside the content's end edge for a vertical toolbar), and SHALL NOT draw a scrim, move content or reach under a system inset.
TBR-6 WHILE orientation is vertical and variant is floating or inline THE toolbar SHALL stack its items from top to bottom in the order given, with its variant's paddings and gap along the vertical axis and at least its variant's container size as its width; WHILE orientation is vertical and variant is docked THE toolbar SHALL lay out as a horizontal docked toolbar and in debug builds report that a docked toolbar is horizontal.
TBR-7 WHEN the layout direction is right-to-left THE toolbar SHALL lay out a horizontal toolbar's items from the right edge, in reading order, mirrored; a vertical toolbar SHALL keep its top-to-bottom order.
TBR-8 WHILE overflow is scroll and the items need more length than the toolbar has along its axis THE toolbar SHALL keep every item at its own size and the gap at its minimum, SHALL scroll its items along its axis so that every item stays reachable, and SHALL bring an item that receives keyboard focus fully into view; it SHALL NOT wrap, shrink or hide an item.
TBR-9 THE toolbar SHALL NOT restyle its items: each SHALL render as the Button it is, from its own tokens, variant and size, and SHALL keep its own press, focus, target and disabled behaviour and its own semantics, a toggle Button staying a toggle. Between two items the hit areas SHALL never overlap (as BGR-4): in a docked toolbar they SHALL meet at the middle of the gap, and in a floating or an inline one where the lengths TBR-16 keeps for the two items meet; each item SHALL keep its full target on every side that has no neighbour. In a docked toolbar the gap (at least comp.toolbar.container.gap.docked) is what keeps an item's target whole between its neighbours: at sys.target.touch minus the item's length or more, every item keeps its full target there, as the default system's gap does for every Button size; a layer that narrows that gap narrows the targets between items. In a floating or an inline toolbar TBR-16 keeps it, whatever comp.toolbar.container.gap.floating or comp.toolbar.container.gap.inline is.
TBR-10 THE toolbar SHALL be one Tab stop: the item that had keyboard focus last, or else the first item that is not disabled. Its items are its own and its groups' items, in reading order; a separator and a Menu anchored to an item are none. WHILE an item has keyboard focus, Right Arrow and Left Arrow in a horizontal toolbar (Left Arrow moving to the next item in a right-to-left layout) and Down Arrow and Up Arrow in a vertical one SHALL move focus to the next and previous item that is not disabled, wrapping at the ends, and Home and End to the first and last such item; moving focus SHALL NOT activate an item, and Enter and Space SHALL act on the focused item as that item does. A disabled item SHALL NOT take focus, as its own spec says (BTN-2).
TBR-11 THE toolbar SHALL expose itself as a toolbar named by label, with its orientation, on a platform that has a toolbar role, and on any other platform as a group named by label that contains its items in order; each item SHALL keep its own name, role and state, and the toolbar SHALL add nothing to them.
TBR-12 WHILE label is empty THE toolbar SHALL still render, and in debug builds report that it has no accessible name. IF the toolbar holds no item, or an element that is neither one of its item kinds nor a Menu anchored to one of its items, THE toolbar SHALL still lay it out, and in debug builds report it, because a field or a slider would take the arrow keys the toolbar moves focus with (the WAI-ARIA toolbar pattern).
TBR-13 WHEN variant names a value that the active design system does not have, or orientation a value the component does not define, THE toolbar SHALL render with the default value (inline, horizontal), and in debug builds report the unknown value. A variant value that a layer adds SHALL take the inline structure with its own values, because the structure is not a value a layer can set. WHEN overflow or separation names a value the component does not define THE toolbar SHALL render with menu or auto, and in debug builds report it.
TBR-14 WHILE the text size is enlarged THE toolbar SHALL grow across its axis to hold its items (its size is a minimum) and SHALL NOT scale its items itself; each item grows or keeps its size as its own spec says.
TBR-15 THE toolbar 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 toolbar is shown THE toolbar SHALL draw itself for the new direction at once, without a motion of its own, keeping its focus and the item its Tab stop stands on.
TBR-16 WHILE variant is floating THE toolbar SHALL lay its items comp.toolbar.container.gap.floating apart (and WHILE it is inline comp.toolbar.container.gap.inline apart, TBR-17), measured between their visible bounds along its axis, and SHALL move two neighbours further apart only as far as each needs in order to keep, centred on itself, a length of sys.target.touch along the axis that its neighbour's does not reach into, because items that stand this close cannot extend a hit area over each other (as BGR-3): where the token is 0, as in the default system, an item at least sys.target.touch long touches its neighbour, and a shorter one stands half of what it lacks away from it. THE toolbar SHALL NOT widen, resize or restyle an item to do so (TBR-9), SHALL space its items the same whatever the input type, so that the toolbar does not change with the pointer, and SHALL space them so along the vertical axis WHILE orientation is vertical (TBR-6). A floating toolbar is as long as its items need (TBR-4) and never spreads them across a width; WHILE variant is docked THE toolbar SHALL spread its items across its width and keep comp.toolbar.container.gap.docked as the least space between them (TBR-2), unchanged.
TBR-17 WHILE variant is inline THE toolbar SHALL lay its items out in one line along its axis where the layout places it, as long as its items need and never longer than the layout allows, with comp.toolbar.container.padding-inline.inline at each end, comp.toolbar.container.gap.inline between neighbours spaced as TBR-16 spaces a floating toolbar's, and at least comp.toolbar.container.size.inline across its axis; it SHALL fill its container with comp.toolbar.container.color.inline, raise it by comp.toolbar.container.elevation.inline, round it by comp.toolbar.container.shape.inline and edge it comp.toolbar.outline.width thick in comp.toolbar.outline.color.inline (transparent, none and no edge in the default system), and SHALL NOT read a system inset, position itself or spread its items.
TBR-18 WHILE overflow is menu and the items, at their own sizes and with the least gaps, need more length along the axis than the layout offers the toolbar — the length it would take with every item shown, which a parent as long as its content passes on from further up, so that it can grow while the toolbar and its parent stay as long as the items still shown — THE toolbar SHALL hide items from its end, in reverse reading order and one at a time, skipping every item whose overflow is never, until the items that remain and the overflow button fit; SHALL draw the overflow button after the last item that remains — an icon-only Tanrei Button of the text variant and the medium size, showing the glyph more_horiz in a horizontal toolbar and more_vert in a vertical one, named by overflowLabel or the product's words, exposed as a button that opens a menu, with its expanded state; and SHALL NOT hide an item whose overflow is never even when the items then do not fit, in which case TBR-8 applies to what remains.
TBR-19 THE toolbar SHALL decide which items are hidden before the first frame in which it is drawn, and again in the frame in which its items or the length the layout offers it (TBR-18) change, so that no item is drawn and then hidden in a later frame, and its size across its axis never changes because an item was hidden or shown; hiding and showing items SHALL NOT be animated, because it answers a change of the layout that a motion would lag behind.
TBR-20 WHEN the overflow button is activated THE toolbar SHALL open a Tanrei Menu anchored to it, placed bottom-end (in a vertical toolbar, at the side away from the edge it stands at), holding the hidden items in reading order: an action or a labelled Button as a menu item with its label and its icon, disabled while it is; a toggle as a checkbox item with its selected state; a menu button as a submenu item holding its menu's items; a Button with menu as an item for its main action followed by a submenu item named by its menuLabel; and a separator, or the boundary between two groups, as the menu's separation. Activating a menu item SHALL do exactly what activating the hidden item does — the same click or change, once, from that item — and close the menu.
TBR-21 WHEN the item that is the toolbar's Tab stop, or has keyboard focus, is hidden THE toolbar SHALL make the overflow button the Tab stop and, if focus was on the item, move focus to the overflow button; THE overflow button SHALL be the last stop of the arrow-key order (TBR-10).
TBR-22 THE toolbar SHALL lay out a group's items in its own line, in place, as items of the toolbar (the group draws nothing of its own), SHALL expose a group whose label is not empty as a group named by that label, and a group whose label is empty as nothing (its items are the toolbar's), unless the product names it (TBR-26).
TBR-23 THE toolbar SHALL set two neighbouring groups — or a group and an item outside any group — apart as separation names: WHILE it is divider by a line comp.toolbar.divider.thickness thick and comp.toolbar.divider.length long across the axis, centred, in comp.toolbar.divider.color, with comp.toolbar.group.gap on each side; WHILE it is gap by twice comp.toolbar.group.gap of empty space. A separator item SHALL be drawn the same way wherever it stands. THE toolbar SHALL expose each such line as a separator, SHALL never make it a stop of the arrow keys, and SHALL draw no line at the start or the end of the toolbar, and never two lines side by side.
TBR-24 WHILE an item is the anchor of a Menu THE toolbar SHALL keep it an item of the arrow-key order and SHALL neither lay out nor count the Menu; WHILE that Menu is open its keys SHALL be the Menu's, and WHEN it closes focus SHALL return to its anchor, which stays the Tab stop.
TBR-25 THE toolbar SHALL make each half of a Button with menu a stop of its own in the arrow-key order, the leading half first in reading order, each keeping its own name, role and state.
TBR-26 WHERE the platform has ARIA attributes (the web), the toolbar's host and a group's host carries its role (TBR-11, TBR-22) itself, so what the product writes on it is not moved, but for a name: WHILE label is not empty THE toolbar SHALL hold the product's aria-label and aria-labelledby on that host as their data-aria- twins, so that label is its whole name although the platform gives aria-labelledby the precedence, and WHEN label is emptied SHALL give them back as they were written; WHILE label is empty a name the product gives so — aria-label, or aria-labelledby naming an element — SHALL be its name and SHALL NOT be reported as having none in debug builds (TBR-12). A group whose label is empty and that the product names so SHALL be exposed as a group named by that name, as one with a label is: a group the product names is a named group, and a name on an element with no role would name nothing (TBR-22). WHEN the product removes one, or its data-aria- twin, or sets the ARIA property that reflects it (ariaLabel, ariaLabelledByElements) to null, THE toolbar SHALL take it away.

مطابقة الأسماء بين المنصات

التكافؤ لا يعني واجهات برمجية متطابقة. تعبّر كل منصة عن العقد نفسه بأسلوبها.

المواصفة Web SwiftUI Jetpack Compose Flutter React Native
المكوّن tanrei-toolbar TanreiToolbar TanreiToolbar TanreiToolbar Toolbar
variant · الخاصية variant variant variant variant variant
orientation · الخاصية orientation orientation orientation orientation orientation
label · الخاصية label label contentDescription semanticLabel accessibilityLabel
overflow · الخاصية overflow overflow overflow overflow overflow
overflowLabel · الخاصية overflowLabel overflowLabel overflowContentDescription overflowSemanticLabel overflowAccessibilityLabel
separation · الخاصية separation separation separation separation separation
ملاحظات The items are <tanrei-button> children, icon-only and labelled, <tanrei-button-with-menu> children, <tanrei-toolbar-group> children holding them, and <tanrei-divider> separators; a <tanrei-menu anchor> child anchored to an item's id is that item's Menu and is not laid out. The host has role="toolbar", aria-orientation and aria-label from label; a group with a label has role="group" and aria-label. The toolbar assigns each of its children, and a group each of its items, to a slot of its own (manual slot assignment), so that the toolbar draws the separations between them and leaves a hidden item unassigned: a hidden item is not drawn and keeps its place, its listeners and its state in the page. The overflow button and its menu are elements of the toolbar's shadow root. The roving Tab stop sets tabindex on the item elements (0 on the Tab stop, -1 on the others): an item delegates focus to the button in its shadow root, and a host whose tabindex is -1 takes that button out of the Tab order; a Button with menu is told which of its halves is the Tab stop through the internal channel (SPB-33). A docked toolbar's bottom inset is env(safe-area-inset-bottom). Snapshot harness: the stages of TBR-1, TBR-4, TBR-6 and TBR-18. TanreiToolbar(_ label: String, variant:, orientation:) { items }, a view builder of TanreiButtons, icon-only and labelled. A docked toolbar is placed with .safeAreaInset(edge: .bottom), its background ignoring the bottom safe area. SwiftUI's own .toolbar with a bottom-bar placement is not used: its bar cannot take the tokens. SwiftUI has no toolbar role: the toolbar is an accessibility container (.accessibilityElement(children: .contain)) labelled by label. The roving Tab stop is one focus group for the keyboard: Full Keyboard Access moves among its items with the arrow keys and leaves it with Tab. Lagging: the inline variant, the overflow menu, groups, separators, menu buttons and Buttons with menu as items are not built on this platform yet; it draws the docked and floating toolbar of icon-only and labelled Buttons, docked by default. .toolbarOverflow(.never) on an item keeps it; the overflow menu is a SwiftUI Menu drawn from the Tanrei Menu's tokens. TanreiToolbar(contentDescription, modifier, variant, orientation, windowInsets) { … }, the items called in its content lambda. windowInsets defaults to WindowInsets.navigationBars for a docked toolbar and to none for a floating one. Compose has no toolbar role: the toolbar is a traversal group (isTraversalGroup) labelled by contentDescription, and the README says so. The roving Tab stop is TanreiRovingFocus, the primitive the list, menu and tabs use, horizontal or vertical by orientation; the toolbar registers each item it holds. Lagging: the inline variant, the overflow menu, groups, separators, menu buttons and Buttons with menu as items are not built on this platform yet; it draws the docked and floating toolbar of icon-only and labelled Buttons, docked by default. Modifier.toolbarOverflow(TanreiToolbarOverflow.Never) on an item keeps it; the overflow menu is a TanreiMenu. TanreiToolbar(semanticLabel:, variant:, orientation:, children: [...]) (orientation is Flutter's Axis). A docked toolbar applies the bottom MediaQuery.padding itself, as SafeArea would, with its color under it. Flutter's widgets library has no toolbar role: the toolbar is a Semantics(container: true, explicitChildNodes: true, label:), and the README says so. The roving Tab stop is TanreiItemGroupMixin, the primitive the list, menu and tabs use, with its item axis set by orientation. Lagging: the inline variant, the overflow menu, groups, separators, menu buttons and Buttons with menu as items are not built on this platform yet; it draws the docked and floating toolbar of icon-only and labelled Buttons, docked by default. An item wrapped in TanreiToolbarItem(overflow: TanreiToolbarOverflow.never, child:) is kept; the overflow menu is a TanreiMenu. <Toolbar variant orientation accessibilityLabel insets>{items}</Toolbar>, the items being Button elements, icon-only and labelled. The view has role="toolbar". A docked toolbar takes the bottom inset from its own insets prop, falling back to TanreiProvider's insets; the package takes no safe-area dependency. The roving Tab stop and the arrow keys work where a hardware keyboard is attached, as the tabs row's do. Lagging: the inline variant, the overflow menu, groups, separators, menu buttons and Buttons with menu as items are not built on this platform yet; it draws the docked and floating toolbar of icon-only and labelled Buttons, docked by default. toolbarOverflow="never" on an item keeps it; the overflow menu is a Menu.

الرموز

الرمز يشير إلى القيمة المحلولة (فاتح)
--tanrei-comp-toolbar-container-color-docked sys.color.surface #ffffff
--tanrei-comp-toolbar-container-color-floating sys.color.surface-bright #ffffff
--tanrei-comp-toolbar-container-color-inline — #000000 · 0%
--tanrei-comp-toolbar-container-elevation-docked sys.elevation.level0
--tanrei-comp-toolbar-container-elevation-floating sys.elevation.level3 0px 0px 0px 1px rgb(0 0 0 / 0.08), 0px 1px 1px 0px rgb(0 0 0 / 0.04), 0px 4px 8px -4px rgb(0 0 0 / 0.04), 0px 16px 24px -8px rgb(0 0 0 / 0.06)
--tanrei-comp-toolbar-container-elevation-inline sys.elevation.level0
--tanrei-comp-toolbar-container-gap-docked — 16px
--tanrei-comp-toolbar-container-gap-floating sys.space.space0 0px
--tanrei-comp-toolbar-container-gap-inline sys.space.space50 4px
--tanrei-comp-toolbar-container-padding-inline-docked sys.space.space200 16px
--tanrei-comp-toolbar-container-padding-inline-floating sys.space.space150 12px
--tanrei-comp-toolbar-container-padding-inline-inline sys.space.space0 0px
--tanrei-comp-toolbar-container-shape-docked sys.shape.corner.none 0px
--tanrei-comp-toolbar-container-shape-floating sys.shape.corner.full 9999px
--tanrei-comp-toolbar-container-shape-inline sys.shape.corner.medium 8px
--tanrei-comp-toolbar-container-size-docked — 64px
--tanrei-comp-toolbar-container-size-floating — 64px
--tanrei-comp-toolbar-container-size-inline — 40px
--tanrei-comp-toolbar-divider-color sys.color.outline-variant #000000 · 8%
--tanrei-comp-toolbar-divider-length sys.space.space300 24px
--tanrei-comp-toolbar-divider-thickness sys.border.hairline 1px
--tanrei-comp-toolbar-group-gap sys.space.space100 8px
--tanrei-comp-toolbar-outline-color-docked sys.color.outline-variant #000000 · 8%
--tanrei-comp-toolbar-outline-color-floating — #000000 · 0%
--tanrei-comp-toolbar-outline-color-inline — #000000 · 0%
--tanrei-comp-toolbar-outline-width sys.border.hairline 1px
--tanrei-comp-toolbar-separation sys.behavior.separation 0

نماذج الاختبار

عروض مرجعية. تلتقط كل المنصات لقطة لكل نموذج بالمعرّف نفسه حتى يمكن مقارنة النتائج.

مولَّد من specs/toolbar.spec.json, tokens/comp/toolbar.tokens.json, design/tokens/

الإرشادات

متى يُستخدم

استخدم شريط الأدوات لمجموعة من عناصر التحكم تعمل على ما هو أمام الشخص: «غامق» و«مائل» و«رابط» فوق محرِّر؛ «تصفية» و«ترتيب» و«تنزيل» فوق جدول؛ «أرشفة» و«حذف» و«نقل» لرسالة مفتوحة؛ قلم وممحاة فوق رسم؛ التكبير والموقع على خريطة. تعمل عناصر التحكم على المحتوى الحالي أو التحديد الحالي، لا على المكان الذي يذهب إليه الشخص بعد ذلك.

لعنوان الشاشة وطريق الرجوع وإجراء عام أو اثنين، استخدم شريط التطبيق في الأعلى. وللانتقال بين الوجهات العليا في التطبيق، استخدم شريط التنقل. لا يجتمع شريط أدوات راسٍ وشريط تنقل في شاشة واحدة أبدًا: كلاهما يطالب بالحافة السفلية.

ضمن المحتوى أم راسٍ أم عائم

الطراز (variant) موضعه العناصر يُستخدم لـ
ضمن المحتوى (الافتراضي) في مكانه داخل المحتوى، حيث يضعه تخطيطك، بلا سطح خاص به في النظام الافتراضي متقاربة، بالطول الذي تحتاج إليه، وكل منها يحتفظ بحيّز لهدف اللمس الخاص به عناصر التحكم في جزء من الصفحة: تنسيق محرِّر، إجراءات جدول، صف من عوامل التصفية
راسٍ على امتداد الحافة السفلية، ملاصقًا لها، ولونه يصل إلى ما تحت شريط النظام موزَّعة على العرض، بينها مسافات متساوية إجراءات شاشة تفاصيل على الهاتف: رسالة مفتوحة، صورة، مستند
عائم سطح مرتفع مستدير الزوايا فوق المحتوى، يضعه تخطيطك متقاربة، بالطول الذي تحتاج إليه، وكل منها يحتفظ بحيّز لهدف اللمس الخاص به أدوات فوق محتوى ينبغي أن يبقى ظاهرًا حولها: لوحة رسم، خريطة

شريط الأدوات الراسي أفقي دائمًا. أما الذي ضمن المحتوى والعائم فقد يكون كل منهما عموديًّا، بجانب المحتوى. ويستطيع المنتج الواحد أن يضع شريط أدوات ضمن المحتوى في شاشة، ويُرسي آخر في شاشة ثانية، ويجعل ثالثًا عائمًا في شاشة ثالثة. والطراز الذي يضيفه نظام تصميم يأخذ بنية الشريط الذي ضمن المحتوى بقيمه هو.

يوزّع شريط الأدوات الراسي عناصره على العرض ولا يقرّب بينها أبدًا أكثر من فجوته (16 في النظام الافتراضي). أما الذي ضمن المحتوى والعائم فيضمّان عناصرهما: لا يتباعد الجاران إلا بالقدر الذي يحتاج إليه كل منهما ليحتفظ بهدف لمس خاص به على امتداد الصف، ولا يتقاربان أبدًا أكثر من الفجوة (4 ضمن المحتوى و0 للعائم في النظام الافتراضي). فالأزرار الكبيرة تتلامس، والمتوسطة تتباعد بمقدار 8، والصغيرة بمقدار 16. ولا يوسّع شريط الأدوات عنصرًا ولا يغيّر مظهره ليفعل ذلك، والتباعد واحد للفأرة واللمس.

عائم: عناصر صغيرة ومتوسطة وكبيرة، وعناصر ضيقة وعريضة

format_boldformat_italicformat_underlinedformat_boldformat_italicformat_underlinedformat_boldformat_italicformat_underlinedundoredoeditink_erasercheck

العناصر

  • استخدم لمعظم الإجراءات أزرارًا بأيقونة فقط من الطراز text. وأعطِ الإجراء الوحيد الذي يقود إليه شريط الأدوات، مثل «إرسال» أو «تم»، وزنًا أكبر: زرًّا بأيقونة فقط من الطراز filled، ربما بالعرض wide، أو زرًّا من الطراز filled له تسمية ظاهرة حين تكون الكلمة أوضح من الأيقونة.
  • الزر بأيقونة فقط وبالعرض narrow يناسب شريط أدوات فيه إجراءات صغيرة كثيرة. يُرسم أضيق من هدفه، ويُبقي شريط الأدوات حيّزًا للهدف بينه وبين جيرانه.
  • اجعل الإجراء الذي يشغّل شيئًا ويوقفه («غامق»، «كتم») زرًّا بأيقونة فقط مع toggle. وعامل التصفية الذي يعمل أو لا يعمل زرٌّ له تسمية ظاهرة مع toggle. يحتفظ كل منهما بحالة التحديد الخاصة به وبإعلانه هو.
  • لعنصر تحكم يتيح الاختيار بين عدة أوامر، اربط قائمة خيارات بزر Button في شريط الأدوات. ولإجراء رئيسي له تنويعات، مثل «حفظ» و«حفظ باسم»، استخدم زرًّا مع قائمة.
  • أبقِ الترتيب ثابتًا. يجد الناس الإجراءات بمواضعها، وشريط الأدوات الذي تتنقل عناصره بين الشاشات صعب التعلّم.
  • شريط الأدوات الراسي الذي فيه عنصر واحد يوسّطه. فكّر هل مكان ذلك العنصر في المحتوى.

المجموعات والفواصل

ضع العناصر المترابطة في مجموعة: «غامق» و«مائل» و«تسطير»؛ «تراجع» و«إعادة»؛ «تكبير» و«تصغير». يفصل شريط الأدوات بين مجموعتين، وبين مجموعة وعنصر خارج أي مجموعة، كما يفصل نظام التصميم بين الأجزاء في غير هذا الموضع: في النظام الافتراضي بخط قصير و8 من المسافة على كل جانب، أو، تحت نظام تصميم يفصل بالمسافة، بمسافة فارغة مقدارها 16 بلا خط. لا تضبط الخاصية separation على شريط أدوات إلا لسبب يخصه. وعنصر الفاصل يرسم الخط نفسه بين عنصرين ليسا في مجموعات.

لا يرسم شريط الأدوات خطًّا عند أي من طرفيه أبدًا، ولا خطين متجاورين. أعطِ المجموعة الخاصية label حين يكون للتجميع معنى عند الشخص («نمط النص»)، كي يسمّيها قارئ الشاشة. ومن غير تسمية، تفصل المجموعة عناصرها ولا تقول شيئًا.

حين لا تتسع المساحة للعناصر

لا يلفّ شريط الأدوات عنصرًا إلى سطر آخر ولا يصغّره أبدًا. وحين تحتاج عناصره إلى حيّز أكبر مما عنده، يخفي عناصر من النهاية، واحدًا بعد واحد، ويُظهر زر الفائض (overflow) بعد آخر عنصر باقٍ. يفتح الزر قائمة خيارات بالعناصر المخفية، بترتيبها، مع تسمياتها وأيقوناتها وحالاتها: الإجراء عنصر قائمة، وزر التبديل عنصر خانة اختيار، وزر قائمة الخيارات قائمة فرعية، والزر مع قائمة إجراؤه الرئيسي تليه قائمة فرعية. واختيار أحدها يفعل بالضبط ما يفعله العنصر المخفي. سمِّ زر الفائض بالخاصية overflow-label («إجراءات إضافية»)، أو مرة واحدة للمنتج كله بواسطة setWords({ toolbarOverflowLabel: … }).

علِّم العنصر الذي يجب أن يبقى، مثل «إرسال» أو «تم»، بالقيمة toolbar-overflow="never": فيخفي شريط الأدوات العناصر التي قبله بدلًا منه. وإن ظل ما لا يُخفى أبدًا لا تتسع له المساحة، صار باقي الصف قابلًا للتمرير. ولإبقاء كل العناصر في الصف وتمريرها بدل إخفاء أي منها، اضبط overflow="scroll".

ما يُخفى يتقرر قبل أن يُرسم شريط الأدوات، ثم من جديد في الإطار الذي يتغير فيه طوله، فلا يُرسم عنصر ثم يُخفى أبدًا، ولا يقفز الصف أبدًا.

افعل

  • سمِّ شريط الأدوات بما تفعله عناصر التحكم فيه: «التنسيق»، «إجراءات الرسالة».
  • عطِّل الإجراء الذي لا ينطبق الآن بدل أن تزيله، فلا تتحرك الإجراءات الأخرى.
  • رتّب العناصر بحيث يأتي أولًا ما يحتاج إليه الناس أكثر: شريط الأدوات يخفي من النهاية.
  • ضع شريط الأدوات العائم بعيدًا عن المحتوى الذي يحتاج الناس إلى رؤيته وهم يستخدمونه، وبعيدًا عن شريط التنقل وهامش النظام.

لا تفعل

  • لا تضع في شريط الأدوات حقل نص ولا شريط تمرير ولا مجموعة رقاقات. كل منها يحتاج إلى مفاتيح الأسهم التي يستخدمها شريط الأدوات لنقل التركيز. البحث مكانه شريط التطبيق أو الصفحة.
  • لا تستخدم شريط أدوات راسيًا وشريط تنقل في الشاشة نفسها.
  • لا تغيّر مظهر العناصر ليبدو شريط الأدوات مؤكَّدًا. اختر للأزرار الطراز tonal أو filled.
  • لا تضع وجهات تنقل في شريط الأدوات. عناصره عناصر تحكم تعمل على المحتوى.

إمكانية الوصول

الدور
toolbar
التسمية
label names the toolbar; it is never drawn. A group's label names the group; empty leaves it unexposed. Each item is named by its own label (an icon-only Button's label, a labelled Button's text), and the overflow button by overflowLabel or the product's words. The toolbar adds no name, role or state to its items.
الحد الأدنى للهدف
تستوفي مساحة اللمس الحد الأدنى لحجم الهدف حتى لو كان الحجم المرئي أصغر. minimum 32px · pointer 44px · spacing 8px · touch 48px

لوحة المفاتيح

المفاتيح الإجراء
Tab / Shift+Tab Moves focus into the toolbar (to the item focused last, or the first enabled item) and out of it: the toolbar is one Tab stop.
Right Arrow / Left Arrow (horizontal), Down Arrow / Up Arrow (vertical) Moves focus to the next or previous enabled item — a group's items and each half of a Button with menu included, separators skipped, the overflow button last — wrapping at the ends (Left and Right mirrored in right-to-left layouts).
Home / End Moves focus to the first or last enabled item.
Enter / Space Activates the focused item, as that Button does; on the overflow button, opens the menu of the hidden items.

ملاحظات

  • The toolbar has no target of its own and takes no input: its items are the product's Buttons, icon-only and labelled, which meet the minimum target themselves (BTN-5). A medium item's target (48) fits inside a floating toolbar's 64, and reaches past an inline toolbar's 40 as a Button's does anywhere.
  • The web has the toolbar role (with aria-orientation) and React Native has role toolbar. SwiftUI, Compose and Flutter have no toolbar role: there the toolbar is a group (an accessibility container, a traversal group, a semantics container) named by label, and each README says so.
  • One Tab stop with arrow-key movement is the WAI-ARIA toolbar pattern. It uses the same roving focus the list, menu and tabs use on each platform; a Button outside a toolbar is unchanged.
  • A toolbar holds Buttons, menu buttons, Buttons with menu, groups of them and separators. Anything else is laid out and reported (TBR-12), because a control that uses the arrow keys would take the keys the toolbar moves focus with.
  • A docked toolbar and a navigation bar are not used on the same screen: both claim the bottom edge.
  • How the items look is their own design system's answer; the toolbar reads no state tokens.
  • Hidden items stay reachable: the overflow button is the last stop of the arrow keys, and its menu holds every hidden item with its own name and state; activating one is activating the item.

مولَّد من specs/toolbar.spec.json, tokens/sys/measure.tokens.json

ما يتكفل به المكوّن

  • شريط الأدوات موضع توقف واحد للمفتاح Tab، وفق نمط toolbar في WAI-ARIA. يدخله المفتاح Tab عند العنصر الذي كان عليه تركيز لوحة المفاتيح آخر مرة، وإلا فعند أول عنصر غير معطَّل، وتخرج منه ضغطة Tab التالية. فشريط تنسيق فيه ثمانية أزرار تبديل يُعبَر بضغطة Tab واحدة، لا بثمانٍ.
  • في داخله، تنقل مفاتيح الأسهم الموافقة لمحوره إلى العنصر التالي أو السابق وتدور عند الطرفين: السهم الأيمن والسهم الأيسر في شريط أدوات أفقي، والسهم السفلي والسهم العلوي في العمودي. وينقل المفتاحان Home و End إلى العنصر الأول والأخير. وفي تخطيط من اليمين إلى اليسار ينقل السهم الأيسر إلى العنصر التالي. وعناصر المجموعة هي عناصر شريط الأدوات، وكل نصف من الزر مع قائمة موضع توقف خاص به، وتُتخطّى الفواصل، وزر الفائض هو آخر موضع توقف.
  • نقل التركيز لا يفعّل عنصرًا أبدًا. يعمل المفتاحان Enter و Space على العنصر الذي عليه التركيز كما يعمل ذلك العنصر، فزر التبديل يبدّل كعادته.
  • ما دامت قائمة خيارات مربوطة بعنصر مفتوحة، فالمفاتيح لها. وحين تُغلق يعود التركيز إلى العنصر الذي فُتحت منه.
  • حين يُخفى العنصر الذي عليه التركيز لأن شريط الأدوات ضاق، ينتقل التركيز إلى زر الفائض.
  • تتخطى مفاتيح الأسهم العناصر المعطَّلة، ولا تكون هذه موضع توقف للمفتاح Tab أبدًا، لأن الزر المعطَّل لا يقبل التركيز.
  • التركيز المتنقل هو نفسه الذي تستخدمه القائمة وقائمة الخيارات وعلامات التبويب على كل منصة.
  • يُعرَّف شريط الأدوات للتقنيات المساعدة شريطَ أدوات (toolbar) تسمّيه الخاصية label، مع اتجاهه، حيث للمنصة دور toolbar (الويب و React Native). وليس في SwiftUI و Compose و Flutter دور كهذا: هناك هو مجموعة تسمّيها الخاصية label وتحوي عناصره بالترتيب.
  • تُعرَّف المجموعة التي لها label مجموعةً بذلك الاسم. وتُعرَّف الخطوط بين المجموعات فواصلَ (separators).
  • يُعرَّف زر الفائض زرًّا يفتح قائمة خيارات، مع حالة توسّعه، وتحوي قائمته كل عنصر مخفي باسمه وحالته.
  • يحتفظ كل عنصر باسمه ودوره وحالته وهدفه. لا يضيف شريط الأدوات إليها شيئًا ولا يغيّر مظهرها أبدًا.
  • لا تتداخل مساحات اللمس بين عنصرين أبدًا. في الشريط الراسي تلتقي في منتصف الفجوة، وفجوة النظام الافتراضي (16) واسعة بما يكفي ليحتفظ كل عنصر بهدف اللمس 48 كاملًا هناك أيضًا؛ ونظام التصميم الذي فجوته أضيق يضيّق الأهداف بين العناصر. وفي الشريط الذي ضمن المحتوى والعائم تتباعد العناصر بالقدر الكافي فقط ليحتفظ كل منها بطول هدف لمس خاص به على امتداد الصف، أيًّا كان المؤشر، فلا يضغط الجيران زرًّا ضيقًا أو صغيرًا أبدًا. وعلى الجانب الذي لا جار فيه يحتفظ العنصر بهدفه كاملًا.
  • حين تكون قيمة overflow هي scroll ويكون العنصر الذي يستقبل تركيز لوحة المفاتيح خارج المجال المرئي بفعل التمرير، يمرّره شريط الأدوات حتى يظهر كاملًا.
  • عند أحجام النص الأكبر يكبر شريط الأدوات في الاتجاه المتعامد مع محوره ليسع عناصره. ولا يكبّرها هي.
  • تبلّغ بنيات التنقيح عن label مفقودة، وشريط أدوات بلا عناصر، وعنصر ليس من أي من أنواعه، وشريط راسٍ ضُبط عموديًّا، واسم مفقود لزر الفائض، وقيمة غير معروفة للطراز أو الاتجاه أو overflow أو separation.

فجوات معروفة في المنصات:

  • ليس في SwiftUI و Compose و Flutter دور toolbar. يسمع قارئ الشاشة مجموعة لها اسم، لا شريط أدوات، وملف README في كل حزمة يقول ذلك. ولا تعرِّف المجموعة اتجاهها.
  • منصات SwiftUI و Compose و Flutter و React Native متأخرة: ليس فيها الطراز الذي ضمن المحتوى، ولا مجموعات ولا فواصل، ولا قائمة الفائض، ولا تقبل عناصرَ إلا أزرار Button.
  • على الويب: يقرأ الشريط الراسي env(safe-area-inset-bottom)، وقيمته صفر ما لم يكن في وسم viewport meta للصفحة viewport-fit=cover.
  • على الويب: تُفتح قائمة الفائض لشريط أدوات عمودي تحت زر الفائض، لا بجانبه، لأن قائمة الخيارات ليس لها موضع جانبي.
  • على الويب: يقيس الشريط الذي ضمن المحتوى والعائم الحيّز الذي يمكنه أن يأخذه من عنصره الأب. والشريط الذي يحدد حيّزه أشقاؤه في صف flex، لا أبوه، لا يقرر ما يتسع إلا حين يتغير حجم أبيه أو حجم عناصره.
  • على الويب: حين تكون العناصر قابلة للتمرير، يُقصّ كل ما يتجاوز شريط الأدوات من العنصر في الاتجاه المتعامد مع محوره: مساحة لمسه، وحلقة تركيزه أو توهّجه، وظل الزر من الطراز elevated. ولا يظهر شريط تمرير.
  • على SwiftUI موضع توقف المفتاح Tab الواحد مجموعة تركيز للوحة المفاتيح: ينتقل Full Keyboard Access بين عناصرها بمفاتيح الأسهم ويخرج منها بالمفتاح Tab. المفاتيح مختبَرة في صورة قواعد، لا بلوحة مفاتيح حقيقية بعد.
  • على SwiftUI: حين تكون العناصر قابلة للتمرير، تتوقف مساحة لمس العنصر الطرفي عند حافة شريط الأدوات. وحين يجعل تغيّر الحجم العناصر تبدأ التمرير أو تكفّ عنه، يُعاد إنشاؤها، فيفقد العنصر تركيز لوحة المفاتيح أو ضغطة جارية.
  • على React Native لا يعمل موضع توقف المفتاح Tab ومفاتيح الأسهم إلا حيث توصَل لوحة مفاتيح فعلية، كما في صف علامات التبويب.
  • في React Native دور toolbar لكن لا سبيل فيه إلى تعريف الاتجاه، فلا يُعلَن شريط الأدوات العمودي عموديًّا.
  • على React Native: عرض شريط الأدوات العائم، والمفاتيح على لوحة مفاتيح فعلية، وتمرير العنصر الذي عليه التركيز حتى يظهر، وهل يعلن VoiceOver و TalkBack شريط الأدوات، كلها فُحصت في Jest فقط، لا على جهاز.
  • تحت m3-like يرسم شريط الأدوات قيم النظام الافتراضي: قيم شريط الأدوات في Material تنتظر أن يشمله مرجع المطابقة. وشريط الأدوات الزاهي (vibrant) في Material، الذي يغيّر ألوان عناصره، لا يمكن رسمه، لأن شريط الأدوات لا يغيّر مظهر عناصره أبدًا (فجوة المحاكاة toolbar-vibrant-color).

ما عليك فعله

  • أعطِ شريط الأدوات الخاصية label، وأعطِ كل عنصر تسميته بلغة منتجك، ومن ذلك الإجراءات بأيقونة فقط، وأعطِ زر الفائض اسمًا بالخاصية overflow-label أو بكلمات منتجك.
  • لا تضع فيه إلا أزرار Button وأزرارًا مع قائمة من Tanrei، منفردة أو في مجموعات أو مع قوائم خيارات مربوطة بها.
  • حين لا ينطبق إجراء فعطِّله، وقل السبب بالقرب منه حين لا يكون واضحًا.
  • افتح قائمة الخيارات الخاصة بزر قائمة الخيارات وأغلقها بنفسك، كما تفعل مع أي قائمة خيارات.
  • ضع شريط الأدوات العائم بحيث لا يغطي محتوى ما زال مطلوبًا وشريط الأدوات مفتوح.