1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
(ns frq.theme
"COSMIC's design tokens, as Flutter values.
The colours, radii and spacing are the user's own, read out of cosmic-config
by tools/cosmic2cljd.py into `frq.theme.cosmic` — so the phone is painted in
whatever accent and surfaces COSMIC Settings is set to, rather than in a
guess at what COSMIC looks like. `just theme` moves them.
What is not in cosmic-config is the typography scale: libcosmic carries
title1..title4, heading, body and caption as code rather than as
configuration. Those numbers are here, and the mapping from glimmer's tags
to them is `crates/jolt-cosmic`'s — `:title` is title3, `:title-2` is title4,
`:label` is body, `:dim-label` is caption."
(:require ["package:flutter/material.dart" :as m]
[frq.theme.cosmic :as c]))
;; ------------------------------------------------------------------ scale
(def space-xxxs c/space-xxxs)
(def space-xxs c/space-xxs)
(def space-xs c/space-xs)
(def space-s c/space-s)
(def space-m c/space-m)
(def radius-xs c/radius-xs)
(def radius-s c/radius-s)
(def radius-m c/radius-m)
;; libcosmic's typography, which is code rather than config.
(def text-title-3 24.0) ; :title
(def text-title-4 20.0) ; :title-2
(def text-body 14.0) ; :label
(def text-caption 12.0) ; :dim-label, :status, :spinner
;; ---------------------------------------------------------------- palette
(def accent c/accent)
(def on-accent c/on-accent)
(def bg c/bg)
(def on-bg c/on-bg)
(def component c/component)
(def component-hover c/component-hover)
(def card c/card)
(def card-component c/card-component)
(def on-card c/on-card)
(def destructive c/destructive)
(def on-destructive c/on-destructive)
(def success c/success)
(def divider c/divider)
(def dim
"`:dim-label` is libcosmic's caption class, which is the body colour stepped
back rather than a colour of its own."
(.withValues ^m/Color on-bg .alpha 0.7))
(defn emoji-style
"A `TextStyle` for a run that is nothing but emoji.
The app sets `fontFamily` on the theme, so every `Text` that says nothing
about its font is set in Fira Sans — a UI font with no emoji in it, and the
screens draw a picture where it has no glyph. Naming the platform's emoji
font here is what keeps `:emoji` and `:reaction` off that font: Noto Color
Emoji is the Android one and the one COSMIC ships, and the fallbacks are the
other two desktops in case this runs on one."
[size]
(m/TextStyle .fontSize size
.fontFamily "Noto Color Emoji"
.fontFamilyFallback ["Apple Color Emoji"
"Segoe UI Emoji"
"Noto Emoji"]))
(def brightness (if c/dark? m/Brightness.dark m/Brightness.light))
(defn app-theme []
(m/ThemeData
.useMaterial3 true
.brightness brightness
.scaffoldBackgroundColor bg
.canvasColor bg
.colorScheme (m/ColorScheme.fromSeed
.seedColor accent
.brightness brightness
.surface bg
.primary accent
.onPrimary on-accent)
;; COSMIC's own UI font. Absent on Android, where the fallback is Roboto —
;; a difference the tokens cannot fix and the only one that shows.
.fontFamily "Fira Sans"))
|