Skip to content

Repository files navigation

Napkin Compose

A Compose Multiplatform theme library inspired by the classic Napkin Look & Feel for Java Swing: every component looks hand-drawn on a napkin — wobbly felt-tip outlines, handwritten headlines, Comic Sans body text, red-pencil scribbles, highlighter swipes, and post-it notes.

Like the Swing original, it is great for keeping provisional UIs looking provisional — a mockup that looks unfinished never gets mistaken for a finished product. It is also just plain whimsical.

Light ("napkin") Dark ("blackboard")
light dark

Targets

  • Desktop JVM (macOS, Windows, Linux)
  • Android (minSdk 24)
  • iOS (arm64, simulator arm64)

Usage

NapkinTheme {                       // or NapkinTheme(darkTheme = true) for blackboard
    Box(Modifier.fillMaxSize().napkinPaper()) {
        Column {
            Text("Hello!", style = MaterialTheme.typography.headlineMedium)
            NapkinButton(onClick = { /* ... */ }) { Text("Click me") }
        }
    }
}

NapkinTheme wraps MaterialTheme (Material 3), so stock Material components pick up the palette and comic type scale automatically; the Napkin* components add the hand-drawn geometry on top.

Components

Composable What you get
NapkinButton Sketched box at a slight tilt; fills with highlighter while pressed
NapkinCheckbox Wobbly ink square; checking animates a green marker tick that overshoots the corner
NapkinRadioButton Wobbly ink ring with a scribbled dot
NapkinSwitch Doodled track with a sliding ink knob
NapkinTextField Sketch-boxed input with a red-pencil cursor and pencilled-in placeholder
NapkinLinearProgress Sketched track filled with a red-pencil zigzag scribble
NapkinCard Slightly whiter paper with its own faint tilt
NapkinDivider A single wobbly pen stroke
NapkinPostIt A yellow post-it at a jaunty angle (stays yellow on the blackboard)

Modifiers

  • Modifier.napkinPaper() — the napkin itself: warm paper with fiber specks
  • Modifier.napkinSketchBorder(...) — hand-sketched outline around anything
  • Modifier.napkinHighlight() — translucent highlighter swipe behind content
  • Modifier.napkinUnderline() — wobbly hand-drawn underline

All sketch geometry is generated by Sketcher from a per-component random seed remembered across recompositions, so outlines wobble but never dance. Tune the look via NapkinTheme(sketch = SketchStyle(wobble = 2.5.dp, ...)).

Typefaces

Two families, mirroring the drawing tools:

  • Headlines/titles use a felt-pen handwriting face. The Swing original used Felt Tip Roman, which is commercial; the closest open equivalent, Patrick Hand (SIL OFL), is bundled.
  • Body/labels use Comic Sans. The genuine Comic Sans MS is a proprietary Microsoft font that cannot be redistributed, so on desktop it is loaded from the OS where installed (macOS, Windows, Linux with msttcorefonts); Android and iOS fall back to the bundled Comic Neue (SIL OFL), the Comic Sans revival.

Why two fonts?

Splitting the type scale is deliberate, for two reasons:

  1. Faithfulness to the original. Napkin LAF didn't actually use Comic Sans — it used Felt Tip Roman, a felt-pen handwriting face, for its scrawled emphasis text alongside a tamer face for regular text. Using the felt-pen family for headings and Comic Sans for body text keeps both traditions alive.
  2. Typography. The two faces have different strengths at different sizes. Patrick Hand is expressive but ships in a single weight with no italics, has a small x-height, and gets hard to read at 12–14sp in dense UI text; it shines at headline sizes, where it reads as "someone wrote a heading on this napkin." Comic Sans was literally designed for small on-screen body text, so it stays legible in labels, buttons, and paragraphs — and its bold/italic variants matter for body and label styles. The contrast also gives you visual hierarchy for free: marker pen for headings, neat hand for notes, just like a real napkin sketch.

Using one font everywhere

Both slots are plain FontFamily parameters on NapkinTheme, so your app can override either or both:

// Comic Sans for everything, headlines included:
NapkinTheme(handwritingFontFamily = rememberComicFontFamily()) { /* ... */ }

// Felt pen for everything, body text included:
NapkinTheme(comicFontFamily = rememberFeltPenFontFamily()) { /* ... */ }

// Or bring your own faces:
NapkinTheme(
    handwritingFontFamily = myMarkerFamily,
    comicFontFamily = myBodyFamily,
) { /* ... */ }

Font attribution lives in napkin/FONT-LICENSES.txt.

Building

./gradlew :napkin:assemble        # library artifacts for all targets
./gradlew :demo:run               # desktop demo gallery
./gradlew :napkin:jvmTest         # sketch-geometry tests
./gradlew :demo:jvmTest           # renders the gallery to demo/build/render/*.png

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages