V3.2 Overview
Framework 3.2 makes plugins theme-aware. It adds opt-in theme stylesheets, the TRMNLPaint JavaScript paint API, adaptive charts and icons, rebuilt border, outline, and stroke utilities, and Fluid Mashups for arranging views, all on top of the v3 color system. Existing markup keeps working; every 3.2 feature is opt-in.
The v3 Color Foundation
3.2 builds on the color system introduced in v3.0: 10 chromatic hues with 14 lightness steps, semantic roles (primary, success, error, warning), a 14-step grayscale, and per-mode CSS custom properties on .screen, so colors follow each device's palette and bit depth with no per-device markup. 3.1 added the TRMNL font bundle as the low-density default. See
Colors
Colors
Complete palette definition: grayscale, chromatic hues, and semantic roles
The Colors system defines the complete palette for the framework: grayscale, chromatic hues, and semantic roles (primary, success, error, warning). Use these tokens with bg--, text--, and other utilities. See Background and Text Color for usage examples.
for the full palette.
Independent Text Scale
Text Scale adjusts every framework font size and pixel line height without applying the same factor to interface geometry or text strokes. It composes with Scale, so a dense layout can keep larger text instead of shrinking both together. See Text Scale Text Scale Scale all framework typography independently of interface geometry Text Scale adjusts every framework font size and pixel line height from one screen modifier. It composes with Scale, so you can change text readability without applying the same factor to interface geometry or text strokes. .
Themes
Restyle a whole screen by loading one extra stylesheet and adding screen--theme-<id>. A theme remaps which tokens paint each surface; device-capability rendering is preserved, so a themed screen still dithers on 1-bit and paints solids on full color. 3.2 ships three themes: Black and Yellow, White and Red, and Dark.
- A theme is a complete color statement:
screen--dark-modehas no effect on a themed screen. - Author your own theme with the
theme-slotsmixins and validate it withrake framework:themes:lint. - Preview any docs example with a theme via the Style selector in the screen picker.
Full reference: Themes Themes Opt-in stylesheets that re-theme screens while preserving device-capability rendering Themes are standalone stylesheets that re-point semantic channels, component slots, and utility tokens at different palette tokens. A themed screen still renders through its device mode: dither patterns on 1-bit, palette images on limited color, solids on full color. .
TRMNLPaint: the JavaScript Paint API
Resolve any framework color, border rail, typography role, or numeric scale from JavaScript. TRMNLPaint reads the live CSS cascade, with device density, scale, bit depth, dark mode, themes, and limited palettes already applied. Token mappings and scale factors are never duplicated in JS.
- Resolvers:
bg(),text(),semantic(),series(),border(),type(), and more. - Painters:
apply(),applyBorder(),applyType()write resolved paint onto nodes. watch()re-runs your build function whenever the screen's device, scale, mode, dark mode, or theme changes.cssVar()reads any public custom property, the documented extension path for themes.scale()reads the composed scale contract, andpx()converts numeric JavaScript dimensions.
Full reference: Paint API Paint API TRMNLPaint: read the live CSS cascade from JavaScript to resolve framework colors and tile patterns TRMNLPaint is the framework's public JavaScript paint API. It reads the live CSS cascade (bit depth, dark mode, theme, limited palette, and tiles all resolved) and hands back a canonical Fill, so token mappings are never duplicated in JavaScript. Charts are just one consumer; any plugin can resolve framework colors from JS for any purpose. .
Generated Paint Assets
Dither paint no longer ships as PNG images. Every grayscale and limited-palette tile is generated at build time as an inline ink SVG: the dark pixels are baked into the asset and the light tone rides the background color, so a screen paints with zero image fetches.
- One tile pipeline: CSS paints from the generated assets, and
TRMNLPaintreads the same resolved output back for JavaScript consumers. - Dark mode and Raw/Preview recolor by re-pointing tokens at other tiles from the same generated set; the geometry never forks.
- Regenerate from the color manifest with
rake framework:color_tokens; hand-edited pattern assets are gone.
Adaptive Charts
Charts historically painted explicit colors and ignored bit depth, dark mode, and themes. The plugin runtime now bundles TRMNLCharts, a Highcharts adapter built on TRMNLPaint. Chart series pull from the screen's chart-series ramp, grid lines use the border system, and plotted text uses framework typography, so charts adapt with the rest of the screen.
options()andmerge()give you adaptive Highcharts defaults under your own settings.series(i, n)resolves each series fill;applySwatches()paints matching legend markers.watch()rebuilds the chart on device, scale, mode, dark mode, or theme changes.TRMNLPaint.px()scales numeric chart dimensions from the same live CSS contract.
Usage and live examples: Chart Chart Visualize data optimized for 1-bit rendering With careful, minimal styling choices, TRMNL can display a variety of numerical or time centric content as charts and graphs. . For charting beyond Highcharts, use Paint API Paint API TRMNLPaint: read the live CSS cascade from JavaScript to resolve framework colors and tile patterns TRMNLPaint is the framework's public JavaScript paint API. It reads the live CSS cascade (bit depth, dark mode, theme, limited palette, and tiles all resolved) and hands back a canonical Fill, so token mappings are never duplicated in JavaScript. Charts are just one consumer; any plugin can resolve framework colors from JS for any purpose. directly.
Adaptive Icons
Add image--adaptive to a monochrome silhouette icon and the framework repaints it with the screen's icon paint, following the same Raw/Preview, bit-depth, dark-mode, and theme cascade as framework text. One set of icons works everywhere, as long as they are same-origin or CORS-readable. See
Image
Image
Optimize images using dithering techniques for 1-bit rendering
Place images on a screen and control their size, object fit, and inversion. On 1-bit displays, dithering arranges black and white pixels so an image still reads as shades of gray.
.
Rebuilt Borders, Outlines, and Strokes
The Border, Outline, Text Stroke, and Image Stroke utilities were rebuilt on the same token model as the color and pattern system. Each one paints from semantic and theme variables, so dark mode, themes, and bit depth recolor it with no per-mode markup.
- Borders: a shade-step rail,
border--h-{step}andborder--v-{step}on the same 10 to 75 scale as backgrounds, plus semanticborder--h-black/border--h-whiterails. The rail renders as generated gradients instead of PNG tiles, so a bordered screen fetches no images, and themes repaint it without changing its geometry. The numbered levelsborder--h-1throughborder--h-7still work but are deprecated. See Border Border Apply border patterns that create the illusion of different border intensities Draw a horizontal or vertical rule on any element with the border--h and border--v utilities, named on the same 10 to 75 shade scale as backgrounds. On 1-bit displays a step renders as a dither pattern of black and white pixels, so a rule can read as gray. 4-bit and full-color screens draw all 14 steps; the other rails pair them onto seven levels. . - Outline: draws a pixel-perfect dotted rounded border from CSS gradients on 1-bit, and a solid rounded border on 2-bit and 4-bit. It paints from the semantic border channel, so dark mode and themes recolor it. See Outline Outline Pixel-perfect dotted rounded borders drawn with CSS gradients on 1-bit displays The Outline utility draws a pixel-perfect dotted rounded border on any element. On 1-bit displays it places single-pixel dots at exact integer coordinates with pure CSS gradients; on 2-bit and 4-bit displays it falls back to a standard CSS border with border-radius. .
- Text Stroke: renders as concentric drop-shadow rings instead of native
-webkit-text-stroke, so the stroke sits behind the glyph in every browser and survives background-clipped pattern fills. Sizes runtext-stroke--smalltotext-stroke--xlarge; colors resolve through the theme chain. See Text Stroke Text Stroke Legible text when displayed on shaded backgrounds Outline text so it stays legible on a shaded background. Set the stroke width and color with the text stroke utilities. . - Image Stroke: outlines transparent images with the same size and color variants, now resolved through the theme and semantic layers so themed and dark-mode screens recolor them. See Image Stroke Image Stroke Legible images when displayed on shaded backgrounds Outline a vector or transparent raster image so it stays legible on a shaded background. Set the stroke width and color with the image stroke utilities. .
Mashup Backdrop
The screen--backdrop modifier now paints through the semantic backdrop slot. Themes restyle mashup backdrops, and dark mode gets its own backdrop treatment. See
Mashup
Mashup
Assemble multiple plugin views into a single interface
A Mashup arranges multiple plugin views within a single screen. A fixed mashup modifier (e.g. mashup--1Lx1R, mashup--2x2) positions the views, while each view's own modifier sets how much space it occupies. Fluid Mashups use the mashup--3x3 layout and cell placement modifiers for custom tilings.
.
Fluid Mashups
Fluid Mashups sit alongside the fixed layouts: the mashup--3x3 layout uses mashup-cell placement modifiers for custom three by three tilings, with no inline grid styles. Every cell draws the window frame and a compact title bar at any size, across bit depths, dark mode, and themes. See
Mashup
Mashup
Assemble multiple plugin views into a single interface
A Mashup arranges multiple plugin views within a single screen. A fixed mashup modifier (e.g. mashup--1Lx1R, mashup--2x2) positions the views, while each view's own modifier sets how much space it occupies. Fluid Mashups use the mashup--3x3 layout and cell placement modifiers for custom tilings.
.
Complete Scale Modifiers
Scale modifiers now compose with each device's native UI density and resize framework gaps, pixel-based utilities, image presets, component geometry, radii, and strokes. The new screen--scale-xxsmall level adds a 66% scale for dense dynamic mashups, and TRMNLPaint.px() converts JavaScript dimensions from the same live CSS contract. See
Scale
Scale
Scale interface to affect content density and readability
Scale the whole interface from one screen modifier by changing the UI scale factor. Use it to match content density to viewing distance or user preference.
.
Under the Hood
- Smaller stylesheets: utility gate selectors and responsive variants are refactored onto
:is()screen scopes, reducing the CSS footprint.
Start Here
- Upgrading an existing plugin? → V3.2 Upgrade Guide V3.2 Upgrade Guide Compatibility notes for upgrading plugins to Framework 3.2 Framework 3.2 is fully backward compatible with 3.0 and 3.1. Existing class names render unchanged, and every 3.2 feature (themes, the paint API, adaptive charts, adaptive icons) is opt-in. This guide lists the few things worth reviewing when you upgrade. .
- Want to adopt themes, adaptive charts, and adaptive icons? → V3.2 Enhancement Guide V3.2 Enhancement Guide Make your plugin theme-ready and adopt adaptive charts, icons, and JS paint Framework 3.2 lets an existing plugin follow themes, dark mode, and device modes everywhere: in markup, in charts, in icons, and in text and image outlines. This guide walks through each enhancement you can adopt (theme readiness, adaptive charts, adaptive icons, JS paint, the border step rail, and legible overlaid text and images), one at a time and in any order. .
- New to the framework? Start with Colors Colors Complete palette definition: grayscale, chromatic hues, and semantic roles The Colors system defines the complete palette for the framework: grayscale, chromatic hues, and semantic roles (primary, success, error, warning). Use these tokens with bg--, text--, and other utilities. See Background and Text Color for usage examples. and Themes Themes Opt-in stylesheets that re-theme screens while preserving device-capability rendering Themes are standalone stylesheets that re-point semantic channels, component slots, and utility tokens at different palette tokens. A themed screen still renders through its device mode: dither patterns on 1-bit, palette images on limited color, solids on full color. .