زر الإجراء الرئيسي
ينفّذ الإجراء الأهم الوحيد في الشاشة على حاوية مرتفعة تطفو فوق المحتوى، واسمه مكتوب كاملًا، أو مطويًّا إلى أيقونته وحدها.
- الفئة
- الإجراءات
- الرموز
comp.main-action-button- المستوى
- أساسي
- Web
tanrei-main-action-buttonschedule - SwiftUI
TanreiMainActionButtonradio_button_unchecked - Jetpack Compose
TanreiMainActionButtonradio_button_unchecked - Flutter
TanreiMainActionButtonradio_button_unchecked - React Native
MainActionButtonradio_button_unchecked
مولَّد من docs/status/status.json, specs/main-action-button.spec.json
ممتد ومطويّ
زر الإجراء الرئيسي هو الإجراء الوحيد الذي وُجدت الشاشة من أجله: «إنشاء» في صندوق بريد، «حدث جديد» في تقويم، «إضافة» في قائمة. يقع على حاوية مرتفعة تطفو فوق المحتوى، فيبقى في المتناول والمحتوى يُمرَّر تحته.
هو زر واحد له هيئتان. الهيئة الممتدة (الافتراضية) تعرض أيقونته وتسميته. والهيئة المطويّة تعرض الأيقونة وحدها، في مربع ارتفاعه ارتفاع الهيئة الممتدة، وهو دائرة في النظام الافتراضي. ينقله المنتج بين الهيئتين، كأن يطويه والمحتوى يُمرَّر ثم يمدّه من جديد عند الأعلى. هو إجراء، وليس زر تبديل أبدًا: الطيّ يغيّر شكله لا معناه، وتبقى التسمية اسمه المتاح للتقنيات المساعدة في الهيئتين.
على الويب هو <tanrei-main-action-button>، وفي React هو MainActionButton. أما SwiftUI و Compose و Flutter و React Native فلم تنفّذه بعد.
التسمية خاصية لا محتوى، لأنها لازمة في الهيئتين: تُرسم في الهيئة الممتدة، وهي الاسم المتاح للتقنيات المساعدة دائمًا. والأيقونة رسم (glyph) من مجموعة الأيقونات. الزر لا يضع نفسه: تخطيطك هو الذي يضعه، عادةً في الزاوية السفلى من جهة النهاية في الشاشة، بعيدًا عن شريط التنقل.
<tanrei-main-action-button class="primary-action" label="إنشاء">
<span slot="icon">edit</span>
</tanrei-main-action-button>
<!-- مطويّ: السمة هي عكس الخاصية extended. -->
<tanrei-main-action-button label="إنشاء" collapsed><span slot="icon">edit</span></tanrei-main-action-button>
<!-- الرسم الذي يشير إلى حيث يذهب الإجراء يقع بعد التسمية. -->
<tanrei-main-action-button label="التالي" icon-position="trailing"><span slot="icon">arrow_forward</span></tanrei-main-action-button>
<style>
/* العنصر لا يضع شيئًا: الصفحة تضعه في الزاوية السفلى من جهة النهاية. */
tanrei-main-action-button.primary-action {
position: fixed;
inset-inline-end: var(--tanrei-sys-space-space400);
inset-block-end: var(--tanrei-sys-space-space400);
}
</style>
<script type="module">
import '@tanrei/web/components/main-action-button';
const compose = document.querySelector('tanrei-main-action-button.primary-action');
compose.addEventListener('click', newMessage);
// extended خاصية قيمتها الافتراضية true؛ اطوِه من الخارج، مثلًا حين تكون الصفحة ممرَّرة.
addEventListener('scroll', () => (compose.extended = scrollY === 0), { passive: true });
</script>import { MainActionButton } from '@tanrei/react';
<MainActionButton className="primary-action" label="إنشاء" extended={atTop} onClick={newMessage}>
<span slot="icon">edit</span>
</MainActionButton>
<MainActionButton variant="tonal" label="التالي" iconPosition="trailing" onClick={next}>
<span slot="icon">arrow_forward</span>
</MainActionButton>يحل زر الإجراء الرئيسي محل زر الإجراء العائم (floating action button) و FAB الممتد. ما كانا مكوّنين يبدّل المنتج بينهما صارا هيئتين لمكوّن واحد.
| قبل | الآن |
|---|---|
زر الإجراء العائم (fab) |
زر إجراء رئيسي مطويّ: الخاصية extended مضبوطة على false |
FAB الممتد (extended-fab) |
زر إجراء رئيسي ممتد (الافتراضي) |
الخاصية expanded في FAB الممتد |
extended |
comp.fab.* و comp.extended-fab.* |
comp.main-action-button.* |
- الأسماء FAB و small FAB و large FAB في Material 3 هي زر إجراء رئيسي مطويّ بالأحجام medium و small و large. والاسم extended FAB فيه هو الهيئة الممتدة.
- الخاصية
expandedفي Compose (علىExtendedFloatingActionButton) والخاصيةisExtendedفي Flutter (علىFloatingActionButton.extended) هماextended. - ألوان FAB في Material 3، وهي primary و secondary و tertiary و surface، تقابل الطُرُز
filledوtonalوsurfaceوالقيم التي يضيفها إعداد جاهز. الإعداد الجاهز m3-like يرسم زوايا المربع المستدير والارتفاعين 56 و 96 الخاصة بنظام Material عبر رموز (tokens) هذا المكوّن. - بلغة Material، زر الإجراء الرئيسي هو FAB. وقائمة FAB في Material هي قائمة FAB، وهي مكوّن من طبقة m3-like: تملكها الأنظمة التي تنحدر منها.
الطُرُز
الأحجام، ممتدة ومطويّة
أيقونة في النهاية، وبلا أيقونة، ومعطَّل
البنية
البنية
filled-extended كما ترسمه حزمة الويب.القياسات
القياسات
| الطول | الرمز | القيمة (px) |
|---|---|---|
container padding-inline-start-with-icon | tanrei.comp.main-action-button.container.padding-inline-start-with-icon.medium | 16 |
container gap | tanrei.comp.main-action-button.container.gap.medium | 12 |
container padding-inline-end | tanrei.comp.main-action-button.container.padding-inline-end.medium | 20 |
container height | tanrei.comp.main-action-button.container.height.medium | 56 |
icon size | tanrei.comp.main-action-button.icon.size.medium | 24 |
filled-extended كما ترسمه حزمة الويب.الخصائص
| الخاصية | النوع | القيمة الافتراضية | الوصف |
|---|---|---|---|
variant | filled | tonal | surface | "filled" | Emphasis. Filled is the screen's main action at full strength; tonal is quieter; surface keeps the container neutral where a colored one would compete with the content beneath (a map, a photo). A design system may add values. |
size | small | medium | large | "medium" | Visual height (40 / 56 / 96), which is also the side of the collapsed form, so one button keeps its height while it collapses and extends. Small sits beside a medium one for a related action; large marks the action on a wide or empty screen. The hit area always meets the minimum target. A design system may add values. |
extended | boolean | true | Shows the label beside the icon. False collapses the button to its icon (for example while the content scrolls); the label stays the accessible name. It changes the button's form, never its meaning: this is not a toggle. A button without an icon stays extended, and one without a label never extends (MAB-15, MAB-16). |
fullWidth | boolean | false | Makes the button take the whole width its container gives it, its icon and label centred: the one action of a screen held across its foot on a narrow screen (MAB-24). A full-width button is always drawn extended, so extended is ignored while it is true. |
iconPosition | leading | trailing | "leading" | The side of the label the icon is on, in the reading direction. Trailing is for a glyph that points where the action goes, such as the arrow of Next. Collapsed, the icon is centered whichever side it is on. |
disabled | boolean | false | Prevents interaction and removes the button from the focus order. Hiding it when its action is unavailable is usually better than disabling it. |
label | string | "" | The visible text while extended, and the accessible name in either form. Required: an icon alone is not a name. |
المنافذ
| المنفذ | الوصف |
|---|---|
icon | The icon (a glyph of the system's icon set). |
الأحداث
| الحدث | الوصف |
|---|---|
click | The button was activated by pointer, touch, keyboard or assistive technology. |
الحالات
السلوك
متطلبات بصيغة EARS. يُختبر تنفيذ كل منصة مقابل هذه المعرّفات. يُعرض نص المتطلبات كما ورد في ملف المواصفة، بالإنجليزية.
| المعرّف | المتطلب |
|---|---|
MAB-1 | WHEN the user activates the main action button by pointer, touch, Enter or Space THE main action button SHALL emit click exactly once. |
MAB-2 | WHILE disabled is true THE main action button SHALL NOT emit click, SHALL NOT be focusable and SHALL expose the disabled state to assistive technology. |
MAB-3 | WHILE hovered, keyboard-focused or pressed THE main action button SHALL render its container, label, icon, elevation and opacity from the component tokens of the highest-precedence active state, with precedence pressed over focused over hovered; focus gained by pointer or touch SHALL NOT select the focused state. |
MAB-4 | WHEN the main action button receives keyboard focus THE main action button SHALL show the focus ring without animation; focus gained by pointer or touch SHALL NOT show it. |
MAB-5 | WHERE the visual size is below the minimum target THE main action button SHALL extend its hit area on both axes to sys.target.touch for touch input and sys.target.pointer for fine pointers, without changing its visual size; a platform that cannot tell the input type SHALL use sys.target.touch. |
MAB-6 | WHILE disabled is true THE main action button SHALL render its container, label, icon, elevation and opacity from the disabled component tokens of its variant. |
MAB-7 | WHEN variant or size names a value that the active design system does not have THE main action button SHALL render with the default value's tokens, and in debug builds report the unknown value. |
MAB-8 | WHEN the main action button is pressed by pointer, touch, Enter or Space THE main action button SHALL show the pressed state without delay and SHALL keep it visible for at least sys.motion.duration.press-hold, even when the press ends sooner. |
MAB-9 | WHILE pressed THE main action button SHALL answer as sys.behavior.pressed-feedback names: overlay applies the pressed tokens to the whole container at once; ripple grows the pressed state layer from the point of contact (from the center for keyboard activation); dim applies the pressed opacity to the whole control and draws no state layer; none draws no answer to the press. Under ripple and dim only the container color stays with the state under the press; label, icon, elevation, opacity and shape still come from the pressed tokens. Under none every part stays with the state under the press. The ripple grows over comp.main-action-button.motion.feedback-duration with comp.main-action-button.motion.state-easing, fades over the state duration of its size (comp.main-action-button.motion.state-duration.small, .medium or .large) with comp.main-action-button.motion.state-easing once the press has ended and press-hold has passed, and appears whole where motion is reduced. |
MAB-10 | THE main action button SHALL ease its container corners by sys.shape.corner-smoothing (0 is a quarter circle, 0.6 the iOS continuous corner; a platform with only the OS curve draws it for any amount above 0) and show its keyboard focus as sys.behavior.focus-style names (ring or glow); a platform that cannot draw a choice SHALL fall back to the first value and state that in its README. |
MAB-11 | WHILE it is extended THE main action button SHALL draw a container at least the height of its size (comp.main-action-button.container.height.medium for medium, and so on) with the corners of its size (comp.main-action-button.container.shape.medium, and so on), holding its label and, when it has one, its icon on the side iconPosition names (leading: before the label in the reading direction; trailing: after it), the two separated by comp.main-action-button.container.gap.medium (and so on); it SHALL pad the icon's side by comp.main-action-button.container.padding-inline-start-with-icon.medium for a leading icon or comp.main-action-button.container.padding-inline-end-with-icon.medium for a trailing one, a start without an icon by comp.main-action-button.container.padding-inline-start.medium and an end without an icon by comp.main-action-button.container.padding-inline-end.medium, and the top and bottom by at least comp.main-action-button.container.padding-block.medium (and so on for each size), and SHALL be as wide as that content. |
MAB-12 | THE main action button SHALL set its label in the text style of its size (comp.main-action-button.label.typescale.medium, and so on) and the label color of its variant and state (comp.main-action-button.filled.label.color for filled at rest, and so on), SHALL NOT truncate it (it stays on one line while it fits, wraps when the layout gives it less width, and the container grows in both axes with it), and SHALL draw the icon, in either form, in the same color at the icon size of its size (comp.main-action-button.icon.size.medium, and so on) with the family and fill of an unselected icon, sys.icon.weight, and an optical size clamped between sys.icon.optical-size.min and sys.icon.optical-size.max. |
MAB-13 | WHILE it is collapsed THE main action button SHALL hide its label and draw a square container whose side is the height of its size (comp.main-action-button.container.height.medium, and so on) with the corners of its size (comp.main-action-button.container.shape.medium, and so on; a circle where they are full, as in the default system) and its icon centered in it whichever side iconPosition names, and SHALL keep label as its accessible name. |
MAB-14 | WHEN extended changes THE main action button SHALL change its width between the two forms over comp.main-action-button.motion.resize-duration with comp.main-action-button.motion.resize-easing, keeping its height and corners, fading the label out as it narrows and in as it widens, and moving the icon between its side of the label and the center, and SHALL change at once where motion is reduced; which edge stays in place is decided by the layout that holds it, as for any change of its width. |
MAB-15 | IF the main action button has no icon THEN THE main action button SHALL draw its extended form whatever extended says (there is no empty collapsed form), and in debug builds report it while extended is false. |
MAB-16 | WHILE label is not empty THE main action button SHALL expose it as its accessible name, in either form, over a name the product gives it on the element (aria-label or aria-labelledby). IF label is empty THEN THE main action button SHALL draw its collapsed form whatever extended says, SHALL expose the name the product gives it on the element — aria-label, or aria-labelledby naming an element — as its accessible name, and WHILE the product gives it none SHALL in debug builds report that it has no accessible name; this holds over MAB-15 when it has no icon either. |
MAB-17 | THE main action button SHALL cast the elevation of its variant and state (comp.main-action-button.filled.container.elevation for filled at rest, and so on) outside its container without clipping it, in either form and while it changes between them, and WHEN the elevation or the colors change between states SHALL animate the change over the state duration of its size (comp.main-action-button.motion.state-duration.small, .medium or .large) with comp.main-action-button.motion.state-easing, changing them at once where motion is reduced. |
MAB-18 | THE main action button SHALL NOT position itself: it SHALL lay out at its own size, or across the width of its container while fullWidth is true (MAB-24), where the layout that holds it places it (normally the inline-end bottom corner of the screen, clear of any navigation bar), and SHALL NOT draw a scrim or move content. |
MAB-19 | WHEN the layout direction is right-to-left THE main action button SHALL mirror the order of its icon and label (a leading icon on the right, a trailing one on the left) and apply its paddings by logical start and end, SHALL NOT mirror the glyph itself (the icon helper mirrors a glyph the icon set marks, MAB-22), and SHALL grow a ripple from the point of contact as in left-to-right. |
MAB-20 | THE main action button SHALL expose itself to assistive technology as a button named by label with no pressed, selected, checked or expanded state, and WHEN extended changes SHALL NOT change its role, its name or its focus, and SHALL NOT announce the change. |
MAB-21 | THE main action button 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 main action button is shown THE main action button SHALL draw itself for the new direction at once, without a motion of its own, keeping what it shows and its state. |
MAB-22 | WHERE the layout direction is right-to-left THE main action button SHALL draw the glyph of its icon slot mirrored left to right exactly when the system's icon set marks that glyph's name as mirrored or the product forces mirroring for that use, and unmirrored when the product forbids it: the icon helper mirrors the glyph inside its own box, about the box's vertical centre line, changing neither its place, size, color and fill nor the order MAB-19 gives. THE main action button SHALL NOT mirror a glyph itself, and SHALL NOT mirror content the product gives as an image or a view of its own rather than by a glyph's name. |
MAB-23 | THE main action button SHALL lay out its label as text of its own direction, isolated from the text around it: each takes the base direction of its first strong character, or the layout direction where it has none, so that a left-to-right word, a number with its sign or unit, a telephone number and an address keep their own order in a right-to-left layout and reorder nothing beside them; THE main action button SHALL still place the label and align its lines by the layout direction, not by the text's own. |
MAB-24 | WHILE fullWidth is true THE main action button SHALL take the whole inline size its container gives it and SHALL draw its extended form whatever extended says — the height, corners, paddings, elevation and states of MAB-11 and MAB-17 — with its icon and label centred in that width as one row, in the order MAB-19 gives them; WHERE that width is narrower than the label THE main action button SHALL wrap the label, its lines centred (MAB-12). WHEN extended changes while fullWidth is true THE main action button SHALL NOT change its form, and in debug builds SHALL report that a full-width button does not collapse. MAB-16 holds over this rule: a button with no label draws its collapsed form, at its own size, and is reported. |
MAB-25 | WHERE the platform has ARIA attributes (the web), WHEN the product sets an aria- attribute on the host, by the attribute or by the ARIA property that reflects it, THE main action button SHALL move it to the data-aria- attribute of the same name, so that the host is no second node with its name, description or state, and SHALL expose it on the element that carries its role — an id reference by the elements it names in the host's tree or a tree around it, an error message as part of the description while the main action button is invalid — except those the main action button owns (aria-disabled), which it SHALL move and not expose. WHEN the product removes the aria- attribute or its data-aria- twin, or sets the ARIA property that reflects it (ariaLabel, ariaDescribedByElements…) to null, THE main action button SHALL take it off that element. WHEN the product sets an aria- attribute the main action button owns THE main action button SHALL report it in debug builds. |
مطابقة الأسماء بين المنصات
التكافؤ لا يعني واجهات برمجية متطابقة. تعبّر كل منصة عن العقد نفسه بأسلوبها.
| المواصفة | Web | SwiftUI | Jetpack Compose | Flutter | React Native |
|---|---|---|---|---|---|
| المكوّن | tanrei-main-action-button | TanreiMainActionButton | TanreiMainActionButton | TanreiMainActionButton | MainActionButton |
variant · الخاصية | variant | variant | variant | variant | variant |
size · الخاصية | size | size | size | size | size |
extended · الخاصية | extended | isExtended | expanded | isExtended | extended |
fullWidth · الخاصية | fullWidth | fullWidth | fullWidth | fullWidth | fullWidth |
iconPosition · الخاصية | iconPosition | iconPosition | iconPosition | iconPosition | iconPosition |
disabled · الخاصية | disabled | disabled | enabled | onPressed | disabled |
label · الخاصية | label | title | text | label | label |
click · الحدث | click | action | onClick | onPressed | onPress |
| ملاحظات | The icon is the icon slot (a glyph of the icon font). extended is a boolean property that defaults to true; its attribute is the inverse collapsed, because an HTML boolean attribute cannot default to true. iconPosition is the icon-position attribute. The host has no aria-expanded or aria-pressed (MAB-20). The element is inline; the page positions it (for example with position: fixed or a sticky container). fullWidth is the full-width attribute: the host is then a block-level flex box as wide as its container, and the native <button> fills it (MAB-24). | The initializer takes the title first, as Button(_:action:) does, and an optional icon name. disabled follows .disabled(_:). The view is placed by the caller, typically in an .overlay(alignment: .bottomTrailing). | Compose idiom (as Material 3's extended FAB composable): expanded collapses it; enabled is the inverse flag; text is a String so it is also the content description. Placed through Scaffold's floatingActionButton slot or by the caller. | Flutter idiom (as Material 3's extended FAB): isExtended collapses it and a null onPressed disables it. Placed through Scaffold.floatingActionButton or by the caller; it adds no Hero. | The icon is the icon prop (a glyph name). The caller positions it (for example absolutely inside the screen's root view). |
الرموز
| الرمز | يشير إلى | القيمة المحلولة (فاتح) |
|---|---|---|
--tanrei-comp-main-action-button-container-gap-large | sys.space.space200 | 16px |
--tanrei-comp-main-action-button-container-gap-medium | sys.space.space150 | 12px |
--tanrei-comp-main-action-button-container-gap-small | sys.space.space100 | 8px |
--tanrei-comp-main-action-button-container-height-large | — | 96px |
--tanrei-comp-main-action-button-container-height-medium | — | 56px |
--tanrei-comp-main-action-button-container-height-small | — | 40px |
--tanrei-comp-main-action-button-container-padding-block-large | — | 6px |
--tanrei-comp-main-action-button-container-padding-block-medium | — | 6px |
--tanrei-comp-main-action-button-container-padding-block-small | — | 6px |
--tanrei-comp-main-action-button-container-padding-inline-end-with-icon-large | sys.space.space400 | 32px |
--tanrei-comp-main-action-button-container-padding-inline-end-with-icon-medium | sys.space.space250 | 20px |
--tanrei-comp-main-action-button-container-padding-inline-end-with-icon-small | sys.space.space150 | 12px |
--tanrei-comp-main-action-button-container-padding-inline-end-large | sys.space.space400 | 32px |
--tanrei-comp-main-action-button-container-padding-inline-end-medium | sys.space.space250 | 20px |
--tanrei-comp-main-action-button-container-padding-inline-end-small | sys.space.space200 | 16px |
--tanrei-comp-main-action-button-container-padding-inline-start-with-icon-large | sys.space.space300 | 24px |
--tanrei-comp-main-action-button-container-padding-inline-start-with-icon-medium | sys.space.space200 | 16px |
--tanrei-comp-main-action-button-container-padding-inline-start-with-icon-small | sys.space.space150 | 12px |
--tanrei-comp-main-action-button-container-padding-inline-start-large | sys.space.space400 | 32px |
--tanrei-comp-main-action-button-container-padding-inline-start-medium | sys.space.space250 | 20px |
--tanrei-comp-main-action-button-container-padding-inline-start-small | sys.space.space200 | 16px |
--tanrei-comp-main-action-button-container-shape-large | sys.shape.corner.full | 9999px |
--tanrei-comp-main-action-button-container-shape-medium | sys.shape.corner.full | 9999px |
--tanrei-comp-main-action-button-container-shape-small | sys.shape.corner.full | 9999px |
--tanrei-comp-main-action-button-disabled-opacity | — | 1 |
--tanrei-comp-main-action-button-filled-container-color | sys.color.primary | |
--tanrei-comp-main-action-button-filled-container-elevation | 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-main-action-button-filled-disabled-container-color | — | |
--tanrei-comp-main-action-button-filled-disabled-container-elevation | — | |
--tanrei-comp-main-action-button-filled-disabled-label-color | — | |
--tanrei-comp-main-action-button-filled-disabled-state-layer-color | — | |
--tanrei-comp-main-action-button-filled-focused-container-color | — | |
--tanrei-comp-main-action-button-filled-focused-container-elevation | — | 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-main-action-button-filled-focused-label-color | — | |
--tanrei-comp-main-action-button-filled-focused-state-layer-color | — | |
--tanrei-comp-main-action-button-filled-hovered-container-color | — | |
--tanrei-comp-main-action-button-filled-hovered-container-elevation | — | 0px 0px 0px 1px rgb(0 0 0 / 0.08), 0px 1px 1px 0px rgb(0 0 0 / 0.04), 0px 8px 16px -4px rgb(0 0 0 / 0.04), 0px 24px 32px -8px rgb(0 0 0 / 0.06) |
--tanrei-comp-main-action-button-filled-hovered-label-color | — | |
--tanrei-comp-main-action-button-filled-hovered-state-layer-color | — | |
--tanrei-comp-main-action-button-filled-label-color | sys.color.on-primary | |
--tanrei-comp-main-action-button-filled-pressed-container-color | — | |
--tanrei-comp-main-action-button-filled-pressed-container-elevation | — | 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-main-action-button-filled-pressed-label-color | — | |
--tanrei-comp-main-action-button-filled-pressed-state-layer-color | — | |
--tanrei-comp-main-action-button-filled-state-layer-color | comp.main-action-button.filled.label.color | |
--tanrei-comp-main-action-button-focused-opacity | — | 1 |
--tanrei-comp-main-action-button-hovered-opacity | — | 1 |
--tanrei-comp-main-action-button-icon-size-large | sys.icon.large | 32px |
--tanrei-comp-main-action-button-icon-size-medium | sys.icon.medium | 24px |
--tanrei-comp-main-action-button-icon-size-small | sys.icon.medium | 24px |
--tanrei-comp-main-action-button-motion-feedback-duration | sys.motion.role.feedback | 450ms |
--tanrei-comp-main-action-button-motion-resize-duration | sys.motion.role.resize.large | 400ms |
--tanrei-comp-main-action-button-motion-resize-easing | sys.motion.easing.spatial | cubic-bezier(0.2, 0, 0, 1) |
--tanrei-comp-main-action-button-motion-state-duration-large | sys.motion.role.state.large | 250ms |
--tanrei-comp-main-action-button-motion-state-duration-medium | sys.motion.role.state.default | 250ms |
--tanrei-comp-main-action-button-motion-state-duration-small | sys.motion.role.state.compact | 200ms |
--tanrei-comp-main-action-button-motion-state-easing | sys.motion.easing.state | cubic-bezier(0.2, 0, 0, 1) |
--tanrei-comp-main-action-button-pressed-opacity | — | 1 |
--tanrei-comp-main-action-button-surface-container-color | sys.color.surface-container-lowest | |
--tanrei-comp-main-action-button-surface-container-elevation | 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-main-action-button-surface-disabled-container-color | — | |
--tanrei-comp-main-action-button-surface-disabled-container-elevation | — | |
--tanrei-comp-main-action-button-surface-disabled-label-color | — | |
--tanrei-comp-main-action-button-surface-disabled-state-layer-color | — | |
--tanrei-comp-main-action-button-surface-focused-container-color | — | |
--tanrei-comp-main-action-button-surface-focused-container-elevation | — | 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-main-action-button-surface-focused-label-color | — | |
--tanrei-comp-main-action-button-surface-focused-state-layer-color | — | |
--tanrei-comp-main-action-button-surface-hovered-container-color | — | |
--tanrei-comp-main-action-button-surface-hovered-container-elevation | — | 0px 0px 0px 1px rgb(0 0 0 / 0.08), 0px 1px 1px 0px rgb(0 0 0 / 0.04), 0px 8px 16px -4px rgb(0 0 0 / 0.04), 0px 24px 32px -8px rgb(0 0 0 / 0.06) |
--tanrei-comp-main-action-button-surface-hovered-label-color | — | |
--tanrei-comp-main-action-button-surface-hovered-state-layer-color | — | |
--tanrei-comp-main-action-button-surface-label-color | sys.color.primary | |
--tanrei-comp-main-action-button-surface-pressed-container-color | — | |
--tanrei-comp-main-action-button-surface-pressed-container-elevation | — | 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-main-action-button-surface-pressed-label-color | — | |
--tanrei-comp-main-action-button-surface-pressed-state-layer-color | — | |
--tanrei-comp-main-action-button-surface-state-layer-color | comp.main-action-button.surface.label.color | |
--tanrei-comp-main-action-button-tonal-container-color | sys.color.secondary-container | |
--tanrei-comp-main-action-button-tonal-container-elevation | 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-main-action-button-tonal-disabled-container-color | — | |
--tanrei-comp-main-action-button-tonal-disabled-container-elevation | — | |
--tanrei-comp-main-action-button-tonal-disabled-label-color | — | |
--tanrei-comp-main-action-button-tonal-disabled-state-layer-color | — | |
--tanrei-comp-main-action-button-tonal-focused-container-color | — | |
--tanrei-comp-main-action-button-tonal-focused-container-elevation | — | 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-main-action-button-tonal-focused-label-color | — | |
--tanrei-comp-main-action-button-tonal-focused-state-layer-color | — | |
--tanrei-comp-main-action-button-tonal-hovered-container-color | — | |
--tanrei-comp-main-action-button-tonal-hovered-container-elevation | — | 0px 0px 0px 1px rgb(0 0 0 / 0.08), 0px 1px 1px 0px rgb(0 0 0 / 0.04), 0px 8px 16px -4px rgb(0 0 0 / 0.04), 0px 24px 32px -8px rgb(0 0 0 / 0.06) |
--tanrei-comp-main-action-button-tonal-hovered-label-color | — | |
--tanrei-comp-main-action-button-tonal-hovered-state-layer-color | — | |
--tanrei-comp-main-action-button-tonal-label-color | sys.color.on-secondary-container | |
--tanrei-comp-main-action-button-tonal-pressed-container-color | — | |
--tanrei-comp-main-action-button-tonal-pressed-container-elevation | — | 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-main-action-button-tonal-pressed-label-color | — | |
--tanrei-comp-main-action-button-tonal-pressed-state-layer-color | — | |
--tanrei-comp-main-action-button-tonal-state-layer-color | comp.main-action-button.tonal.label.color | |
--tanrei-comp-main-action-button-label-typescale-large | sys.typescale.heading-5 | 500 16px/1.5 |
--tanrei-comp-main-action-button-label-typescale-medium | sys.typescale.label | 500 14px/1.4286 |
--tanrei-comp-main-action-button-label-typescale-small | sys.typescale.label | 500 14px/1.4286 |
نماذج الاختبار
عروض مرجعية. تلتقط كل المنصات لقطة لكل نموذج بالمعرّف نفسه حتى يمكن مقارنة النتائج.
variant: filled (11)
filled-extended
variant: filled label: Compose slots: icon filled-collapsed
variant: filled extended: false label: Compose slots: icon filled-icon-trailing
variant: filled iconPosition: trailing label: Next slots: icon filled-label-only
variant: filled label: Compose filled-small-extended
variant: filled size: small label: Compose slots: icon filled-small-collapsed
variant: filled size: small extended: false label: Compose slots: icon filled-large-extended
variant: filled size: large label: Compose slots: icon filled-large-collapsed
variant: filled size: large extended: false label: Compose slots: icon filled-disabled
variant: filled disabled: true label: Compose slots: icon filled-full-width
variant: filled fullWidth: true label: Compose slots: icon filled-full-width-collapsed
variant: filled extended: false fullWidth: true label: Compose slots: icon variant: tonal (2)
tonal-extended
variant: tonal label: Compose slots: icon tonal-collapsed
variant: tonal extended: false label: Compose slots: icon variant: surface (2)
surface-extended
variant: surface label: Compose slots: icon surface-collapsed
variant: surface extended: false label: Compose slots: icon مولَّد من specs/main-action-button.spec.json, tokens/comp/main-action-button.tokens.json, design/tokens/
استخدم زر الإجراء الرئيسي للإجراء الذي يأتي معظم الأشخاص إلى الشاشة لتنفيذه، حين ينبغي أن يبقى في المتناول أينما وصل بهم التمرير: كتابة رسالة، إضافة عنصر، بدء تسجيل. للشاشة زر واحد، أو لا شيء. وشاشات كثيرة لا تحتاج إليه: صفحة الإعدادات أو عرض القراءة ليس فيهما إجراء وحيد يستحق أن يطفو فوقهما.
- للإجراء الذي يخص نموذجًا أو مربع حوار أو عنصرًا واحدًا في المحتوى، استخدم زرًّا حيث يكون ذلك المحتوى.
- لعدة إجراءات على الشاشة الحالية أو على التحديد، استخدم شريط أدوات.
- حين يأتي الإجراء الرئيسي في بضع هيئات مترابطة (مستند جديد، أو مجلد، أو رفع ملف)، دع زر الإجراء الرئيسي يفتح لوحة سفلية تسردها. وقائمة FAB تؤدي هذه المهمة في أنظمة طبقة m3-like، حيث تعيش؛ أما النظام الافتراضي فلا يملكها.
- ينفّذ إجراء ولا يأخذ وجهة. عنصر التحكم الذي لا يفعل إلا نقل الأشخاص إلى مكان آخر رابط: زر له الخاصية
href.
ابدأ به ممتدًّا. الاسم المكتوب هو ما يخبر الأشخاص بما يفعله الزر، والأيقونة وحدها لا تكون آمنة إلا بعد أن يتعلموها.
اطوِه حين تكلّف التسمية أكثر مما تعطي: والمحتوى يُمرَّر والزر سيغطيه، أو في نافذة ضيقة. ومدّه من جديد حين تتوفر الفسحة، كما عند العودة إلى أعلى القائمة. التغيير قرارك أنت، بضبط الخاصية extended؛ وضغط الزر لا يغيّر هيئته أبدًا.
- يحتفظ الزر بارتفاعه وبزواياه وهو يتغيّر، وأي حافة تبقى في مكانها قرار تخطيطك. فإن كان مثبَّتًا عند جهة النهاية انطوى نحو تلك الحافة.
- الزر الذي بلا أيقونة يبقى ممتدًّا، لأنه لن يكون هناك ما ينطوي إليه. والزر الذي بلا تسمية يرسم الهيئة المطويّة ويُبلَّغ عنه في بنيات التنقيح (debug): لا اسم له.
- حيث تكون الحركة مقلَّلة، تتغيّر الهيئة فورًا.
| الطراز | التوكيد | يُستخدم لـ |
|---|---|---|
| Filled (الافتراضي) | الأعلى | الإجراء الرئيسي للشاشة بكامل قوته. |
| Tonal | عالٍ | إجراء رئيسي في شاشة ينبغي أن يتصدرها محتواها. |
| Surface | محايد | إجراء رئيسي فوق محتوى له لون أصلًا، كخريطة أو صورة، حيث تنافسه الحاوية الملوّنة. |
يجوز لنظام تصميم أن يضيف طُرُزًا (variants) من عنده.
| الحجم | الارتفاع في النظام الافتراضي | يُستخدم لـ |
|---|---|---|
| Small | 40 | إجراء ثانٍ مرتبط بجانب إجراء من الحجم medium، أو تخطيط كثيف. |
| Medium (الافتراضي) | 56 | الإجراء الرئيسي في معظم الشاشات. |
| Large | 96 | إجراء شاشة واسعة أو شبه فارغة، حيث يضيع زر من الحجم medium. |
الارتفاع هو أيضًا ضلع الهيئة المطويّة، فيحتفظ الزر الواحد بارتفاعه وهو ينطوي ويمتد.
لا يرسم الزر حجابًا (scrim) ولا يحرّك محتوى. ضعه فوق المحتوى، عادةً في الزاوية السفلى من جهة النهاية، وأبعده عن شريط التنقل وعن شريط الأدوات المُرسى (docked) وعن الهوامش التي يحجزها النظام (insets). اترك فسحة في نهاية المحتوى الذي يُمرَّر، كي لا يغطي الزر العنصر الأخير تغطية دائمة. ظله يُلقى خارج حاويته: أعطِه فسحة إن كانت الحاوية التي تحمله تقصّ ما يتجاوزها.
أضف full-width ليصير الزر بعرض حاويته، وتتوسّطه أيقونته وتسميته: الإجراء الوحيد في الشاشة ممتدًّا على أسفلها في شاشة ضيقة، مثل «إتمام الشراء» أو «إرسال». والزر الذي بعرض كامل ممدود دائمًا: لا ينطوي أثناء تمرير المحتوى، وجعل extended خطأً يُبلَّغ عنه في إصدارات التصحيح. ويحتفظ بارتفاع حجمه وزواياه وارتفاعه الظلي، والتسمية التي لا تتسع تنتقل إلى السطر التالي. ولا يزال لا يضع نفسه: ضعه في الحاوية التي تحمله في أسفل الشاشة.
زر إجراء رئيسي بعرض كامل
- سمِّه بالإجراء بصيغة الفعل، أو الفعل والاسم: إنشاء، حدث جديد، إضافة صورة.
- اختر رسمًا يربطه الأشخاص أصلًا بالإجراء، مثل
editللكتابة أوaddللإنشاء. - اضبط الخاصية
iconPositionعلى القيمةtrailingللرسم الذي يشير إلى حيث يذهب الإجراء، كسهم «التالي». - أبقِه في المكان نفسه في كل شاشة فيها زر كهذا.
- أخفِه حين لا يكون إجراؤه متاحًا في شاشة ما. هذا يخدم الأشخاص عادةً أفضل من زر معطَّل يطفو فوق المحتوى.
- لا تضع زرَّي إجراء رئيسي من الحجم نفسه في شاشة واحدة. إن بدا إجراءان مهمَّين بالقدر نفسه فليس أي منهما الرئيسي: استخدم أزرارًا في المحتوى.
- لا تستخدمه للإجراءات الثانوية، ولا للإجراءات التي لا رجعة فيها، ولا لإجراءات التنقل فقط، مثل «حذف» أو «الإعدادات» أو «رجوع».
- لا تستخدمه زر تبديل، ولا تغيّر تسميته أو أيقونته لإظهار حالة.
- لا تطوِه في شاشة يراها الأشخاص أول مرة، حين لا شيء آخر يقول ما تعنيه الأيقونة.
- لا تدعه يغطي محتوى يحتاج إليه الأشخاص ليقرروا هل يضغطونه.
تُكتب التسميات بأسلوب الجملة (sentence case) ومن دون علامة ترقيم في آخرها. اجعلها كلمة أو كلمتين. التسمية لا تُقتطع: تبقى على سطر واحد ما دامت تتسع، وتلتف حين يعطيها التخطيط عرضًا أقل.
- الدور
button- التسمية
- label is the accessible name, whether it is shown or collapsed away. The icon is decorative to assistive technology. A tooltip may show the same text to sighted pointer users while it is collapsed, but it never replaces label.
- الحد الأدنى للهدف
- تستوفي مساحة اللمس الحد الأدنى لحجم الهدف حتى لو كان الحجم المرئي أصغر. minimum 32px · pointer 44px · spacing 8px · touch 48px
لوحة المفاتيح
| المفاتيح | الإجراء |
|---|---|
| Tab | Moves focus to the main action button. |
| Enter / Space | Activates it. |
ملاحظات
- It is an action, never a toggle. Collapsing and extending change what is drawn, not what is announced: the role stays button, the name stays label, and there is no expanded state to report (MAB-20).
- Its place in the focus and reading order is where the layout puts it in the element tree, not where it is drawn. Put it where its action belongs: after the content it acts on, or first when it is the screen's reason to exist.
- Extended, text must remain readable at 200% text size: the container grows, the label never truncates. Collapsed, the icon is not text: where sizes are points or dp (SwiftUI, Compose, Flutter, React Native), text size leaves the square and the icon as they are; on the web every Tanrei size follows the root font size (rem), so the square and its icon grow together and stay square and whole. Either way the label is still announced.
- A trailing icon that points (an arrow) keeps its glyph in right-to-left layouts; the product chooses the glyph that points the right way for the direction.
- How a state looks is a value decision of the active design system; components read the state's tokens and never compute the effect themselves.
مولَّد من specs/main-action-button.spec.json, tokens/sys/measure.tokens.json
- هو زر تسمّيه الخاصية
labelفي الهيئتين. والأيقونة مخفية عن التقنيات المساعدة. - الطيّ والمدّ يغيّران ما يُرسم لا ما يُعلَن: يبقى الدور والاسم والتركيز كما هي، ولا يُعلَن شيء، وليست هناك حالة ضغط ولا حالة توسيع.
- المفتاحان Enter و Space يفعّلانه. وحين يكون معطَّلًا لا يُصدر شيئًا، ويخرج من ترتيب التركيز، ويُعرَّف للتقنيات المساعدة معطَّلًا.
- مساحة اللمس تستوفي الحد الأدنى للهدف في كل حجم، ومنها الحجم small.
- يعرض مؤشر التركيز عند التركيز بلوحة المفاتيح فقط، بلا حركة.
- في الهيئة الممتدة تكبر الحاوية مع حجم النص ولا تُقتطع التسمية أبدًا. وفي الهيئة المطويّة ليست الأيقونة نصًّا. على الويب يتبع كل حجم في Tanrei حجم خط الجذر، فيكبر المربع وأيقونته معًا ويبقى مربعًا.
- في تخطيط من اليمين إلى اليسار تتبادل الأيقونة والتسمية الجهتين، ويتبعهما الحشو. أما الرسم نفسه فلا يُعكس إلا حين تعلّمه مجموعة الأيقونات بأنه يدل على اتجاه.
- بنيات التنقيح تبلّغ عن الزر الذي بلا تسمية، وعن الزر المطويّ الذي بلا أيقونة.
- أعطِه دائمًا الخاصية
label، بلغة منتجك، حتى إن كان لن يظهر إلا مطويًّا. - ضعه في شجرة العناصر حيث ينتمي إجراؤه: بعد المحتوى الذي يعمل عليه، أو أولًا حين يكون هو سبب وجود الشاشة. التقنيات المساعدة والمفتاح Tab يصلان إليه بترتيب الشجرة، لا بحسب موضع رسمه.
- حين يكون مطويًّا، فكّر في تلميح بالنص نفسه لمن يستخدمون مؤشرًا. التلميح لا يغني أبدًا عن
label. - تأكد من أنه لا يحجب المحتوى أو عنصر التحكم الذي عليه تركيز لوحة المفاتيح. اترك فسحة في نهاية المحتوى، أو أزِح الزر عن الطريق.
- لا تعتمد على لون الطراز لحمل معنى. قل ذلك في التسمية.