Skip to content

feat: add Dewfall's theme built from the design tokens - #140

Merged
j0ker70 merged 5 commits into
mainfrom
feat/theme
Oct 20, 2026
Merged

j0ker70 merged 5 commits into
mainfrom
feat/theme

Conversation

@j0ker70

@j0ker70 j0ker70 commented Oct 20, 2026

Copy link
Copy Markdown
Contributor

Closes #26.

What changed and why

This builds Dewfall's Material 3 theme in :core:designsystem from the design system's tokens, and switches the app to it.

The theme (core/designsystem/src/main/kotlin/io/github/dewfallapp/core/designsystem/theme/):

  • DewfallTheme is the entry point. On Android 12 and later it takes the colors from the wallpaper, as the design brief asks. Older phones get Dewfall's own light and dark palettes. There's no setting to turn dynamic color off, because the brief has none. The dynamicColor parameter is there for previews.
  • The light and dark color schemes have all 48 roles from tokens.json, the fixed roles included. Then the type scale in Manrope, the shape scale, and DewfallSpacing. The values are copied from the export's tokens.json and compose-theme.md, and docs/design/ is unchanged.
  • The palettes, type scale and shapes are internal, so screens reach them only through MaterialTheme. Material 3 is an api dependency of the module.
  • The opacity tokens aren't in code. Material 3 already uses the same state layer and disabled opacities, and its modal bottom sheet puts scrim behind itself at 32%. Compose dialogs dim through Android's dialog window instead, so the first dialog needs a check against the design system's 32%.

Manrope. Version 4.505 of the variable font Manrope[wght].ttf, from googlefonts/manrope at commit 468c0db, is res/font/manrope.ttf (164,700 bytes). Its SIL Open Font License 1.1 text, which starts with the copyright notice, ships in the APK as assets/licenses/Manrope-OFL.txt. No screen shows it yet. #139 tracks that, and stays open.

One change from the plan: Compose's Font(R.font.manrope, weight) sets the weight axis only after the font loads. On the API 29 and API 36 emulators that had no effect, and every style drew at the file's default weight, 200 (ExtraLight). So each weight loads through a font XML, such as manrope_regular.xml, whose android:fontVariationSettings sets the axis while the font loads. The family has 400, 500 and 600 for the type scale, plus 700 and 800 for Android's Bold text setting, as you decided.

The app. DewfallApp uses DewfallTheme instead of Material 3's default color schemes. Nothing else in :app changed.

Tests. DesignTokensTest compares every color, text style, shape and spacing value with tokens.json, and fails when a token group gains or loses a token. ManropeTest checks that each Manrope font loads one of the font XMLs, and that each XML sets the weight it declares. tokens.json and the font folder are test inputs, so the build cache never hides a change.

Docs. A new "The theme" section and a fonts paragraph under Network access in docs/architecture.md, one line in docs/testing.md, and a sentence about the font's license in the README. The license rule now says that bundled fonts may use the SIL Open Font License 1.1 and must ship with their copyright notice and license text. The sentence is in AGENTS.md, CONTRIBUTING.md, openspec/config.yaml and ADR 0003, with a note in the ADR. The roadmap has two new tasks: matching the launch window to Dewfall's colors in Phase 4 (#138), and an open-source licenses section in settings in Phase 9 (#139). Both issues are on the board and stay open.

Checks run locally:

  • The all-checks command passes. :core:designsystem:testDebugUnitTest runs 6 tests with 0 failures.
  • DesignTokensTest failed on a deliberately wrong color, and ran again and failed after a temporary token edit. ManropeTest failed when one weight went back to R.font.manrope, and when one XML had the wrong weight. All of these were reverted.
  • On the API 29 emulator, the placeholder's background is exactly Dewfall's surface: #F5FBF2 in light and #101411 in dark. On the API 36 emulator it's dynamic color: #FAF8FF in light and #121318 in dark. The type scale shows 400, 500 and 600 on both. With Bold text on, on API 36, body text draws at 700 and titles at 800.
  • :app's debug and release runtime classpaths are unchanged.
  • The debug APK grows by 171,042 bytes. The font is 67,807 bytes compressed, the license 2,051 and the five font XMLs about 1.3 KB. The rest is the theme's code, unshrunk in a debug build.

New dependencies

No new Gradle plugins. Licenses are taken from each POM, and from the font's OFL.txt.

Artifact Version License Ships in the app
Manrope font, res/font/manrope.ttf 4.505 SIL Open Font License 1.1 Yes, with its license text
org.jetbrains.kotlinx:kotlinx-serialization-json (-jvm) 1.11.0 Apache 2.0 No, tests only
org.jetbrains.kotlinx:kotlinx-serialization-core (-jvm) 1.11.0 Apache 2.0 No, tests only
org.jetbrains.kotlinx:kotlinx-serialization-bom 1.11.0 Apache 2.0 No, tests only
androidx.compose.material3:material3 and the other Compose BOM libraries, now also in :core:designsystem BOM 2026.09.00 Apache 2.0 Already ships, same versions

kotlinx-serialization 1.12.0 was published on 2026-10-19, one day before this work, so this uses 1.11.0. Test libraries never ship, so they fall under the build tool rule in AGENTS.md.

Checklist

  • OpenSpec change archived, or not needed. Not needed: the theme puts the approved design system into code, and has no behavior to specify. The brief and ADR 0006 already decide that dynamic color is on by default.
  • docs/architecture.md updated, or the structure of the app didn't change
  • ADR added for any decision that would be hard to reverse, or there was none. There was none. ADR 0003 gets the font sentence, with a note that its decision is unchanged.

Reviewer

Final verdict: Ready

The reviewer ran three rounds. Round one was Ready, with six should-fix items, all done: the emulator finding worded as an emulator finding, sources for two numbers, the dialog dim claim narrowed, "every color role" corrected, and a new test for the font XMLs. Round two was Ready, with one comment to reflow. Round three, on the committed branch, was Ready with nothing to change. You answered its three questions: the Bold text weights and the README sentence are in this pull request, and the launch window is #138.

🤖 Generated with Claude Code

- DewfallTheme in :core:designsystem sets the light and dark color
  schemes with all 48 roles, the Manrope type scale and the shapes from
  tokens.json, and DewfallSpacing holds the spacing, so screens read
  every value from the theme.
- Dynamic color replaces the palette on Android 12 and later, as the
  design brief asks, and older phones get Dewfall's own palette.
- Bundle Manrope 4.505 as one variable font, with its OFL license text
  in the APK's assets, since the license asks every copy to carry it.
- Load each weight through a font XML that sets the weight axis,
  because Compose's Font(resId, weight) left every weight at the file's
  ExtraLight default on the API 29 and 36 emulators. 700 and 800 are
  there for Android's Bold text setting.
- Expose Material 3 as an api dependency, because screens use its
  components and MaterialTheme.
- Mark .ttf files as binary, so Git never changes the font's bytes.
- DesignTokensTest compares the theme with tokens.json and ManropeTest
  guards the font XMLs. Both files are test inputs, so a cached result
  never hides a change. kotlinx-serialization-json reads the tokens in
  tests only.
- Replace Material 3's default color schemes in DewfallApp with
  DewfallTheme, so the placeholder shows Dewfall's palette or dynamic
  color, and Manrope.
- Drop the KDoc sentence that said the default colors stayed until #26,
  since it no longer holds.
- Add The theme to architecture.md: where the values come from, dynamic
  color, the font and its license, the font XML workaround, the token
  checks and how to open the previews on a phone.
- Note under Network access that the font is bundled rather than
  downloaded, since downloadable fonts would ask Google Play services
  for it.
- Correct the module table and the sentences that said #26 would add
  the theme, now that it has.
- List the theme check among the fast tests in testing.md.
- Say in the README that the bundled font is under the OFL, with a link
  to its license file, since the repository now ships more than GPLv3
  code.
- Bundled fonts may use the SIL Open Font License 1.1 and must ship
  with their copyright notice and license text, since the app now
  bundles Manrope and the rule only listed code licenses.
- Apply the same sentence in AGENTS.md, CONTRIBUTING.md,
  openspec/config.yaml and ADR 0003, with a note in the ADR that the
  decision itself is unchanged.
- Add matching the launch window to Dewfall's colors to Phase 4,
  because the window theme's background shows before the first frame
  and doesn't match the theme (#138).
- Add an open-source licenses section in settings to Phase 9, after the
  debug info button, so the font's and the libraries' licenses can be
  read inside the app (#139).
@j0ker70
j0ker70 merged commit 2024806 into main Oct 20, 2026
1 check passed
@j0ker70
j0ker70 deleted the feat/theme branch October 20, 2026 02:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Build the theme from design tokens

1 participant