JetLime
A Kotlin Multiplatform library to display a timeline view. ๐
Install / Use
/learn @pushpalroy/JetLimeREADME
JetLime ๐
A simple yet highly customizable UI library to show a timeline view in Compose Multiplatform.
![badge][badge-android] ![badge][badge-ios] ![badge][badge-jvm] ![badge][badge-web]
| Basic | Dashed | Dynamic | |:---------------------------------------:|------------------------------------------|:-----------------------------------------:| | <img src="art/basic.gif" width=180 /> | <img src="art/dashed.png" width=180 /> | <img src="art/dynamic.gif" width=180 /> | | Custom | Extended | | | <img src="art/custom.png" width=180 /> | <img src="art/extended.png" width=180 /> | |
Supported Platform Samples
| Android | iOS | Desktop | Web | |:------------------------------------------------:|----------------------------------------------|:-----------------------------------------------:|---------------------------------------------| | <img src="art/platform/android.png" width=120 /> | <img src="art/platform/iOS.png" width=120 /> | <img src="art/platform/desktop.png" width=240/> | <img src="art/platform/web.png" width=240/> |
โจ Highlights
- Compose Multiplatform timelines: Android, iOS, Desktop (JVM), Web (JS & WASM)
- Vertical and horizontal layouts (JetLimeColumn / JetLimeRow)
- Flexible point placement: START, CENTER, END with continuous line joins
- RTL layout support for JetLimeRow and JetLimeExtendedEvent (mirrors timelines and keeps content visible in right-to-left layouts)
- Dashed/gradient/solid lines via Brush + PathEffect
- Extended events with dual content slots (left/right), icons, and animations
- Small, focused API with sensible defaults (JetLimeDefaults)
๐ฆ Installation
In build.gradle of shared module, include the following dependency
dependencies {
implementation("io.github.pushpalroy:jetlime:4.1.1")
}
๐ Usage
๐ Add items in a Vertical Timeline
Use the JetLimeColumn
val items = remember { mutableListOf(Item1, Item2, Item3) } // Any type of items
JetLimeColumn(
modifier = Modifier.padding(16.dp),
itemsList = ItemsList(items),
key = { _, item -> item.id },
) { index, item, position ->
JetLimeEvent(
style = JetLimeEventDefaults.eventStyle(
position = position
),
) {
// Content here
}
}
๐ Add items in a Horizontal Timeline
Use the JetLimeRow
val items = remember { mutableListOf(Item1, Item2, Item3) } // Any type of items
JetLimeRow(
modifier = Modifier.padding(16.dp),
itemsList = ItemsList(items),
key = { _, item -> item.id },
) { index, item, position ->
JetLimeEvent(
style = JetLimeEventDefaults.eventStyle(
position = position
),
) {
// Content here
}
}
Pass the key to define factory of stable and unique keys representing the item. Using the same key for multiple items in the list is not allowed.
This key will be used by a LazyColumn or LazyRow internally.
If we want to to add items dynamically from a data source, we should use mutableStateListOf, so that our list can be observed as a state:
val items = remember { mutableStateListOf<MyItem>() }
๐งฉ Extended Events (Vertical Timeline)
Use the JetLimeExtendedEvent with a JetLimeColumn Using this we can pass an additional content to draw on the left side of the timeline.
val items = remember { mutableListOf(Item1, Item2, Item3) } // Any type of items
JetLimeColumn(
modifier = Modifier.padding(16.dp),
itemsList = ItemsList(items),
key = { _, item -> item.id },
style = JetLimeDefaults.columnStyle(contentDistance = 24.dp),
) { index, item, position ->
JetLimeExtendedEvent(
style = JetLimeEventDefaults.eventStyle(
position = position
),
additionalContent = {
// Additional content here
}
) {
// Content here
}
}
๐๏ธ Customize JetLimeColumn Style
Use the JetLimeDefaults.columnStyle()
JetLimeColumn(
style = JetLimeDefaults.columnStyle(
contentDistance = 32.dp,
itemSpacing = 16.dp,
lineThickness = 2.dp,
lineBrush = JetLimeDefaults.lineSolidBrush(color = Color(0xFF2196F3)),
lineVerticalAlignment = RIGHT,
),
) {
// Code to add events
}
๐๏ธ Customize JetLimeRow Style
Use the JetLimeDefaults.rowStyle()
JetLimeRow(
style = JetLimeDefaults.rowStyle(
contentDistance = 32.dp,
itemSpacing = 16.dp,
lineThickness = 2.dp,
lineBrush = JetLimeDefaults.lineSolidBrush(color = Color(0xFF2196F3)),
lineHorizontalAlignment = BOTTOM,
),
) {
// Code to add events
}
๐๏ธ Customize JetLimeEvent Style
Use the JetLimeEventDefaults.eventStyle()
JetLimeEvent(
style = JetLimeEventDefaults.eventStyle(
position = position,
pointColor = Color(0xFF2889D6),
pointFillColor = Color(0xFFD5F2FF),
pointRadius = 14.dp,
pointAnimation = JetLimeEventDefaults.pointAnimation(),
pointType = EventPointType.filled(0.8f),
pointStrokeWidth = 2.dp,
pointStrokeColor = MaterialTheme.colorScheme.onBackground,
),
) {
// Code to add event content
}
โ๏ธ JetLimeColumn and JetLimeRow Properties
๐งญ Alignment
The timeline line and point circles can be set to either side.
For a JetLimeColumn the alignment can be set to LEFT or RIGHT
lineVerticalAlignment = LEFT or RIGHT // Default is LEFT
For a JetLimeRow the alignment can be set to TOP or BOTTOM
lineHorizontalAlignment = TOP or BOTTOM // Default is TOP
๐จ Line Style
The line can be drawn by passing a Brush object to lineBrush in a columnStyle or rowStyle.
Default values can also be used from JetLimeDefaults and colors can be modified for quick setup:
lineBrush = JetLimeDefaults.lineGradientBrush()
or
lineBrush = JetLimeDefaults.solidBrush()
A dashed/dotted line can also be drawn using the pathEffect property by passing a PathEffect to a columnStyle or rowStyle.
style = JetLimeDefaults.columnStyle(
pathEffect = PathEffect.dashPathEffect(
intervals = floatArrayOf(30f, 30f),
phase = 0f,
)
)
โ๏ธ Content Distance
The contentDistance in Dp specifies how far the timeline line should be from the timeline content.
โ๏ธ Item Spacing
The itemSpacing in Dp specifies the gap between the event items.
๐ Line Thickness
The lineThickness in Dp the thickness of the timeline line.
๐ RTL Layout Support
JetLime supports right-to-left (RTL) layouts ou
Related Skills
node-connect
345.4kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
104.6kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
345.4kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
345.4kQQBot ๅฏๅชไฝๆถๅ่ฝๅใไฝฟ็จ <qqmedia> ๆ ็ญพ๏ผ็ณป็ปๆ นๆฎๆไปถๆฉๅฑๅ่ชๅจ่ฏๅซ็ฑปๅ๏ผๅพ็/่ฏญ้ณ/่ง้ข/ๆไปถ๏ผใ
