The tuile theme system resolves a small base palette into semantic colour roles for every surface, text, border and chrome element. Every role on Theme is a plain Rgb value you can read directly; most are derived by CIE-Lab lightness transformations or auto-contrast blending.
Set directly by ThemeSpec:
Role Field Derived from Used for
Primary colour primaryThemeSpec.primaryBorders, buttons, accents (Primary variant)
Secondary colour secondaryThemeSpec.secondary or primarySecondary variant buttons, links
Warning colour warningThemeSpec.warning or primaryWarning variant elements
Error colour errorThemeSpec.error or secondaryError variant elements
Success colour successThemeSpec.success or secondarySuccess variant elements
Accent colour accentThemeSpec.accent or primaryAccent variant highlights
Background backgroundThemeSpec.background or #121212 (dark) / #efefef (light)Page background
Foreground foregroundThemeSpec.foreground or background.inverse()Maximum contrast text reference
Role Field Derived from Used for
Surface surfaceThemeSpec.surface or #1e1e1e (dark) / #f5f5f5 (light)Default widget background
Panel panelsurface.blend(primary, 0.1) + 4% contrast tint (dark)Containers, panels, cards
Boost boostsurface.blend(foreground, 0.04)Nested containers (Textual $boost)
All text roles are derived for readability over the background. The auto N% notation means background.text_on(N), which blends the best-contrast text (white or black) at the given alpha.
Role Field Derived from Used for
Default text textbackground.text_on(0.87)Primary body text (auto 87%)
Muted text text_mutedbackground.text_on(0.60)Secondary labels, help text (auto 60%)
Disabled text text_disabledbackground.text_on(0.38)Disabled controls (auto 38%)
Primary text text_primaryforeground.blend(primary, 0.66)Tinted text for Primary variant
Secondary text text_secondaryforeground.blend(secondary, 0.66)Tinted text for Secondary variant
Accent text text_accentforeground.blend(accent, 0.66)Tinted text for Accent variant
Success text text_successforeground.blend(success, 0.66)Tinted text for Success variant
Warning text text_warningforeground.blend(warning, 0.66)Tinted text for Warning variant
Error text text_errorforeground.blend(error, 0.66)Tinted text for Error variant
Role Field Derived from Used for
Border (focused) borderprimaryFocused widget borders
Border (blurred) border_blurredsurface.darken(0.025)Unfocused borders (CIE-Lab −2.5% L*)
Cursor background cursor_bgprimaryText cursor fill colour
Cursor foreground cursor_fgprimary.text_on(0.9)Text under cursor (auto 90% on cursor_bg)
Cursor blurred cursor_blurred_bgsurface.blend(primary, 0.3)Unfocused cursor (30% primary over surface)
Role Field Derived from Used for
Hover background hover_bgsurface.blend(foreground, 0.08)Button/item hover state
Selection background selection_bgsurface.blend(primary, 0.5)Selected text, list items
Link colour linksecondary.blend(foreground, 0.2)Hyperlinks
Role Field Derived from Used for
Scrollbar thumb scrollbarbackground.darken(0.15).blend(primary, 0.4)Scrollbar handle (40% primary on darkened bg)
Scrollbar hover scrollbar_hoverbackground.darken(0.15).blend(primary, 0.6)Hovered scrollbar thumb (60% primary)
Scrollbar track scrollbar_bgbackground.darken(0.15)Scrollbar track (CIE-Lab −15% L*)
Role Field Derived from Used for
Toast background toast_bgpanel.lighten(0.15)Toast/notification background (CIE-Lab +15% L*)
Footer background footer_bgpanelKeyFooter background
Footer key footer_keyaccentKeyFooter key binding colour
Footer description footer_descpanel.text_on(0.87)KeyFooter description text (auto 87% on panel)
Markdown code background markdown_code_bgsurface.blend(foreground, 0.06)Inline code blocks in Markdown
pub fn shade(c: Rgb, n: i32) -> Rgb
Textual’s $color-lighten-N / $color-darken-N: shifts CIE-Lab L* by 15% per step. Positive n lightens, negative darkens. Matches Textual’s lightness transformations (e.g. shade(primary, 1) = +15% L*, shade(primary, -2) = −30% L*).
pub fn text_on(self, alpha: f32) -> Rgb
Textual’s auto N%: blends the best-contrast text (white or black, chosen by self.contrast_text()) over this colour at the given alpha (0.0 = transparent, 1.0 = fully opaque). Use this to generate readable text over any background: bg.text_on(0.87) gives primary readable text, bg.text_on(0.60) gives muted secondary text.
What you are drawing Role to use
Text over the page background text, text_muted or text_disabled
Text over a widget surface or panel surface.text_on(0.87) or panel.text_on(0.87)
Text inside a coloured button or badge variant_colour.text_on(0.9)
Text tinted to carry meaning text_primary, text_success, text_error and the rest of that set
A border border when focused, border_blurred when not
A hover state blend hover_bg over the widget surface
A lighter or darker step of any colour Theme::shade(colour, steps), which matches Textual’s 15% L* step, rather than raw lighten()