コールアウト
コンテンツの一部としてその場に残る通知です。注記、注意、理由の説明、問題の要約などを、控えめな塗りまたは枠線で、ステータスがあればその色とグリフで描きます。タイトル、アクション、閉じるボタンを付けられます。
- カテゴリ
- コミュニケーション
- トークン
comp.callout- レベル
- 基礎
- Web
tanrei-calloutschedule - SwiftUI
TanreiCalloutradio_button_unchecked - Jetpack Compose
TanreiCalloutradio_button_unchecked - Flutter
TanreiCalloutradio_button_unchecked - React Native
Calloutradio_button_unchecked
生成元 docs/status/status.json, specs/callout.spec.json
注記、タイトル付きの注意、アクションと閉じるボタンのある通知
コールアウトは、ページの流れの中にある通知です。置いた場所に、その場所の幅いっぱいで、コンテンツがある限り残ります。既定では注記であり、前の段落と同じように、ある場所で読まれます。フォーカスを取ることはありません。
Web では <tanrei-callout> です。ほかのプラットフォームはまだ実装していません。
本文は要素自身の内容です。タイトルは headline 属性で渡すか、独自の内容や見出しにする場合は title スロットに入れます。アイコンセットのグリフは icon スロットに、独自のボタンやリンクは actions スロットに入れます。
<!-- 注記。ステータスはタイトルの言葉で伝わっています。 -->
<tanrei-callout status="info">
<p slot="title">注記</p>
テキストスタイルの名前は、サイズではなくレベルで付けます。
</tanrei-callout>
<!-- タイトルがステータスを伝えていない場合:status-label を先に読み上げます(「警告、…」)。描画はしません。 -->
<tanrei-callout status="warning" status-label="警告" headline="アクセシビリティ">
プリセットは元のデザインに合わせるもので、このコントラストのしきい値には合わせません。
</tanrei-callout>
<!-- ヒント:ステータスなし、独自のグリフ、言葉はタイトルに。 -->
<tanrei-callout headline="ヒント">
<span slot="icon">lightbulb</span>
アクションは有効なままにして、使われたときに何が足りないかを説明します。
</tanrei-callout>
<!-- 長文の内容はプローズです。コールアウトのサイズで、行長の制限なしにします。 -->
<tanrei-callout size="large" status="warning">
<h3 slot="title">移行の前にバックアップを取ってください</h3>
<div class="tanrei-prose" data-size="large" data-measure="false">
<p>移行はデータベースをその場で書き換えます。<a href="#restore">コピーから復元する方法を見る</a>。</p>
<ul><li>…</li></ul>
</div>
</tanrei-callout>
<script type="module">
import '@tanrei/web/components/callout';
import '@tanrei/web/callout.css'; // サーバーで描画したコールアウトが、要素の定義前に保つボックス
</script>import { Button, Callout } from '@tanrei/react';
<Callout status="warning" headline="ディスク上のファイルが変更されました" live open={conflict} closable closeLabel="閉じる" onDismiss={() => setConflict(false)}>
ここには、そのファイルにない編集があります。選ぶまで何も上書きされません。
<Button slot="actions" variant="outlined" onClick={reload}>ディスクから再読み込み</Button>
<Button slot="actions" variant="text" onClick={keep}>自分の編集を残す</Button>
</Callout>2 つの見た目と、それぞれのステータス
タイトル、独自のグリフ、アクション、閉じるボタン、large サイズ
構成要素
構成要素
tonal の上に描いています。| パーツ | 説明 |
|---|---|
1 container | The block that holds the notice, as wide as its place in the layout and as tall as its content, flat on the surface it sits on. Filled in the tonal look (a quiet neutral, or a status's quiet container) and edged in the outlined look. It carries no state: nothing about it answers a pointer, a press or focus. |
2 outline · 任意 | The outlined look's edge: one hairline inside the container, the same in every status. |
3 icon · 任意 | The glyph at the start, on the first line of the text: the status's glyph from the system's icon set (info, warning, error or check_circle, the ones a snackbar draws), or the glyph the product names. In the status's own color, a little softer than the text. Decorative: the status is given in words. |
4 title · 任意 | A few words that name the notice, above the body. Plain text unless the product gives a heading; it wraps and is never cut. |
5 body | The notice itself: the product's content, from one sentence to several paragraphs with lists, links, code and tables. Long-form blocks in it are prose. |
6 actions · 任意 | One or two of the product's own Buttons or links that follow up on the notice, in a row below the text. |
7 close-button · 任意 | An icon-only Button of the small size showing the close glyph at the end of the first row, in the variant comp.callout.close-button.variant names (tonal in the default system) and, on a filled look, in the tone of that fill: its content color, so that its container is that color made translucent and its glyph is that color. The callout places it and chooses its variant and its tone; everything else it reads from Button's own tokens. The only part of a callout that answers a pointer, a press or focus, and it answers as a Button. |
寸法
寸法
| 長さ | トークン | 値(px) |
|---|---|---|
container padding-inline | tanrei.comp.callout.container.padding-inline | 16 |
tonal の上に描いています。プロパティ
| プロパティ | 型 | 既定値 | 説明 |
|---|---|---|---|
title | string | "" | A few words above the body that name the notice ("Not published yet"). Plain text, never a heading. Empty draws the body alone. The title slot takes its place where the product needs a heading of its own level or inline content. |
status | default | info | warning | error | success | "default" | What the notice is, in the names the snackbar and the tag use. default: a neutral aside, with no glyph unless the product gives one. info, warning, error and success draw the look in that status's color roles with that status's glyph; a live callout is announced assertively for warning and error. Use them for what they mean everywhere in the system: advice is not a success. |
statusLabel | string | "" | The status in words, in the product's language ("Warning"), read by assistive technology before the title and the body and not drawn, so that the status never rests on color and glyph alone. For a callout whose title does not itself say the status; needed when it has a status and no title. Ignored while status is default. |
variant | tonal | outlined | "tonal" | How much the callout weighs. tonal: a quiet fill, the default. outlined: no fill and one hairline, for a callout on a tinted surface or inside a filled card, where a fill would vanish, and for many callouts close together. A design system may add values. |
size | medium | large | "medium" | The size of the text, in prose's two sizes. medium sets the body in the interface's own text style, for a callout among controls: a form, a panel, a dialog. large sets it in the style for long reading, for a callout in a page whose purpose is the text. Paddings, the glyph and the close button are the same at both. A design system may add values. |
live | boolean | false | Whether the callout is announced. False, the default, is for a callout that is part of what was written: it is a note, read where it stands. True is for one that appears or changes in answer to something (a summary of a form's errors after a submit, a notice that the file changed underneath the person): it is a live region, announced once when it is shown and when its content changes, politely or, for warning and error, assertively. It changes nothing that is drawn. |
closable | boolean | false | Draws a close button, for a notice the person may put away (an announcement, a hint they have read). A caution that qualifies the content beside it should not be closable. |
closeLabel | string | "" | The close button's accessible name, in the product's language ("Close"). Required while closable is true. |
open | boolean | true | Whether the callout is shown. The close button sets it to false; the product sets it to show a callout again or to show one in answer to something. A callout that is not open draws nothing and takes no space. |
スロット
| スロット | 説明 |
|---|---|
default | The body: text, or the product's own blocks (paragraphs, lists, a table, a code block, any component). Long-form blocks are laid out as prose of the callout's size. |
icon | A glyph of the system's icon set, by name, drawn in place of the status glyph, or as the glyph of a callout without a status (a tip's lightbulb). |
title | The product's own title content in place of the title prop: text with inline content, or a heading of the level the page's outline needs. The callout draws it in the title's style and changes neither its role nor its level. |
actions | The actions: the product's own Buttons or links, one or two. The callout lays them out below the text and does nothing else to them. |
イベント
| イベント | 説明 |
|---|---|
dismiss | The person closed the callout with its close button. Emitted exactly once, after open became false; never emitted when the product sets open. |
状態
振る舞い
EARS 記法による要件です。各プラットフォームの実装は、この ID に対応するテストで検証されます。要件の原文は仕様ファイルのものをそのまま掲載しています。
| ID | 要件 |
|---|---|
CLO-1 | THE callout SHALL draw a container as wide as the layout it is placed in gives it (CLO-22) and as tall as its content, with corners comp.callout.container.shape eased by sys.shape.corner-smoothing and no elevation, padded by comp.callout.container.padding-block above its first line and below its last block, by comp.callout.container.padding-inline at the start, and at the end by comp.callout.container.padding-inline where the text meets it or by comp.callout.container.padding-inline-end-with-close after the close button. Inside it SHALL lay out, from the start: the glyph, where it has one (CLO-5, CLO-6); comp.callout.icon.gap after it a column that takes the remaining width and holds the title (CLO-7), the body (CLO-8) and the actions (CLO-9), in that order; and comp.callout.container.gap after that column the close button, where it has one (CLO-10). THE callout SHALL centre the glyph and the close button on the first line of the text (the title's, or the body's without a title) and keep them there however tall the text grows, and any height the container has beyond its content SHALL lie below the content. |
CLO-2 | WHILE status is default THE callout SHALL fill its container with the container color of its variant and draw its title, its body and a glyph the product gave in that variant's title, body and icon colors: comp.callout.container.color.tonal, comp.callout.title.color.tonal, comp.callout.body.color.tonal and comp.callout.icon.color.tonal for tonal, and outlined's tokens of the same names (comp.callout.container.color.outlined, comp.callout.body.color.outlined, and so on). |
CLO-3 | WHILE status is info, warning, error or success THE callout SHALL draw its container, its title, its body and its glyph from the parts of its variant prefixed with the status: for a tonal info callout comp.callout.info.container.color.tonal, comp.callout.info.title.color.tonal, comp.callout.info.body.color.tonal and comp.callout.info.icon.color.tonal; for outlined, and for warning, error and success, their own tokens of the same names (comp.callout.error.icon.color.outlined, comp.callout.success.container.color.tonal, and so on). A status SHALL change these colors, the glyph (CLO-5), the tone of the close button (CLO-10) and how a live callout is announced (CLO-21), and nothing else: the callout's size, shape, layout and edge stay those of its variant and size. |
CLO-4 | WHILE variant is outlined THE callout SHALL draw an edge comp.callout.outline.width wide in comp.callout.outline.color inside its container's size, following its corners, in every status, without changing the callout's size or the place of its content; WHILE variant is tonal it SHALL draw no edge. A status SHALL NOT color the edge: it is the system's one hairline. |
CLO-5 | WHILE status is info, warning, error or success and the icon slot is empty THE callout SHALL draw that status's glyph from the system's icon set (info for info, warning for warning, error for error, check_circle for success), the glyphs a snackbar draws, in a box of comp.callout.icon.size, in its form's icon color (CLO-3) drawn at comp.callout.icon.opacity (an opacity of the glyph alone, which fades nothing else), with sys.icon.family.unselected and sys.icon.fill.unselected, sys.icon.weight and an optical size clamped between sys.icon.optical-size.min and sys.icon.optical-size.max. The glyph so drawn SHALL keep 3:1 against its container in every scheme of the default system, and against every surface role in the outlined look. THE callout SHALL keep the glyph from assistive technology, which is given the status in words (CLO-20). WHILE status is default and the icon slot is empty THE callout SHALL draw no glyph and no room for one: the text starts at the start padding. |
CLO-6 | WHERE the icon slot holds a glyph THE callout SHALL draw it in the place, the box, the color and the opacity CLO-5 gives the status glyph (the icon color of its form, CLO-2 and CLO-3), in every status and without one, SHALL draw no status glyph beside it, and SHALL keep it from assistive technology: the product's glyph says what kind of notice this is (advice, an experiment, something new), and the words say it to everyone. |
CLO-7 | WHILE title is not empty THE callout SHALL draw it above the body in the text style of its size (comp.callout.title.typescale.medium for medium, comp.callout.title.typescale.large for large) and the title color of its form (CLO-2, CLO-3), with comp.callout.title.gap between it and the body; the title SHALL wrap and SHALL never be cut. WHERE the title slot holds content THE callout SHALL draw that content in the title's place, style and color instead of the title prop, and SHALL change neither its role nor its level: a title given as text is plain text and never a heading, and a title the product gives as a heading stays a heading of the level the product gave it, drawn as every other title is. WHILE both are empty THE callout SHALL draw the body alone, on the first line. THE callout SHALL set the title's letter-spacing by the script of its text, as every title is set (PRS-20): no negative letter-spacing WHERE its language is Chinese, Japanese or Korean, and none WHERE its script joins its letters or stacks marks on them. |
CLO-8 | THE callout SHALL draw the content of its default slot as its body, below the title, and SHALL give it the text style of its size (comp.callout.body.typescale.medium for medium, comp.callout.body.typescale.large for large) and the body color of its form (CLO-2, CLO-3) as the style and color its text takes where nothing inside sets another. The body SHALL wrap and SHALL never be cut or limited to a number of lines. WHERE the body holds long-form blocks (paragraphs, lists, a quote, a table, a code block) they SHALL be laid out as prose of the callout's size (PRS-1, PRS-5), without a measure of their own, so that the first block has no space before it and the last none after it and the body is exactly as tall as its content; the callout SHALL add no style to anything inside a component placed in its body, and a link in the body SHALL be underlined at rest (PRS-17). |
CLO-9 | WHERE the actions slot holds content THE callout SHALL lay it out as a row below the text (the body, or the title where there is no body), comp.callout.actions.gap below it, starting at the text's start edge, with comp.callout.actions.item-gap between two actions along the row and between rows where they wrap; an action's label SHALL NOT be cut to make the row fit. The actions are the product's own Buttons and links: THE callout SHALL NOT restyle them, SHALL NOT answer their presses and SHALL NOT close when one is activated. They SHALL follow the body in reading order and in the focus order, before the close button. |
CLO-10 | WHILE closable is true THE callout SHALL draw at the end of its first row an icon-only Button of the small size showing the glyph close of the system's icon set and named by closeLabel, in the variant comp.callout.close-button.variant names and, in every look but outlined, in the tone of its form (BTN-45): the body color of that form (comp.callout.body.color.tonal without a status, comp.callout.info.body.color.tonal for info, and so on), the content color of the fill it stands on, so that its container is that color made translucent and its glyph is that color; both given through the channel a Button reads from the component that places it, and otherwise unrestyled: it reads Button's own tokens, answers hover, focus and press as any Button does and keeps its own minimum target (BTN-5). The outlined look has no fill, so its close button takes no tone and is drawn as the variant draws it on the surface the callout sits on. THE callout's container, its text and its glyph SHALL NOT change under a pointer, a press or focus: the callout itself has no states. WHILE closable is false THE callout SHALL draw no close button and keep no room for one. |
CLO-11 | WHEN the user activates the close button by pointer, touch, Enter or Space THE callout SHALL set open to false, emit dismiss exactly once and close (CLO-13). THE callout SHALL NOT close by itself after a time, and SHALL NOT answer Escape: it is part of the content, and Escape belongs to whatever overlay or field the person is in. |
CLO-12 | WHEN a callout closes while focus is inside it THE callout SHALL move focus to the element that had it before focus entered the callout or, where that element no longer exists or cannot take focus, leave focus to the platform's default, so that the next Tab reaches what followed the callout; WHEN it closes while focus is elsewhere it SHALL NOT move focus. |
CLO-13 | WHILE open is false THE callout SHALL draw nothing, take no space and expose nothing to assistive technology, and its content SHALL NOT be reachable by focus; WHEN open changes THE callout SHALL appear or disappear at once, without a motion of its own, and SHALL emit dismiss only for a close the person made (CLO-11), never when the product sets open. |
CLO-19 | THE callout 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); a platform that cannot draw it SHALL fall back to a quarter circle and state that in its README. Its close button's corners and its focus indicator are the Button's (BTN-10). |
CLO-20 | WHILE live is false THE callout SHALL be exposed to assistive technology as a note: a part of the content that qualifies what is around it, read where it stands in reading order, named by its title where it has one and otherwise by statusLabel where status is not default and the product gave one. WHILE status is not default and statusLabel is not empty THE callout SHALL expose statusLabel as text before the title and the body, set apart so that it is read as a phrase of its own ("Warning, …"), and SHALL NOT draw it; WHILE status is default it SHALL ignore statusLabel. A callout that is not live SHALL NOT be announced when it is shown or when its content changes, SHALL NOT move focus, and SHALL NOT be a stop in the focus order: static content is not an alert. |
CLO-21 | WHILE live is true THE callout SHALL be a live region in place of a note. WHEN it is shown after its page or view was first presented (open becomes true, or the product adds it), and WHEN its title, its body or its status changes while it is shown, THE callout SHALL have assistive technology announce it once: statusLabel first when status is not default, then the title when it has one, then the whole body. It SHALL announce politely (after what is being read) when status is default, info or success, and assertively (interrupting what is being read) when status is warning or error, as a snackbar does, and SHALL NOT move keyboard or screen-reader focus. A live callout that is drawn with the first presentation of its page or view SHALL NOT announce itself then. live SHALL change nothing that is drawn. |
CLO-22 | THE callout SHALL lay itself out as a block in the flow of its container: it SHALL take the whole inline size the container gives it, in a page, in a list item, in a tab's panel, in a card or in another callout's body alike, with its start edge on the start edge of the text around it; it SHALL bring no outer space of its own (PRS-15: the space between it and its neighbours is its container's), SHALL never be wider than its container, SHALL have no minimum width, no maximum width and no measure of its own, and SHALL NOT scroll: content that cannot shrink (a table, a line of code) scrolls inside its own box. THE callout SHALL NOT float over the content, stick to an edge while the content scrolls or raise itself above it: where it stands is the product's layout. |
CLO-23 | WHILE the text size is enlarged THE callout SHALL grow its title and its body with it, keep its paddings and gaps, wrap, and grow in height; it SHALL keep the glyph's box at comp.callout.icon.size and the close button at its own size (a Button's icon-only circle, BTN-12), both still centred on the first line (CLO-1), SHALL cut nothing and set no fixed height, SHALL lose no content when the reader raises line height, paragraph spacing, letter spacing or word spacing, and SHALL need no horizontal scrolling at a width of 320 points with text at 200 %. |
CLO-24 | WHERE the platform draws with a person's own forced colors (the web's forced-colors mode, and a platform's equivalent where it has one) THE callout SHALL draw an edge comp.callout.outline.width wide in the platform's text color inside its container in every variant and status, its title, body and glyph in that text color with the glyph whole (no opacity), links in the platform's link color and still underlined, and its close button as a Button draws itself there, so that a look whose fill the mode removes is still a bounded block; the status SHALL then rest on the glyph's shape, the title's words and statusLabel. |
CLO-25 | WHERE the layout direction is right-to-left THE callout SHALL mirror the order of its content and apply its paddings by logical start and end: the glyph at the right, the text after it, the actions starting at the text's right edge and the close button at the left. |
CLO-26 | THE callout 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 callout is shown THE callout SHALL draw itself for the new direction at once, without a motion of its own, keeping its open state and its focus. |
CLO-27 | WHERE the layout direction is right-to-left THE callout 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 opacity nor the order CLO-25 gives. THE callout SHALL NOT mirror a glyph itself, SHALL NOT mirror content the product gives as an image or a view of its own rather than by a glyph's name, and its own glyphs (the four status glyphs) are drawn through the same helper, which mirrors none of them under the default icon set; the close button's glyph is the Button's (BTN-19). |
CLO-28 | THE callout SHALL lay out a title given as text as text of its own direction, isolated from the text around it: it takes the base direction of its first strong character, or the layout direction where it has none, so that a left-to-right name, a number with its unit and a version keep their own order in a right-to-left layout and reorder nothing beside them; THE callout SHALL still place the title and align its lines by the layout direction, not by the text's own. The body's blocks are laid out as prose lays out a block (PRS-25): each by its own first strong character unless the content states a direction, with its lines aligned to the start edge of the layout. |
CLO-29 | WHILE the system's icon set cannot yet draw a glyph the callout draws itself (a status's glyph, or the icon slot's; its font is still loading) THE callout SHALL draw nothing in that glyph's place, never the glyph's name as text, SHALL keep the glyph's box, and SHALL draw the glyph once the set can; statusLabel and closeLabel SHALL still reach assistive technology. The close button's glyph is the Button's to draw. |
CLO-30 | WHEN variant or size names a value that the active design system does not have, or status names a value this spec does not have, THE callout SHALL render with the default value (the default variant's or size's tokens, status default), and in debug builds report the unknown value. |
CLO-31 | IF the title, the title slot and the body are all empty THE callout SHALL draw nothing, take no space and expose nothing, and in debug builds report that a callout has no content: a glyph, actions or a close button alone are not a notice. WHILE status is not default and both the title and statusLabel are empty THE callout SHALL still render and in debug builds report that the status is not given in words; WHILE closable is true and closeLabel is empty it SHALL still render the close button and in debug builds report that the button has no accessible name; IF statusLabel is not empty while status is default THE callout SHALL ignore it and in debug builds report it. |
CLO-32 | WHERE the platform has ARIA attributes (the web), the host carries its note or live region role (CLO-20, CLO-21) itself, so what the product writes on it is not moved, but for a name: WHILE its name (its title, else statusLabel) is not empty THE callout SHALL hold the product's aria-label and aria-labelledby on that host as their data-aria- twins, so that its name (its title, else statusLabel) is its whole name although the platform gives aria-labelledby the precedence, and WHEN its name (its title, else statusLabel) is emptied SHALL give them back as they were written; WHILE its name (its title, else statusLabel) is empty a name the product gives so — aria-label, or aria-labelledby naming an element — SHALL be its name. WHILE it is closed or empty (CLO-13) it exposes nothing, and SHALL hold them as well, giving them back when it is shown. WHEN the product removes one, or its data-aria- twin, or sets the ARIA property that reflects it (ariaLabel, ariaLabelledByElements) to null, THE callout SHALL take it away. |
プラットフォーム別の名前対応
パリティは API が同一であることを意味しません。同じ契約を、各プラットフォームの流儀で表現します。
| 仕様 | Web | SwiftUI | Jetpack Compose | Flutter | React Native |
|---|---|---|---|---|---|
| コンポーネント | tanrei-callout | TanreiCallout | TanreiCallout | TanreiCallout | Callout |
title · プロパティ | headline | title | title | title | title |
status · プロパティ | status | status | status | status | status |
statusLabel · プロパティ | statusLabel | statusLabel | statusDescription | statusSemanticLabel | statusAccessibilityLabel |
variant · プロパティ | variant | variant | variant | variant | variant |
size · プロパティ | size | size | size | size | size |
live · プロパティ | live | isLive | live | live | live |
closable · プロパティ | closable | isClosable | closable | closable | closable |
closeLabel · プロパティ | closeLabel | closeLabel | closeDescription | closeSemanticLabel | closeAccessibilityLabel |
open · プロパティ | open | isPresented | visible | visible | open |
dismiss · イベント | dismiss | onDismiss | onDismiss | onDismiss | onDismiss |
| 備考 | <tanrei-callout> with the body as light-DOM children, the glyph in the icon slot, the title in the title slot (<p slot="title">, or <h3 slot="title"> where it is a heading) or the headline attribute (HTML's global title attribute would show a tooltip over the whole block, as the snackbar's and the app bar's), and Buttons or links in the actions slot. statusLabel and closeLabel are the status-label and close-label attributes. open is a boolean property that defaults to true; the open attribute spells it, and open="false" is how markup starts a callout closed. The host is display: block with no margin, role="note" and aria-labelledby naming the title, set through ElementInternals where axe can see it and as attributes otherwise; with live the host's role is status or alert by status, and the announcement is made through a visually hidden live region in the shadow root that exists from the element's first render, so that a callout opened later is announced (CLO-21). statusLabel is drawn as visually hidden text before the title in the shadow root, followed by a comma and a space; the glyph is aria-hidden. The body takes the form's content color and the size's text style through inherited color and font, so text placed directly in the element is styled, and a body that is rendered Markdown is wrapped by the product in <div class="tanrei-prose" data-measure="false"> with the callout's data-size (prose re-enters inside a Tanrei element). The glyph's opacity is applied to its color (a mix with transparent), never as an element's opacity. The close button is a <tanrei-button size="small"> with the close glyph in its icon slot and close-label as its label, in the shadow root (part close-button); the callout gives it the variant --tanrei-comp-callout-close-button-variant names and, in a look with a fill, the tone of its form (the form's body-color custom property) through the Button's internal channel, after each update (CLO-10). Under forced-colors: active the container takes a CanvasText border of the outline width (CLO-24). The stylesheet of @tanrei/web gives tanrei-callout:not(:defined) display: block, so the content keeps its place before the element is defined. dismiss is a CustomEvent. | TanreiCallout(_ title: String? = nil, status:, statusLabel:, variant:, size:, isLive:, isClosable:, closeLabel:, isPresented:, icon:, onDismiss:) { body } actions: { … }, the body and the actions as @ViewBuilders, the glyph by name through icon:, and a second initializer whose title is a @ViewBuilder (the title slot; .accessibilityAddTraits(.isHeader) is the product's). isPresented is a Binding<Bool> that defaults to a constant true. The container is an accessibility container labelled by the title or statusLabel; a live callout posts AccessibilityNotification.Announcement at default priority, or high for warning and error. | TanreiCallout(title, status, statusDescription, variant, size, live, closable, closeDescription, visible, icon, onDismiss, titleContent, actions) { body }, the body, titleContent and actions as composable lambdas, the glyph by name through icon. visible is hoisted state: the close button calls onDismiss and the product sets it. The container merges no descendants and carries paneTitle-free semantics: a content description of the status description on a leading invisible node, and for a live callout liveRegion polite or assertive by status. | TanreiCallout(title: …, status:, statusSemanticLabel:, variant:, size:, live:, closable:, closeSemanticLabel:, visible:, icon:, titleWidget:, actions:, onDismiss:, child:), the body as child, the title slot as titleWidget, the actions as a list of widgets, the glyph by name through icon. visible is the product's state; the close button calls onDismiss. A Semantics(container: true, label:) over the block, with liveRegion: true for a live callout and SemanticsService.announce with its assertiveness for warning and error. | <Callout title="…" status="warning">…</Callout>; the body is children, the title slot is the titleContent prop, the actions are the actions prop (elements), and the glyph is the icon prop (a glyph name). open is controlled when given, with onDismiss. A live callout sets accessibilityLiveRegion (polite or assertive) on Android and calls AccessibilityInfo.announceForAccessibility on iOS. Follows the app's direction where an ancestor's is not known. |
トークン
| トークン | 参照先 | 解決値(ライト) |
|---|---|---|
--tanrei-comp-callout-actions-gap | sys.space.space150 | 12px |
--tanrei-comp-callout-actions-item-gap | sys.space.space100 | 8px |
--tanrei-comp-callout-body-color-outlined | sys.color.on-surface | |
--tanrei-comp-callout-body-color-tonal | sys.color.on-secondary-container | |
--tanrei-comp-callout-close-button-variant | — | 1 |
--tanrei-comp-callout-container-color-outlined | — | |
--tanrei-comp-callout-container-color-tonal | sys.color.secondary-container | |
--tanrei-comp-callout-container-gap | sys.space.space100 | 8px |
--tanrei-comp-callout-container-padding-block | sys.space.space150 | 12px |
--tanrei-comp-callout-container-padding-inline | sys.space.space200 | 16px |
--tanrei-comp-callout-container-padding-inline-end-with-close | sys.space.space100 | 8px |
--tanrei-comp-callout-container-shape | sys.shape.corner.medium | 8px |
--tanrei-comp-callout-error-body-color-outlined | comp.callout.body.color.outlined | |
--tanrei-comp-callout-error-body-color-tonal | sys.color.on-error-container | |
--tanrei-comp-callout-error-container-color-outlined | comp.callout.container.color.outlined | |
--tanrei-comp-callout-error-container-color-tonal | sys.color.error-container | |
--tanrei-comp-callout-error-icon-color-outlined | sys.color.error | |
--tanrei-comp-callout-error-icon-color-tonal | sys.color.error | |
--tanrei-comp-callout-error-title-color-outlined | comp.callout.error.body.color.outlined | |
--tanrei-comp-callout-error-title-color-tonal | comp.callout.error.body.color.tonal | |
--tanrei-comp-callout-icon-color-outlined | sys.color.on-surface-variant | |
--tanrei-comp-callout-icon-color-tonal | comp.callout.body.color.tonal | |
--tanrei-comp-callout-icon-gap | sys.space.space150 | 12px |
--tanrei-comp-callout-icon-opacity | — | 0.85 |
--tanrei-comp-callout-icon-size | sys.icon.small | 20px |
--tanrei-comp-callout-info-body-color-outlined | comp.callout.body.color.outlined | |
--tanrei-comp-callout-info-body-color-tonal | sys.color.on-info-container | |
--tanrei-comp-callout-info-container-color-outlined | comp.callout.container.color.outlined | |
--tanrei-comp-callout-info-container-color-tonal | sys.color.info-container | |
--tanrei-comp-callout-info-icon-color-outlined | sys.color.info | |
--tanrei-comp-callout-info-icon-color-tonal | sys.color.info | |
--tanrei-comp-callout-info-title-color-outlined | comp.callout.info.body.color.outlined | |
--tanrei-comp-callout-info-title-color-tonal | comp.callout.info.body.color.tonal | |
--tanrei-comp-callout-outline-color | sys.color.outline-variant | |
--tanrei-comp-callout-outline-width | sys.border.hairline | 1px |
--tanrei-comp-callout-success-body-color-outlined | comp.callout.body.color.outlined | |
--tanrei-comp-callout-success-body-color-tonal | sys.color.on-success-container | |
--tanrei-comp-callout-success-container-color-outlined | comp.callout.container.color.outlined | |
--tanrei-comp-callout-success-container-color-tonal | sys.color.success-container | |
--tanrei-comp-callout-success-icon-color-outlined | sys.color.success | |
--tanrei-comp-callout-success-icon-color-tonal | sys.color.success | |
--tanrei-comp-callout-success-title-color-outlined | comp.callout.success.body.color.outlined | |
--tanrei-comp-callout-success-title-color-tonal | comp.callout.success.body.color.tonal | |
--tanrei-comp-callout-title-color-outlined | comp.callout.body.color.outlined | |
--tanrei-comp-callout-title-color-tonal | comp.callout.body.color.tonal | |
--tanrei-comp-callout-title-gap | sys.space.space50 | 4px |
--tanrei-comp-callout-warning-body-color-outlined | comp.callout.body.color.outlined | |
--tanrei-comp-callout-warning-body-color-tonal | sys.color.on-warning-container | |
--tanrei-comp-callout-warning-container-color-outlined | comp.callout.container.color.outlined | |
--tanrei-comp-callout-warning-container-color-tonal | sys.color.warning-container | |
--tanrei-comp-callout-warning-icon-color-outlined | sys.color.warning | |
--tanrei-comp-callout-warning-icon-color-tonal | sys.color.warning | |
--tanrei-comp-callout-warning-title-color-outlined | comp.callout.warning.body.color.outlined | |
--tanrei-comp-callout-warning-title-color-tonal | comp.callout.warning.body.color.tonal | |
--tanrei-comp-callout-body-typescale-large | sys.typescale.body-large | 400 16px/1.625 |
--tanrei-comp-callout-body-typescale-medium | sys.typescale.body | 400 14px/1.5714 |
--tanrei-comp-callout-title-typescale-large | sys.typescale.heading-5 | 500 16px/1.5 |
--tanrei-comp-callout-title-typescale-medium | sys.typescale.heading-6 | 500 14px/1.4286 |
フィクスチャ
基準となる描画パターンです。全プラットフォームが同じ ID でスナップショットを撮り、結果を比較できるようにしています。
variant: tonal (27)
tonal
{} tonal-info
status: info statusLabel: Information variant: tonal tonal-warning
status: warning statusLabel: Warning variant: tonal tonal-error
status: error statusLabel: Error variant: tonal tonal-success
status: success statusLabel: Success variant: tonal title
title: Sizes are minimums title-info
title: A revised spec, not yet on every platfor… status: info title-only
title: All checks passed status: success large
size: large large-title-info
title: A revised spec, not yet on every platfor… status: info size: large icon
title: Tip slots: icon icon-info
title: Experimental status: info slots: icon title-slot
status: info slots: title actions
title: The file changed on disk status: warning slots: actions closable
closable: true closeLabel: Close closable-title-actions
title: Three fields need attention status: error live: true closable: true closeLabel: Close slots: actions status-label
status: warning statusLabel: Warning live-success
status: success statusLabel: Success live: true long-body
title: A revised spec, not yet on every platfor… status: info long-title
title: The native platforms have not renamed th… status: warning closable: true closeLabel: Close tonal-info-rtl
title: ملاحظة status: info direction: rtl closable-actions-rtl
title: تغيّر الملف على القرص status: warning closable: true closeLabel: إغلاق direction: rtl slots: actions icon-rtl
title: التالي direction: rtl slots: icon docs-note
title: Note status: info size: large docs-tip
title: Tip size: large slots: icon docs-caution
title: Back up before you migrate status: warning size: large docs-danger
title: Danger status: error size: large variant: outlined (11)
outlined
variant: outlined outlined-info
status: info statusLabel: Information variant: outlined outlined-warning
status: warning statusLabel: Warning variant: outlined outlined-error
status: error statusLabel: Error variant: outlined outlined-success
status: success statusLabel: Success variant: outlined title-outlined-warning
title: Accessibility status: warning statusLabel: Warning variant: outlined large-outlined-error
status: error statusLabel: Error variant: outlined size: large icon-outlined
title: Tip variant: outlined slots: icon actions-outlined
variant: outlined slots: actions closable-outlined-info
status: info statusLabel: Information variant: outlined closable: true closeLabel: Close ltr-title-rtl
title: v2.1 beta status: success variant: outlined direction: rtl 生成元 specs/callout.spec.json, tokens/comp/callout.tokens.json, design/tokens/
この 3 つは、どこに置かれ、どれだけ残るかで区別します。
| 種類 | 何であるか | 置かれる場所 | 残る時間 | 読み上げ |
|---|---|---|---|---|
| スナックバー | アプリがいま行ったこと、いま起きたことの結果。 | コンテンツの上、ウィンドウの端。 | 短い間、または閉じるまで。 | 常に読み上げます。 |
| コールアウト | コンテンツの一部である通知。 | 流れの中、置いた場所。 | コンテンツがある限り。 | 何かへの応答として現れたときだけ(live)。 |
| ダイアログ | 先へ進む前に答える必要のある問い。 | すべての上、スクリム付き。 | 答えるまで。 | フォーカスを取ることで伝えます。 |
バナー(ページや画面全体に向けた、コンテンツの上の通知)は、4 つ目のものではありません。その領域のコンテンツの上に置いたコールアウトです。多くは live で、アクションか閉じるボタンを持ちます。関係する領域の読み上げ順で最初に来る場所に置きます。
1 つのフィールドの下に出すメッセージ(この値は日付ではありません、など)も、コールアウトではありません。フィールド自身の補足テキストです。
variant |
描画 | 用途 |
|---|---|---|
tonal(既定) |
控えめな塗り。 | ほとんどのコールアウト。 |
outlined |
塗りなし、細い線 1 本。 | 色の付いたサーフェスの上や、塗りのあるカードの中など、塗りが見えなくなる場所。コールアウトが近くに多く並ぶ場合。 |
線は、どのステータスでもシステムの細い線 1 本です。ステータスの色は付きません。
status は default、info、warning、error、success のいずれかです。スナックバーとタグが使う名前であり、システムのどこでも同じ意味で使います。ステータスは、色とグリフ(info、warning、error、check_circle)を描き、ライブのコールアウトの読み上げ方を決めます。それ以外は何も変えません。
| 書いているもの | 使うもの |
|---|---|
| 注記:知っておくとよいこと | status="info" |
| 注意:気を付ける必要があること | status="warning" |
| 危険:うまくいかなくなること | status="error" |
| ヒント:読み手が採用できる助言 | status="default"、icon スロットにグリフ lightbulb、タイトルに「ヒント」 |
ヒントは成功ではありません。何も成功していないからです。icon スロットは、ステータスの有無にかかわらずアイコンセットのどのグリフも受け取るので、「実験的」や「このバージョンの新機能」にも新しい値は要りません。言葉はタイトルに書きます。
size |
タイトル | 本文 | 用途 |
|---|---|---|---|
medium(既定) |
文字サイズ 14 / 行の高さ 20 | 14 / 22 | コントロールの間にあるコールアウト。フォーム、パネル、ダイアログ。 |
large |
16 / 24 | 16 / 26 | 文章を読むことが目的のページにあるコールアウト。 |
これはプローズの 2 つのサイズです。変わるのはテキストスタイルだけで、パディング、グリフ、閉じるボタンは同じです。
headline はプレーンテキストであり、見出しにはなりません。ほとんどのタイトルは注記のラベルです。アウトラインに「注記」が 5 回並ぶページは、かえって使いにくくなります。コールアウトが、人が移動してくるページの一部を始める場合は、アウトラインに合ったレベルの見出しを title スロットに入れます。コールアウトはそれをほかのタイトルと同じように描き、ロールもレベルも変えません。
サーバーで描画するページでは、タイトルを title スロットで渡します。headline 属性は要素が描くため、要素が定義されるまで表示されません。
要素に直接置いたテキストは、コールアウトのテキストスタイルと色になります。長文のブロック(段落、リスト、表、コードブロック)は、コールアウトのサイズで行長の制限のないプローズに入れます。
<tanrei-callout status="info">
<div class="tanrei-prose" data-measure="false">…描画済みの Markdown…</div>
</tanrei-callout>プローズは色を持たないので、どの塗りの上でも読めます。リンクには下線が付きます。本文に置いたコンポーネントは、自身のスタイルを保ちます。行長を制限しているプローズの中のコールアウトは、テキストのブロックと同じようにその行長に収まります。それ以外の場所では、与えられた幅いっぱいに広がります。
アクションは、独自のボタンまたはリンクで、1 つか 2 つです。outlined か text のボタンを使います。tonal のボタンは、ステータスのない tonal のコールアウトと同じ塗りなので、そこではボタンに見えません。コールアウトはアクションを折り返す行に並べるだけです。アクションが押されても閉じません。
closable は閉じるボタンを描きます。小さなアイコンだけのボタンで、名前は close-label で付け、variant は --tanrei-comp-callout-close-button-variant が決めます(既定のシステムでは tonal)。tonal のコールアウトでは、コールアウト自身の文字色で描きます。その色を半透明にした丸の中に、同じ色のグリフを置くので、どのステータスの塗りの上でも見えます。塗りのない outlined のコールアウトでは、ほかの場所と同じボタンのままです。ホバー、フォーカス、押下には、どのボタンとも同じように応えます。押すと open が false になり、dismiss が発火します。コールアウトが自分から閉じることはなく、Escape にも応えません。人が閉じたら、そのことを記憶してください。訪れるたびに戻ってくる閉じられるコールアウトは、雑音です。隣のコンテンツに条件を付ける注意は、閉じられるようにしません。
live は、人が作業している間に現れたり変わったりするコールアウトのためのものです。送信後のフォームのエラーの要約や、ファイルが手元で変更されたという通知などです。open="false" でページに置いておき、必要になったら open を設定します。
押したことへの応答として表示される、ライブのコールアウト
<tanrei-callout id="errors" live open="false" status="error" headline="3 つのフィールドを確認してください">
名前を入力し、開始日を選び、メールを受け取れるアドレスを指定してください。
</tanrei-callout>
<script type="module">
form.addEventListener('submit', (event) => {
if (!form.checkValidity()) {
event.preventDefault();
document.querySelector('#errors').open = true; // 1 回、割り込んで読み上げます
}
});
</script>ライブのコールアウトは、表示されたときと、タイトル、本文、ステータスが変わったときに、1 回読み上げられます。default、info、success では控えめに、warning と error では割り込んで読み上げます。ページの読み込み時にマークアップにあったものは、そのときには読み上げません。
Web では、ページの読み込み後にスクリプトが追加したライブのコールアウトは読み上げられます。要素には、何かへの応答として追加されたコールアウトと、シングルページアプリケーションの新しいビューと一緒に追加されたコールアウトの区別が付きません。新しいビューの一部にすぎない通知には、live を付けないでください。
本文、タイトルのスロット、アクションは要素自身の子なので、ドキュメントの中にあります。ページ内検索で見つかり、翻訳され、選択でき、スクリプトなしで読めます。@tanrei/web/callout.css は、まだ定義されていないコールアウトに、定義後と同じボックスを与えます。パディング、テキストスタイル、グリフと閉じるボタンのための余白です。open="false" のものには何も描きません。そのため、要素が定義されても何も動きません。定義されるまでは、塗り、グリフ、閉じるボタンなしで表示されます。
- ステータスは言葉で伝えます。「警告:先にバックアップを」ならそれで十分です。警告に付けた「アクセシビリティ」というタイトルには
status-label="警告"が必要です。 - ステータスは、どこでも同じ意味で使います。助言は成功ではありません。
- コールアウトをいくつも並べるのではなく、1 つのコールアウトに要点のリストを 1 つ入れます。
- ページに書かれた注記に、ライブのコールアウトを使わない。静的なコンテンツはアラートではありません。
- コールアウトを入れ子にしない。ページの先頭にいくつも積むこともしません。同じ重さの通知が並ぶと、互いを打ち消します。
- エラーの要約にフォーカスを移すことと、それを読み上げることを両方は行わない。最初のエラーが画面外にあるかもしれない長いフォームには、要約へのフォーカス移動が向いています。短いフォームには、読み上げたうえで最初のエラーのフィールドへフォーカスを移す方法が向いています。
- ステータスを色だけに頼らない。強制カラーモードでは、どのコールアウトも文字色の縁とテキストになります。
- ロール
note- ラベル付け
- A callout that is not live is a note (the note role on the web), read where it stands, named by its title or, without one, by statusLabel. A live callout is a live region instead: polite in the default, info and success forms (the status role on the web) and assertive in the warning and error forms (the alert role on the web), announced once when it is shown after its page was presented and when its content changes. In both, statusLabel is exposed as text before the title and the body; the glyph is hidden. A title given as text is plain text; a heading in the title slot keeps its level. The close button's name is closeLabel. Actions are the product's own controls with their own names.
- 最小ターゲット
- 見た目のサイズが小さくても、ヒット領域は最小ターゲットサイズを満たします。 minimum 32px · pointer 44px · spacing 8px · touch 48px
キーボード操作
| キー | 動作 |
|---|---|
| Tab | Reaches, at the callout's place in the page, the links and controls of the body, then the actions, then the close button. The callout itself is not a stop, and showing one never moves focus. |
| Enter / Space | Activates the focused close button: the callout closes and focus returns to where it was before it entered the callout (CLO-12). |
備考
- Static content is not an alert. A callout written into a page (a note in documentation, a caution above a procedure) must not interrupt a screen reader when the page loads or be repeated as a status message: it is read in order, as the paragraph before it is. live is for what appears or changes in answer to something, and even then a callout that the page is first presented with is not announced (CLO-21).
- A summary of a form's errors is a live callout with the error status, shown after the submit. Whether focus also moves to it is the product's decision, by its own means (the callout takes no focus by itself): moving focus to the summary suits a long form whose first error may be off screen; announcing it and moving focus to the first field in error suits a short one. Do not do both.
- A notice for a whole page or screen (a banner: the connection is lost, the file changed on disk, a trial ends) is a callout placed by the product above that region's content, live, usually with an action or a close button. Put it where it comes first in reading order for the region it concerns.
- WCAG 1.4.1 (use of color): a status is never told by color alone. A status form draws the status's glyph, a shape of the icon set, and the status is in the title's words or in statusLabel (CLO-20). The component cannot tell whether a title says its status, so that is the product's to check: "Accessibility" on a warning needs statusLabel "Warning"; "Warning: not published yet" does not.
- WCAG 1.3.1 (info and relationships): the callout does not decide whether its title is a heading. Most titles are labels of a note and should stay text, or the page's outline fills with entries such as "Note". Where a callout does open a part of the page that people navigate to, the product gives a heading of the right level in the title slot.
- WCAG 1.4.3 and 1.4.11 (contrast) in the default system: the title and the body are a role on its paired role (on-secondary-container on secondary-container, on-info-container on info-container, on-surface on a surface), each held to 4.5:1 by the token invariants. The glyph is drawn at an opacity of its color, so its contrast is that of the color as drawn: at least 3.5:1 on its own status container and on every surface, in every scheme. A link in the body is the system's link color, underlined: at least 4.6:1 on every tonal container (7.2:1 in the high-contrast schemes). The outlined look's edge is decorative.
- Actions are the product's Buttons. A filled or a tonal Button brings its own fill and keeps its own contrast; the label of an outlined or a text Button sits on the callout's fill, where the default system's primary keeps at least 13:1 on every tonal container. A tonal Button has the fill of the tonal callout without a status and cannot be seen as a button there: use outlined or text. The focus indicator of a product's control in the body or the actions is the system's focus color, at least 4.6:1 on every tonal container of the default system.
- A closable callout that returns on every visit is noise: when the person closes one, the product should remember it. The callout only reports the close (dismiss).
- Do not nest callouts, and do not stack several at the top of a page: two notices of the same weight side by side cancel each other. One callout may hold a list of points.
- Forced colors (CLO-24): a tonal callout loses its fill, so every look gains an edge in the text color. Statuses then differ by glyph and words alone.
- Web: the body, the title slot and the actions are light-DOM children of `<tanrei-callout>`, so they stay in the document: they are found by search in the page, translated, selected and read without script, and before the element is defined they show as plain blocks in the page's own text styles, without the fill, the glyph and the close button. A title given by the `headline` attribute is not shown until the element is defined; content pages should use the title slot.
- The callout itself has no states: nothing about its container, its text or its glyph answers a pointer, a press or focus. Its close button is a Button, and answers them as every Button does.
- WCAG 1.4.11 (non-text contrast) and 2.4.13 (focus appearance) for the close button: in a filled look it is drawn in the tone of the fill (BTN-45), its glyph in the fill's content color (the body color, held to 4.5:1 on the fill by the token invariants) over a container of that color at comp.button.tone.container.opacity. In the default system the glyph keeps against that blend, in every status, at least 9.5:1 at rest in the light schemes and 7.7:1 in the dark ones, and at least 6.0:1 hovered, focused or pressed in every scheme; the focus indicator's outer stroke, in the same color on the callout's fill, keeps at least 12:1. In the outlined look it is the variant's own Button on the surface, whose glyph the Button's own tokens hold.
生成元 specs/callout.spec.json, tokens/sys/measure.tokens.json
- 注記(
role="note")であり、タイトルで名前が付きます。タイトルがなければstatus-labelで付きます。liveを付けると、代わりにライブリージョンになります。role="status"、警告とエラーではrole="alert"です。 status-labelは、タイトルと本文の前に別の語句として読まれます(「警告、…」)。描画はしません。statusがdefaultの間は無視します。- グリフは支援技術から隠します。
- テキストで渡したタイトルはプレーンテキストです。
titleスロットの見出しはレベルを保ちます。 - フォーカスが止まる位置にはならず、フォーカスを動かすこともありません。Tab は、本文のリンクとコントロール、アクション、閉じるボタンの順に進みます。
- フォーカスが中にある状態で閉じると、フォーカスは、コールアウトに入る前にあった要素に戻ります。次の Tab は、コールアウトの後にあったものに進みます。
- 閉じるボタンはボタンです。ヒット領域は最小ターゲットに届きます。tonal のコールアウトでは、グリフとフォーカスリングがコールアウトの文字色になり、既定のシステムのすべてのステータスと配色で、ボタンに対して 6:1 以上を保ちます。
- 文字を拡大すると、すべてが折り返して大きくなります。グリフと閉じるボタンは 1 行目に残ります。
- 強制カラーモードでは、どの見た目にも文字色の縁が付き、グリフは不透明度なしで描きます。
- 右から左のレイアウトでは、グリフが右に、閉じるボタンが左に移ります。アイコンセットが指定するグリフは左右反転し、左から右のタイトルは自身の語順を保ちます。
- 未知のバリアント、サイズ、ステータス、タイトルも本文もないコールアウト、言葉で伝えられていないステータス、名前のない閉じるボタン、ステータスのない
status-labelは、デバッグビルドで報告します。
- それぞれのコールアウトの言葉がステータスを伝えているかを確かめます。タイトルが伝えているかどうかは、コンポーネントには分かりません。
status-labelとclose-labelはページの言語で書きます。liveは、何かへの応答として現れたり変わったりするコールアウトにだけ使います。- アクションには、収まる長さのラベルを付けます。ボタンのラベルは 1 行なので、文字を拡大した狭い画面では、長いラベルがコールアウトより広くなることがあります。