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

مجموعة الأزرار

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

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

نظرة عامة

Web
tanrei-button-group
schedule
SwiftUI
TanreiButtonGroup
schedule
Jetpack Compose
TanreiButtonGroup
schedule
Flutter
TanreiButtonGroup
schedule
React Native
ButtonGroup
schedule

مولَّد من docs/status/status.json, specs/button-group.spec.json

الطرازان standard و connected

إلغاءحفظ المسودةنشرformat_boldformat_italicformat_underlined

الاستخدام

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

تعرض عيّنتا Web و React المواصفة الحالية. أما SwiftUI و Compose و Flutter و React Native فمتأخرة: ما زالت تقدّم المراجعة السابقة من مجموعة الأزرار، وهي صف واحد بلا orientation ولا fullWidth ولا separation ولا رايات الترتيب، تفصل بين عناصره المتصلة دائمًا فجوة ضيقة، وعناصره ذات الأيقونة وحدها زر أيقونة منفصل. وتعرض عيّناتها تلك المراجعة إلى أن تلحق بالمواصفة.

<!-- dismissive يذهب إلى بداية الصف، و confirming إلى نهايته؛ وفي العمود يتبادلان المكانين. -->
<tanrei-button-group>
  <tanrei-button variant="outlined" dismissive>إلغاء</tanrei-button>
  <tanrei-button variant="tonal">حفظ المسودة</tanrei-button>
  <tanrei-button variant="filled" confirming>نشر</tanrei-button>
</tanrei-button-group>

<!-- عمود بعرض حاويته: «سماح» يُرسم فوق «ليس الآن». -->
<tanrei-button-group orientation="vertical" full-width>
  <tanrei-button variant="tonal" dismissive>ليس الآن</tanrei-button>
  <tanrei-button variant="tonal" confirming>سماح</tanrei-button>
</tanrei-button-group>

<!-- التسمية تسمّي المجموعة. وكل زر تبديل يحتفظ بقيمة selected الخاصة به. -->
<tanrei-button-group variant="connected" label="نمط النص">
  <tanrei-button variant="tonal" toggle label="غامق"><span slot="icon">format_bold</span></tanrei-button>
  <tanrei-button variant="tonal" toggle label="مائل"><span slot="icon">format_italic</span></tanrei-button>
  <tanrei-button variant="tonal" toggle label="تسطير"><span slot="icon">format_underlined</span></tanrei-button>
</tanrei-button-group>

<script type="module">
  import '@tanrei/web/components/button-group';
  import '@tanrei/web/components/button';
  // المجموعة لا تُصدر أحداثًا خاصة بها: استمع على الأزرار، كما في أي مكان.
  document.querySelector('[label="غامق"]').addEventListener('change', (e) => setBold(e.detail.selected));
</script>
import { Button, ButtonGroup } from '@tanrei/react';

// confirming و dismissive سمتان تقرؤهما المجموعة من أبنائها.
<ButtonGroup>
  <Button variant="outlined" dismissive onClick={cancel}>إلغاء</Button>
  <Button variant="tonal" onClick={saveDraft}>حفظ المسودة</Button>
  <Button variant="filled" confirming onClick={publish}>نشر</Button>
</ButtonGroup>

<ButtonGroup orientation="vertical" fullWidth>
  <Button variant="tonal" dismissive onClick={notNow}>ليس الآن</Button>
  <Button variant="tonal" confirming onClick={allow}>سماح</Button>
</ButtonGroup>

<ButtonGroup variant="connected" label="نمط النص">
  <Button variant="tonal" toggle selected={bold} label="غامق" onChange={(e) => setBold(e.detail.selected)}><span slot="icon">format_bold</span></Button>
  <Button variant="tonal" toggle selected={italic} label="مائل" onChange={(e) => setItalic(e.detail.selected)}><span slot="icon">format_italic</span></Button>
</ButtonGroup>
import Tanrei

TanreiButtonGroup {
    TanreiButton("إلغاء", variant: .outlined) { cancel() }
    TanreiButton("حفظ المسودة", variant: .tonal) { saveDraft() }
    TanreiButton("نشر") { publish() }
}

TanreiButtonGroup(variant: .connected, label: "نمط النص") {
    TanreiIconButton("غامق", isSelected: $bold, variant: .tonal) { Image(systemName: "bold") }
    TanreiIconButton("مائل", isSelected: $italic, variant: .tonal) { Image(systemName: "italic") }
    TanreiIconButton("تسطير", isSelected: $underline, variant: .tonal) { Image(systemName: "underline") }
}
import io.github.chnotchy.tanrei.components.TanreiButton
import io.github.chnotchy.tanrei.components.TanreiButtonGroup
import io.github.chnotchy.tanrei.components.TanreiButtonGroupVariant
import io.github.chnotchy.tanrei.components.TanreiIconButton
import io.github.chnotchy.tanrei.primitives.TanreiText
import io.github.chnotchy.tanrei.tokens.TanreiButtonVariant
import io.github.chnotchy.tanrei.tokens.TanreiIconButtonVariant

TanreiButtonGroup {
    TanreiButton(text = "إلغاء", onClick = ::cancel, variant = TanreiButtonVariant.Outlined)
    TanreiButton(text = "حفظ المسودة", onClick = ::saveDraft, variant = TanreiButtonVariant.Tonal)
    TanreiButton(text = "نشر", onClick = ::publish)
}

// contentDescription يسمّي المجموعة. ليس في Compose دور مجموعة: هي مجموعة اجتياز (traversal group).
TanreiButtonGroup(variant = TanreiButtonGroupVariant.Connected, contentDescription = "نمط النص") {
    TanreiIconButton(
        onClick = {},
        contentDescription = "غامق",
        variant = TanreiIconButtonVariant.Tonal,
        checked = bold,
        onCheckedChange = { bold = it },
    ) { TanreiText("format_bold") }
    TanreiIconButton(
        onClick = {},
        contentDescription = "مائل",
        variant = TanreiIconButtonVariant.Tonal,
        checked = italic,
        onCheckedChange = { italic = it },
    ) { TanreiText("format_italic") }
}
import 'package:tanrei/tanrei.dart';

TanreiButtonGroup(
  children: <Widget>[
    TanreiButton(variant: TanreiButtonVariant.outlined, onPressed: cancel, child: const Text('إلغاء')),
    TanreiButton(variant: TanreiButtonVariant.tonal, onPressed: saveDraft, child: const Text('حفظ المسودة')),
    TanreiButton(onPressed: publish, child: const Text('نشر')),
  ],
);

TanreiButtonGroup(
  variant: TanreiButtonGroupVariant.connected,
  semanticLabel: 'نمط النص',
  children: <Widget>[
    TanreiIconButton(
      isSelected: bold,
      onPressed: () => setState(() => bold = !bold),
      variant: TanreiIconButtonVariant.tonal,
      semanticLabel: 'غامق',
      icon: const Icon(AppSymbols.formatBold),
    ),
    TanreiIconButton(
      isSelected: italic,
      onPressed: () => setState(() => italic = !italic),
      variant: TanreiIconButtonVariant.tonal,
      semanticLabel: 'مائل',
      icon: const Icon(AppSymbols.formatItalic),
    ),
  ],
);
import { Button, ButtonGroup, IconButton } from '@tanrei/react-native';

<ButtonGroup>
  <Button variant="outlined" onPress={cancel}>إلغاء</Button>
  <Button variant="tonal" onPress={saveDraft}>حفظ المسودة</Button>
  <Button onPress={publish}>نشر</Button>
</ButtonGroup>

<ButtonGroup variant="connected" accessibilityLabel="نمط النص">
  <IconButton variant="tonal" accessibilityLabel="غامق" toggle selected={bold} onSelectedChange={setBold}>
    format_bold
  </IconButton>
  <IconButton variant="tonal" accessibilityLabel="مائل" toggle selected={italic} onSelectedChange={setItalic}>
    format_italic
  </IconButton>
</ButtonGroup>

صف أم عمود، وترتيب الإجراءات

الخاصية orientation ترتّب الأزرار في صف واحد (horizontal، وهو الافتراضي) أو ترصّها في عمود واحد (vertical)، وفيه يكون كل زر بعرض العمود. والخاصية fullWidth تجعل المجموعة تملأ حاويتها: أزرار الصف تتقاسم العرض بالتساوي، وأزرار العمود كل منها بذلك العرض. هذه هي الهيئة المناسبة للإجراءات في أسفل لوحة أو لوح ضيق.

رايتان على الزر تخبران المجموعة بمكانه، كي يبقى الاتجاهان متسقين أحدهما مع الآخر:

الراية الزر في الصف في العمود
confirming يُتمّ المهمة: «موافق»، «حفظ»، «التالي»، «حذف» في النهاية في الأعلى
dismissive يتراجع عنها: «إلغاء»، «رجوع»، «ليس الآن» في البداية في الأسفل
لا هذه ولا تلك أي شيء آخر بين الاثنين، بالترتيب المعطى بين الاثنين، بالترتيب المعطى

الأزرار الثلاثة نفسها في صف وفي عمود

إلغاءحفظ المسودةنشرإلغاءحفظ المسودةنشر

العرض الكامل: صف يتقاسم العرض، وعمود

ليس الآنسماح
ليس الآنسماح

تركيز لوحة المفاتيح وقارئات الشاشة يتبعان الترتيب بعد الوضع، فيلقى الجميع الإجراءات بالترتيب الذي رُسمت به. الرايتان تصفان المهمة لا النبرة: في «إلغاء · حذف»، الزر «حذف» هو الذي يُتمّ المهمة. والإجراء الذي لا رجعة فيه يُميَّز بمظهره (الخاصية destructive للزر) وتسميته، لا بمكانه. ومربع الحوار واللوحة الجانبية يضعان إجراءاتهما بالرايتين نفسيهما.

الوصل بفاصل أو بفجوة

المجموعة من الطراز connected تصل أزرارها بإحدى طريقتين. مع الفاصل تتلامس الأزرار، وتكون زواياها قائمة حيث تلتقي، ويعلّم خط كل موضع وصل. ومع الفجوة تفصل بينها فجوة ضيقة، وتكون زواياها أضيق حيث يواجه أحدها الآخر. يختار نظام التصميم مرة واحدة لكل مكوّن يصل أجزاء (النظام الافتراضي يرسم فاصلًا)، ويستطيع نظام تصميم أن يخص مجموعة الأزرار باختيار مختلف، والخاصية separation (auto أو divider أو gap) تضبط مجموعة واحدة. والمجموعة من الطراز standard تتجاهلها.

متصلة بفاصل وبفجوة، في صف وفي عمود

قصنسخلصققصنسخلصقaddremoveaddremove

مع الفاصل، لا يحمل موضع الوصل خطًّا إلا حيث يستند الزران إلى التعبئة نفسها. بين زر تبديل محدَّد وآخر غير محدَّد، أو بين زر من الطراز filled وآخر من الطراز outlined، تعلّم حافة التعبئة موضع الوصل أصلًا، فلا يُرسم خط هناك.

أزرار تبديل متصلة بفاصل: لا خط بجانب الزر المحدَّد

format_boldformat_italicformat_underlinedformat_strikethrough

المواصفات

الطراز connected: outlined، والحجم large، ومع عنصر معطَّل

قصنسخلصقالسابقاليومالتاليقصنسخلصق

البنية

الجزء الوصف
1 group The row or column that holds the Buttons. It places and spaces the Buttons, joins them in the connected variant, and names them as a group. It draws nothing of its own but the dividers of a connected group.
2 button A Tanrei Button placed in the group: icon-only, label-only or both, its icon on either side, a toggle or not. It is drawn from its own tokens and keeps its own states, focus, events and semantics.
3 inner-corner · اختياري In the connected variant, a corner of a Button that faces its neighbour. The group sets it.
4 outer-corner · اختياري In the connected variant, a corner at an end of the joined shape: the start corners of the first Button and the end corners of the last in a row, the top corners of the first and the bottom corners of the last in a column. The group sets it.
5 divider · اختياري In the connected variant under divider, the line on the seam between two Buttons that touch. The group draws it; under gap there is none.

الخصائص

الخاصية النوع القيمة الافتراضية الوصف
variant standard | connected "standard" standard spaces the Buttons apart. connected joins them into one shape with rounded outer ends, by a divider or by a narrow gap (separation), for a closely related set (Bold, Italic, Underline; Previous, Today, Next).
orientation horizontal | vertical "horizontal" horizontal lays the Buttons out in one row; vertical stacks them in one column, every Button as wide as the column. The confirming and dismissive Buttons change places with the orientation (BGR-13, BGR-14).
separation auto | divider | gap "auto" How the Buttons of a connected group are joined. divider: they touch, and a line is drawn on each seam. gap: they stand a narrow gap apart, with tighter corners where they face each other. Auto takes comp.button-group.connected.separation, the design system's answer (divider in the default system). Ignored while variant is standard.
fullWidth boolean false The group fills its container's width and its Buttons share it equally (in a column, each is the container's width). For the actions at the foot of a dialog, a picker or a side sheet.
label string "" The accessible name of the group ("Text style"). Optional: a group of actions that are each named by their own label needs none.

العناصر

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

button

A Button in the group: the button component, placed, spaced and (when connected) given its corners and minimum size by the group, otherwise drawn and behaving as it does anywhere.

الخاصية النوع القيمة الافتراضية الوصف
variant filled | tonal | elevated | outlined | text "filled" Its emphasis, as the Button's variant.
size small | medium | large "medium" Its height, as the Button's size. Give every Button of a group the same size.
width default | narrow | wide "default" An icon-only Button's width, as the Button's width. A connected group still widens it to its minimum (BGR-3).
icon string "" The glyph in the Button's icon slot, by its name in the system's icon set. Empty for a label-only Button. It is how a fixture fills that slot; in an application the icon slot is filled as the Button's own spec says.
iconPosition leading | trailing "leading" Which side of the label the icon is on, as the Button's iconPosition.
label string "" Its accessible name, as the Button's label prop. Required for an icon-only Button.
toggle boolean false As the Button's toggle.
selected boolean false As the Button's selected.
disabled boolean false As the Button's disabled.
confirming boolean false The Button completes the task (OK, Save, Next, Delete). The group places it at the end of a row and at the top of a column (BGR-13, BGR-14). It changes the Button's place only, never its look (BGR-19).
dismissive boolean false The Button backs out of the task (Cancel, Back, Not now). The group places it at the start of a row and at the bottom of a column (BGR-13, BGR-14). It changes the Button's place only, never its look (BGR-19).
المنفذ الوصف
label Its label, as the Button's default slot. A fixture item's content is this label; an icon-only item has none.
icon Its glyph, as the Button's icon slot. A fixture fills it through the icon prop.
الحدث الوصف
click The Button was activated, as the Button's click.
change A toggle Button 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
size · الخاصية size size size size size
width · الخاصية width width width width width
icon · الخاصية slot="icon" icon icon icon icon
iconPosition · الخاصية iconPosition iconPosition iconPosition iconAlignment iconPosition
label · الخاصية label label contentDescription semanticLabel accessibilityLabel
toggle · الخاصية toggle isSelected onCheckedChange isSelected toggle
selected · الخاصية selected isSelected checked isSelected selected
disabled · الخاصية disabled disabled enabled onPressed disabled
confirming · الخاصية confirming tanreiGroupPlacement(.confirming) Modifier.confirming() TanreiButtonGroupItem.placement confirming
dismissive · الخاصية dismissive tanreiGroupPlacement(.dismissive) Modifier.dismissive() TanreiButtonGroupItem.placement dismissive
click · الحدث click action onClick onPressed onPress
change · الحدث change isSelected onCheckedChange onPressed onSelectedChange
ملاحظات A tanrei-button child, as anywhere: its label is its content and its glyph a tanrei-icon in its icon slot. confirming and dismissive are boolean attributes on the child that the group reads (a MutationObserver re-places the items when they change, BGR-11); the Button itself draws nothing for them. A TanreiButton child, as anywhere. A toggle is a Button given an isSelected binding. The two flags are one modifier, .tanreiGroupPlacement(.confirming) or (.dismissive), a LayoutValueKey the group's layout reads, as .layoutPriority is read by a stack; one enum cannot be both (BGR-18 cannot arise). A TanreiButton child, as anywhere; a toggle is a Button given checked and onCheckedChange, and enabled is disabled's inverse. The two flags are modifiers of the group's scope, Modifier.confirming() and Modifier.dismissive(), parent data the group's layout reads, as RowScope.weight is. A TanreiButton child, as anywhere; a null onPressed disables it, and a non-null isSelected makes it a toggle. The two flags are one ParentDataWidget, TanreiButtonGroupItem(placement: TanreiGroupPlacement.confirming | .dismissive, child:), as Flexible is for a Flex; one enum cannot be both (BGR-18 cannot arise). A Button child, as anywhere. confirming and dismissive are props on the child that the group reads from its children; the Button itself draws nothing for them.

الحالات

السلوك

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

المعرّف المتطلب
BGR-1 WHILE orientation is horizontal THE button group SHALL lay out its items in one row, in the order BGR-13 gives, each at its own size and width unless fullWidth is true (BGR-17): WHILE variant is standard comp.button-group.standard.gap apart and centred on the row's middle; WHILE variant is connected joined as its separation names (BGR-21) — comp.button-group.connected.gap apart under gap, touching under divider — and each stretched to the height of the tallest item (a Button's height is a minimum), so that the joined shape stays even when a label wraps or text is enlarged.
BGR-2 WHILE variant is connected and orientation is horizontal THE button group SHALL give the start corners of the first item and the end corners of the last the radius comp.button-group.connected.horizontal.outer-shape, and each corner that faces a neighbouring item the radius comp.button-group.connected.inner-shape WHILE its separation is gap and no radius, a square corner, WHILE its separation is divider (BGR-21), each capped at half the item's height and eased by sys.shape.corner-smoothing; the item's fill, outline, state layer, ripple and focus ring SHALL follow the resulting shape. WHILE variant is standard THE button group SHALL leave every corner of every item as the item draws it.
BGR-3 WHILE variant is connected THE button group SHALL make each item at least sys.target.touch for touch input and sys.target.pointer for fine pointers along the direction in which it meets its neighbours — wide in a row, high in a column — because joined items cannot extend a hit area over each other: an icon-only Button narrower than that widens its container around its centred icon, and a Button lower than that in a column grows its container around its centred content. Across the other direction the items SHALL extend their hit areas as BTN-5 says. A platform that cannot tell the input type SHALL use sys.target.touch.
BGR-4 WHILE variant is standard and the hit areas that two neighbouring items extend (BTN-5) overlap THE button group SHALL give every press on an item's visible bounds to that item, and a press in the gap between two items to the nearer one, so that neighbouring hit areas meet at the middle of the gap. comp.button-group.standard.gap is what keeps each item's target whole there: at sys.target.touch minus an item's width (in a row) or height (in a column) or more, no hit areas overlap and every item keeps its full target between its neighbours, as the default system's gap does for every Button size; a layer that narrows the gap narrows the targets between items.
BGR-5 THE button group SHALL NOT restyle its items beyond BGR-2, BGR-3, BGR-12, BGR-16, BGR-17, BGR-22 and BGR-23: each item SHALL render from its own tokens, answer hover, focus and press itself, switch itself WHILE its toggle is true, emit its own events, keep its own semantics and be its own Tab stop in the order BGR-15 gives; the group itself SHALL NOT take focus, SHALL NOT handle arrow keys and SHALL keep no selection of its own.
BGR-6 WHILE label is not empty THE button group SHALL expose itself to assistive technology as a group named by label that contains its items; WHILE label is empty THE button group SHALL expose no element of its own, only its items, unless the product names it (BGR-25).
BGR-7 WHERE orientation is horizontal, fullWidth is false and the row is wider than the space its layout gives it THE button group SHALL narrow its labelled Buttons in proportion to their widths, down to the width of their longest word, letting their labels wrap as a Button's label does when its layout gives it less width, and SHALL keep icon-only Buttons at their width; it SHALL NOT wrap the row onto a second line or scroll it, and in debug builds SHALL report a row that still does not fit.
BGR-8 WHEN the layout direction is right-to-left THE button group SHALL, in a row, put its start at the right — the dismissive items at the right and the confirming items at the left (BGR-13), the first placed item's outer corners on its right — and mirror which corners are inner corners; in a column it SHALL keep the top-to-bottom order of BGR-14. Each item's content SHALL follow the layout direction as the Button's does.
BGR-9 WHEN variant, orientation or separation names a value the button group does not define THE button group SHALL render with that prop's default (standard, horizontal, auto), and in debug builds report the unknown value.
BGR-10 WHILE the group holds fewer than two items, or content that is not a Tanrei Button, THE button group SHALL still render it, a single item keeping every corner as it draws it, and in debug builds report it; a platform that cannot inspect its content SHALL state the rule in its README and docs page.
BGR-11 WHEN an item becomes disabled, is added or is removed, or its confirming or dismissive changes, THE button group SHALL place its items again by BGR-13 and BGR-14 and recompute which corners are inner and outer corners, where its dividers are (BGR-24) and which items carry the outer padding of BGR-23, at once, without animation; a disabled item SHALL keep its place, its gap or its dividers, and its corners, and an item that has focus while it moves SHALL keep it.
BGR-12 WHILE orientation is vertical THE button group SHALL lay out its items in one column, top to bottom in the order BGR-14 gives, comp.button-group.standard.gap apart WHILE variant is standard and, WHILE variant is connected, comp.button-group.connected.gap apart under gap and touching under divider (BGR-21), and SHALL make every item as wide as the column — the widest item's width, or the container's width WHILE fullWidth is true — its content centred as a Button centres it in a wider container. WHERE the column is given less width than its widest item every item SHALL take that width and its label SHALL wrap as BGR-7 says; the column SHALL NOT scroll.
BGR-13 WHILE orientation is horizontal THE button group SHALL place its items from start to end in three runs: first the items whose dismissive is true, then the items with neither flag, then the items whose confirming is true; within each run the items SHALL keep the order they were given in. The start is the left in a left-to-right layout and the right in a right-to-left one (BGR-8).
BGR-14 WHILE orientation is vertical THE button group SHALL place its items from top to bottom in three runs: first the items whose confirming is true, then the items with neither flag, then the items whose dismissive is true; within each run the items SHALL keep the order they were given in, the first on top, in either layout direction.
BGR-15 THE button group SHALL make the focus order, and the order in which assistive technology reads its items, the placed order of BGR-13 and BGR-14 — start to end in a row, top to bottom in a column — whatever order the items were given in; a platform whose visual reordering the focus order does not follow (the web's CSS order) SHALL reorder the items themselves in the tree that focus and assistive technology walk.
BGR-16 WHILE variant is connected and orientation is vertical THE button group SHALL give the top corners of the first item and the bottom corners of the last the radius comp.button-group.connected.vertical.outer-shape, and every other corner of every item comp.button-group.connected.inner-shape WHILE its separation is gap and no radius, a square corner, WHILE its separation is divider (BGR-21), each capped at half the item's height and eased by sys.shape.corner-smoothing; the item's fill, outline, state layer, ripple and focus ring SHALL follow the resulting shape.
BGR-17 WHILE fullWidth is true and orientation is horizontal THE button group SHALL take the whole width its container gives it and divide it, less the gaps (none under divider), into equal shares, one per item, whatever each item holds: a label shorter than its share SHALL be centred in it, a label longer SHALL wrap as BGR-7 says, and an icon-only Button SHALL widen its container around its centred icon. WHERE a share is narrower than an item's minimum width (BGR-3, or an icon-only Button's own width) THE button group SHALL give that item its minimum, share the rest equally among the others, and in debug builds report it. WHILE fullWidth is false THE button group SHALL take its natural width.
BGR-18 IF an item's confirming and dismissive are both true THE button group SHALL place it among the items with neither flag and in debug builds report it.
BGR-19 THE button group SHALL NOT change an item's look, emphasis or semantics for its confirming or dismissive: the flags decide its place only. A destructive confirming action (Delete) takes its look from its own variant and its own destructive (BTN-40), and a Button is not made filled, or destructive, by being confirming.
BGR-20 THE button group 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 button group is shown THE button group SHALL draw itself for the new direction at once, without a motion of its own, keeping what it shows and its state.
BGR-21 WHILE variant is connected THE button group SHALL join its items as its separation names: WHILE separation is auto, as comp.button-group.connected.separation names, which follows sys.behavior.separation unless a design system sets it apart; WHILE separation is divider or gap, as that value names, whatever the tokens say. Under gap the items SHALL stand comp.button-group.connected.gap apart with nothing drawn between them and the inner corners of BGR-2 and BGR-16; under divider the items SHALL touch, with square inner corners and the divider of BGR-22 on each seam. WHILE variant is standard THE button group SHALL ignore separation and space its items by comp.button-group.standard.gap. WHEN separation, or the token it follows, changes THE button group SHALL draw the other form at once, without animation, keeping the order, the focus and the state of its items. A platform that cannot draw a choice SHALL fall back to the first value, divider, and state that in its README.
BGR-22 WHILE variant is connected and its separation is divider THE button group SHALL draw, on each seam between two neighbouring items that BGR-24 says carries one, a line comp.button-group.connected.divider.thickness thick, in the color BGR-24 names (comp.button-group.connected.divider.color, or comp.button-group.connected.divider.on-fill.color between two emphasis fills), centred on the seam, over the items' fills and state layers, running along the seam — top to bottom in a row, start to end in a column — and stopping comp.button-group.connected.divider.inset short of each end of it. The line SHALL take no space of its own, SHALL NOT take a press (a press on it goes to the item under the point), SHALL NOT be exposed to assistive technology and SHALL keep its color whatever state its neighbours are in. Each item SHALL draw neither its outline nor the ring of its elevation along an edge that meets a seam, whether or not a line is drawn on it, so that the divider is the only line a seam can carry and the outline of an outlined group runs once around the joined shape, in the color of its rules in the default system; an item's state layer, ripple and focus ring SHALL still follow that item's own shape.
BGR-23 WHILE variant is connected and orientation is horizontal THE button group SHALL add comp.button-group.connected.horizontal.outer-inset to the inline padding of the first item at its start and of the last item at its end, under either separation, so that content beside a rounded outer end looks as far from it as from the tighter corner on its other side: a labelled Button SHALL be wider by that amount with its content moved inward by it, and an icon-only Button SHALL be wider by that amount with its glyph centred in what is left, half of it nearer its neighbour. A single item (BGR-10) SHALL get none; a column SHALL add none, its ends not being full (BGR-16); WHILE fullWidth is true the shares of BGR-17 SHALL be divided first and the padding taken inside the end items' shares. In a right-to-left layout the start is the right, as BGR-8 says.
BGR-24 WHILE variant is connected and its separation is divider THE button group SHALL draw the line of BGR-22 on a seam only WHILE the two items it joins rest on the same fill: the colors from which they render their containers at rest — comp.button.outlined.container.color for an outlined Button, and so on for each variant, and for a toggle the selected or the unselected part of its variant (BTN-15) — are the same color in the active scheme, two containers that have no fill counting as the same. WHILE the two fills differ (a selected toggle beside an unselected one, a filled Button beside an outlined one) THE button group SHALL draw no line on that seam, because the edge of the fill already marks it, and the two items SHALL still draw neither outline nor elevation ring along it (BGR-22). A toggle of the text variant has no fill, selected or not, so its seams keep their lines. THE button group SHALL draw the line in comp.button-group.connected.divider.color, and in comp.button-group.connected.divider.on-fill.color WHILE both items rest on an emphasis fill: a filled Button that is not a toggle, or a selected toggle of the filled, tonal, elevated or outlined variant. It SHALL compare the fills the items have at rest: hover, focus and press SHALL neither add nor remove a line nor change its color, and a disabled item SHALL be compared by the look it has when enabled, so that disabling an item moves no line (BGR-11). WHEN an item's selected, toggle or variant changes THE button group SHALL add, remove or recolor the lines beside it at once, without animation.
BGR-25 WHERE the platform has ARIA attributes (the web), the host carries its group role (BGR-6) itself, so what the product writes on it is not moved, but for a name: WHILE label is not empty THE button group 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. WHILE label is empty and the product names it so THE button group SHALL be exposed as a group named by that name, as with a label: a group the product names is a named group, and a name on an element with no role would name nothing. WHEN the product removes one, or its data-aria- twin, or sets the ARIA property that reflects it (ariaLabel, ariaLabelledByElements) to null, THE button group SHALL take it away.

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

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

المواصفة Web SwiftUI Jetpack Compose Flutter React Native
المكوّن tanrei-button-group TanreiButtonGroup TanreiButtonGroup TanreiButtonGroup ButtonGroup
variant · الخاصية variant variant variant variant variant
orientation · الخاصية orientation orientation orientation orientation orientation
separation · الخاصية separation separation separation separation separation
fullWidth · الخاصية fullWidth fullWidth fullWidth fullWidth fullWidth
label · الخاصية label label contentDescription semanticLabel accessibilityLabel
ملاحظات <tanrei-button-group variant="connected" orientation="vertical" full-width label="Text style"> holds tanrei-button children. It places them without moving them in the author's DOM: its shadow root has three slots in the order of the orientation (dismissive, unflagged, confirming in a row; confirming, unflagged, dismissive in a column) and assigns each child to one with manual slot assignment, so focus and the accessibility tree, which walk the flat tree, follow the placed order (BGR-15) and CSS order is not used. It sets role group and aria-label on its own element only while label is not empty (ElementInternals is not used for the role: axe-core does not see semantics set through it). It gives a connected item its corners and minimum size through CSS custom properties that Button reads on its container (--tanrei-group-start-radius, --tanrei-group-end-radius, and in a column the top and bottom radii, --tanrei-group-min-width, --tanrei-group-min-height); these are an internal contract between Tanrei elements, not a styling API. Each item also learns its place in the group through an internal controller, because three things cannot be done with custom properties alone: a label that may wrap (BGR-7, BGR-17), corners that never animate and pill ends held to half the measured height (BGR-11), and a hit area that stops at half the gap (BGR-4). It reports other children in debug builds (BGR-10). separation is an attribute (auto, divider, gap); auto reads the name in --tanrei-comp-button-group-connected-separation. Under divider the group draws each rule itself, in its shadow root over the seam, and tells each item through the same internal controller which of its edges meet a seam (no outline, no ring) and how much padding to add at an outer end (BGR-22, BGR-23). Owed on the web: orientation="vertical" must really stack the items (BGR-12, BGR-14, BGR-16) — today the element and the review gallery draw every vertical fixture as a row — and its fixtures must be drawn as columns in the gallery and the baselines. Lagging: ships an earlier revision, a row of Buttons and the retired icon-only kind with no orientation, placement flags or full width. The target: TanreiButtonGroup(variant:, orientation:, fullWidth:, label:) { TanreiButton … }, a custom Layout that places its subviews by BGR-13 and BGR-14 and gives them .accessibilitySortPriority in that order so VoiceOver and keyboard focus follow it (BGR-15). The group passes a connected item its corners and minimum size through an environment value that TanreiButton reads (internal to the package). With a label it is .accessibilityElement(children: .contain) with .accessibilityLabel(label). The group reads its content through a variadic view, as the menu and tabs do, so it reports fewer than two items and content that is not a Tanrei Button in debug builds (BGR-10). Also owed: separation (auto, divider, gap), the divider of BGR-22, the outer padding of BGR-23 and the nine new fixtures; reading comp.button-group.connected.separation as a typed choice needs the native token emitters to write a component's choice of kind as a typed enumeration, which they do not yet. Lagging: ships an earlier revision, a row of Buttons and the retired icon-only kind with no orientation, placement flags or full width. The target: TanreiButtonGroup(variant, orientation, fullWidth, contentDescription) { TanreiButton(…) }, a custom Layout whose items read a CompositionLocal for their corners and minimum size (internal to the library). It places the items by BGR-13 and BGR-14 and sets traversalIndex in that order so TalkBack and focus follow it (BGR-15). With a content description it is semantics { isTraversalGroup = true; contentDescription = … }; Compose has no group role. Debug builds report content that is not a Tanrei Button, and a group of fewer than two items (BGR-10). Also owed: separation (auto, divider, gap), the divider of BGR-22, the outer padding of BGR-23 and the nine new fixtures; reading comp.button-group.connected.separation as a typed choice needs the native token emitters to write a component's choice of kind as a typed enumeration, which they do not yet. Lagging: ships an earlier revision, a row of Buttons and the retired icon-only kind with no orientation, placement flags or full width. The target: TanreiButtonGroup(variant:, orientation:, fullWidth:, semanticLabel:, children: [TanreiButton(…)]), a MultiChildRenderObjectWidget that places its children by BGR-13 and BGR-14 and wraps each in a FocusTraversalOrder and Semantics(sortKey:) in that order (BGR-15); the items read an InheritedWidget for their corners and minimum size (internal to the package). With a label it is Semantics(container: true, label:, explicitChildNodes: true). Children of another type are reported in debug builds (BGR-10). Also owed: separation (auto, divider, gap), the divider of BGR-22, the outer padding of BGR-23 and the nine new fixtures; reading comp.button-group.connected.separation as a typed choice needs the native token emitters to write a component's choice of kind as a typed enumeration, which they do not yet. Lagging: ships an earlier revision, a row of Buttons and the retired icon-only kind with no orientation, placement flags or full width. The target: <ButtonGroup variant orientation fullWidth accessibilityLabel>{…}</ButtonGroup> with Button children, which it renders in the order of BGR-13 and BGR-14 (reordering the children themselves, so focus and the screen reader follow it, BGR-15) and which read a React context for their corners and minimum size (internal to the package). With a label it has role="group" and accessibilityLabel; without one it adds no accessibility element. Children of another type are reported in development builds (BGR-10). Also owed: separation (auto, divider, gap), the divider of BGR-22, the outer padding of BGR-23 and the nine new fixtures; reading comp.button-group.connected.separation as a typed choice needs the native token emitters to write a component's choice of kind as a typed enumeration, which they do not yet.

الرموز

الرمز يشير إلى القيمة المحلولة (فاتح)
--tanrei-comp-button-group-connected-divider-color sys.color.outline-variant #000000 · 8%
--tanrei-comp-button-group-connected-divider-inset sys.space.space100 8px
--tanrei-comp-button-group-connected-divider-on-fill-color sys.color.outline #848484
--tanrei-comp-button-group-connected-divider-thickness sys.border.hairline 1px
--tanrei-comp-button-group-connected-gap sys.space.space25 2px
--tanrei-comp-button-group-connected-horizontal-outer-inset sys.space.space50 4px
--tanrei-comp-button-group-connected-horizontal-outer-shape sys.shape.corner.full 9999px
--tanrei-comp-button-group-connected-inner-shape sys.shape.corner.small 6px
--tanrei-comp-button-group-connected-separation sys.behavior.separation 0
--tanrei-comp-button-group-connected-vertical-outer-shape sys.shape.corner.large 12px
--tanrei-comp-button-group-standard-gap — 16px

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

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

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

الإرشادات

متى يُستخدم

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

صف الإجراءات للشاشة الحالية أو للتحديد، الذي يوصَل إليه موضعَ توقف واحدًا للمفتاح Tab وتنتقل مفاتيح الأسهم بين إجراءاته، هو شريط أدوات. والإجراء الرئيسي الموصول بقائمة خيارات من تنويعاته هو زر مع قائمة: يشبه مجموعة متصلة من زرين، لكن نصفه الثاني يفتح قائمة خيارات دائمًا.

زر مقسَّم أم مجموعة أزرار أم رقاقات أم علامات تبويب

هذه الأربعة كلها تضع بضعة أشياء مترابطة في صف، فيسهل الخلط بينها. تختلف في ما تفعله الضغطة وفي طريقة تنقل لوحة المفاتيح خلالها.

المكوّن ما هو التحديد لوحة المفاتيح يُستخدم لـ
الزر المقسَّم (إعدادات Material الجاهزة والإعداد الجاهز cupertino؛ ليس في نظام Tanrei) عنصر تحكم واحد: خياران إلى خمسة خيارات متصلة تجيب عن سؤال واحد. خاص به، بالقيمة: خيار واحد، أو عدة خيارات. موضع توقف واحد للمفتاح Tab. مفاتيح الأسهم تنتقل بين الخيارات، وفي التحديد الواحد تختار أيضًا. إعداد له بضع إجابات ثابتة ويُطبَّق فورًا: يوم، أسبوع، شهر؛ اليسار، الوسط، اليمين.
مجموعة الأزرار صف أو عمود من أزرار منفصلة، متباعدة أو متصلة في شكل واحد. لا شيء. زر التبديل في المجموعة يحتفظ بحالة التشغيل أو الإيقاف الخاصة به. كل زر موضع توقف مستقل للمفتاح Tab. إجراءات مترابطة: «إلغاء»، «حفظ المسودة»، «نشر»؛ و«غامق» و«مائل» و«تسطير» أزرارَ تبديل مستقلة.
الرقاقات عناصر تحكم صغيرة منفصلة في صف يلتف أو يُمرَّر. كل رقاقة تصفية تُشغَّل أو تُوقَف بمفردها. كل رقاقة موضع توقف مستقل للمفتاح Tab. عوامل تصفية فوق قائمة، ردود مقترحة، عناصر أدخلها المستخدم.
علامات التبويب عروض لموضوع واحد، لكل منها لوحته الخاصة. علامة تبويب واحدة: العرض الظاهر على الشاشة. موضع توقف واحد للمفتاح Tab. مفاتيح الأسهم تنتقل وتحدّد. تبديل المحتوى المعروض: «نظرة عامة»، «النشاط»، «الإعدادات».

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

اختيار الطراز

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

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

صف أم عمود

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

افعل

  • أعطِ كل أزرار المجموعة الحجم نفسه.
  • أنفق التوكيد كما تفعل في أي مكان: زر واحد من الطراز filled على الأكثر، وعادةً في النهاية.
  • أعطِ المجموعة تسمية حين لا تكون أزرارها مفهومة إلا معًا، مثل «نمط النص». واحذفها في صف إجراءات يقول كل منها ما يفعله.
  • استخدم طرازًا واحدًا لأزرار المجموعة من الطراز connected، ليُقرأ الشكل الموصول واحدًا.
  • علّم الزر الذي يُتمّ المهمة بالراية confirming والزر الذي يتراجع عنها بالراية dismissive، ودع المجموعة تضعهما. اكتبهما بأي ترتيب؛ المجموعة لا تحرّكهما في ترميزك.
  • اترك separation على القيمة auto ما لم يجب أن تختلف مجموعة واحدة، ليُميَّز كل عنصر تحكم موصول في المنتج بالطريقة نفسها.

لا تفعل

  • لا تستخدم أزرار التبديل في مجموعة لخيارات يستبعد أحدها الآخر، كالمحاذاة إلى اليسار والوسط واليمين. المجموعة لا تجعل أزرار التبديل فيها حصرية. استخدم علامات التبويب حيث يغيّر الاختيار المحتوى الذي تحته، وأزرار الاختيار حيث يضبط قيمة، أو زرًّا مقسَّمًا حيث يتضمنه النظام.
  • لا تضع في المجموعة شيئًا غير أزرار Tanrei، بتسمية أو بأيقونة وحدها: لا حقول ولا رقاقات ولا قوائم خيارات. بنيات التنقيح (debug) تبلّغ عن أي محتوى آخر.
  • لا تستخدم الرايتين للنبرة. الزر «حذف» الذي لا رجعة فيه ويُتمّ المهمة هو confirming، ويأخذ مظهره من خاصيته destructive؛ والزر الذي له الرايتان معًا يوضع كما لو لم تكن له أي منهما، ويُبلَّغ عنه.
  • لا تتوقع أن يلتف الصف. الصف الذي لا يتسع يضيّق أزراره ويلفّ تسمياتها. ولا ينتقل أبدًا إلى سطر ثانٍ ولا يُمرَّر.
  • لا تخلط الأحجام في مجموعة واحدة. المجموعة لا تغيّر حجم أزرارها.

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

الدور
group
التسمية
label, when given, names the group ("Text style"). Each item is named as it is anywhere: a Button by its label text, an icon-only Button by its label prop.
الحد الأدنى للهدف
تستوفي مساحة اللمس الحد الأدنى لحجم الهدف حتى لو كان الحجم المرئي أصغر. minimum 32px · pointer 44px · spacing 8px · touch 48px

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

المفاتيح الإجراء
Tab / Shift+Tab Moves focus to each enabled item in turn in the placed order (BGR-15): start to end in a row, top to bottom in a column.
Enter / Space Activates the focused item, as the Button itself says (a toggle switches).

ملاحظات

  • A button group is a layout of actions: each item is its own Tab stop with its own semantics. A row that should be one Tab stop with arrow keys is a toolbar; one choice among several is a single-selection control: tabs where it changes the content below, a radio group where it sets a value, or a segmented button in a system that ships one.
  • A toggle Button in a group keeps its own on/off state; the group does not make its toggles exclusive. One choice among several is a single-selection control: tabs where it changes the content below, a radio group where it sets a value, or a segmented button in a system that ships one.
  • confirming and dismissive are not announced: they decide where a Button is, and focus and reading follow that place, so a screen-reader user meets the actions in the same order a sighted user sees them.
  • The two flags describe the task, not the tone: in "Cancel · Delete" Delete is confirming. A destructive action is told apart by its own look (the Button's destructive) and its label, not by its place.
  • Compose has no group role: the group is a traversal group whose content description is label, and each item keeps its own role.
  • Text size: Buttons in a group grow as they do anywhere; a connected row stretches every item to the tallest, and a column makes every item as wide as the widest.
  • A divider is decoration: it is not exposed, takes no press and is no boundary a person must find. What tells two joined Buttons apart for assistive technology is that each is its own button with its own name; for sight, their content and the line or the gap between them.
  • A seam between a selected and an unselected toggle carries no line: the fill of the selected item ends there, at a contrast far above 3:1 against its neighbour, and that edge is the boundary. The selected state itself is exposed by the toggle (BTN-14), never by the line.
  • In the default system the outline of an outlined group and its rules are the hairline (the divider's color), far below 3:1 against the surface. That is within WCAG 1.4.11: each Button is identified by its label or its icon, not by its edge.

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

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

  • كل زر يحتفظ بدوره واسمه وحالته وموضع توقف المفتاح Tab الخاص به. المفتاح Tab ينتقل خلالها بالترتيب بعد الوضع: من البداية إلى النهاية في الصف، ومن الأعلى إلى الأسفل في العمود. المجموعة لا تأخذ التركيز، ولا تعالج مفاتيح الأسهم، ولا تحتفظ بتحديد.
  • الرايتان confirming و dismissive لا تُعلَنان. تقرران مكان الزر، والتركيز والقراءة يتبعان ذلك المكان.
  • الفاصل زخرفة: هو مخفي عن التقنيات المساعدة ولا يستقبل ضغطًا. ما يميّز زرين موصولين أحدهما من الآخر هو أن كلًّا منهما زر مستقل له اسمه.
  • مع تسمية، تُعرَّف المجموعة للتقنيات المساعدة مجموعةً (group) تسمّيها التسمية وتحتوي أزرارها. ومن دونها لا تضيف شيئًا إلى شجرة إمكانية الوصول.
  • في المجموعة من الطراز connected عرض كل زر لا يقل عن هدف واحد، ومساحة لمسه تمتد فوق الصف وتحته إلى الحد الأدنى للهدف. وفي المجموعة من الطراز standard، الضغط داخل الحدود المرئية للزر يذهب دائمًا إلى ذلك الزر، والضغط في الفجوة يذهب إلى الأقرب.
  • مؤشر التركيز يتبع شكل كل زر، ومنه الزوايا الموصولة.
  • عند أحجام النص الأكبر تكبر الأزرار كما تفعل في أي مكان. الصف الموصول يمدّ كل زر إلى ارتفاع أطولها، والعمود يجعل كل زر بعرض أعرضها، فيبقى الشكل الموصول مستويًا.
  • في النظام الافتراضي حدّ المجموعة من الطراز outlined وفواصلها هي الخط الرفيع، وهو هادئ عن قصد: كل زر يُعرَف بتسميته أو بأيقونته، لا بحافته.
  • بنيات التنقيح تبلّغ عن مجموعة فيها أقل من عنصرين، وعن محتوى ليس زرًّا من Tanrei، وعن زر له الرايتان معًا، وعن قيمة مجهولة للطراز أو الاتجاه أو الفصل، وعن صف بالعرض الكامل لا تستطيع أزراره تقاسم العرض بالتساوي، وعن صف ما زال لا يتسع بعد أن ضاقت أزراره.

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

  • الويب: زر الأيقونة الموصول يكون بعرض هدف المؤشر مع مؤشر دقيق، كالفأرة، وبعرض هدف اللمس مع مؤشر غير دقيق. حيث يكون شكل العنصر نفسه كبسوليًّا (pill)، تكون الزوايا التي يديرها نحو جار دائرية لا ملطَّفة بتنعيم الزوايا. داخل مجموعة قد تلتف تسمية Button؛ وخارجها تبقى على سطر واحد. والتبليغ عن صف ما زال لا يتسع يُفحص حين يتغيّر حجم المجموعة أو يتغيّر أبناؤها، لا حين تتغيّر تسمية عنصر.
  • ليس في SwiftUI دور مجموعة. المجموعة التي لها تسمية حاوية تسمّيها تسميتها وتحمل أزرارها. الزر Button الذي عنوانه LocalizedStringKey، كما هو حال السلسلة الحرفية، يمكن أن يضيق إلى ما دون أطول كلماته، فتنكسر عندئذ داخل الكلمة. والتبليغ عن صف ما زال لا يتسع هو فشل تأكيد (assertion failure) في بنيات التنقيح، فالتخطيط الذي يضيق أكثر مما يجب للحظة، كحاوية يتحرك عرضها، يوقف تطبيق التنقيح.
  • ليس في Compose دور مجموعة. المجموعة التي لها تسمية مجموعة اجتياز (traversal group) وصف محتواها هو التسمية، وكل زر يحتفظ بدوره.
  • في React Native: كيف يقسم iOS و Android الضغط في الفجوة بين زرين، والأزرار الممدودة في مجموعة من الطراز connected عند أحجام النص الكبيرة، وهل يُعلِن VoiceOver و TalkBack اسم المجموعة حين يدخلها التركيز، لم تُفحص على جهاز.
  • في React Native: الزر Button الذي ضاق يمكن أن ينكمش إلى ما دون أطول كلماته، فتنكسر حروفها عندئذ على أسطر، لأن تخطيط React Native ليس فيه حد أدنى لعرض محتوى النص.
  • في المجموعة من الطراز standard تلتقي مساحات اللمس عند منتصف الفجوة. فجوة النظام الافتراضي (16) واسعة بما يكفي ليحتفظ كل زر أيقونة، ومنه الصغير، بهدف اللمس 48 كاملًا بين جيرانه. ونظام التصميم الذي فجوته أضيق يضيّق الأهداف بين الأزرار.

ما عليك فعله

  • سمِّ كل زر أيقونة. تسمية المجموعة لا تسمّي الأزرار التي داخلها.
  • ضع المجموعة حيث تنتمي أزرارها في ترتيب القراءة. التقنيات المساعدة تصل إليها واحدًا واحدًا، بالترتيب الذي تظهر به.
  • إن وجب أن تبقى مجموعة من أزرار التبديل حصرية فيما بينها، فاستخدم عنصر تحكم بتحديد واحد: علامات التبويب حيث يغيّر الاختيار المحتوى الذي تحته، وأزرار الاختيار حيث يضبط قيمة، أو زرًّا مقسَّمًا حيث يتضمنه النظام. كل منها يُعلَن اختيارًا واحدًا؛ أما صف من أزرار التبديل فلا.