Skip to content

Components

Icon tile

A tinted glass square that holds one glyph and fills with its colour when selected. Use it for icon-only actions where a label would crowd the screen.

Preview

Variants

Pick a variant with the controls. The preview and both code blocks follow.

Glyph
Tone
Size
State
Variant.tsx
<AppIconTile glyph="moon" label="Moon" />

Implementation

The React tab is this site's own component, the same source that draws the preview, styled by the CSS below it. The Flutter tab is the Dart a screen builds it with, from the app's tokens.

Usage
<AppIconTile glyph="moon" tone="deep-space" label="Moon" /><AppIconTile glyph="graph" tone="aurora-green" label="Graphs" pressed />
app-icons.tsx · AppIconTile
/** Glass icon tile. Pass `pressed` for a toggle; `label` is the accessible name. */export function AppIconTile({  glyph,  tone = "deep-space",  size,  label,  pressed,  disabled,}: {  glyph: GlyphName;  tone?: TileTone;  size?: "sm" | "lg";  label: string;  pressed?: boolean;  disabled?: boolean;}) {  return (    <button      type="button"      className={`app-ui app-tile${size ? ` is-${size}` : ""}`}      style={{ ["--tone" as string]: toneVar(tone) }}      aria-label={label}      aria-pressed={pressed}      disabled={disabled}    >      <Glyph name={glyph} />    </button>  );}
app-icons.tsx · Glyph
export const Glyph = ({ name }: { name: GlyphName }) => (  <svg viewBox="0 0 24 24" aria-hidden="true">    <path d={GLYPHS[name]} fillRule="evenodd" />  </svg>);
app-ui.css
.app-tile {  --tone: var(--color-deep-space-200);  --tile-size: var(--spacing-f55);  position: relative;  display: inline-grid;  place-items: center;  width: var(--tile-size);  aspect-ratio: 1;  border-radius: calc(var(--tile-size) * var(--phi-inverse-squared));  border: var(--spacing-f1) solid color-mix(in srgb, var(--tone) var(--mag-3), transparent);  color: var(--tone);  cursor: pointer;  overflow: hidden;  isolation: isolate;  background:    radial-gradient(circle at 50% 115%, color-mix(in srgb, var(--tone) var(--mag-1), transparent), transparent 65%),    linear-gradient(160deg, color-mix(in srgb, var(--tone) var(--mag-4), var(--c-ink)), color-mix(in srgb, var(--tone) var(--mag-6), var(--c-ink)));  box-shadow: var(--highlight), 0 var(--spacing-f13) var(--spacing-f34) calc(var(--spacing-f13) * -1) color-mix(in srgb, var(--tone) var(--mag-1), transparent);  transition: transform 0.4s cubic-bezier(0.215, 0.61, 0.355, 1), box-shadow 0.4s;}.app-tile svg { width: calc(var(--tile-size) * var(--phi-inverse-squared)); height: calc(var(--tile-size) * var(--phi-inverse-squared)); fill: currentColor; filter: drop-shadow(0 0 var(--spacing-f8) color-mix(in srgb, var(--tone) var(--mag-1), transparent)); }.app-tile:hover { transform: translateY(calc(var(--spacing-f3) * -1)); }.app-tile[aria-pressed="true"] { background: var(--tone); color: var(--c-ink); box-shadow: var(--highlight), 0 var(--spacing-f13) var(--spacing-f34) calc(var(--spacing-f8) * -1) var(--tone); }.app-tile.is-sm { --tile-size: var(--spacing-f34); }.app-tile.is-lg { --tile-size: var(--spacing-f89); }

API reference

React propFlutter parameterTypeDefaultMeaning
glyphiconGlyphName / IconDatarequiredThe shape drawn at 44% of the tile.
tonetoneAstrTonedeep-spaceAccent colour; a system stop.
sizesizesm, md, lg / AstrTileSizemd34, 55 or 89.
labellabelstringrequiredAccessible name.
pressedselectedbooleanfalseFilled state for toggles.
disabledonPressed: nullbooleanfalseNot interactive.

Design tokens

Every value on this component is a system token. The last column is what the app widget uses today, so the gap to close is visible.

RoleCSS tokenDart tokenApp widget today
Sizes--spacing-f34, f55, f89AstrTileSize.sm, md, lgnew
Corner radiussize × --phi-inverse-squared (13, 21, 34)size * AstrLayout.minornew
Glyph sizesize × --phi-inverse-squaredsize * AstrLayout.minornew
Bordertone at --mag-3tone.withValues(alpha: Mag.m3)new
Filltone at --mag-4 to --mag-6 over --color-space-grey-950Color.alphaBlend(tone, Mag.m4 and m6)new
Selected fillthe tone, glyph --color-space-grey-950tone, _inknew
Disabledopacity --mag-2Mag.m2new
Tones--color-deep-space-200, aurora-green-400, aurora-pink-400, sodium-airglow-400, oxygen-airglow-400AstrTone.colornew