メインコンテンツへスキップ
menumenu tanreiexpand_morecontrasttranslate
tanreiexpand_more
はじめにWebReactSwiftUIJetpack ComposeFlutterReact Nativeプリセット自分のデザインシステムを作るAI エージェントと Tanrei を使うブランドデザイントークンデザインシステムとカスタマイズTheme Studioカラータイポグラフィアイコン形状エレベーションモーションインタラクション状態振る舞いレイアウトアクセシビリティ言葉カラートークンタイプスケールトークン形状トークンエレベーショントークンモーショントークン状態トークンスペースと寸法のトークンコンポーネントボタンメインアクションボタンセグメントボタンボタングループメニュー付きボタンツールバーコピーボタンチェックボックスラジオボタンスイッチチップメニュースライダースライダーフィールドカレンダーDateTimePickerフィールドグループラジオグループチェックボックスグループセレクトセレクトフィールドメニューバーファイルアップロードファイルピッカー 上級者向けドロップゾーンテキスト入力欄 上級者向けテキストフィールドチップフィールドフィールドコンボボックス 上級者向けコンボボックスフィールド数値入力欄 上級者向け数値フィールドカラー入力欄 上級者向けカラーフィールドワンタイムコード入力欄 上級者向けワンタイムコードフィールド埋め込みテキスト入力欄 上級者向けチャットコンポーザーカード区切り線モーダルレイヤー 上級者向けダイアログリストリスト行ボトムシートサイドシートカルーセルコードブロックテーブルポップオーバーステップアコーディオン説明リスト図アプリシェルページヘッダーツリービュータイムライン画像プレビューハンドルサイズ変更できる枠スクロールエリアバッジプログレスインジケーターメーターナンバーティッカーローディングインジケータースナックバーツールチップキーボードショートカットタグインラインコードコールアウトアバター空の状態タググループスケルトンファイル項目色見本マーキーテキストタブタブビューアプリバーナビゲーションバーナビゲーションドロワー検索リンクページネーション前後のリンクステッパーパンくずリスト目次リンクカードFAB メニューステータスTanrei の作り方コントリビューションライセンスと帰属
ホームコンポーネントファイル項目

ファイル項目

1 つのファイルを見せます。形式を表すグリフか小さな画像、名前、そしてプロダクトがそのファイルについて伝えることを描き、取り除くアクションともう一度試すアクションが付きます。縦に並ぶファイルの行にも、画像の並びのタイルにもなります。押してファイルを開くこともできます。自身がファイルを読むことも、保持することも、送ることもありません。

content_copyMarkdown で表示
カテゴリ
コミュニケーション
トークン
comp.file-item
レベル
基礎

概要

Web
tanrei-file-item
schedule
SwiftUI
TanreiFileItem
radio_button_unchecked
Jetpack Compose
TanreiFileItem
radio_button_unchecked
Flutter
TanreiFileItem
radio_button_unchecked
React Native
FileItem
radio_button_unchecked

生成元 docs/status/status.json, specs/file-item.spec.json

行にした 1 つのファイルと、タイルにしたファイル

ファイル項目は、1 つのファイルを見せるものです。名前の前には、ファイルの形式を表すグリフか、そのファイルの小さな画像があります。名前の下の 1 行には、プロダクトがそのファイルについて伝えることが入ります。形式、サイズ、送信がどこまで進んだか、何が問題だったかです。末尾には、ファイルに対する 2 つのアクションがあります。取り除くことと、もう一度試すことです。

形は 2 つあります。

  • row(既定)。置かれた場所の幅いっぱいに広がる 1 行です。縦に並ぶファイルに使います。
  • tile。利用者側が指定した幅と高さのボックスで、その下に名前があります。画像の並びに使います。

見せるだけで、ほかには何もしません

ファイル項目は、ファイルを 1 バイトも読まず、ファイルを保持せず、何も送りません。取り除くこともしません。取り除くアクションは、その人が求めたことを利用者側に伝えるだけで、項目を取り除くのは利用者側です。見せるものは、プロパティに指定されたとおりです。

使われている場所は、ファイルアップロードです。そこでは、選ばれたファイルの 1 つ 1 つがファイル項目です。単独では、プロダクトが持っているファイルを見せる場所ならどこでも使います。メッセージの添付ファイル、記録に付いた書類、すでに送信された申請のファイルなどです。

次の場合は、ほかのものを使います。

  • ファイルを選んでもらい、それを一覧にする場合。それはファイルアップロードです。ファイル項目を利用者側の代わりに持ちます。
  • ファイルを並べ替えてもらう場合。それは、項目にファイル項目を入れた、並べ替えられるリストです。並べ替えられるファイルを見てください。
  • ファイルの中から選択してもらう場合。それは、選択のあるリストです。ファイル項目に、選択の状態はありません。
  • 画像そのものがコンテンツで、見てもらうためのものである場合。ファイル項目の画像は、グリフがあるはずの場所に置かれるもので、代替テキストを持ちません。

Web では <tanrei-file-item> です。ほかのプラットフォームはまだ実装していません。

使い方

name と、手元にあるテキストを指定します。value は、click、remove、retry が利用者側に返す値です。

<ul class="attachments" aria-label="添付ファイル">
  <li>
    <tanrei-file-item value="a" name="brief.pdf" format-text="PDF" size-text="820 KB"
                      href="/files/brief.pdf" remove-label="{name} を取り除く"></tanrei-file-item>
  </li>
  <li>
    <tanrei-file-item value="b" name="floor-plan.png" size-text="3.4 MB"
                      status="uploading" status-text="アップロード中" progress="0.4"
                      remove-label="{name} を取り除く" retry-label="{name} をもう一度試す"></tanrei-file-item>
  </li>
</ul>

<script type="module">
  import '@tanrei/web/components/file-item';

  const list = document.querySelector('.attachments');
  // ファイル項目が自分で消えることはありません。利用者側が項目を取り除き、ファイルの送信を止め、フォーカスを移します。
  list.addEventListener('remove', (event) => {
    cancel(event.detail.value);
    event.target.closest('li').remove();
  });
  list.addEventListener('retry', (event) => send(event.detail.value));
</script>
import { FileItem } from '@tanrei/react';

<ul aria-label="添付ファイル">
  {files.map((file) => (
    <li key={file.id}>
      <FileItem value={file.id} name={file.name} sizeText={file.sizeText}
        status={file.status} statusText={file.statusText} progress={file.progress}
        errorText={file.errorText} retryable={file.retryable}
        removeLabel="{name} を取り除く" retryLabel="{name} をもう一度試す"
        onRemove={() => remove(file.id)} onRetry={() => retry(file.id)} />
    </li>
  ))}
</ul>

removeLabel と retryLabel は、setWords() でプロダクト全体に一度だけ指定できます。それ以外のテキストは、すべてインスタンスのものです。

仕様

状態ごとの行。待機中、40% まで送信、送信中、完了、失敗して再試行できる、失敗して再試行できない

構成要素

構成要素

Web パッケージが描くフィクスチャ row の上に描いています。
パーツ 説明
1 container The body: the glyph or the picture, and the texts. One part, and the one that is pressed where the file item is pressable. The actions stand beside it, never inside it.
2 media The box of the glyph or the picture: the leading box of a row, the whole box of a tile.
3 icon · 任意 The glyph of the file's format, by its name in the system's icon set; or the product's own glyph. Hidden from assistive technology.
4 preview · 任意 The picture of an image file, in the glyph's place.
5 headline · 任意 The file's name.
6 supporting-text · 任意 The second line: the format, the size and the status in words, or the error text in the status's place.
7 status-icon · 任意 The mark before the words of a file that is done or failed.
8 progress · 任意 A thin bar while the file is being sent: how far it has come, or that it is under way.
9 action · 任意 The actions: retry (while it failed and can be tried again) and remove. Icon-only, each with its own state layer and focus ring.
10 focus-ring The system's focus indicator around the body or an action that has keyboard focus.

プロパティ

プロパティ 型 既定値 説明
form row | tile "row" How the file is shown. row: one line across the width the layout gives — the glyph or a small picture, the name, the second line, the bar, the actions at the end — for a column of files. tile: a box of a width and a height, holding the picture or the glyph, with the texts beneath it and the actions at its corner — for a strip of attached pictures. The product chooses by where the file stands. A design system may add values.
value string "" What identifies the file to the product: given back by click, remove and retry.
name string "" The file's name as the person knows it ("report-2026.pdf"). The file item's name for assistive technology in every form, also where it is not drawn.
mediaType string "" The file's kind as the platform reports it ("image/png"), from which the glyph is chosen. Empty, the kind is read from the end of name.
glyph string "" The name of a glyph of the system's icon set, drawn in place of the one the file's format would choose. Empty lets the format choose.
formatText string "" The file's format in the product's words ("PDF", "Spreadsheet"), drawn first on the second line. Empty draws none: the file item has no word for a format.
sizeText string "" The file's size as text, formatted by the product for the reader's locale ("1.2 MB"). Empty draws none.
status pending | uploading | done | error "pending" Where the file stands. pending: chosen or kept, and nothing is happening to it — the whole life of a file in a form that is submitted as one, and of a file that is only shown. uploading: the product is sending it; the bar is drawn. done: the product has it. error: it failed or was refused; errorText says why.
statusText string "" The status in the product's words ("Waiting", "Uploading", "Uploaded"), drawn last on the second line and read with the file. The mark and its color are never the only sign of a status.
progress number null How far the sending has come, from 0 to 1, while status is uploading. Null draws the bar as under way without saying how far. Ignored in every other status.
errorText string "" Why the file failed and what to do, in the product's words ("Larger than 10 MB", "The connection was lost"). Drawn in the status's place while status is error, in every form, and never cut.
retryable boolean false Whether a failed file offers the retry action. True for a failure that trying again may cure (a lost connection); false for one it cannot (a file that is too large).
preview boolean false Whether a picture of the file is drawn in the glyph's place, where the file is an image and the product gave an address (previewSrc) or the file itself in the platform's idiom. False draws the glyph, also for an image. The picture is drawn by the platform; the file item reads no file.
previewSrc string "" The address of a picture of the file, as the platform's images take one: a small rendition the product's server made of a file it already has. With preview it is drawn for a file of any format. Empty, the picture comes from the file itself where the product gave it.
fit cover | contain "cover" How the picture fills its box. cover: it fills the box and what does not fit is cut at the edges, for photographs in a strip. contain: the whole picture is drawn inside the box, on the box's ground, for a picture whose edges matter — a scan, a signature, a diagram.
nameHidden boolean false In the tile form: the name is not drawn beneath a tile that draws a picture, for a dense strip of pictures. The name stays the file item's name for assistive technology, and is drawn all the same wherever no picture is (FIT-8). Not read in the row form.
width number null In the tile form: the width of the box, in the platform's layout unit. Null makes it as wide as it is high.
height number null In the tile form: the height of the box, in the platform's layout unit. Null reads comp.file-item.tile.media.height.
interactive boolean false Makes the body — the glyph or the picture, and the texts — one pressable action that emits click, for a product that opens the file where it is: an image in an Image preview, a document in a viewer. The actions stay their own. A file item whose action is to go to the file takes href instead and is a link.
href string "" The destination: the address of the file, as the platform's links take one. Not empty, it makes the body a link — to a file the product already has, to open or to download — whether interactive is set or not.
target same | new "same" Where the destination opens. same: where the person is. new: a new context — a new tab or window on the web, outside the current screen elsewhere — which a row marks and targetLabel says. Ignored without href.
targetLabel string "" What assistive technology reads after the link's name while target is new ("opens in a new tab"). The product's words.
removeLabel string "" The accessible name of the remove action: the whole name in the product's language with one place, {name}, which the file item fills with the file's name ("Remove {name}", "{name}を削除"), so that the actions of two files are told apart by their names and the product still writes one word, not one per file. Empty reads the product's words.
retryLabel string "" The accessible name of the retry action, with the place {name} filled by the file's name as removeLabel is ("Retry {name}", "{name}を再試行"). Empty reads the product's words.
disabled boolean false The actions are disabled and the body cannot be pressed. What the file item shows of the file stays as it is and stays readable.
readOnly boolean false The file is shown and cannot be taken back: no remove action and no retry action is drawn. For a file of a record that is only read. The body can still be pressed where interactive or href says so.

スロット

スロット 説明
icon A glyph of the product's own in place of the format's glyph, where a name in the system's icon set (glyph) is not enough. Decorative.

イベント

イベント 説明
click The body of a pressable file item was activated by pointer, touch, keyboard or assistive technology. Carries value. A link emits it before its destination opens; a product that takes the navigation itself cancels it.
remove The person asked to take this file back, by its remove action. Carries value. The file item removes nothing: whoever holds it removes it — and stops sending the file, if it was — and moves focus.
retry The person asked to try a failed file again, by its retry action. Carries value. The product sends the file again and sets status.

状態

振る舞い

EARS 記法による要件です。各プラットフォームの実装は、この ID に対応するテストで検証されます。要件の原文は仕様ファイルのものをそのまま掲載しています。

ID 要件
FIT-1 THE file item SHALL show one file in the form that form names: a row (FIT-2) or a tile (FIT-3). In both it SHALL draw the same parts from the same props — the glyph of the file's format or a picture of the file (FIT-5, FIT-6), its name, a second line (FIT-4), a bar while it is sent (FIT-10) and its actions (FIT-11) — so that a form changes where the parts stand and how large they are, never what is known of the file. THE file item SHALL draw no container, fill or edge around the whole, SHALL hold one file and never a list of files, and SHALL NOT sort, group, number or count itself among others: how file items are arranged is the layout's, or the component's that holds them.
FIT-2 WHILE form is row THE file item SHALL be as wide as its layout gives it and as tall as its parts, and SHALL lay out from its start edge: the glyph in a box of comp.file-item.row.icon.size — or, WHILE preview is true, a square of comp.file-item.row.media.height with corners of comp.file-item.row.media.shape and the ground comp.file-item.media.color, holding the picture, or the glyph centred where no picture is drawn (FIT-6); comp.file-item.row.container.gap after it the texts, taking the room that is left; and comp.file-item.row.container.gap after them the actions (FIT-11), with the glyph or the square and the actions centred on the row's first two lines. The first line SHALL be name in comp.file-item.headline.typescale and comp.file-item.headline.color, drawn whole: it SHALL wrap, breaking inside a word where it must, and SHALL never be cut with an ellipsis, because the end of a file's name says what kind of file it is and a row has the room. WHILE form is row THE file item SHALL NOT read width, height or nameHidden, and in debug builds SHALL report nameHidden.
FIT-3 WHILE form is tile THE file item SHALL draw a box height high — comp.file-item.tile.media.height WHILE height is null — and width wide, as wide as it is high WHILE width is null, with corners of comp.file-item.tile.container.shape and the ground comp.file-item.media.color, holding the picture clipped to those corners (FIT-6) or, where no picture is drawn, the glyph centred at comp.file-item.tile.icon.size; and beneath the box, comp.file-item.tile.container.gap from it and as wide as it, the name on one line (FIT-9) and the second line (FIT-4). The file item SHALL be exactly as wide as the box. It SHALL draw the actions inside the box at its top end corner, comp.file-item.tile.action.inset from the top and from the end edge, the retry action before the remove action (FIT-11), each on a disc of the tile's action container color so that it is read over any picture; and SHALL draw the box no narrower than both actions, the space between them and the inset on each side need, and no lower than one action and the inset above and below it, in debug builds reporting a width or a height that is less. WHERE its layout gives the tile less room than width THE file item SHALL draw the box as wide as that room and as high as keeps the proportion of width to height, and SHALL never be wider than its layout.
FIT-4 THE file item SHALL draw below the name one line in comp.file-item.supporting-text.typescale that wraps and is never cut: formatText, sizeText and statusText, each WHILE it is not empty, in that order, with a middle dot and a space on each side between two that are drawn, in comp.file-item.supporting-text.color; and WHILE status is error and errorText is not empty, errorText in statusText's place, in comp.file-item.error.supporting-text.color. WHILE status is done or error THE file item SHALL draw before the words of the status or the error, comp.file-item.status.icon.gap from them, a mark at comp.file-item.status.icon.size by its name in the system's icon set and through the platform's icon helper — the checked-circle glyph in comp.file-item.done.icon.color WHILE status is done, the error glyph in comp.file-item.error.icon.color WHILE status is error — and SHALL keep the mark from assistive technology, which is told the status by the words. WHILE the line would hold nothing THE file item SHALL draw none and keep no room for it. A status SHALL never be told by the mark or its color alone: WHILE status is done or error and the product gives no words for it (statusText, errorText) THE file item SHALL still render, with the mark alone on the line, and in debug builds report it. THE file item SHALL draw the second line in every form and whatever nameHidden says: what went wrong is never hidden.
FIT-5 THE file item SHALL choose the glyph from the file's format, in one of ten kinds, by mediaType — read without regard to case, without anything after a semicolon and without the white space around it — and, WHERE mediaType is empty, is application/octet-stream or is on no list below, by the end of name after its last dot, without regard to case, the first kind that matches in this order, each kind by a closed list of media types and a closed list of endings: pdf (application/pdf; pdf); spreadsheet (text/csv, text/tab-separated-values, application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.oasis.opendocument.spreadsheet, application/vnd.apple.numbers, application/x-iwork-numbers-sffnumbers; xls, xlsx, ods, numbers, csv, tsv); presentation (application/vnd.ms-powerpoint, application/vnd.openxmlformats-officedocument.presentationml.presentation, application/vnd.oasis.opendocument.presentation, application/vnd.apple.keynote, application/x-iwork-keynote-sffkey; ppt, pptx, odp, key); archive (application/zip, application/x-zip-compressed, application/x-tar, application/gzip, application/x-gzip, application/x-bzip2, application/x-xz, application/x-7z-compressed, application/vnd.rar, application/x-rar-compressed; zip, tar, gz, tgz, bz2, xz, 7z, rar); code (text/html, text/css, text/javascript, application/javascript, application/x-javascript, text/typescript, application/typescript, text/jsx, text/tsx, application/json, application/xml, text/xml, text/yaml, text/x-yaml, application/yaml, application/x-yaml, application/x-sh, text/x-sh, text/x-shellscript, text/x-python, text/x-script.python, text/x-ruby, application/x-ruby, text/x-go, text/x-rust, text/x-java, text/x-java-source, text/x-kotlin, text/x-swift, text/x-c, text/x-chdr, text/x-csrc, text/x-c++, text/x-c++src, text/x-csharp, text/x-php, application/x-php, application/x-httpd-php, application/sql, text/x-sql; html, css, js, mjs, ts, tsx, jsx, json, xml, yaml, yml, sh, py, rb, go, rs, java, kt, swift, c, h, cpp, cs, php, sql); image (every media type that begins with image/; png, jpg, jpeg, gif, webp, avif, svg, bmp, tif, tiff, heic, heif, ico); video (every media type that begins with video/; mp4, mov, m4v, webm, mkv, avi); audio (every media type that begins with audio/; mp3, wav, m4a, aac, ogg, oga, flac, opus); document (every media type that begins with text/ and is on no list above, application/rtf, application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/vnd.oasis.opendocument.text, application/vnd.apple.pages, application/x-iwork-pages-sffpages; txt, md, rtf, doc, docx, odt, pages); and other for everything else, a name without a dot among them. A media type that is on no list SHALL choose nothing by itself: the ending decides, and then other. video/mp2t SHALL choose nothing by itself either, though it begins with video/: platforms guess it from the ending .ts, which TypeScript files share with MPEG transport streams, so the media type is no surer than the ending and the ending decides. The lists are the whole of the rule on every platform, so that one file draws one glyph wherever it is shown; a platform SHALL add no media type and no ending of its own. It SHALL draw, by its name in the system's icon set and through the platform's icon helper: picture_as_pdf, table, slideshow, folder_zip, code, image, movie, music_note, description and draft, in the order of the kinds. WHILE glyph is not empty THE file item SHALL draw that glyph in the format's place, and WHILE the icon slot holds a glyph SHALL draw the slot's in the place of both. THE file item SHALL draw every such glyph in comp.file-item.icon.color, whatever the format — a format has no color of its own, because a color says one thing wherever it is used and a format is not a status — and SHALL keep it from assistive technology: the name says which file it is, and formatText says its format in words where the product has them. THE file item SHALL NOT open the file to learn its format, and SHALL NOT change the glyph because of status.
FIT-6 WHILE preview is true THE file item SHALL draw a picture of the file in the glyph's place: the picture at previewSrc WHILE previewSrc is not empty, whatever the file's format; otherwise, WHILE the file's kind is image (FIT-5) and the product gave the file item the file itself in the platform's idiom, the platform's own drawing of that file (FIT-7). It SHALL fill the box as fit names — cover: scaled to fill the box and centred, what does not fit cut at the box's edges; contain: scaled to stand whole inside the box, centred on the box's ground — never stretched out of its proportion and never drawn larger than the box. Until the picture can be drawn, and IF it cannot be drawn — an address that does not answer, a format the platform does not draw, a file that is not a picture after all — THE file item SHALL draw the glyph of the file's format in its place, SHALL draw no sign of loading and no sign of the failure, SHALL NOT set status and SHALL emit nothing for it, and in debug builds SHALL report a previewSrc that could not be drawn. WHEN the picture can be drawn THE file item SHALL draw it at once in the glyph's place, without a motion and without changing the size of anything. THE file item SHALL keep the picture from assistive technology: it stands where the glyph stood, and the file is named by name. WHILE preview is false, WHILE preview is true and neither an address nor a file was given, and for a file that is not an image and has no previewSrc, THE file item SHALL draw the glyph. THE file item SHALL draw no picture of a video, of a page of a document or of anything else it would have to open and read to draw.
FIT-7 THE file item SHALL NOT read a file: it SHALL open no connection for a file, SHALL NOT read a file's bytes into memory of its own, SHALL NOT copy, store, resize or encode a file, and SHALL make of the file the product gave it nothing but what the platform needs to draw the picture of FIT-6. WHERE the platform draws a picture of a file from an address it makes for the file's handle (the web's object URL) THE file item SHALL make that address itself, at most one per file item; SHALL make it only WHILE FIT-6 has it draw the picture from the file — preview is true, previewSrc is empty, the kind is image — and only once the file item is in or near what is in view; SHALL give it to nothing but its own picture; and SHALL release it WHEN the file item is taken out of the page or the screen, WHEN the product gives it another file or none, and WHEN preview becomes false, previewSrc is given or the kind is no longer image. WHERE the platform makes a small picture of a file itself (a thumbnail the system gives for a handle) THE file item SHALL ask for one no larger than its box and SHALL cancel the request on the same occasions. A file item whose preview is false SHALL cost what its texts cost: no address, no picture and no request is made for it, however many there are.
FIT-8 WHILE form is tile and nameHidden is true and the box draws a picture THE file item SHALL NOT draw the name beneath the box and SHALL keep no room for it. WHILE the box draws no picture — preview is false, the picture is not drawn yet or cannot be drawn — THE file item SHALL draw the name whatever nameHidden says, because a glyph of a format does not tell two files of that format apart. In every case name SHALL stay the file item's name for assistive technology (FIT-19), and the second line SHALL be drawn (FIT-4). IF name is empty THE file item SHALL still render and in debug builds report that the file has no name.
FIT-9 WHILE form is tile THE file item SHALL draw the name on one line in comp.file-item.headline.typescale and comp.file-item.headline.color, no wider than the box. WHERE the name does not fit THE file item SHALL cut it in the middle and never at its end: the ending of the name — from its last dot, WHERE that dot is not the name's first character and is among its last eight — SHALL stay drawn, the start of the name SHALL be drawn as far as the room that is left allows, and an ellipsis SHALL stand between the two, so that two pictures from one camera are still told from a document of the same name; a name with no such ending SHALL be cut at its end, with an ellipsis. The ellipsis is a mark of the platform's text layout and not a word. The whole name SHALL reach assistive technology, and the cut SHALL be made in the drawing alone: THE file item SHALL NOT change name. The second line of a tile SHALL wrap inside the box's width and SHALL never be cut (FIT-4).
FIT-10 WHILE status is uploading THE file item SHALL draw a bar comp.file-item.progress.thickness high: a track in comp.file-item.progress.track.color and over it, from the track's start, an indicator in comp.file-item.progress.indicator.color across the fraction progress gives, clamped to 0 and 1, moving to a new value over comp.file-item.motion.progress-duration with comp.file-item.motion.progress-easing. WHILE form is row the bar SHALL stand comp.file-item.progress.gap below the texts and as wide as them, with ends rounded by comp.file-item.progress.shape; WHILE form is tile it SHALL lie along the bottom edge of the box, inside it and as wide as it, clipped by the box's corners, over the picture or the ground. WHILE progress is null THE file item SHALL draw the bar as a linear progress indicator draws its indeterminate form (PRG-2), once per comp.file-item.motion.cycle-duration with comp.file-item.motion.cycle-easing, and SHALL NOT run it while the file item is not visible. WHERE reduced motion is requested THE file item SHALL show a new value at once and draw the indeterminate bar as PRG-7 says. In every other status THE file item SHALL draw no bar and, in a row, keep no room for one. THE file item SHALL never move the bar by itself: progress is the product's report of its own sending.
FIT-11 WHILE readOnly is false THE file item SHALL draw a remove action, and before it, comp.file-item.action.gap from it, a retry action WHILE status is error and retryable is true: each an icon-only button, a square of comp.file-item.action.size with corners of comp.file-item.action.shape, filled with the action container color of its form, holding the icon set's close glyph (remove) or refresh glyph (retry) at comp.file-item.action.icon.size in the action icon color of its form — at the end of a row (FIT-2), at the top end corner of a tile (FIT-3). WHEN the person activates one by pointer, touch, Enter or Space THE file item SHALL emit remove or retry exactly once with value and do nothing else: it SHALL NOT take itself away, change its status or move focus because of the activation. The actions SHALL NOT be inside the body (FIT-12) and SHALL NOT activate it. Each SHALL be a stop in the focus order after the body, retry before remove; THE file item SHALL handle no arrow key, Delete or Backspace, SHALL hold no selected state and draw no handle, and SHALL NOT be moved by dragging: an order that people change is the List's, in whose rows a file item is content.
FIT-12 WHILE interactive is true and href is empty THE file item SHALL make its body — the glyph or the picture, and the texts — exactly one focusable element with the button role, before the actions in the focus order, and WHEN the person activates it by pointer, touch, Enter or Space SHALL emit click exactly once with value. It SHALL open nothing itself: the product opens the file where it means to. WHILE interactive is false and href is empty THE file item's body SHALL NOT be focusable, SHALL NOT emit click, and SHALL draw no hover, focus or press answer. In a tile the body is the box and the texts beneath it; a press on an action's visible bounds SHALL go to that action and never to the body under it (FIT-18).
FIT-13 WHILE href is not empty THE file item SHALL make its body a link, whether interactive is true or false, as every control with a destination is: the platform's own link to href, with the link role and not the button role; activated by pointer, touch or Enter and not by Space; emitting click exactly once with value and then opening href where target names, unless the product cancelled that click, and never holding the navigation back for sys.motion.duration.press-hold; drawn from the same tokens in every state as a pressable body. WHILE target is new THE file item SHALL open href in a new context, SHALL expose targetLabel as the link's description after its name and role — in debug builds reporting an empty one — and WHILE form is row SHALL draw, comp.file-item.row.container.gap after the texts and before the actions, the glyph open_in_new of the system's icon set through the icon helper at comp.file-item.action.icon.size in comp.file-item.icon.color, hidden from assistive technology; a tile has no such place and draws none. WHILE disabled is true THE file item's link SHALL NOT be followed by any means the platform gives a link, SHALL keep the link role with the disabled state and no destination, and SHALL NOT be focusable. IF href is only white space, names a script to run, or cannot be read as an address THE file item SHALL be what interactive makes it, without a destination, and in the last two cases report it in debug builds. THE file item SHALL load nothing from href and SHALL NOT learn the file's name, size or format from it.
FIT-14 WHILE the body of a pressable file item is hovered, keyboard-focused or pressed THE file item SHALL render the body's container color from the component tokens of its form in the highest-precedence active state, with precedence pressed over focused over hovered, as a layer over the glyph or the picture and the texts — in a row over the body's bounds grown by comp.file-item.row.container.outset on every side, with corners of comp.file-item.row.container.shape, taking no room; in a tile over the box, with the box's corners. WHILE an action is hovered, keyboard-focused or pressed THE file item SHALL render that action's container, glyph and opacity from the action parts of the same tokens, with the same precedence. Focus gained by pointer or touch SHALL NOT select the focused state. The name, the second line, the glyph, the picture, the bar and the part that is not under the pointer, the press or the focus SHALL NOT change. WHEN the body or an action receives keyboard focus THE file item SHALL show the focus ring around it without animation — the system's focus indicator, sys.focus.offset from the part and following its corners, sys.focus.outer-width wide in the color role focus-ring, with the inner stroke of sys.focus.inner-width where the system has one; focus gained by pointer or touch SHALL NOT show it.
FIT-15 WHEN the body of a pressable file item or one of its actions is pressed by pointer, touch, Enter or Space THE file item 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. A body that is a link is not pressed by Space (FIT-13).
FIT-16 WHILE the body of a pressable file item or one of its actions is pressed THE file item 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 part 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; glyph, 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.file-item.motion.feedback-duration with comp.file-item.motion.state-easing, fades over comp.file-item.motion.state-duration with comp.file-item.motion.state-easing once the press has ended and press-hold has passed, and appears whole where motion is reduced.
FIT-17 THE file item SHALL ease the corners of a tile's box, of a row's picture, of the body's state layer and of its actions 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 the keyboard focus of its body and of an action 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.
FIT-18 WHERE the visual size of an action, or of the body of a pressable file item, is below the minimum target THE file item 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. WHILE the extended hit areas of two parts overlap — the retry and the remove action, an action and the body, or the actions of two file items — THE file item SHALL give a press on a part's visible bounds to that part, a press on an action's visible bounds to the action even where it lies over the body, and a press between two actions to the nearer one. THE file item SHALL set two actions that stand side by side — the retry and the remove action — apart by comp.file-item.action.gap, or by twice the amount by which the minimum target in force exceeds comp.file-item.action.size where that is more, so that the hit area of each reaches the minimum target on its own half of the space between them; it SHALL NOT shrink the hit area of either below the minimum target to keep them nearer, and the hit area of the action at the item's end SHALL still reach no further than the item's end edge.
FIT-19 THE file item SHALL expose itself to assistive technology as a group named by name, in every form and whatever nameHidden says, read in this order: name; formatText, sizeText, then statusText or — WHILE status is error — errorText; then, WHILE status is uploading, the bar as a progress bar named by name whose value is progress as a share of 0 to 1, or busy WHILE progress is null; then the retry action WHERE it is drawn, as a button named retryLabel, and the remove action WHERE it is drawn, as a button named removeLabel, each with its place {name} filled by name, so that "Remove brief.pdf" is the action's name and two files' actions are told apart wherever names are listed; neither action SHALL carry the name a second time as a description. WHILE the body is pressable it SHALL be a button, or a link (FIT-13), named by name and described by the second line's texts. WHILE a component holds the file item as one of the items of a list of its own THE file item SHALL be exposed as an item of that list in the group's place, by the word of that component and through no prop of its own. The glyph, the picture, the status mark and the mark of a new context SHALL be kept from assistive technology. THE file item SHALL have no live region and SHALL announce nothing — not that it appeared, not a change of status or of progress: what is said of many files is said once, by whoever holds them.
FIT-20 THE file item SHALL have no words of its own: it SHALL take removeLabel and retryLabel from the instance's prop and, WHILE that is empty, from the product's words of the keys removeLabel and retryLabel, and name, formatText, sizeText, statusText, errorText and targetLabel from the product alone, and from nowhere else. IF neither gives removeLabel or retryLabel THE file item SHALL still draw the action, expose it without a name, and in debug builds report the missing word once per page or screen, naming the prop. IF the word given has no place {name} THE file item SHALL name the action with it as it is written and in debug builds report that every file's action has the same name; another text between braces, and a brace that opens or closes nothing, SHALL be kept as written and reported. THE file item SHALL build no word from mediaType, from the end of name or from a number: it SHALL NOT write a format, a size or a share of progress in words.
FIT-21 WHILE disabled is true THE file item SHALL render each action from the disabled tokens of its form and disable it, so that it leaves the focus order — an action keeps the container it has at rest, none in a row and the disc in a tile, and only its glyph fades, as a quiet icon-only button grows no fill when it is disabled; SHALL make the body not pressable and not focusable, drawing no hover, focus or press answer on it; and SHALL emit neither click, remove nor retry. The name, the second line, the glyph, the picture, the status mark and the bar SHALL stay drawn as they are and readable by assistive technology: what was chosen is still what was chosen.
FIT-22 WHILE readOnly is true THE file item SHALL draw neither the remove action nor the retry action, SHALL keep no room for them — a row's texts reach its end edge — and SHALL emit neither remove nor retry. Everything else SHALL hold as without it: the status, the bar and the error are drawn, and the body is pressable WHERE interactive or href makes it so.
FIT-23 WHEN the colors of the body or of an action change between states THE file item SHALL animate the change over comp.file-item.motion.state-duration with comp.file-item.motion.state-easing, and SHALL change them at once where motion is reduced. A change of form, of status, of a text, of the glyph or of the picture SHALL be drawn at once, without a motion of the file item's own. THE file item SHALL NOT run a picture that moves: WHERE the platform can hold a moving picture still it SHALL draw its first frame, and where it cannot (the web's image element) it SHALL leave the picture to the platform and state that in its README.
FIT-24 WHILE the text size is enlarged THE file item SHALL grow with its texts: a row's lines wrap and are never cut, its glyph keeps its box, its picture comp.file-item.row.media.height and its actions comp.file-item.action.size; a tile's box keeps the size the product or the token gives, its name stays one line and grows in height, and its second line wraps beneath it. WHERE what stands beside a row's texts — its glyph or picture, the mark of a new context, its actions and the gaps between them — would leave the texts less than half the width of the row (a narrow screen, enlarged text) THE file item SHALL place the actions on a line of their own below the texts and the bar, at the row's end and in the same order, the line as tall as the minimum target in force, so that the name and the second line take the whole width after the glyph; otherwise a row's actions SHALL stay at its end beside its first lines. The answer SHALL be the same wherever the actions stand now, so that placing them does not change it. At 200 % in a width of 320 no text SHALL be lost or lie over another part, a tile SHALL be no wider than its layout (FIT-3), and nothing SHALL need scrolling in two directions.
FIT-25 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 file item SHALL draw its texts and glyphs in the platform's text color, a link's name in the platform's link color; SHALL draw the bar with its indicator in the platform's highlight color on a track edged in the text color; SHALL draw a tile's box and a row's picture box with an edge in the text color, since their ground is gone; SHALL draw each action of a tile on the platform's surface color with an edge in the text color; SHALL draw disabled actions in the platform's disabled text color; SHALL leave a picture as it is; and SHALL rely on no color of its own to tell a failed file from another: its words and its mark's shape do.
FIT-26 WHERE the layout direction is right-to-left THE file item SHALL mirror its layout: a row's glyph or picture at the right, its texts after it toward the left, the mark of a new context and the actions at the left with remove outermost; a tile's actions at the top left corner of its box with remove outermost; the status mark at the right of its words; and the bar filling — and its indeterminate segment moving — from right to left. A picture SHALL never be mirrored, and a ripple SHALL still grow from the point of contact.
FIT-27 THE file item 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 file item is shown THE file item SHALL draw itself for the new direction at once, without a motion of its own, keeping its focus.
FIT-28 THE file item SHALL lay out each text it draws — the name, the format, the size, the status and the error — 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 file name in Latin letters keeps its order, its dot and its extension in a right-to-left row, and the cut of FIT-9 keeps the name's own ending wherever that is drawn. WHERE the layout direction is right-to-left a glyph SHALL be mirrored exactly when the system's icon set marks its name as mirrored or the product forces it, by the icon helper and inside its own box; THE file item SHALL mirror no glyph itself.
FIT-29 WHEN form, status, fit or target names a value the file item does not know THE file item SHALL behave as row, pending, cover and same; IF width or height is given and is not a number above zero THE file item SHALL behave as if it were null; IF glyph names a glyph the icon set does not have THE file item SHALL draw nothing in its box and keep the box; and in each case debug builds SHALL report it. IF preview is true WHILE previewSrc is empty and the product gave no file THE file item SHALL draw the glyph and report nothing: a product may give the file later.
FIT-30 WHEN a prop changes while the file item is shown THE file item SHALL draw and expose the new value at once, keeping its focus, and SHALL announce nothing (FIT-19). WHEN the retry action leaves — status is no longer error, retryable or readOnly changed — while focus is on it THE file item SHALL move focus to its remove action, or to its body WHERE that is pressable and no remove action is drawn. THE file item SHALL NOT move focus otherwise, and where focus goes when a file item itself is taken away is its holder's to say.
FIT-31 WHILE the system's icon set cannot yet draw a glyph (its font is still loading) THE file item 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; removeLabel and retryLabel SHALL still reach assistive technology.
FIT-32 IF the file item holds a child that is not the glyph of its icon slot THE file item SHALL NOT draw it and in debug builds report it: the file item has no place for content of the product's — a menu of further actions, a caption, a checkbox — and a product that needs one puts it beside the file item, in its own layout or in the trailing place of a List's row. A platform that cannot inspect its content SHALL state the rule in its README and docs page.
FIT-33 THE file item SHALL NOT upload and SHALL NOT know more of a file than its props say: it SHALL send no file or part of one to anyone, SHALL keep no file beyond the handle the product gave it for FIT-6, SHALL set neither status nor progress itself, SHALL take name and mediaType, WHERE the product left them empty and gave the file itself, from what the platform reports of that file without opening it, and nothing else from it, and SHALL load nothing about a destination. This holds on every platform.

プラットフォーム別の名前対応

パリティは API が同一であることを意味しません。同じ契約を、各プラットフォームの流儀で表現します。

仕様 Web SwiftUI Jetpack Compose Flutter React Native
コンポーネント tanrei-file-item TanreiFileItem TanreiFileItem TanreiFileItem FileItem
form · プロパティ form form form form form
value · プロパティ value id key key value
name · プロパティ name name name name name
mediaType · プロパティ mediaType mediaType mediaType mediaType mediaType
glyph · プロパティ glyph glyph glyph glyph glyph
formatText · プロパティ formatText formatText formatText formatText formatText
sizeText · プロパティ sizeText sizeText sizeText sizeText sizeText
status · プロパティ status status status status status
statusText · プロパティ statusText statusText statusText statusText statusText
progress · プロパティ progress progress progress progress progress
errorText · プロパティ errorText errorText errorText errorText errorText
retryable · プロパティ retryable isRetryable retryable retryable retryable
preview · プロパティ preview showsPreview showPreview showPreview preview
previewSrc · プロパティ previewSrc previewURL previewModel previewImage previewSource
fit · プロパティ fit contentMode contentScale fit resizeMode
nameHidden · プロパティ nameHidden isNameHidden nameHidden nameHidden nameHidden
width · プロパティ width width width width width
height · プロパティ height height height height height
interactive · プロパティ interactive action onClick onPressed onPress
href · プロパティ href destination href href href
target · プロパティ target opens target target target
targetLabel · プロパティ targetLabel targetLabel targetLabel targetLabel targetLabel
removeLabel · プロパティ removeLabel removeLabel removeContentDescription removeSemanticLabel removeAccessibilityLabel
retryLabel · プロパティ retryLabel retryLabel retryContentDescription retrySemanticLabel retryAccessibilityLabel
disabled · プロパティ disabled disabled enabled enabled disabled
readOnly · プロパティ readOnly isReadOnly readOnly readOnly readOnly
click · イベント click action onClick onPressed onPress
remove · イベント remove onRemove onRemove onRemove onRemove
retry · イベント retry onRetry onRetry onRetry onRetry
備考 The shadow-root form: a part with states and actions of its own. Class TanreiFileItem; React FileItem. <tanrei-file-item name="brief.pdf" size-text="820 KB" remove-label="Remove"></tanrei-file-item>; a tile: <tanrei-file-item form="tile" preview width="160" height="90" name="floor-plan.png"></tanrei-file-item>. Attributes media-type, format-text, size-text, status-text, error-text, preview-src, name-hidden, target-label, remove-label, retry-label, readonly; progress absent for null; width and height are numbers of CSS pixels, as an image's, and are the box of the tile alone. **The file**: the property file (a File or null, never an attribute) is the platform's handle. With preview and an image kind and no preview-src, the element creates one object URL for it when it first comes near the viewport (an IntersectionObserver), gives it to its own <img part="preview" alt="" decoding="async"> and to nothing else, and revokes it in disconnectedCallback, when file is set again and when preview, preview-src or the kind stops asking for it (FIT-7); reconnected, it makes a new one when it is next in view. name and media-type left empty are read from file.name and file.type (FIT-33). file is also what a File upload submits for the item (FUP-31). **The body** is <div part="container">, or <button part="container"> with interactive, or <a part="container" href> with href (the shared link primitive; web-only rel and download are forwarded to the anchor, and download is how a link saves the file in place of opening it); the two actions are native buttons beside it in the shadow root, with aria-label — the product's sentence with the file's name filled in — never inside it. In a tile the actions are placed over the box and come after the body in the DOM, so the order of focus is the order read. click, remove and retry are CustomEvents that bubble and are composed, with detail.value; click is cancelable for a link. The host has role="group" and aria-label from name; a File upload that holds it sets role="listitem" on it through an internal channel that is not part of its public surface (FIT-19). The cut of a tile's name (FIT-9) is two spans — the start, which shrinks with an ellipsis, and the ending, which does not — inside one <bdi>. Parts: container, media, icon, preview, headline, supporting-text, status-icon, progress, action. The bar is <tanrei-progress-indicator> (the small linear one), drawn from this component's own bar tokens. No form participation: a file item submits nothing; what holds it does. TanreiFileItem(name: "brief.pdf", sizeText: "820 KB", onRemove: { }); a tile: TanreiFileItem(name:, form: .tile, width: 160, height: 90, showsPreview: true, file: url). interactive is whether action is given (a nil action is not pressable); destination makes it a Link. The file is a URL: the picture is QLThumbnailGenerator's thumbnail for the box's size at the display's scale, asked for when the view appears and cancelled when it disappears (FIT-7); previewURL goes through AsyncImage. contentMode is .fill for cover and .fit for contain. disabled follows .disabled(_:). The middle cut is .truncationMode(.middle), which keeps the ending. TanreiFileItem(name = "brief.pdf", sizeText = "820 KB", onRemove = { }). interactive is whether onClick is given; disabled is the inverse flag enabled. The file is a content Uri: the picture is ContentResolver.loadThumbnail(uri, size, signal) for the box's size, started in a LaunchedEffect keyed by the Uri and cancelled when the item leaves composition (FIT-7); previewModel is whatever the product's image loader takes, drawn through a painter slot so that the package depends on no loader. contentScale is Crop for cover and Fit for contain. The middle cut is TextOverflow.MiddleEllipsis. A link has no link role: Compose has none for a clickable element. TanreiFileItem(name: 'brief.pdf', sizeText: '820 KB', onRemove: () {}). interactive is whether onPressed is given; disabled is the inverse flag enabled. The framework has no thumbnail of a file by its handle: previewImage is an ImageProvider the product gives (a FileImage with ResizeImage for a local picture, a NetworkImage for one its server made), and the file item makes none itself — FIT-7's address is the product's on this platform, and the README says so. fit is BoxFit.cover or BoxFit.contain. The middle cut is drawn by measuring with a TextPainter. A link opens through the opener the app provides. <FileItem name="brief.pdf" sizeText="820 KB" onRemove={…} />. interactive is whether onPress is given. previewSource is an Image source ({ uri }): for a picked file the product passes the picker's uri, which the platform's image view draws scaled down without the file item reading it; no address is made (FIT-7). resizeMode is cover or contain. The middle cut is ellipsizeMode="middle". A link opens through Linking.

トークン

トークン 参照先 解決値(ライト)
--tanrei-comp-file-item-action-gap sys.space.space200 16px
--tanrei-comp-file-item-action-icon-size sys.icon.small 20px
--tanrei-comp-file-item-action-shape sys.shape.corner.full 9999px
--tanrei-comp-file-item-action-size — 32px
--tanrei-comp-file-item-disabled-opacity — 1
--tanrei-comp-file-item-done-icon-color sys.color.success #077b32
--tanrei-comp-file-item-error-icon-color sys.color.error #cd262f
--tanrei-comp-file-item-error-supporting-text-color sys.color.error #cd262f
--tanrei-comp-file-item-focused-opacity — 1
--tanrei-comp-file-item-headline-color sys.color.on-surface #1b1b1b
--tanrei-comp-file-item-hovered-opacity — 1
--tanrei-comp-file-item-icon-color sys.color.on-surface-variant #4b4b4b
--tanrei-comp-file-item-media-color sys.color.surface-container #f6f6f6
--tanrei-comp-file-item-motion-cycle-duration sys.motion.duration.extra-long4 1000ms
--tanrei-comp-file-item-motion-cycle-easing sys.motion.easing.standard cubic-bezier(0.2, 0, 0, 1)
--tanrei-comp-file-item-motion-feedback-duration sys.motion.role.feedback 450ms
--tanrei-comp-file-item-motion-progress-duration sys.motion.duration.medium2 300ms
--tanrei-comp-file-item-motion-progress-easing sys.motion.easing.standard cubic-bezier(0.2, 0, 0, 1)
--tanrei-comp-file-item-motion-state-duration sys.motion.role.state.large 250ms
--tanrei-comp-file-item-motion-state-easing sys.motion.easing.state cubic-bezier(0.2, 0, 0, 1)
--tanrei-comp-file-item-pressed-opacity — 1
--tanrei-comp-file-item-progress-gap sys.space.space75 6px
--tanrei-comp-file-item-progress-indicator-color sys.color.primary #1b1b1b
--tanrei-comp-file-item-progress-shape sys.shape.corner.full 9999px
--tanrei-comp-file-item-progress-thickness — 2px
--tanrei-comp-file-item-progress-track-color sys.color.surface-variant #eeeeee
--tanrei-comp-file-item-row-action-container-color — #000000 · 0%
--tanrei-comp-file-item-row-action-icon-color sys.color.on-surface-variant #4b4b4b
--tanrei-comp-file-item-row-action-state-layer-color comp.file-item.row.action.icon.color #4b4b4b
--tanrei-comp-file-item-row-container-color — #000000 · 0%
--tanrei-comp-file-item-row-container-gap sys.space.space150 12px
--tanrei-comp-file-item-row-container-outset sys.space.space50 4px
--tanrei-comp-file-item-row-container-shape sys.shape.corner.small 6px
--tanrei-comp-file-item-row-disabled-action-container-color — #000000 · 0%
--tanrei-comp-file-item-row-disabled-action-icon-color — #1b1b1b · 38%
--tanrei-comp-file-item-row-disabled-action-state-layer-color — #1b1b1b · 38%
--tanrei-comp-file-item-row-disabled-container-color — #000000 · 0%
--tanrei-comp-file-item-row-disabled-state-layer-color — #1b1b1b · 38%
--tanrei-comp-file-item-row-focused-action-container-color — #4b4b4b · 10%
--tanrei-comp-file-item-row-focused-action-icon-color — #4b4b4b
--tanrei-comp-file-item-row-focused-action-state-layer-color — #4b4b4b
--tanrei-comp-file-item-row-focused-container-color — #1b1b1b · 10%
--tanrei-comp-file-item-row-focused-state-layer-color — #1b1b1b
--tanrei-comp-file-item-row-hovered-action-container-color — #4b4b4b · 8%
--tanrei-comp-file-item-row-hovered-action-icon-color — #4b4b4b
--tanrei-comp-file-item-row-hovered-action-state-layer-color — #4b4b4b
--tanrei-comp-file-item-row-hovered-container-color — #1b1b1b · 8%
--tanrei-comp-file-item-row-hovered-state-layer-color — #1b1b1b
--tanrei-comp-file-item-row-icon-size sys.icon.medium 24px
--tanrei-comp-file-item-row-media-height — 40px
--tanrei-comp-file-item-row-media-shape sys.shape.corner.small 6px
--tanrei-comp-file-item-row-pressed-action-container-color — #4b4b4b · 10%
--tanrei-comp-file-item-row-pressed-action-icon-color — #4b4b4b
--tanrei-comp-file-item-row-pressed-action-state-layer-color — #4b4b4b
--tanrei-comp-file-item-row-pressed-container-color — #1b1b1b · 10%
--tanrei-comp-file-item-row-pressed-state-layer-color — #1b1b1b
--tanrei-comp-file-item-row-state-layer-color comp.file-item.headline.color #1b1b1b
--tanrei-comp-file-item-status-icon-gap sys.space.space50 4px
--tanrei-comp-file-item-status-icon-size sys.icon.extra-small 16px
--tanrei-comp-file-item-supporting-text-color sys.color.on-surface-variant #4b4b4b
--tanrei-comp-file-item-tile-action-container-color sys.color.surface-container-lowest #ffffff
--tanrei-comp-file-item-tile-action-icon-color sys.color.on-surface-variant #4b4b4b
--tanrei-comp-file-item-tile-action-inset sys.space.space50 4px
--tanrei-comp-file-item-tile-action-state-layer-color comp.file-item.tile.action.icon.color #4b4b4b
--tanrei-comp-file-item-tile-container-color — #000000 · 0%
--tanrei-comp-file-item-tile-container-gap sys.space.space75 6px
--tanrei-comp-file-item-tile-container-shape sys.shape.corner.medium 8px
--tanrei-comp-file-item-tile-disabled-action-container-color — #ffffff
--tanrei-comp-file-item-tile-disabled-action-icon-color — #1b1b1b · 38%
--tanrei-comp-file-item-tile-disabled-action-state-layer-color — #1b1b1b · 38%
--tanrei-comp-file-item-tile-disabled-container-color — #000000 · 0%
--tanrei-comp-file-item-tile-disabled-state-layer-color — #1b1b1b · 38%
--tanrei-comp-file-item-tile-focused-action-container-color — #ededed
--tanrei-comp-file-item-tile-focused-action-icon-color — #4b4b4b
--tanrei-comp-file-item-tile-focused-action-state-layer-color — #4b4b4b
--tanrei-comp-file-item-tile-focused-container-color — #1b1b1b · 10%
--tanrei-comp-file-item-tile-focused-state-layer-color — #1b1b1b
--tanrei-comp-file-item-tile-hovered-action-container-color — #f1f1f1
--tanrei-comp-file-item-tile-hovered-action-icon-color — #4b4b4b
--tanrei-comp-file-item-tile-hovered-action-state-layer-color — #4b4b4b
--tanrei-comp-file-item-tile-hovered-container-color — #1b1b1b · 8%
--tanrei-comp-file-item-tile-hovered-state-layer-color — #1b1b1b
--tanrei-comp-file-item-tile-icon-size sys.icon.large 32px
--tanrei-comp-file-item-tile-media-height — 96px
--tanrei-comp-file-item-tile-pressed-action-container-color — #ededed
--tanrei-comp-file-item-tile-pressed-action-icon-color — #4b4b4b
--tanrei-comp-file-item-tile-pressed-action-state-layer-color — #4b4b4b
--tanrei-comp-file-item-tile-pressed-container-color — #1b1b1b · 10%
--tanrei-comp-file-item-tile-pressed-state-layer-color — #1b1b1b
--tanrei-comp-file-item-tile-state-layer-color comp.file-item.headline.color #1b1b1b
--tanrei-comp-file-item-headline-typescale sys.typescale.body 400 14px/1.5714
--tanrei-comp-file-item-supporting-text-typescale sys.typescale.body-small 400 13px/1.5385

フィクスチャ

基準となる描画パターンです。全プラットフォームが同じ ID でスナップショットを撮り、結果を比較できるようにしています。

生成元 specs/file-item.spec.json, tokens/comp/file-item.tokens.json, design/tokens/

ガイドライン

2 つの形

同じ 3 つのファイルを、行とタイルで

観点 row(既定) tile
使う場面 種類を問わない、縦に並ぶファイル。 画像の並び。
幅 置かれた場所の幅。 ボックスの幅である width。置かれた場所より広くはなりません。
グリフまたは画像 名前の前。preview があれば、小さな正方形です。 ボックス全体。width × height です。
名前 折り返され、切り詰められません。 ボックスの下の 1 行。末尾が残るように、中ほどで切り詰められます。
2 行目 名前の下。 ボックスの下。ボックスの幅の中で折り返されます。
バー テキストの下。 ボックスの下端に沿って。
アクション 末尾。再試行、取り除くの順です。 ボックスの中、上の末尾側の角。

width と height は数値で、読まれるのはタイルの形のときだけです。height がなければ、ボックスの高さはトークン comp.file-item.tile.media.height のとおりです。width がなければ、正方形になります。手元にある画像の縦横比に合わせて選びます。スクリーンショットなら width="160" height="90"、人物の写真なら正方形です。ボックスが、2 つのアクションに必要な幅より狭くなることはありません。

3 つ目の、小さくまとめた形はありません。1 行に収めたファイルは、2 行目に何もない行です。

見せるもの

それぞれのパーツは、利用者側が指定したときに見えます。見えるものを変えるのは、オンとオフを切り替える 2 つのプロパティ、preview と nameHidden です。見せるパーツの一覧を受け取るプロパティはありません。

パーツ 見える条件
グリフ 画像が描かれない場所では、常に。
画像 preview が設定されていて、描く画像があるとき。
名前 行では常に。タイルでは、nameHidden が設定されて画像が描かれているときを除いて。
言葉で表した形式 formatText を指定したとき。Tanrei は、形式を表す言葉を持ちません。
サイズ 読む人の言語に合わせて整形した sizeText を指定したとき。
言葉で表した状態 statusText を指定したとき。
エラー status が error で、errorText を指定したとき。どの形でも、状態の場所に置かれ、切り詰められません。
バー status が uploading のとき。progress の値まで塗られます。progress が設定されていない間は不確定の表示です。

完了したファイルと失敗したファイルには、状態の言葉の前に印があります。チェックと、エラーの印です。名前の前のグリフは、状態によって変わりません。利用者は、それぞれについて場所を 1 つ覚えるだけで済みます。名前の前はそのファイルが何であるか、状態の前はそれがどうなっているかです。

nameHidden は、密に並んだ画像のためのものです。名前が隠れるのは、画像が描かれているときだけです。グリフを見せているタイルは、名前を保ちます。形式のグリフでは、同じ形式の 2 つのファイルを見分けられないためです。どの場合も、支援技術にとっての項目の名前は、その名前のままです。

グリフは形式を表す

グリフの種類は 10 あります。種類ごとに、メディアタイプの一覧とファイルの拡張子の一覧があります。グリフは mediaType から選ばれます。メディアタイプが空であるか、application/octet-stream であるか、どの一覧にもない場合は、name の拡張子から選ばれます。種類は次の順に照合されます。一覧は固定で、どのプラットフォームでも同じです。そのため、1 つのファイルは、どこで見せても同じグリフになります。video/mp2t も種類を決めません。プラットフォームはこれを拡張子 .ts から推定しますが、この拡張子は TypeScript のファイルと動画のストリームが共有しています。そのため index.ts はコードのグリフになります。

10 の種類

種類 グリフ メディアタイプ 末尾
pdf picture_as_pdf application/pdf pdf
spreadsheet table text/csv, text/tab-separated-values, application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.oasis.opendocument.spreadsheet, application/vnd.apple.numbers, application/x-iwork-numbers-sffnumbers xls, xlsx, ods, numbers, csv, tsv
presentation slideshow application/vnd.ms-powerpoint, application/vnd.openxmlformats-officedocument.presentationml.presentation, application/vnd.oasis.opendocument.presentation, application/vnd.apple.keynote, application/x-iwork-keynote-sffkey ppt, pptx, odp, key
archive folder_zip application/zip, application/x-zip-compressed, application/x-tar, application/gzip, application/x-gzip, application/x-bzip2, application/x-xz, application/x-7z-compressed, application/vnd.rar, application/x-rar-compressed zip, tar, gz, tgz, bz2, xz, 7z, rar
code code text/html, text/css, text/javascript, application/javascript, application/x-javascript, text/typescript, application/typescript, text/jsx, text/tsx, application/json, application/xml, text/xml, text/yaml, text/x-yaml, application/yaml, application/x-yaml, application/x-sh, text/x-sh, text/x-shellscript, text/x-python, text/x-script.python, text/x-ruby, application/x-ruby, text/x-go, text/x-rust, text/x-java, text/x-java-source, text/x-kotlin, text/x-swift, text/x-c, text/x-chdr, text/x-csrc, text/x-c++, text/x-c++src, text/x-csharp, text/x-php, application/x-php, application/x-httpd-php, application/sql, text/x-sql html, css, js, mjs, ts, tsx, jsx, json, xml, yaml, yml, sh, py, rb, go, rs, java, kt, swift, c, h, cpp, cs, php, sql
image image image/ で始まるすべてのタイプ png, jpg, jpeg, gif, webp, avif, svg, bmp, tif, tiff, heic, heif, ico
video movie video/ で始まるすべてのタイプ mp4, mov, m4v, webm, mkv, avi
audio music_note audio/ で始まるすべてのタイプ mp3, wav, m4a, aac, ogg, oga, flac, opus
document description text/ で始まるほかのすべてのタイプと、application/rtf, application/msword, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/vnd.oasis.opendocument.text, application/vnd.apple.pages, application/x-iwork-pages-sffpages txt, md, rtf, doc, docx, odt, pages
other draft — それ以外のすべてと、ドットのない名前
  • メディアタイプが、名前の末尾より先に決めます。メディアタイプが一覧にあるファイルは、名前の末尾が何であっても、その種類です。
  • 形式を知るためにファイルを開くことはありません。
  • プロダクト独自の形式には、glyph でアイコンセットのグリフを指定するか、icon スロットに自分のグリフを入れます。
  • グリフはどれも同じ 1 色です。形式に固有の色はありません。色は、どこで使われても 1 つのことを意味します。そして形式は状態ではありません。
  • 形式が大事な場面では、formatText を使って言葉で伝えます。グリフは、支援技術から隠されています。

プレビューとそのコスト

preview は、グリフの場所にファイルの画像を描きます。画像の出どころは 2 つあります。

  • previewSrc。サーバーが作った、そのファイルの小さな画像のアドレスです。どの形式のファイルにも描かれます。
  • ファイルそのもの。previewSrc が空で、ファイルが画像である場合です。Web では、file プロパティに File を設定します。

fit は、画像がボックスをどう埋めるかを決めます。cover(既定)は、ボックスを埋め、収まらない部分を切り落とします。写真に使います。contain は、ボックスの地の上に画像の全体を見せます。スキャン、署名、図のように、端が大事なものに使います。

160 × 90 のボックス。cover、contain、名前を隠したもの

プレビューのコストは次のとおりです。

画像の出どころ かかるコスト
preview がオフのとき(既定) ありません。100 個のファイル項目のコストは、そのテキストのコストだけです。
previewSrc があるとき 項目ごとに画像のリクエストが 1 つ。プラットフォーム自身の画像の読み込みが行います。
ファイルそのものを使うとき ファイルのアドレスが 1 つ。項目が、初めて表示範囲かその近くに入ったときに作ります。項目がページを離れたとき、別のファイルを渡すかファイルをなくしたとき、プレビューが求められなくなったときに解放します。ファイルを読んで描くのは、プラットフォームの画像デコーダーです。項目自身は何も読みません。
  • ファイルから描かれるのは、画像だけです。動画の 1 コマや書類の 1 ページを描くには、ファイルを開いて読む必要があり、Tanrei のコンポーネントはどれもそれをしません。そうしたファイルには previewSrc を指定します。
  • 画像を描けるようになるまでの間と、描けなかった場合は、形式のグリフが描かれます。スピナーも、壊れた画像の印もなく、status も変わりません。サムネイルを読み込めなかったことは、ファイルの失敗ではありません。
  • 画像に代替テキストはありません。画像はグリフがあった場所に置かれ、ファイルの名前は name が伝えます。

押せる本体、リンク、読み取り専用

既定では、ファイル項目の本体はフォーカスを受け取らず、何にも応えません。項目は、アクションを持つだけです。

ボタンである本体、新しいタブで開くリンク、読み取り専用のファイル

プロパティ 本体 使う場面
interactive ボタンです。value を持つ click を発火します。 その人が今いる場所でファイルを開く場合。画像を自身のビューアーで、書類をパネルで開くときです。
href ファイルへのリンクです。先に click を発火します。キャンセルすると、移動を利用者側で引き受けられます。 サーバーがすでに持っているファイル。target="new" を指定するときは、targetLabel も指定します。
どちらもなし 押せません。 一覧に並べるだけのファイル。

本体は、グリフまたは画像と、テキストです。アクションは本体の横にあり、本体の中に入ることはありません。そのため、押せるファイル項目でも、フォーカスが止まる位置は多くて 3 つです。本体、再試行、取り除くです。

readOnly は、どちらのアクションも描かず、その場所も空けません。読むだけの記録に付いたファイルに使います。本体は、このときも押せます。

disabled は、アクションと本体を無効にします。項目が見せるものはそのまま残り、読めるままです。無効なアクションは待機時の地を保ちます。行では地がなく、タイルでは円の地があり、薄くなるのはグリフだけです。

並べ替えられるファイル

ファイル項目には、ハンドルも独自の順序もありません。並べ替えはリストのものです。それぞれのファイル項目を、並べ替えられるリストの項目に入れます。リストはファイル項目の横にハンドルを描き、項目全体をドラッグできるようにし、ハンドルから移動のメニューを開きます。ファイル項目は、グリフ、テキスト、バー、アクションをそのまま保ちます。

並べ替えられるファイル:並べ替えられるリストの中のファイル項目

<tanrei-list reorderable gap="small" label="Attachments" drag-handle-label="Reorder {label}"
             move-to-start-label="Move to top" move-before-label="Move up"
             move-after-label="Move down" move-to-end-label="Move to bottom"
             lifted-text="{label} lifted: {position} of {count}"
             moved-text="{label}: {position} of {count}"
             cancelled-text="{label} returned to {position} of {count}">
  <tanrei-list-item><tanrei-file-item name="cover-letter.pdf" size-text="120 KB" remove-label="Remove {name}"></tanrei-file-item></tanrei-list-item>
  …
</tanrei-list>

リストは自分では何も動かしません。move を受けたら項目を新しい順に並べてください。リストは移動ごとに読み上げ、動かした項目のハンドルにフォーカスを保ちます。詳しくはリストを見てください。各リスト項目はそのファイルで名付けられます(ファイル名がコンテンツのテキストなので、ほかに何も要りません)。ファイルアップロードも同じ方法でファイルを並べます。

言葉

ファイル項目は、自身の言葉を持ちません。2 つは setWords() でプロダクト全体に一度だけ指定でき、それ以外のテキストはすべてインスタンスのプロパティです。

プロパティ プロダクトの言葉のキー ない場合
removeLabel removeLabel 取り除くアクションは描かれますが、名前がありません。デバッグビルドが報告します。
retryLabel retryLabel 再試行のアクションは描かれますが、名前がありません。デバッグビルドが報告します。

それぞれのアクションの名前には、そのファイルの名前が入ります。removeLabel と retryLabel は場所 {name} を持つ文で、ファイル項目がファイルの名前を入れます(「{name} を取り除く」)。1 つの文ですべてのファイルに足り、利用者には言語の語順のまま「brief.pdf を取り除く、ボタン」と聞こえます。スクリーンリーダーがページのボタンを一覧にしたときも同じです。{name} のない文は、どのファイルのアクションも同じ名前にしてしまうので、デバッグビルドが報告します。

右から左

右から左のレイアウトでは、グリフまたは画像が右に、アクションが左に並び、取り除くアクションがいちばん外側になります。バーは右から伸び、タイルのアクションは左上の角に置かれます。画像が反転することはありません。ラテン文字のファイル名は、ドットと拡張子を含めて、自身の並びを保ちます。形式の 10 のグリフのうち、反転するのは other のグリフだけです。アイコンセットがそう指定しているためです。

推奨

  • 完了したファイルには statusText を、失敗したファイルには errorText を指定します。状態を、印や色だけで伝えることはありません。
  • retryable は、もう一度試せば直る可能性のある失敗にだけ指定します。大きすぎるファイルは、次も大きすぎます。
  • サイズは利用者側で整形します。1 メガバイトを 1000 キロバイトとするか 1024 キロバイトとするかは、プロダクトが決めます。
  • ひとまとまりのファイル項目は、名前を付けた <ul> のような利用者側のリストか、ファイルアップロードに入れます。
  • 項目を取り除いた後は、利用者側でフォーカスを移します。単独のファイル項目は、自分の隣に何があるかを知ることができません。

非推奨

  • 項目が自分で消えたり、状態を変えたり、バーを動かしたりすることを期待しない。項目は、設定された内容を描きます。
  • 画像でないファイルに nameHidden を使わない。そのタイルは、どのみち名前を保ちます。
  • メニュー、チェックボックス、キャプションを中に入れない。スロットはグリフの 1 つだけです。ファイルに対するほかのアクションは、項目の横に置きます。
  • 選択したり並べ替えたりするリストの行として使わない。それはリストの行です。

アクセシビリティ

ロール
group
ラベル付け
A group named by the file's name — also in a tile that does not draw it — reading the name, the format, the size and the status or the error in words, a progress bar named by the file while it is sent, and its actions: buttons named retryLabel and removeLabel, each with the file's name in its place ({name}). A pressable body is a button, or a link, named by the file's name and described by the second line. Inside a File upload the file item is an item of the upload's list in the group's place (FUP-25).
最小ターゲット
見た目のサイズが小さくても、ヒット領域は最小ターゲットサイズを満たします。 minimum 32px · pointer 44px · spacing 8px · touch 48px

キーボード操作

キー 動作
Tab / Shift+Tab Moves focus to the body, where the file item is pressable, then to its retry action where it has one, then to its remove action. A file item that is not pressable and is read-only is no stop at all.
Enter / Space On a pressable body: emits click, for the product to open the file. On an action: asks whoever holds the file item to retry or to remove the file.
Enter On a body that is a link: follows it. Space does what it does on any link (FIT-13).

備考

  • The name is the name in every form (FIT-8, FIT-19): hiding it in a strip of pictures hides it from sight alone, and only behind a picture that is drawn. A picture is no text alternative for a name, and the file item asks for no description of the picture: the picture stands for the file, which has a name. A product that shows the picture as content — to be looked at — shows it in an Image preview, whose images have their own alternative text.
  • Status is never color alone (WCAG 1.4.1): a done or failed file has words, and its mark has a shape of its own. The glyph before the name says the format and never the status, so that a person learns one place for each.
  • A failure is never hidden (WCAG 3.3.1): errorText is drawn in every form, wraps and is never cut, also beneath a tile whose name is hidden.
  • A format has no color. Ten colors for ten kinds would be ten meanings a person must learn, would compete with the two status colors on the same line, and would say nothing to a person who does not tell them apart; the glyph's shape and, where the product has them, the format's words carry it.
  • The remove and retry actions are named by one sentence of the product's with the file's name in it, so a person tabbing through a list, or listing the buttons of the page, hears "Remove brief.pdf, button" — in the order of the product's language — without the product writing a sentence per file.
  • Nothing is announced by a file item (FIT-19). A component that holds file items — a File upload, a chat composer — has one live region for all of them and says what was added, finished and failed there; a product that arranges file items itself does the same with a region of its own.
  • A cut name (FIT-9) is cut for sight alone and keeps its ending. The whole name is the accessible name; on the web it is also the body's or the name's `title` only where the product asks for one, because a tooltip is not reachable by touch and is no substitute for the row form, which never cuts.
  • A picture that moves (an animated image) is the platform's to hold still or not (FIT-23). On the web an image element plays it; a product whose strip must not move gives a still `previewSrc`.
  • Without script, and until the component is defined, on the web: nothing is drawn, because the name is an attribute. A page that must list files where script does not run writes its own links to them, as it would without Tanrei.
  • Compose and React Native: the group is a node with the name as its content description (Compose) or a labelled container (React Native), and the actions keep their own nodes.

生成元 specs/file-item.spec.json, tokens/sys/measure.tokens.json

コンポーネントが担うこと

  • 単独のファイル項目は、ファイルの名前が付いたグループです。ファイルアップロードの中では、そのリストの項目です。
  • 押せる本体は、1 つのボタンまたは 1 つのリンクです。ファイルの名前が名前になり、2 行目が説明になります。フォーカス順では、アクションより前です。リンクは Enter で動作し、Space では動作しません。新しいタブで開くリンクは、名前の後に targetLabel を伝えます。
  • アクションはボタンです。removeLabel と retryLabel が名前になり、その場所 {name} にファイルの名前が入ります。再試行が、取り除くより前です。
  • バーは、そのファイルの名前が付いたプログレスバーです。エラーは 2 行目のテキストで、状態の場所で読まれます。
  • グリフ、画像、状態の印は、支援技術から隠されています。それらが示すことは、言葉が伝えます。
  • ファイル項目は、何も読み上げません。多くのファイル項目を持つ側が、全体のためのライブリージョンを 1 つ持ちます。ファイルアップロードがそうしています。
  • 名前の全体が、常に支援技術に届きます。タイルが名前を切り詰めているときも、nameHidden が隠しているときも同じです。
  • テキストが 200% のとき、行は折り返され、何も失われません。グリフとアクションが名前に行の半分の幅も残さないときは、アクションがテキストの下の独立した段に、行の末尾に揃えて移り、名前が行の幅いっぱいを使います。タイルのボックスは大きさを保ち、テキストがその下で大きくなります。
  • 強制カラーモードでは、ボックスと、タイルのアクションの円形の地が縁を保ち、バーも見えたままです。画像はそのままです。
  • 状態の間の色の変化は、短い時間をかけて動きます。動きを減らす設定では、すぐに変わります。

Web での既知の不足は次のとおりです。

  • アニメーション GIF のような動く画像は、ブラウザーの画像要素が再生します。ファイル項目は、それを止めておくことができません。それが大事な場面では、previewSrc に静止画を指定します。
  • 要素が定義されるまでは、何も描かれません。名前が属性であって、文書の中のテキストではないからです。スクリプトが動かない場所でファイルを一覧にする必要があるページは、自身のリンクを書きます。

利用者側で行うこと

  • name を必ず指定します。
  • removeLabel と retryLabel を、要素に、または setWords() で一度だけ指定します。
  • 状態と失敗は、必ず言葉で伝えます。statusText と errorText です。
  • target="new" を指定するときは、targetLabel も指定します。
  • ひとまとまりのファイル項目には、利用者側のリストと名前を与えます。追加されたもの、完了したもの、失敗したものは、利用者側の 1 つのライブリージョンで伝えます。ファイルアップロードは、この両方を代わりに行います。
  • 項目を取り除いた後は、フォーカスを次のファイルの取り除くアクションへ、またはファイルを追加したものへ移します。