A Compose-inspired UI toolkit for Svelte, focused on explicit composition, immutable modifiers, and theme-driven design.
Inspired by Jetpack Compose, built natively for the web using Svelte and standard web technologies.
ModifiersThis is not a Material clone.
It is a Compose-like system that can be styled beyond Material Design.
Jetpack Compose introduced a clear, explicit and composable mental model for UI. This project explores how that same philosophy translates to the web, using Svelte as a native, compiler-driven foundation.
The goal is not to replicate Android UI, but to bring Compose’s clarity and composability to modern web applications.
npm install compose-svelte
<script>
import {
ComposeTheme,
AppRoot,
Surface,
Text,
Modifier
} from "compose-svelte";
</script>
<ComposeTheme mode="system">
<AppRoot>
<Surface modifier={Modifier.fillMaxSize()}>
<Text>Hello Compose</Text>
</Surface>
</AppRoot>
</ComposeTheme>
<Column modifier={Modifier.padding(16)}>
<Text textStyle="titleLarge">Title</Text>
<Text>Body text</Text>
</Column>
<Row horizontalArrangement={Arrangement.spacedBy(8)}>
<Text>Left</Text>
<Text>Right</Text>
</Row>
<Box modifier={Modifier.size(120)}>
<Text modifier={Modifier.align(Alignment.Center)}>Centered</Text>
</Box>
Provides theming for the entire app.
<ComposeTheme mode="dark">
<AppRoot>
<Surface>
<Text>Dark mode</Text>
</Surface>
</AppRoot>
</ComposeTheme>
<TextField
label="Email"
placeholder="[email protected]"
value={email}
onValueChange={(v) => email = v}
/>
<OutlinedTextField
label="Email"
value={email}
onValueChange={(v) => email = v}
/>
<Button onClick={submit}>
Submit
</Button>
<TextButton onClick={cancel}>
Cancel
</TextButton>
<OutlinedButton>
Outlined
</OutlinedButton>
Modifiers are immutable and chainable.
Modifier
.padding(16)
.fillMaxWidth()
.background(ColorScheme.Surface)
size, width, height, fill, weightpadding, marginbackground, border, clipclickableoffsetverticalScroll, horizontalScrollRoundedCornerShape(12)
RoundedCornerShape({ topStart: 16, topEnd: 16 })
Shapes are value objects and reusable across components.
ColorScheme.Primary
ColorScheme.Surface
ColorScheme.OnSurface
TextStyle.TitleLarge
TextStyle.BodyMedium
TextStyle.LabelSmall
<Image
painter={painterResource(Res.image("logo.png"))}
contentScale={ContentScale.Fit}
/>
<Icon
painter="https://api.iconify.design/mdi/home.svg"
modifier={Modifier.size(24)}
/>
Clarity over cleverness.
If something is not explicit, it is probably not part of the API.
MIT