Skip to content

Token input

How token files get into the playground before anything is loaded: the drop area takes the page (playground spec, decision 15). It takes files dragged onto it and is also the button that opens the file picker, so it works with a keyboard and on phones, where dragging is not an option. Several files at once. Under it: the examples, “Load example” (brand-ab, which lints clean) and “Example with problems” (the same tokens with three flaws the default rules catch, so a visitor sees what a finding looks like; TICKET-113), and “Paste JSON instead”, which swaps the drop area for a paste field.

The component reads the files and hands them on as { fileName, content }; it does not interpret them (the playground decides between per-mode files and a plugin export, as the CLI does). Once something is loaded the input shrinks to the Source bar; its “Paste JSON instead” opens the same paste field (PasteForm, exported from this component), and its “Replace files” reads files with the same readFiles. A Preact component, because the playground is a Preact island; the stories render it to static HTML.

  • As the whole page of a tool that needs input first, before there is anything to show.
  • Not once something is loaded: then the Source bar says what it is and offers to replace it.

Drop area, example, paste field

Light

Per-mode files ({Collection}.{Mode}.json, several at once), .tokens files or one plugin export. They stay in your browser.

brand-ab: BrandA and BrandB, three breakpoints
brand-ab with a broken alias, a circular alias and a default mode name
Graphite

Per-mode files ({Collection}.{Mode}.json, several at once), .tokens files or one plugin export. They stay in your browser.

brand-ab: BrandA and BrandB, three breakpoints
brand-ab with a broken alias, a circular alias and a default mode name

Story: /stories/token-input/empty/

Paste JSON instead: the paste field in the drop area's place

Light

File name: for one per-mode file; a plugin export needs none.

brand-ab: BrandA and BrandB, three breakpoints
brand-ab with a broken alias, a circular alias and a default mode name
Graphite

File name: for one per-mode file; a plugin export needs none.

brand-ab: BrandA and BrandB, three breakpoints
brand-ab with a broken alias, a circular alias and a default mode name

Story: /stories/token-input/paste/

  • The drop area is a dashed ink outline on bg-surface: a place to put something. It is tall (about 40 % of the screen, at least 220 px), so it is the page until something is loaded. Hover and focus turn the outline action-bg; while files are dragged over it, it fills with action-subtle.
  • Its label says both ways in: “Drop token files”, then “or choose files” in action-text, underlined like a link. The help line under it names what it accepts.
  • The actions under it: the examples (examples: id, button label, what it loads), one under the other, each an outline Button with what it loads beside it in mono fg-subtle (the button’s description, aria-describedby); the buttons share one column width, so the descriptions line up. At the end of the first row “Paste JSON instead” (link button). Below 560 px of container width each description goes under its button and the switch follows the examples. The paste field takes the drop area’s place, and the button then says “Choose files instead”; switching moves focus to the field or back to the drop area.
  • The examples are bundled with the page (fixtures in test/fixtures/, read with import.meta.glob), so loading one needs no request; onExample gets the id.
  • The paste field is mono, labelled above like Text field. A pasted per-mode file needs a {Collection}.{Mode}.json name; a plugin export needs none. “Check pasted JSON” is the one primary action; under the Source bar the form also has “Cancel” (and Escape).
  • Input that cannot be read (broken JSON, a file name without collection and mode, an export in no known format) is not shown in the input: the playground answers with the input’s diagnostics as an error status banner above everything else (Findings with banner, in the status colours), with the Source bar to try again. The Findings page shows both: “Input that cannot be read” and “An export it does not know”.
  • Motion: the drop area (or the paste field in its place) is the view-transition part dta-source: a page that loads inside transition() collapses it into the Source bar. Switching between drop area and paste field crossfades; the drop area’s hover and drag states change over motion.duration.fast. See Motion.

Read from the component’s source:

--action-bg--action-subtle--action-text--bg-surface--border-strong--fg-default--fg-muted--fg-subtle--font-mono--font-sans--motion-duration-fast--motion-ease-standard--radius-lg--radius-sm--space-1--space-2--space-3--space-4--space-6--stroke-focus--stroke-ink--type-body-sm-line-height--type-body-sm-size--type-code-line-height--type-label-line-height--type-label-size--type-label-weight--type-meta-line-height--type-meta-size--type-title-line-height--type-title-size--type-title-weight