Kgothatso Ngako 05e80bf099 feat: hold every screen's content to a readable line, and centre it in the window
Phase 6, step 5, first half. Every one of the 40 screens rendered a single column
that filled whatever width it was given, so on a 1800dp desktop window a
paragraph became a 1800dp line -- long enough that the eye loses the start of the
next one -- and a six-character text field stretched to 1700dp.

M3: *"across all breakpoints, adjust margins and type styles to keep text between
40–60 characters per line."*

**The measure is derived, not written down.** `readableContentWidth()` is
`bodyLarge`'s font size converted through the current density, times half an em
per character, times sixty: 480dp at the default text size. Writing `480.dp`
instead would be the same number today and wrong for anybody who has turned text
size up -- at 200% the same column holds thirty characters, silently, because the
text still fits. Deriving it means the column widens with the type and keeps its
sixty. `AverageCharacterAdvance` is the one estimate in it, named and documented,
because a proportional face has no character width and half an em is the standard
figure for mixed-case Latin prose.

Only the ceiling is enforced. The floor needs nothing: a 400dp compact window
less its two 16dp margins holds about 46 characters, which is inside the range,
and no cap can add characters to a window that has none. There is a test for
exactly that, so the claim is checked rather than asserted in a comment.

**The column is centred; the text is not.** Those are opposite things and it is
worth being explicit, because "centre it" is how the second one gets done by
accident. A centred column still has one straight leading edge for every row,
avatar and icon to align to, which is what the grids-and-spacing page asks for.
Centred text has none. The 91 `TextAlign.Center` uses are a separate question and
a separate commit.

**Applied at 49 sites in one pass**, at the point every screen consumes its
`Scaffold`'s padding -- the one place in each file that is reliably the top of the
content. Below 480dp it is not a cap, an inset or a centring; it is nothing, so
no phone layout moves.

**Verified by measuring a real composition, not by reading the code.**
`readableContent()` is `fillMaxWidth` then `wrapContentWidth` then `widthIn`, and
every permutation of those three compiles and renders something that looks right
in a phone-width preview. This needed `compose.desktop.uiTestJUnit4` in `jvmTest`
-- pinned to the same 1.11.1 as the rest of Compose Multiplatform, test-only --
and `runDesktopComposeUiTest(width = 1400)`, which gives a window that genuinely
is 1400 pixels across at density 1.

Four assertions, and they bite: swapping the last two modifiers makes the
1400dp case report `Actual width is 1400.0.dp, expected 480.0.dp`, which is the
"centred but never capped" failure the doc comment names. The same test also
pins `currentBreakpoint()` to the real window at all five widths -- 400, 700,
1000, 1400, 1800 -- with the screen margin following. A version of it that
measured the parent's constraints rather than the window would answer `Compact`
everywhere and pass every unit test in the suite.

37 theme tests green; android and desktop both compile.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-08 07:31:33 +02:00
2026-07-05 23:21:02 +02:00
2026-07-28 09:10:20 +02:00
2026-03-24 04:47:19 +02:00
2026-03-23 01:41:39 +02:00
2026-03-23 01:41:39 +02:00
2026-03-23 01:41:39 +02:00

This is a Kotlin Multiplatform project targeting Android, iOS, Desktop (JVM).

  • /composeApp is for code that will be shared across your Compose Multiplatform applications. It contains several subfolders:

    • commonMain is for code thats common for all targets.
    • Other folders are for Kotlin code that will be compiled for only the platform indicated in the folder name. For example, if you want to use Apples CoreCrypto for the iOS part of your Kotlin app, the iosMain folder would be the right place for such calls. Similarly, if you want to edit the Desktop (JVM) specific part, the jvmMain folder is the appropriate location.
  • /iosApp contains iOS applications. Even if youre sharing your UI with Compose Multiplatform, you need this entry point for your iOS app. This is also where you should add SwiftUI code for your project.

Build and Run Android Application

To build and run the development version of the Android app, use the run configuration from the run widget in your IDEs toolbar or build it directly from the terminal:

  • on macOS/Linux
    ./gradlew :composeApp:assembleDebug
    
  • on Windows
    .\gradlew.bat :composeApp:assembleDebug
    

Build and Run Desktop (JVM) Application

To build and run the development version of the desktop app, use the run configuration from the run widget in your IDEs toolbar or run it directly from the terminal:

  • on macOS/Linux
    ./gradlew :composeApp:run
    
  • on Windows
    .\gradlew.bat :composeApp:run
    

Build and Run iOS Application

To build and run the development version of the iOS app, use the run configuration from the run widget in your IDEs toolbar or open the /iosApp directory in Xcode and run it from there.


Learn more about Kotlin Multiplatform

Description
Mantra as a kotlin multiplatform project
https://mantra.press
Readme 8.2 MiB
Languages
Kotlin 100%