// Material 3 theme for colour displays // // Tokens are layered: // 1. Base tokens: raw values without meaning (tones, scales) // 2. Semantic tokens: Material 3 roles (colors, shapes, density, states) // 3. Widget tokens: per widget, built from semantic tokens // Styles only use widget tokens, or semantic tokens for shared state styles. @theme material; @config { isDark: bool = false; isCompact: bool = false; animationsEnabled: bool = true; colorPrimary: color = #00bbff; colorSecondary: color = #ee81c3; colorError: color = #EF6C00; // Replaces the surface (screen background) colour surfaceOverride: bool = false; colorSurface: color = #000000; fontSmall: font = raw("LV_FONT_DEFAULT"); fontNormal: font = raw("LV_FONT_DEFAULT"); fontLarge: font = raw("LV_FONT_DEFAULT"); } // Tactility widgets @widget toolbar: lvgl_toolbar_class; @widget icon_button: lvgl_icon_button_class; @widget icon_button_filled: lvgl_icon_button_filled_class; @widget icon_button_tonal: lvgl_icon_button_tonal_class; @widget sliderbox: lvgl_sliderbox_class; @widget card: lvgl_card_class; @widget chip: lvgl_chip_class; @widget badge: lvgl_badge_class; @widget page_indicator: lvgl_page_indicator_class; @widget page_indicator_dot: lvgl_page_indicator_dot_class; @widget flex_list: lvgl_list_class; @widget flex_list_text: lvgl_list_text_class; @widget flex_list_button: lvgl_list_button_class; // ============================================================ // 1. Base tokens // ============================================================ // Neutral tones (greys by Material 3 tone) @neutral-4: #0E0E0E; @neutral-6: #131313; @neutral-10: #1C1C1C; @neutral-12: #1F1F1F; @neutral-17: #2B2B2B; @neutral-20: #303030; @neutral-22: #343434; @neutral-30: #474747; @neutral-50: #777777; @neutral-60: #919191; @neutral-80: #C6C6C6; @neutral-90: #E2E2E2; @neutral-92: #E8E8E8; @neutral-94: #EEEEEE; @neutral-95: #F0F0F0; @neutral-96: #F3F3F3; @neutral-98: #FAFAFA; @neutral-100: #FFFFFF; // How much of the primary color tints the neutral tones @tint-neutral: 4%; @tint-neutral-variant: 8%; // Shape scale @corner-none: 0; @corner-extra-small: 4dp; @corner-small: 8dp; @corner-medium: 12dp; @corner-large: 16dp; @corner-extra-large: 28dp; @corner-full: circle; @corner-compact: 3; // Spacing scale (4dp grid) @space-1: 4dp; @space-2: 8dp; @space-3: 12dp; @space-4: 16dp; @space-6: 24dp; // Opacity scale @opacity-state-hover: 8%; @opacity-state-focus: 10%; @opacity-state-pressed: 10%; @opacity-disabled-content: 38%; @opacity-disabled-container: 12%; @opacity-scrim: 32%; // Motion @duration-short: 100; @duration-medium: 250; @duration-long: 500; // ============================================================ // 2. Semantic tokens // ============================================================ // Tonal roles derived from a seed color @color-primary: if($isDark, mix($colorPrimary, white, 55%), $colorPrimary); @color-on-primary: if($isDark, mix($colorPrimary, black, 50%), white); @color-primary-container: if($isDark, mix($colorPrimary, black, 70%), mix($colorPrimary, white, 25%)); @color-on-primary-container: if($isDark, mix($colorPrimary, white, 20%), mix($colorPrimary, black, 60%)); @color-secondary: if($isDark, mix($colorSecondary, white, 55%), $colorSecondary); @color-on-secondary: if($isDark, mix($colorSecondary, black, 50%), white); @color-secondary-container: if($isDark, mix($colorSecondary, black, 70%), mix($colorSecondary, white, 25%)); @color-on-secondary-container: if($isDark, mix($colorSecondary, white, 20%), mix($colorSecondary, black, 60%)); @color-error: if($isDark, mix($colorError, white, 55%), $colorError); @color-on-error: if($isDark, mix($colorError, black, 50%), white); // Surfaces: neutral tones tinted with the primary color. // In dark mode, they're derived from the screen background colour (the low container tone, which apps and the window use). @dark-background: #21222b; @color-surface: if($surfaceOverride, $colorSurface, if($isDark, mix(#000000, @dark-background, 20%), mix($colorPrimary, @neutral-98, @tint-neutral))); @color-on-surface: mix($colorPrimary, if($isDark, @neutral-90, @neutral-10), @tint-neutral); @color-on-surface-variant: mix($colorPrimary, if($isDark, @neutral-80, @neutral-30), @tint-neutral-variant); // With a surface override, the containers are the surface lifted towards the text colour, in the same steps as the neutral tones @surface-lift: if($isDark, #FFFFFF, #000000); @surface-sink: if($isDark, #000000, #FFFFFF); @color-surface-container-lowest: if($surfaceOverride, mix(@surface-sink, $colorSurface, 25%), if($isDark, mix(#000000, @dark-background, 35%), mix($colorPrimary, @neutral-100, @tint-neutral))); @color-surface-container-low: if($surfaceOverride, mix(@surface-lift, $colorSurface, if($isDark, 4%, 2%)), if($isDark, @dark-background, mix($colorPrimary, @neutral-96, @tint-neutral))); @color-surface-container: if($surfaceOverride, mix(@surface-lift, $colorSurface, if($isDark, 6%, 4%)), if($isDark, mix(#FFFFFF, @dark-background, 3%), mix($colorPrimary, @neutral-94, @tint-neutral))); @color-surface-container-high: if($surfaceOverride, mix(@surface-lift, $colorSurface, if($isDark, 11%, 6%)), if($isDark, mix(#FFFFFF, @dark-background, 8%), mix($colorPrimary, @neutral-92, @tint-neutral))); @color-surface-container-highest: if($surfaceOverride, mix(@surface-lift, $colorSurface, if($isDark, 16%, 8%)), if($isDark, mix(#FFFFFF, @dark-background, 13%), mix($colorPrimary, @neutral-90, @tint-neutral))); @color-outline: mix($colorPrimary, if($isDark, @neutral-60, @neutral-50), @tint-neutral-variant); @color-outline-variant: mix($colorPrimary, if($isDark, @neutral-30, @neutral-80), @tint-neutral-variant); @color-inverse-surface: mix($colorPrimary, if($isDark, @neutral-90, @neutral-20), @tint-neutral); @color-inverse-on-surface: mix($colorPrimary, if($isDark, @neutral-20, @neutral-95), @tint-neutral); @color-scrim: black; // Shapes @shape-control: if($isCompact, @corner-compact, @corner-full); @shape-container: if($isCompact, @corner-compact, @corner-medium); @shape-field: if($isCompact, @corner-compact, @corner-extra-small); @shape-key: if($isCompact, @corner-compact, @corner-small); @shape-dialog: if($isCompact, @corner-compact, @corner-extra-large); @shape-menu: if($isCompact, @corner-compact, @corner-extra-small); // Density @density-container-pad: if($isCompact, 2, @space-4); @density-container-gap: if($isCompact, 2, @space-3); @density-container-border: if($isCompact, 1, 0); @density-control-pad-hor: if($isCompact, 3, @space-6); @density-control-pad-ver: if($isCompact, 3, 10dp); @density-control-gap: if($isCompact, 2, @space-2); @density-field-pad-hor: if($isCompact, 2, @space-4); @density-field-pad-ver: if($isCompact, 2, @space-2); @density-list-pad: if($isCompact, 2, @space-2); @density-list-item-pad-hor: if($isCompact, 2, @space-4); @density-list-item-pad-ver: if($isCompact, 2, @space-3); @density-dialog-pad: if($isCompact, 2, @space-6); @density-key-gap: if($isCompact, 2, @space-1); @density-border: 1dp; // Focus indicator @focus-color: @color-secondary; @focus-width: if($isCompact, 1, 3dp); @focus-offset: if($isCompact, 1, 2dp); // Drawn inside the widget, for widgets with little room around them (icon buttons) @focus-inset-width: if($isCompact, 1, 2dp); @edit-color: @color-primary; // State layers: the state color blended over the container color @state-pressed-on-primary: mix(@color-on-primary, @color-primary, @opacity-state-pressed); @state-pressed-on-secondary: mix(@color-on-secondary, @color-secondary, @opacity-state-pressed); @state-layer-color: @color-on-surface; // Motion @motion-duration-short: if($animationsEnabled, @duration-short, 0); @motion-duration-medium: if($animationsEnabled, @duration-medium, 0); @motion-duration-long: if($animationsEnabled, @duration-long, 0); // ============================================================ // 3. Widget tokens // ============================================================ // Screen @screen-color: @color-surface; @screen-text-color: @color-on-surface; @screen-gap: @density-container-gap; // Container (lv_obj): Material 3 filled card @container-color: @color-surface-container-low; @container-text-color: @color-on-surface; @container-border-color: @color-outline-variant; @container-border-width: @density-container-border; @container-shape: @shape-container; @container-pad: @density-container-pad; @container-gap: @density-container-gap; // Card (lvgl_card_create): a container one tone above the background, so it stands out @card-color: @color-surface-container-high; @card-text-color: @color-on-surface; @card-border-color: @color-outline-variant; @card-border-width: @density-container-border; @card-shape: @shape-container; @card-pad: @density-container-pad; @card-gap: @density-container-gap; // Chip (lvgl_chip_create): Material 3 filter chip, selected when checked @chip-label-color: @color-on-surface-variant; @chip-border-color: @color-outline; @chip-selected-color: @color-secondary-container; @chip-selected-label-color: @color-on-secondary-container; @chip-shape: if($isCompact, @corner-compact, @corner-small); @chip-pad-hor: if($isCompact, 3, @space-4); @chip-pad-ver: if($isCompact, 2, 6dp); // Page indicator (lvgl_page_indicator_create): a dot per page, the current page's dot is filled @page-indicator-color: @color-on-surface-variant; @page-indicator-dot-size: if($isCompact, 6, 8dp); @page-indicator-gap: if($isCompact, 4, 6dp); // Badge (lvgl_badge_create): a small dot that marks an item, e.g. a favourite @badge-color: @color-secondary; @badge-size: if($isCompact, 4, 6dp); // Scrollbar @scrollbar-color: @color-outline; @scrollbar-opacity: 40%; @scrollbar-scrolled-opacity: 70%; @scrollbar-width: if($isCompact, 2, @space-1); @scrollbar-pad: if($isCompact, 1, @space-1); // Button: Material 3 filled button @button-container-color: @color-primary; @button-label-color: @color-on-primary; @button-pressed-container-color: @state-pressed-on-primary; @button-checked-container-color: @color-secondary; @button-checked-label-color: @color-on-secondary; @button-checked-pressed-container-color: @state-pressed-on-secondary; @button-disabled-container-color: @color-on-surface; @button-disabled-container-opacity: @opacity-disabled-container; @button-disabled-label-color: @color-on-surface; @button-disabled-label-opacity: @opacity-disabled-content; @button-shape: @shape-control; @button-pad-hor: @density-control-pad-hor; @button-pad-ver: @density-control-pad-ver; @button-gap: @density-control-gap; // Text button (dialog actions, menu header buttons) @text-button-label-color: @color-primary; @text-button-pressed-container-color: @color-primary; @text-button-pad-hor: if($isCompact, 3, @space-3); // Icon button (dialog and window header buttons) @icon-button-color: @color-on-surface; // Filled and tonal icon buttons: Material 3 large icon buttons with a container @icon-button-container-shape: if($isCompact, @corner-compact, @corner-large); @icon-button-filled-color: @color-primary; @icon-button-filled-icon-color: @color-on-primary; @icon-button-filled-pressed-color: @state-pressed-on-primary; @icon-button-tonal-color: @color-secondary-container; @icon-button-tonal-icon-color: @color-on-secondary-container; @icon-button-tonal-pressed-color: mix(@color-on-secondary-container, @color-secondary-container, @opacity-state-pressed); // Toolbar: Material 3 top app bar, in the same colour as the app content and the statusbar (which shows the window's container colour) @app-bar-color: @color-surface-container-low; @app-bar-content-color: @color-on-surface; @app-bar-pressed-opacity: 20%; @app-bar-pad-hor: if($isCompact, 0, @space-1); @app-bar-gap: if($isCompact, 2, @space-1); // The focus ring is drawn inside toolbar buttons, as there's little room around them @app-bar-focus-width: @focus-inset-width; // Focus ring @focus-ring-color: @focus-color; @focus-ring-width: @focus-width; @focus-ring-offset: @focus-offset; @edit-ring-color: @edit-color; // Switch @switch-width: if($isCompact, 25, 52dp); @switch-height: if($isCompact, 15, 32dp); @switch-track-color: @color-surface-container-highest; @switch-track-border-color: @color-outline; @switch-track-border-width: if($isCompact, 1, 2dp); @switch-track-selected-color: @color-primary; @switch-handle-color: @color-outline; @switch-handle-selected-color: @color-on-primary; @switch-handle-pad: if($isCompact, -3, -8dp); @switch-handle-selected-pad: if($isCompact, -2, -4dp); @switch-handle-pressed-pad: if($isCompact, -1, -2dp); // Checkbox @checkbox-gap: if($isCompact, 3, @space-3); @checkbox-box-color: @color-surface; @checkbox-box-opacity: transp; @checkbox-box-border-color: @color-on-surface-variant; @checkbox-box-border-width: if($isCompact, 1, 2dp); @checkbox-box-shape: if($isCompact, 2, 2dp); @checkbox-box-pad: if($isCompact, 1, 2dp); @checkbox-box-selected-color: @color-primary; @checkbox-icon-color: @color-on-primary; // Slider, bar (linear progress) @slider-track-color: @color-secondary-container; @slider-active-track-color: @color-primary; @slider-handle-color: @color-primary; // The track is half of LVGL's default thickness (LV_DPI_DEF / 10). The knob is the track height plus its padding on both // sides, so the padding includes the removed thickness to keep the knob's size. @slider-track-height: 8dp; @slider-handle-pad: if($isCompact, 2, 6dp) + 4dp; // Sliderbox: in the normal layout, the gap between the slider and its buttons leaves room for the knob, which sticks out at the slider's ends @sliderbox-gap: if($isCompact, 4, (@slider-track-height / 2) + @slider-handle-pad + @space-2); @progress-track-color: @color-secondary-container; @progress-indicator-color: @color-primary; // Arc, spinner (circular progress) @arc-track-color: @color-secondary-container; @arc-indicator-color: @color-primary; @arc-width: if($isCompact, 3, @space-1); @arc-handle-color: @color-primary; @arc-handle-pad: if($isCompact, 2, @space-1); // Text field: Material 3 outlined text field (textarea, spinbox, dropdown) @field-color: @color-surface; @field-opacity: transp; @field-text-color: @color-on-surface; @field-border-color: @color-outline; @field-border-width: @density-border; @field-focused-border-color: @color-primary; @field-focused-border-width: if($isCompact, 1, 2dp); @field-shape: @shape-field; @field-pad-hor: @density-field-pad-hor; @field-pad-ver: @density-field-pad-ver; @field-placeholder-color: @color-on-surface-variant; @field-cursor-color: @color-primary; @field-cursor-width: if($isCompact, 1, 2dp); @field-selection-color: @color-primary-container; @field-selection-text-color: @color-on-primary-container; @spinbox-cursor-color: @color-primary; @spinbox-cursor-text-color: @color-on-primary; // Menu: Material 3 menu (dropdown list) @menu-color: @color-surface-container; @menu-text-color: @color-on-surface; @menu-shape: @shape-menu; @menu-pad: if($isCompact, 1, @space-2); @menu-max-height: dpi-def * 2; @menu-item-selected-color: @color-secondary-container; @menu-item-selected-text-color: @color-on-secondary-container; @menu-item-line-space: if($isCompact, 4, @space-4); // Roller @roller-color: @color-surface-container; @roller-text-color: @color-on-surface-variant; @roller-selected-color: @color-secondary-container; @roller-selected-text-color: @color-on-secondary-container; @roller-line-space: if($isCompact, 4, @space-4); // Button matrix and keyboard: keys are tonal buttons @keys-color: @color-surface-container; @keys-pad: @density-key-gap; @keys-gap: @density-key-gap; @key-color: @color-surface-container-highest; @key-text-color: @color-on-surface; @key-shape: @shape-key; @key-checked-color: @color-secondary-container; @key-checked-text-color: @color-on-secondary-container; @key-selected-color: @color-primary; @key-selected-text-color: @color-on-primary; // List @list-color: @color-surface; @list-pad: @density-list-pad; @list-item-color: @color-surface; @list-item-opacity: transp; @list-item-text-color: @color-on-surface; @list-item-pad-hor: @density-list-item-pad-hor; @list-item-pad-ver: @density-list-item-pad-ver; @list-item-gap: if($isCompact, 3, @space-4); @list-item-focused-color: @color-secondary-container; @list-item-focused-text-color: @color-on-secondary-container; @list-divider-color: @color-outline-variant; @list-divider-width: @density-border; @list-subheader-text-color: @color-on-surface-variant; // Tabs: the tab bar is a Material 3 navigation bar with a pill-shaped active indicator @tabs-color: @card-color; @tabs-pad: if($isCompact, 2, @space-1); @tabs-gap: if($isCompact, 2, @space-1); @tab-label-color: @color-on-surface-variant; @tab-pad: if($isCompact, 2, @space-1); @tab-shape: @shape-control; @tab-selected-color: @color-secondary-container; @tab-selected-label-color: @color-on-secondary-container; @tab-page-pad: @density-container-pad; // Dialog (message box) @dialog-color: @color-surface-container-high; @dialog-text-color: @color-on-surface-variant; @dialog-title-color: @color-on-surface; @dialog-shape: @shape-dialog; @dialog-pad: @density-dialog-pad; @dialog-gap: if($isCompact, 2, @space-2); @dialog-scrim-color: @color-scrim; @dialog-scrim-opacity: @opacity-scrim; // Settings menu (lv_menu) @settings-color: @color-surface; @settings-section-color: @color-surface-container-low; @settings-section-shape: @shape-container; @settings-item-pad-hor: @density-list-item-pad-hor; @settings-item-pad-ver: @density-list-item-pad-ver; @settings-item-gap: @density-container-gap; @settings-divider-color: @color-outline-variant; @settings-item-selected-color: @color-secondary-container; @settings-item-selected-text-color: @color-on-secondary-container; // Window @window-header-color: @color-surface-container; @window-header-pad: if($isCompact, 2, @space-2); @window-content-pad: @density-container-pad; // Table @table-color: @color-surface; @table-cell-text-color: @color-on-surface; @table-cell-pad: if($isCompact, 2, @space-3); @table-divider-color: @color-outline-variant; // Chart @chart-color: @color-surface-container-low; @chart-grid-color: @color-outline-variant; @chart-series-width: if($isCompact, 1, 2dp); @chart-point-size: if($isCompact, 3, 6dp); @chart-indicator-color: @color-primary; // Calendar @calendar-color: @color-surface-container-high; @calendar-shape: if($isCompact, @corner-compact, @corner-large); @calendar-pad: if($isCompact, 2, @space-2); @calendar-day-text-color: @color-on-surface; @calendar-header-pad: if($isCompact, 2, @space-3); // Scale @scale-color: @color-on-surface-variant; @scale-width: @density-border; @scale-tick-length: if($isCompact, 3, 6dp); // Divider (lv_line) @divider-color: @color-outline-variant; @divider-width: @density-border; // LED @led-glow-width: if($isCompact, 4, 15dp); @led-glow-spread: if($isCompact, 1, 5dp); // ============================================================ // Transitions // ============================================================ @transition state-enter { props: bgColor, bgOpa, borderColor, textColor, outlineWidth, outlineOpa; path: ease-out; duration: @motion-duration-short; delay: 0; } @transition state-exit { props: bgColor, bgOpa, borderColor, textColor, outlineWidth, outlineOpa; path: ease-out; duration: @motion-duration-short; delay: 70; } // ============================================================ // Styles: shared states // ============================================================ transition_enter { @if ($animationsEnabled) { transition: state-enter; } } transition_exit { @if ($animationsEnabled) { transition: state-exit; } } focus_ring { outlineColor: @focus-ring-color; outlineWidth: @focus-ring-width; outlinePad: @focus-ring-offset; outlineOpa: cover; } edit_ring { outlineColor: @edit-ring-color; outlineWidth: @focus-ring-width; outlinePad: @focus-ring-offset; outlineOpa: cover; } focus_ring_inset { outlineColor: @focus-ring-color; outlineWidth: @focus-inset-width; outlinePad: -@focus-inset-width; outlineOpa: cover; } edit_ring_inset { outlineColor: @edit-ring-color; outlineWidth: @focus-inset-width; outlinePad: -@focus-inset-width; outlineOpa: cover; } // State layer for transparent containers state_pressed { bgColor: @state-layer-color; bgOpa: @opacity-state-pressed; } disabled { opa: @opacity-disabled-content; } scrollbar { bgColor: @scrollbar-color; bgOpa: @scrollbar-opacity; radius: circle; width: @scrollbar-width; padAll: @scrollbar-pad; } scrollbar_scrolled { bgOpa: @scrollbar-scrolled-opacity; } // Page-like widgets show the shared app background instead of painting their own page { bgOpa: transp; borderWidth: 0; radius: 0; padAll: 0; padGap: 0; } // ============================================================ // Styles: widgets // ============================================================ screen { bgColor: @screen-color; bgOpa: cover; textColor: @screen-text-color; textFont: $fontNormal; padRow: @screen-gap; padColumn: @screen-gap; rotarySensitivity: dpi / 4 * 256; } container { bgColor: @container-color; bgOpa: cover; textColor: @container-text-color; borderColor: @container-border-color; borderWidth: @container-border-width; borderPost: true; radius: @container-shape; padAll: @container-pad; padGap: @container-gap; lineColor: @divider-color; lineWidth: @divider-width; } card { bgColor: @card-color; bgOpa: cover; textColor: @card-text-color; borderColor: @card-border-color; borderWidth: @card-border-width; radius: @card-shape; padAll: @card-pad; padGap: @card-gap; } page_indicator { bgOpa: transp; borderWidth: 0; padAll: 0; padGap: @page-indicator-gap; } page_indicator_label { textColor: @page-indicator-color; } page_indicator_dot { width: @page-indicator-dot-size; height: @page-indicator-dot-size; radius: circle; bgColor: @page-indicator-color; bgOpa: transp; borderColor: @page-indicator-color; borderWidth: 1; } page_indicator_dot_current { bgOpa: cover; } badge { width: @badge-size; height: @badge-size; radius: circle; bgColor: @badge-color; bgOpa: cover; } chip { bgOpa: transp; textColor: @chip-label-color; borderColor: @chip-border-color; borderWidth: @density-border; radius: @chip-shape; padHor: @chip-pad-hor; padVer: @chip-pad-ver; // Room for the focus ring, which the parent would clip marginAll: @focus-width + @focus-offset; } chip_selected { bgColor: @chip-selected-color; bgOpa: cover; textColor: @chip-selected-label-color; borderColor: @chip-selected-color; } button { bgColor: @button-container-color; bgOpa: cover; textColor: @button-label-color; radius: @button-shape; padHor: @button-pad-hor; padVer: @button-pad-ver; padGap: @button-gap; // Room for the focus ring, which the parent would clip marginAll: @focus-width + @focus-offset; } button_pressed { bgColor: @button-pressed-container-color; } button_checked { bgColor: @button-checked-container-color; textColor: @button-checked-label-color; } button_checked_pressed { bgColor: @button-checked-pressed-container-color; } button_disabled { bgColor: @button-disabled-container-color; bgOpa: @button-disabled-container-opacity; textColor: @button-disabled-label-color; textOpa: @button-disabled-label-opacity; } text_button { bgOpa: transp; textColor: @text-button-label-color; radius: @button-shape; padHor: @text-button-pad-hor; padVer: @button-pad-ver; padGap: @button-gap; } text_button_pressed { bgColor: @text-button-pressed-container-color; bgOpa: @opacity-state-pressed; } icon_button { bgOpa: transp; textColor: @icon-button-color; radius: @button-shape; padAll: @button-pad-ver; } icon_button_filled { bgColor: @icon-button-filled-color; bgOpa: cover; textColor: @icon-button-filled-icon-color; radius: @icon-button-container-shape; padAll: @button-pad-ver; } icon_button_filled_pressed { bgColor: @icon-button-filled-pressed-color; } icon_button_tonal { bgColor: @icon-button-tonal-color; bgOpa: cover; textColor: @icon-button-tonal-icon-color; radius: @icon-button-container-shape; padAll: @button-pad-ver; } icon_button_tonal_pressed { bgColor: @icon-button-tonal-pressed-color; } app_bar { bgColor: @app-bar-color; bgOpa: cover; textColor: @app-bar-content-color; radius: 0; borderWidth: 0; padHor: @app-bar-pad-hor; padVer: 0; padGap: @app-bar-gap; } app_bar_button { padAll: 0; textColor: @app-bar-content-color; } app_bar_button_pressed { bgColor: @app-bar-content-color; bgOpa: @app-bar-pressed-opacity; } app_bar_focus_ring { outlineColor: @focus-ring-color; outlineWidth: @app-bar-focus-width; outlinePad: -@app-bar-focus-width; outlineOpa: cover; } app_bar_field { textColor: @app-bar-content-color; borderColor: @app-bar-content-color; } switch_track { width: @switch-width; height: @switch-height; // Room for the focus ring, which the parent would clip marginAll: @focus-width + @focus-offset; bgColor: @switch-track-color; bgOpa: cover; borderColor: @switch-track-border-color; borderWidth: @switch-track-border-width; radius: circle; animDuration: @motion-duration-short; } switch_track_selected { borderColor: @switch-track-selected-color; } switch_indicator_selected { bgColor: @switch-track-selected-color; bgOpa: cover; radius: circle; } switch_handle { bgColor: @switch-handle-color; bgOpa: cover; radius: circle; padAll: @switch-handle-pad; } switch_handle_selected { bgColor: @switch-handle-selected-color; padAll: @switch-handle-selected-pad; } switch_handle_pressed { padAll: @switch-handle-pressed-pad; } checkbox { padGap: @checkbox-gap; textColor: @color-on-surface; } checkbox_box { bgColor: @checkbox-box-color; bgOpa: @checkbox-box-opacity; borderColor: @checkbox-box-border-color; borderWidth: @checkbox-box-border-width; radius: @checkbox-box-shape; padAll: @checkbox-box-pad; textFont: $fontSmall; textColor: @checkbox-icon-color; } checkbox_box_selected { bgColor: @checkbox-box-selected-color; bgOpa: cover; borderColor: @checkbox-box-selected-color; bgImageSrc: symbol(ok); } sliderbox { padColumn: @sliderbox-gap; // Room for the focus ring of the step buttons, which the sliderbox would clip padAll: @focus-width + @focus-offset; } slider_track_size { height: @slider-track-height; } // The knob extends beyond the slider by its padding, so the slider reserves that room above and below it in layouts. // Not left and right: flex grow (e.g. in the sliderbox) doesn't take a growing item's own margins into account. slider_knob_room { marginVer: @slider-handle-pad; } slider_track { bgColor: @slider-track-color; bgOpa: cover; radius: circle; } slider_active_track { bgColor: @slider-active-track-color; bgOpa: cover; radius: circle; } slider_handle { bgColor: @slider-handle-color; bgOpa: cover; radius: circle; padAll: @slider-handle-pad; } progress_track { bgColor: @progress-track-color; bgOpa: cover; radius: circle; } progress_indicator { bgColor: @progress-indicator-color; bgOpa: cover; radius: circle; } arc_track { arcColor: @arc-track-color; arcWidth: @arc-width; arcRounded: true; } arc_indicator { arcColor: @arc-indicator-color; arcWidth: @arc-width; arcRounded: true; } arc_handle { bgColor: @arc-handle-color; bgOpa: cover; radius: circle; padAll: @arc-handle-pad; } field { bgColor: @field-color; bgOpa: @field-opacity; textColor: @field-text-color; borderColor: @field-border-color; borderWidth: @field-border-width; radius: @field-shape; padHor: @field-pad-hor; padVer: @field-pad-ver; padGap: @field-pad-ver; } field_focused { borderColor: @field-focused-border-color; borderWidth: @field-focused-border-width; } field_placeholder { textColor: @field-placeholder-color; } field_cursor { borderColor: @field-cursor-color; borderWidth: @field-cursor-width; borderSide: left; padLeft: -1; animDuration: @motion-duration-long; } field_selection { bgColor: @field-selection-color; textColor: @field-selection-text-color; } spinbox_cursor { bgColor: @spinbox-cursor-color; bgOpa: cover; textColor: @spinbox-cursor-text-color; } menu { bgColor: @menu-color; bgOpa: cover; textColor: @menu-text-color; radius: @menu-shape; padAll: @menu-pad; textLineSpace: @menu-item-line-space; maxHeight: @menu-max-height; clipCorner: true; } menu_item { bgOpa: transp; } menu_item_selected { bgColor: @menu-item-selected-color; bgOpa: cover; textColor: @menu-item-selected-text-color; } roller { bgColor: @roller-color; bgOpa: cover; textColor: @roller-text-color; radius: @shape-container; textLineSpace: @roller-line-space; textAlign: center; animDuration: @motion-duration-medium; } roller_selected { bgColor: @roller-selected-color; bgOpa: cover; textColor: @roller-selected-text-color; } keys { bgColor: @keys-color; bgOpa: cover; radius: @shape-container; padAll: @keys-pad; padGap: @keys-gap; } key { bgColor: @key-color; bgOpa: cover; textColor: @key-text-color; radius: @key-shape; } key_pressed { bgColor: mix(@state-layer-color, @key-color, @opacity-state-pressed); } key_checked { bgColor: @key-checked-color; textColor: @key-checked-text-color; } key_selected { bgColor: @key-selected-color; textColor: @key-selected-text-color; } list { bgColor: @list-color; bgOpa: cover; padHor: 0; padVer: @list-pad; padGap: 0; clipCorner: true; } list_item { bgColor: @list-item-color; bgOpa: @list-item-opacity; textColor: @list-item-text-color; padHor: @list-item-pad-hor; padVer: @list-item-pad-ver; padColumn: @list-item-gap; borderColor: @list-divider-color; borderWidth: @list-divider-width; borderSide: bottom; } list_item_focused { bgColor: @list-item-focused-color; bgOpa: cover; textColor: @list-item-focused-text-color; } list_subheader { textColor: @list-subheader-text-color; textFont: $fontSmall; padHor: @list-item-pad-hor; padTop: @list-item-pad-ver; padBottom: @list-pad; } tabs { bgColor: @tabs-color; bgOpa: cover; borderWidth: 0; radius: @card-shape; padAll: @tabs-pad; padGap: @tabs-gap; } tab { bgOpa: transp; textColor: @tab-label-color; radius: @tab-shape; padAll: @tab-pad; } tab_selected { bgColor: @tab-selected-color; bgOpa: cover; textColor: @tab-selected-label-color; } tab_page { padAll: @tab-page-pad; } dialog { bgColor: @dialog-color; bgOpa: cover; textColor: @dialog-text-color; radius: @dialog-shape; padAll: 0; padGap: 0; clipCorner: true; } dialog_header { padHor: @dialog-pad; padTop: @dialog-pad; padBottom: @dialog-gap; padGap: @dialog-gap; } dialog_title { textColor: @dialog-title-color; textFont: $fontLarge; } dialog_content { padHor: @dialog-pad; padVer: @dialog-gap; } dialog_actions { padAll: @dialog-pad; padTop: @dialog-gap; padGap: @dialog-gap; } dialog_scrim { bgColor: @dialog-scrim-color; bgOpa: @dialog-scrim-opacity; } settings { bgColor: @settings-color; bgOpa: cover; padAll: 0; padGap: 0; radius: 0; clipCorner: true; } settings_sidebar { padAll: 0; padGap: 0; borderColor: @settings-divider-color; borderWidth: @density-border; borderSide: right; } settings_content { padAll: 0; padGap: 0; } settings_page { padHor: 0; padGap: 0; } settings_header { padHor: @settings-item-pad-hor; padVer: @density-list-pad; padGap: @settings-item-gap; } settings_section { bgColor: @settings-section-color; bgOpa: cover; radius: @settings-section-shape; clipCorner: true; } settings_item { padHor: @settings-item-pad-hor; padVer: @settings-item-pad-ver; padGap: @settings-item-gap; } settings_item_selected { bgColor: @settings-item-selected-color; bgOpa: cover; textColor: @settings-item-selected-text-color; } settings_separator { bgOpa: transp; padVer: @density-list-pad; } window_header { bgColor: @window-header-color; bgOpa: cover; padAll: @window-header-pad; padGap: @window-header-pad; } window_title { textFont: $fontLarge; } window_content { bgOpa: transp; padAll: @window-content-pad; padGap: @density-container-gap; } table { bgColor: @table-color; bgOpa: cover; padAll: 0; radius: 0; borderColor: @table-divider-color; borderWidth: @density-border; } table_cell { bgOpa: transp; textColor: @table-cell-text-color; padAll: @table-cell-pad; borderColor: @table-divider-color; borderWidth: @density-border; borderSide: bottom; } chart { bgColor: @chart-color; bgOpa: cover; radius: @shape-container; padAll: @density-container-pad; lineColor: @chart-grid-color; borderPost: false; } chart_series { lineWidth: @chart-series-width; size: @chart-point-size, @chart-point-size; radius: @chart-point-size; } chart_indicator { bgColor: @chart-indicator-color; bgOpa: cover; radius: circle; size: @chart-point-size, @chart-point-size; } calendar { bgColor: @calendar-color; bgOpa: cover; radius: @calendar-shape; padAll: @calendar-pad; padGap: @calendar-pad; } calendar_days { bgOpa: transp; padAll: 0; padGap: @density-key-gap; } calendar_day { bgOpa: transp; textColor: @calendar-day-text-color; radius: circle; } calendar_header { padAll: @calendar-header-pad; padGap: @calendar-header-pad; } scale { lineColor: @scale-color; lineWidth: @scale-width; arcColor: @scale-color; arcWidth: @scale-width; textColor: @scale-color; length: @scale-tick-length; } divider { lineColor: @divider-color; lineWidth: @divider-width; } led { bgColor: white; bgOpa: cover; bgGradColor: palette(grey); radius: circle; shadowWidth: @led-glow-width; shadowColor: white; shadowSpread: @led-glow-spread; } // ============================================================ // Apply rules // ============================================================ apply(null > *) { screen: default; scrollbar: part.scrollbar; scrollbar_scrolled: part.scrollbar, state.scrolled; } // Base object apply(tabview > obj[1]) { // Tab content area: no styles } apply(tabview > obj[0]) { tabs: default; } apply(tabview > * > obj) { tab_page: default; scrollbar: part.scrollbar; scrollbar_scrolled: part.scrollbar, state.scrolled; } apply(win > obj[0]) { window_header: default; } apply(win > obj[1]) { window_content: default; scrollbar: part.scrollbar; scrollbar_scrolled: part.scrollbar, state.scrolled; } apply(calendar > obj) { // No styles } apply(obj) { container: default; scrollbar: part.scrollbar; scrollbar_scrolled: part.scrollbar, state.scrolled; } // Buttons apply(tabview > *[0] > button) { tab: default; transition_exit: default; state_pressed: state.pressed; transition_enter: state.pressed; tab_selected: state.checked; focus_ring: state.focusKey; edit_ring: state.edited; } apply(menu_sidebar_header_cont > button, menu_main_header_cont > button, win > obj[0] > button) { icon_button: default; transition_exit: default; state_pressed: state.pressed; transition_enter: state.pressed; focus_ring: state.focusKey; disabled: state.disabled; } apply(button) { button: default; transition_exit: default; button_pressed: state.pressed; transition_enter: state.pressed; button_checked: state.checked; button_checked_pressed: state.checked, state.pressed; focus_ring: state.focusKey; edit_ring: state.edited; button_disabled: state.disabled; } apply(toolbar > icon_button) { icon_button: default; app_bar_button: default; transition_exit: default; app_bar_button_pressed: state.pressed; transition_enter: state.pressed; app_bar_focus_ring: state.focusKey; app_bar_focus_ring: state.edited; disabled: state.disabled; } apply(toolbar > dropdown) { @include dropdown; app_bar_field: default; app_bar_focus_ring: state.focusKey; } apply(toolbar) { app_bar: default; } apply(icon_button) { icon_button: default; transition_exit: default; state_pressed: state.pressed; transition_enter: state.pressed; focus_ring_inset: state.focusKey; edit_ring_inset: state.edited; disabled: state.disabled; } apply(icon_button_filled) { icon_button_filled: default; transition_exit: default; icon_button_filled_pressed: state.pressed; transition_enter: state.pressed; focus_ring: state.focusKey; edit_ring: state.edited; button_disabled: state.disabled; } apply(icon_button_tonal) { icon_button_tonal: default; transition_exit: default; icon_button_tonal_pressed: state.pressed; transition_enter: state.pressed; focus_ring: state.focusKey; edit_ring: state.edited; button_disabled: state.disabled; } apply(msgbox_header_button) { icon_button: default; transition_exit: default; state_pressed: state.pressed; transition_enter: state.pressed; focus_ring: state.focusKey; disabled: state.disabled; } apply(msgbox_footer_button) { text_button: default; transition_exit: default; text_button_pressed: state.pressed; transition_enter: state.pressed; focus_ring: state.focusKey; disabled: state.disabled; } // Labels apply(msgbox_header > label) { dialog_title: default; } apply(win > obj[0] > label) { window_title: default; } apply(textarea > label) { field_selection: part.selected; } // Selection controls apply(switch) { switch_track: default; switch_track_selected: state.checked; switch_indicator_selected: part.indicator, state.checked; switch_handle: part.knob; switch_handle_selected: part.knob, state.checked; switch_handle_pressed: part.knob, state.pressed; focus_ring: state.focusKey; edit_ring: state.edited; disabled: state.disabled; } apply(checkbox) { checkbox: default; focus_ring: state.focusKey; checkbox_box: part.indicator; checkbox_box_selected: part.indicator, state.checked; transition_exit: part.indicator; transition_enter: part.indicator, state.pressed; disabled: state.disabled; } apply(page_indicator) { page_indicator: default; } apply(page_indicator > label) { page_indicator_label: default; } // Labels can be selectable, e.g. rows that keys move through apply(label) { focus_ring: state.focusKey; } apply(page_indicator_dot) { page_indicator_dot: default; page_indicator_dot_current: state.checked; } apply(badge) { badge: default; } // Focusable images, e.g. the statusbar icons apply(image) { focus_ring_inset: state.focusKey; } apply(chip) { chip: default; transition_exit: default; state_pressed: state.pressed; transition_enter: state.pressed; chip_selected: state.checked; focus_ring: state.focusKey; edit_ring: state.edited; disabled: state.disabled; } apply(card) { card: default; scrollbar: part.scrollbar; } apply(sliderbox) { sliderbox: default; } apply(slider) { slider_track: default; slider_track_size: default; slider_knob_room: default; focus_ring: state.focusKey; edit_ring: state.edited; slider_active_track: part.indicator; slider_handle: part.knob; disabled: state.disabled; } apply(bar) { slider_track_size: default; progress_track: default; progress_indicator: part.indicator; focus_ring: state.focusKey; } apply(arc) { arc_track: default; arc_indicator: part.indicator; arc_handle: part.knob; focus_ring: state.focusKey; edit_ring: state.edited; } apply(spinner) { arc_track: default; arc_indicator: part.indicator; } // Text input apply(textarea) { field: default; field_focused: state.focused; focus_ring: state.focusKey; edit_ring: state.edited; disabled: state.disabled; scrollbar: part.scrollbar; scrollbar_scrolled: part.scrollbar, state.scrolled; field_cursor: part.cursor, state.focused; field_placeholder: part.textareaPlaceholder; } apply(spinbox) { field: default; field_focused: state.focused; focus_ring: state.focusKey; edit_ring: state.edited; spinbox_cursor: part.cursor; } apply(dropdown) { field: default; transition_exit: default; state_pressed: state.pressed; transition_enter: state.pressed; focus_ring: state.focusKey; edit_ring: state.edited; disabled: state.disabled; } apply(dropdownlist) { menu: default; scrollbar: part.scrollbar; scrollbar_scrolled: part.scrollbar, state.scrolled; menu_item: part.selected; menu_item_selected: part.selected, state.checked; state_pressed: part.selected, state.pressed; } apply(roller) { roller: default; roller_selected: part.selected; focus_ring: state.focusKey; edit_ring: state.edited; } // Button matrix and keyboard apply(calendar > buttonmatrix) { calendar_days: default; calendar_day: part.items; state_pressed: part.items, state.pressed; key_selected: part.items, state.checked; focus_ring: part.items, state.focusKey; edit_ring: part.items, state.edited; disabled: part.items, state.disabled; } apply(buttonmatrix) { keys: default; focus_ring: state.focusKey; edit_ring: state.edited; key: part.items; key_pressed: part.items, state.pressed; key_selected: part.items, state.checked; focus_ring: part.items, state.focusKey; disabled: part.items, state.disabled; } apply(keyboard) { keys: default; focus_ring: state.focusKey; edit_ring: state.edited; key: part.items; key_pressed: part.items, state.pressed; key_checked: part.items, state.checked; key_selected: part.items, state.focusKey; disabled: part.items, state.disabled; } // Lists apply(list) { list: default; scrollbar: part.scrollbar; scrollbar_scrolled: part.scrollbar, state.scrolled; } apply(list_text) { list_subheader: default; } apply(list_button) { list_item: default; transition_exit: default; state_pressed: state.pressed; transition_enter: state.pressed; list_item_focused: state.focusKey; disabled: state.disabled; } apply(flex_list) { list: default; scrollbar: part.scrollbar; scrollbar_scrolled: part.scrollbar, state.scrolled; } apply(flex_list_text) { list_subheader: default; } apply(flex_list_button) { list_item: default; transition_exit: default; state_pressed: state.pressed; transition_enter: state.pressed; list_item_focused: state.focusKey; disabled: state.disabled; } apply(table) { table: default; focus_ring: state.focusKey; edit_ring: state.edited; scrollbar: part.scrollbar; scrollbar_scrolled: part.scrollbar, state.scrolled; table_cell: part.items; state_pressed: part.items, state.pressed; list_item_focused: part.items, state.focusKey; } // Settings menu apply(menu) { settings: default; } apply(menu_sidebar_cont) { settings_sidebar: default; scrollbar: part.scrollbar; scrollbar_scrolled: part.scrollbar, state.scrolled; } apply(menu_main_cont) { settings_content: default; scrollbar: part.scrollbar; scrollbar_scrolled: part.scrollbar, state.scrolled; } apply(menu_page) { settings_page: default; scrollbar: part.scrollbar; scrollbar_scrolled: part.scrollbar, state.scrolled; } apply(menu_sidebar_header_cont, menu_main_header_cont) { settings_header: default; } apply(menu_section) { settings_section: default; } apply(menu_cont) { settings_item: default; state_pressed: state.pressed; settings_item_selected: state.checked; settings_item_selected: state.focusKey; } apply(menu_separator) { settings_separator: default; } // Dialog apply(msgbox) { dialog: default; } apply(msgbox_backdrop) { dialog_scrim: default; } apply(msgbox_header) { dialog_header: default; } apply(msgbox_content) { dialog_content: default; scrollbar: part.scrollbar; scrollbar_scrolled: part.scrollbar, state.scrolled; } apply(msgbox_footer) { dialog_actions: default; } // Containers apply(tabview, win) { page: default; } apply(tileview) { page: default; scrollbar: part.scrollbar; scrollbar_scrolled: part.scrollbar, state.scrolled; } apply(tileview_tile) { scrollbar: part.scrollbar; scrollbar_scrolled: part.scrollbar, state.scrolled; } // Data display apply(chart) { chart: default; scrollbar: part.scrollbar; scrollbar_scrolled: part.scrollbar, state.scrolled; chart_series: part.items; chart_indicator: part.indicator; chart_series: part.cursor; } apply(calendar) { calendar: default; } apply(calendar_header_arrow, calendar_header_dropdown) { calendar_header: default; } apply(scale) { scale: part.main; scale: part.indicator; scale: part.items; } apply(line) { divider: default; } apply(led) { led: default; }