libLuna Dokumentacja
PL EN
GitHub

Wygląd jako dane

Motywy i tokeny

W libLunie wygląd nie jest rozsiany po widgetach. Jest w Theme: palecie, odstępach, promieniach, typografii i metrykach kontrolek. Zmiana motywu to podmiana danych — nie przepisywanie komponentów.

Trzy warstwy wyglądu

Wariant

ThemePreference: System, Light lub Dark. Wybiera bazową paletę.

Akcent

Accent: 9 kolorów. Podmienia colors.accent i accent_fg.

Metryki

Metrics: wysokości, paddingi i rozmiary per widget. Geometria też jest tokenem.

Theme w kodzie

rust · budowa motywu
use libluna::prelude::*;

// Dwa gotowe warianty
let light = Theme::light();
let dark = Theme::dark();

// Ten sam motyw z innym akcentem
let purple = Theme::light().accented(
    Accent::Purple.color(),
    Accent::Purple.foreground(),
);

// Preferencja użytkownika + stan systemu → konkretny motyw
let theme = ThemePreference::System.resolve(true, Accent::Teal);
Pole ThemeTypCo zawiera
colorsColorSchemePaleta jasna lub ciemna.
spacingSpacingSkala odstępów 3/6/12/18/24.
radiusRadiusPromienie 6/9/12/pill.
typographyTypographyStyle: title, heading, body, caption.
metricsMetricsGeometria 32 grup widgetów.
appearanceAppearanceLight / Dark.

Paleta

Nazwy tokenów są wspólne dla obu wariantów; różnią się wartości. Poniżej paleta jasna:

window_bg #fafafa
view_bg #ffffff
card_bg #ffffff
headerbar_bg #f2f2f2
sidebar_bg #ebebeb
text #2e2e2e
accent #3584e4
error #c01c28
warning #e5a50a
success #2ec27e

W ciemnym motywie window_bg to #242424, card_bg #303030, a text #ffffff. Wartości pochodzą z ColorScheme::dark().

Kolory akcentu — spróbuj tutaj

Kliknięcie zmienia akcent tej strony (i zapisuje wybór w localStorage). W aplikacji robi to Frame::set_accent(...). Ten sam akcent trafia do Theme::accented.

rust · akcent z aplikacji
for accent in Accent::ALL {
    println!("{} → {:?}", accent.name(), accent.color());
}

frame.set_accent(Accent::Purple);
frame.set_preference(ThemePreference::Dark);

Odstępy, promienie, typografia

Spacing

  • xs — 3 px
  • sm — 6 px
  • md — 12 px
  • lg — 18 px
  • xl — 24 px

Radius

  • small — 6 px
  • medium — 9 px
  • large — 12 px
  • pill — 999 px

Typography

  • title — 20 px / 700 / 26
  • heading — 15 px / 700 / 20
  • body — 14 px / 400 / 20
  • caption — 12 px / 400 / 16

FontStyle

  • size — rozmiar w px logicznych
  • weight — 400 / 500 / 700
  • line_height — wysokość wiersza
  • monospace — czcionka stałej szerokości
rust · tokeny w rysowaniu
let pad = theme.spacing.md;
let radius = theme.radius.large;
let title = theme.typography.title;

scene.fill_rounded_rect(rect, radius, theme.colors.card_bg);
scene.text(
    TextRun::new(Point::new(rect.x() + pad, rect.y() + pad + title.size),
                 "Tytuł", title.size)
        .with_weight(title.weight)
        .with_color(theme.colors.text),
);

Metryki kontrolek

Widgety nie mają zaszytych wysokości. Czytają je z theme.metrics, więc styl może zmienić np. wysokość paska tytułu albo rozmiar przełącznika. Przykładowe wartości standardowe:

GrupaKluczStandard
headerbarheight / control38 / 30 px
buttonheight / pad_x34 / 14 px
switchwidth / height44 / 24 px
slidertrack_height / knob_r6 / 9 px
entryheight / pad_x34 / 12 px
tabsheight / min_width34 / 120 px
itemviewtile_w / tile_h100 / 76 px
toastheight / margin_bottom40 / 40 px
stack (metryki kontenerów)container.gap8 px

Pełna lista 32 grup jest w indeksie API i w rustdoc.

Style z plików .theme

Wygląd można też zainstalować jak w GNOME/KDE. Format jest liniowy, z kropkowymi kluczami; nieznane klucze są ignorowane (zgodność w przód).

theme · nord.theme
__name__ = Nord
appearance = dark
accent = teal

colors.card_bg = #3b4252
colors.text = #eceff4
colors.window_bg = #2e3440
colors.sidebar_bg = #2e3440

radius.small = 5
radius.large = 10
metrics.button.height = 36
metrics.headerbar.height = 48
metrics.switch.width = 48
KatalogPriorytet
~/.config/luna/themesnajwyższy
~/.local/share/luna/themesśredni
/usr/share/luna/themessystemowy
LUNA_THEMES_DIRdodatkowe katalogi (dev/testy)
rust · ThemePatch
use libluna::core::{available_themes, ThemePatch};

for style in available_themes() {
    println!("{} ({})", style.name, style.id);
}

let patch = ThemePatch::from_file(path)?;
let theme = patch.build(Theme::light());

// albo na istniejącym motywie
let mut theme = Theme::dark();
patch.apply(&mut theme);

Styl steruje nie tylko kolorami, ale i geometrią: metrics.* zmienia rozmiary kontrolek, a spacing.* i radius.* — odstępy i zaokrąglenia.

Zmiana motywu z aplikacji

Frame trzyma bieżące ThemeSettings i zapisuje zmiany od razu. Po zmianie następna klatka dostaje już nowy theme.

rust · przełącznik motywu
if clicked_light {
    frame.set_preference(ThemePreference::Light);
}
if clicked_dark {
    frame.set_preference(ThemePreference::Dark);
}
if clicked_auto {
    frame.set_preference(ThemePreference::System);
}

if clicked_purple {
    frame.set_accent(Accent::Purple);
}
if clicked_custom_style {
    frame.set_style(Some("nord".into()));
}

Ustawienia trafiają do ~/.config/luna/theme.conf. W trybie System ciemność pochodzi z LUNA_SYSTEM_DARK (docelowo portal D-Bus).