replica(telefon): architecture, tokens (20 pairs AA), components
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
// Generated from tokens.json by gen_theme.py. Do not edit by hand.
|
||||
package app.telefon.ui.theme
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
|
||||
object WColor {
|
||||
val bg = Color(0xFFF6F7FB)
|
||||
val card = Color(0xFFFFFFFF)
|
||||
val text = Color(0xFF191C20)
|
||||
val textMuted = Color(0xFF44474E)
|
||||
val missed = Color(0xFFBA1A1A)
|
||||
val chipOn = Color(0xFFD3E3FD)
|
||||
val onChipOn = Color(0xFF041E49)
|
||||
val accept = Color(0xFF1E6B38)
|
||||
val onAccept = Color(0xFFFFFFFF)
|
||||
val hangup = Color(0xFFC5221F)
|
||||
val onHangup = Color(0xFFFFFFFF)
|
||||
val toggle = Color(0xFFFFFFFF)
|
||||
val onToggle = Color(0xFF191C20)
|
||||
val toggleOn = Color(0xFFD3E3FD)
|
||||
val onToggleOn = Color(0xFF041E49)
|
||||
val slideTrack = Color(0xFFE2E5EC)
|
||||
val onSlideTrack = Color(0xFF191C20)
|
||||
val darkBg = Color(0xFF111318)
|
||||
val darkCard = Color(0xFF1D2024)
|
||||
val darkText = Color(0xFFE2E2E9)
|
||||
val darkTextMuted = Color(0xFFC4C6D0)
|
||||
val darkMissed = Color(0xFFFFB4AB)
|
||||
val darkChipOn = Color(0xFF2F4A72)
|
||||
val darkOnChipOn = Color(0xFFD6E3FF)
|
||||
val darkAccept = Color(0xFF6FDC8C)
|
||||
val darkOnAccept = Color(0xFF00391A)
|
||||
val darkHangup = Color(0xFFF2645A)
|
||||
val darkOnHangup = Color(0xFF410002)
|
||||
val darkToggle = Color(0xFF2B2F36)
|
||||
val darkOnToggle = Color(0xFFE2E2E9)
|
||||
val darkToggleOn = Color(0xFFA8C7FA)
|
||||
val darkOnToggleOn = Color(0xFF062E6F)
|
||||
val darkSlideTrack = Color(0xFF2B2F36)
|
||||
val darkOnSlideTrack = Color(0xFFE2E2E9)
|
||||
}
|
||||
|
||||
object WType {
|
||||
val label = TextStyle(fontSize = 12.sp, lineHeight = 16.sp, fontWeight = FontWeight.W500)
|
||||
val bodySm = TextStyle(fontSize = 14.sp, lineHeight = 20.sp, fontWeight = FontWeight.W400)
|
||||
val body = TextStyle(fontSize = 16.sp, lineHeight = 24.sp, fontWeight = FontWeight.W400)
|
||||
val title = TextStyle(fontSize = 22.sp, lineHeight = 28.sp, fontWeight = FontWeight.W400)
|
||||
val caller = TextStyle(fontSize = 40.sp, lineHeight = 48.sp, fontWeight = FontWeight.W400)
|
||||
val dial = TextStyle(fontSize = 36.sp, lineHeight = 44.sp, fontWeight = FontWeight.W400)
|
||||
val key = TextStyle(fontSize = 30.sp, lineHeight = 36.sp, fontWeight = FontWeight.W400)
|
||||
}
|
||||
|
||||
object WSpace {
|
||||
val s0 = 0.dp
|
||||
val s4 = 4.dp
|
||||
val s8 = 8.dp
|
||||
val s12 = 12.dp
|
||||
val s16 = 16.dp
|
||||
val s24 = 24.dp
|
||||
val s32 = 32.dp
|
||||
}
|
||||
|
||||
object WRadius {
|
||||
val cardOuter = 24.dp
|
||||
val cardInner = 4.dp
|
||||
val pill = 999.dp
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
# Komponenten: Telefon
|
||||
|
||||
Avatars: photo from contacts, else initial on a colour derived from the name (stable), unknown number = person icon. On call screens the avatar is a large scalloped cookie (12 waves).
|
||||
CallLogGroup: rows inside one card per day, outer radius 24, inner 4, 2dp gaps (same kit as the settings tiles). Row: avatar 40, name (or formatted number), line 2 = direction icon + label/type + time, missed in error colour, trailing call icon button.
|
||||
SlideToAnswer: track pill, labels "Ablehnen" left / "Annehmen" right, thumb with phone icon; past 50 % acts; custom accessibility actions.
|
||||
InCallControls: 4 round toggles 64dp with label below (Wähltasten, Stumm, Lautsprecher, Mehr), red hang-up pill 160×64 below; "Mehr" sheet: Halten, Anruf hinzufügen.
|
||||
Keypad: 3×4 keys (digit 30sp + letters 11sp), green round call FAB 72dp, backspace.
|
||||
```
|
||||
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env python3
|
||||
"""tokens.json -> Tokens.kt (Compose). Re-run after every token change."""
|
||||
import json, re, sys, pathlib
|
||||
src = pathlib.Path(sys.argv[1] if len(sys.argv) > 1 else "tokens.json")
|
||||
out = pathlib.Path(sys.argv[2] if len(sys.argv) > 2 else src.with_name("Tokens.kt"))
|
||||
t = json.loads(src.read_text())
|
||||
camel = lambda s: re.sub(r"-(\w)", lambda m: m.group(1).upper(), s)
|
||||
L = ["// Generated from tokens.json by gen_theme.py. Do not edit by hand.",
|
||||
"package app.telefon.ui.theme", "",
|
||||
"import androidx.compose.ui.graphics.Color",
|
||||
"import androidx.compose.ui.text.TextStyle",
|
||||
"import androidx.compose.ui.text.font.FontWeight",
|
||||
"import androidx.compose.ui.unit.dp",
|
||||
"import androidx.compose.ui.unit.sp", "",
|
||||
"object WColor {"]
|
||||
L += [f" val {camel(k)} = Color(0xFF{v.lstrip('#').upper()})" for k, v in t["color"].items()]
|
||||
L += ["}", "", "object WType {"]
|
||||
for k, v in t["type"].items():
|
||||
L.append(f" val {camel(k)} = TextStyle(fontSize = {v['size']}.sp, lineHeight = {v['line']}.sp, fontWeight = FontWeight.W{v['weight']})")
|
||||
L += ["}", "", "object WSpace {"]
|
||||
L += [f" val s{v} = {v}.dp" for v in t["space"]]
|
||||
L += ["}", "", "object WRadius {"]
|
||||
L += [f" val {camel(k)} = {v}.dp" for k, v in t["radius"].items()]
|
||||
L += ["}", ""]
|
||||
out.write_text("\n".join(L))
|
||||
print("wrote", out)
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"_about": "Telefon tokens from replica/telefon/screens/ref-01..03. Fallback palette; dynamic colour on Android 12+. Check with contrast.py.",
|
||||
"color": {
|
||||
"bg": "#f6f7fb", "card": "#ffffff", "text": "#191c20", "text-muted": "#44474e", "missed": "#ba1a1a",
|
||||
"chip-on": "#d3e3fd", "on-chip-on": "#041e49", "accept": "#1e6b38", "on-accept": "#ffffff",
|
||||
"hangup": "#c5221f", "on-hangup": "#ffffff", "toggle": "#ffffff", "on-toggle": "#191c20", "toggle-on": "#d3e3fd", "on-toggle-on": "#041e49",
|
||||
"slide-track": "#e2e5ec", "on-slide-track": "#191c20",
|
||||
"dark-bg": "#111318", "dark-card": "#1d2024", "dark-text": "#e2e2e9", "dark-text-muted": "#c4c6d0", "dark-missed": "#ffb4ab",
|
||||
"dark-chip-on": "#2f4a72", "dark-on-chip-on": "#d6e3ff", "dark-accept": "#6fdc8c", "dark-on-accept": "#00391a",
|
||||
"dark-hangup": "#f2645a", "dark-on-hangup": "#410002", "dark-toggle": "#2b2f36", "dark-on-toggle": "#e2e2e9", "dark-toggle-on": "#a8c7fa", "dark-on-toggle-on": "#062e6f",
|
||||
"dark-slide-track": "#2b2f36", "dark-on-slide-track": "#e2e2e9"
|
||||
},
|
||||
"pairs": [
|
||||
["text","bg"],["text","card"],["text-muted","card"],["missed","card"],["on-chip-on","chip-on"],["on-accept","accept"],["on-hangup","hangup"],
|
||||
["on-toggle","toggle"],["on-toggle-on","toggle-on"],["on-slide-track","slide-track"],
|
||||
["dark-text","dark-bg"],["dark-text","dark-card"],["dark-text-muted","dark-card"],["dark-missed","dark-card"],["dark-on-chip-on","dark-chip-on"],
|
||||
["dark-on-accept","dark-accept"],["dark-on-hangup","dark-hangup"],["dark-on-toggle","dark-toggle"],["dark-on-toggle-on","dark-toggle-on"],["dark-on-slide-track","dark-slide-track"]
|
||||
],
|
||||
"type": {
|
||||
"label": {"size": 12, "line": 16, "weight": 500}, "body-sm": {"size": 14, "line": 20, "weight": 400}, "body": {"size": 16, "line": 24, "weight": 400},
|
||||
"title": {"size": 22, "line": 28, "weight": 400}, "caller": {"size": 40, "line": 48, "weight": 400}, "dial": {"size": 36, "line": 44, "weight": 400}, "key": {"size": 30, "line": 36, "weight": 400}
|
||||
},
|
||||
"space": [0, 4, 8, 12, 16, 24, 32],
|
||||
"radius": {"card-outer": 24, "card-inner": 4, "pill": 999},
|
||||
"layout": {"avatar-row": 56, "avatar-call": 200}
|
||||
}
|
||||
Reference in New Issue
Block a user