Skip to content

Themes and styling

Global theme

from apkpy_lib import Theme

app_theme = Theme(
    mode="dark",
    primary="#8B5CF6",
    secondary="#22D3EE",
    background="#09090B",
    surface="#18181B",
    text="#FAFAFA",
    text_secondary="#A1A1AA",
    border="#3F3F46",
    error="#FCA5A5",
    success="#4ADE80",
    radius=16,
    spacing=14,
    font_family="sans-serif",
)

Pass the theme to run():

run(start_screen=home, theme=app_theme)

The theme styles screens, text, buttons, inputs, containers, cards, lists, navigation, player surfaces and Android system bars.

Design tokens

Reference normalized theme values from CSS:

body {
    background-color: var(--background);
    color: var(--text);
}

panel {
    background-color: var(--surface);
    border-color: var(--border);
    border-radius: var(--radius);
    padding: var(--spacing);
}

danger_action {
    background-color: var(--error);
}

Available tokens:

primary, secondary, background, surface, text, text_secondary, on_primary, error, success, border, radius, spacing and font-family.

Cascade

Styles resolve in this order:

Theme defaults → component selector → component ID
button {
    border-radius: 12px;
}

save_button {
    background-color: var(--secondary);
}

The ID rule changes the background of save_button without losing the shared button radius.

Useful properties

Area Properties
Colour color, background-color, border-color, pressed-color
Type font-size, font-weight, font-family, text-align
Shape border-width, border-radius, box-shadow
Space padding, margin, gap
Size width, height, min-width, max-width
Layout display, flex/grid properties, positioning and z-index

Responsive style rules

Use media rules when only style values change across widths:

content {
    padding: 18px;
}

@media (min-width: 600px) {
    content {
        padding: 32px;
        max-width: 900px;
    }
}

Use responsive() when the component arrangement itself must change.

Animations

@keyframes appear {
    from { opacity: 0; scale: 0.96; }
    to   { opacity: 1; scale: 1; }
}

hero_card {
    animation: appear 320ms ease-out;
}

Keep motion brief and functional. Confirm the result in both the Previewer and Android build.