|
| 1 | +# GuideKit |
| 2 | + |
| 3 | +Reusable Compose Multiplatform coachmark overlay. |
| 4 | + |
| 5 | +GuideKit owns step navigation internally. The host app provides the steps, target bounds, and completion callbacks. |
| 6 | + |
| 7 | +## Usage |
| 8 | + |
| 9 | +```kotlin |
| 10 | +import androidx.compose.foundation.BorderStroke |
| 11 | +import androidx.compose.foundation.gestures.animateScrollBy |
| 12 | +import androidx.compose.foundation.layout.PaddingValues |
| 13 | +import androidx.compose.foundation.shape.RoundedCornerShape |
| 14 | +import androidx.compose.material3.MaterialTheme |
| 15 | +import androidx.compose.ui.Alignment |
| 16 | +import androidx.compose.ui.Modifier |
| 17 | +import androidx.compose.ui.graphics.Color |
| 18 | +import androidx.compose.ui.unit.dp |
| 19 | +import io.github.guidekit.GuideKit |
| 20 | +import io.github.guidekit.GuideKitAnchor |
| 21 | +import io.github.guidekit.GuideKitArrowConfig |
| 22 | +import io.github.guidekit.GuideKitArrowHead |
| 23 | +import io.github.guidekit.GuideKitArrowLineStyle |
| 24 | +import io.github.guidekit.GuideKitArrowStroke |
| 25 | +import io.github.guidekit.GuideKitAutoScrollConfig |
| 26 | +import io.github.guidekit.GuideKitInstructionBoxShadow |
| 27 | +import io.github.guidekit.GuideKitInstructionBoxStyle |
| 28 | +import io.github.guidekit.GuideKitStep |
| 29 | +import io.github.guidekit.GuideKitStyle |
| 30 | +import io.github.guidekit.GuideKitTargetHighlightShape |
| 31 | +import io.github.guidekit.GuideKitTargetHighlightStroke |
| 32 | +import io.github.guidekit.GuideKitTargetHighlightStyle |
| 33 | +import androidx.compose.ui.graphics.StrokeCap |
| 34 | + |
| 35 | +GuideKit( |
| 36 | + steps = listOf( |
| 37 | + GuideKitStep( |
| 38 | + targetBounds = firstTargetBounds, |
| 39 | + title = "Your day, at a glance.", |
| 40 | + description = "Important updates appear here when they are needed.", |
| 41 | + primaryButtonText = null, // Defaults to "Next", or "Got it" on the last step. |
| 42 | + descriptionHighlight = null, |
| 43 | + descriptionHighlights = emptyList(), |
| 44 | + instructionBottomPadding = 104.dp, |
| 45 | + arrowConfig = null, // Uses GuideKitStyle.arrowConfig. |
| 46 | + targetHighlight = null, // Uses GuideKitStyle.targetHighlight. |
| 47 | + instructionBox = null, // Uses GuideKitStyle.instructionBox. |
| 48 | + autoScroll = GuideKitAutoScrollConfig( |
| 49 | + enabled = true, |
| 50 | + minTopVisibleDistance = null, // Defaults to arrowConfig.minVisibleDistance + 1.dp. |
| 51 | + spacing = null, // Defaults to arrowConfig.minVisibleDistance + 1.dp. |
| 52 | + ), |
| 53 | + ), |
| 54 | + GuideKitStep( |
| 55 | + targetBounds = secondTargetBounds, |
| 56 | + title = "Help is always within reach.", |
| 57 | + description = "Press and hold for 3 seconds.", |
| 58 | + primaryButtonText = "Done", |
| 59 | + arrowConfig = GuideKitArrowConfig( |
| 60 | + from = GuideKitAnchor.BottomCenter, |
| 61 | + to = GuideKitAnchor.CenterLeft, |
| 62 | + arrowHead = GuideKitArrowHead.BothSides, |
| 63 | + lineStyle = GuideKitArrowLineStyle.Solid, |
| 64 | + ), |
| 65 | + targetHighlight = GuideKitTargetHighlightStyle( |
| 66 | + shape = GuideKitTargetHighlightShape.Circle, |
| 67 | + ), |
| 68 | + instructionBox = GuideKitInstructionBoxStyle( |
| 69 | + alignment = Alignment.BottomCenter, |
| 70 | + ), |
| 71 | + autoScroll = GuideKitAutoScrollConfig(enabled = false), |
| 72 | + ), |
| 73 | + ), |
| 74 | + modifier = Modifier, |
| 75 | + initialStepIndex = 0, |
| 76 | + showStepIndicator = true, |
| 77 | + style = GuideKitStyle( |
| 78 | + accentColor = Color(0xFF5ED5B3), |
| 79 | + overlayColor = Color.Black.copy(alpha = 0.68f), |
| 80 | + titleColor = null, // Defaults to MaterialTheme.colorScheme.onSurface. |
| 81 | + descriptionColor = null, // Defaults to MaterialTheme.colorScheme.onSurfaceVariant. |
| 82 | + highlightedDescriptionColor = null, // Defaults to accentColor. |
| 83 | + stepIndicatorActiveColor = null, // Defaults to accentColor. |
| 84 | + stepIndicatorInactiveColor = null, // Defaults to MaterialTheme.colorScheme.outlineVariant. |
| 85 | + primaryButtonContainerColor = null, // Defaults to accentColor. |
| 86 | + primaryButtonContentColor = Color(0xFF062D25), |
| 87 | + skipIconTint = null, // Defaults to MaterialTheme.colorScheme.onSurfaceVariant. |
| 88 | + arrowConfig = GuideKitArrowConfig( |
| 89 | + enabled = true, |
| 90 | + from = GuideKitAnchor.TopCenter, |
| 91 | + to = GuideKitAnchor.BottomCenter, |
| 92 | + curveSeed = 0, |
| 93 | + minVisibleDistance = 20.dp, |
| 94 | + lineStyle = GuideKitArrowLineStyle.Dashed, |
| 95 | + dashIntervalsPx = floatArrayOf(20f, 15f), |
| 96 | + dashPhasePx = 0f, |
| 97 | + strokes = listOf( |
| 98 | + GuideKitArrowStroke(widthPx = 9f, color = Color.Black.copy(alpha = 0.24f)), |
| 99 | + GuideKitArrowStroke(widthPx = 5.5f, color = null, alpha = 0.95f), // Defaults to GuideKitStyle.accentColor. |
| 100 | + GuideKitArrowStroke(widthPx = 1.7f, color = Color.White.copy(alpha = 0.62f)), |
| 101 | + ), |
| 102 | + strokeCap = StrokeCap.Round, |
| 103 | + arrowHead = GuideKitArrowHead.TargetSide, |
| 104 | + arrowHeadLengthPx = 38f, |
| 105 | + arrowHeadAngleDegrees = 30f, |
| 106 | + arrowHeadStrokes = listOf( |
| 107 | + GuideKitArrowStroke(widthPx = 9f, color = Color.Black.copy(alpha = 0.22f)), |
| 108 | + GuideKitArrowStroke(widthPx = 5.5f, color = null, alpha = 0.96f), // Defaults to GuideKitStyle.accentColor. |
| 109 | + GuideKitArrowStroke(widthPx = 1.6f, color = Color.White.copy(alpha = 0.55f)), |
| 110 | + ), |
| 111 | + ), |
| 112 | + targetHighlight = GuideKitTargetHighlightStyle( |
| 113 | + enabled = true, |
| 114 | + shape = GuideKitTargetHighlightShape.RoundedRect, |
| 115 | + cutoutEnabled = true, |
| 116 | + paddingPx = 10f, |
| 117 | + cornerRadius = 28.dp, |
| 118 | + glowStrokes = listOf( |
| 119 | + GuideKitTargetHighlightStroke(widthPx = 30f, alpha = 0.11f), |
| 120 | + GuideKitTargetHighlightStroke(widthPx = 22f, alpha = 0.18f), |
| 121 | + GuideKitTargetHighlightStroke(widthPx = 14f, alpha = 0.30f), |
| 122 | + GuideKitTargetHighlightStroke(widthPx = 8f, alpha = 0.45f), |
| 123 | + ), |
| 124 | + borderColor = null, // Defaults to GuideKitStyle.accentColor. |
| 125 | + borderWidthPx = 2.5f, |
| 126 | + innerBorderColor = Color.White.copy(alpha = 0.7f), |
| 127 | + innerBorderWidthPx = 1.2f, |
| 128 | + innerBorderInsetPx = 2f, |
| 129 | + ), |
| 130 | + instructionBox = GuideKitInstructionBoxStyle( |
| 131 | + alignment = Alignment.BottomCenter, |
| 132 | + outerPadding = null, // Defaults to start/end 18.dp and step.instructionBottomPadding. |
| 133 | + contentPadding = PaddingValues(horizontal = 22.dp, vertical = 24.dp), |
| 134 | + fillMaxWidth = true, |
| 135 | + minWidth = null, |
| 136 | + maxWidth = null, |
| 137 | + minHeight = null, |
| 138 | + maxHeight = null, |
| 139 | + shape = RoundedCornerShape(30.dp), |
| 140 | + containerColor = null, // Defaults to MaterialTheme.colorScheme.surface. |
| 141 | + contentColor = null, // Defaults to MaterialTheme.colorScheme.onSurface. |
| 142 | + border = BorderStroke(1.dp, Color(0xFF5ED5B3).copy(alpha = 0.28f)), |
| 143 | + tonalElevation = 0.dp, |
| 144 | + shadowElevation = 26.dp, |
| 145 | + modifier = Modifier, |
| 146 | + shadow = GuideKitInstructionBoxShadow( |
| 147 | + elevation = 30.dp, |
| 148 | + ambientColor = Color.Black.copy(alpha = 0.42f), |
| 149 | + spotColor = Color.Black.copy(alpha = 0.42f), |
| 150 | + ), |
| 151 | + ), |
| 152 | + ), |
| 153 | + onStepChanged = { stepIndex -> }, |
| 154 | + onScrollBy = { deltaPx -> scrollState.animateScrollBy(deltaPx) }, |
| 155 | + onSkipped = onSkip, |
| 156 | + onFinished = onFinished, |
| 157 | +) |
| 158 | +``` |
| 159 | + |
| 160 | +All values shown above are optional defaults. `GuideKitStyle` defines screen-level defaults for arrows, target highlights, and the instruction box. A `GuideKitStep` can override any of them for that specific step; omitted step values inherit from `GuideKitStyle`. |
| 161 | + |
| 162 | +Auto-scroll is enabled by default. GuideKit calculates the smallest scroll needed to keep the highlighted target clear of the instruction box. If scrolling upward, the target highlight is clamped so its top stays at least `minTopVisibleDistance` from the top edge. Set `autoScroll = GuideKitAutoScrollConfig(enabled = false)` on a step to disable it. The host app must provide `onScrollBy` when the page is scrollable. |
| 163 | + |
| 164 | +## Sample App |
| 165 | + |
| 166 | +A Compose Multiplatform sample app is available under `sample/`. |
| 167 | + |
| 168 | +```bash |
| 169 | +./gradlew :sample:composeApp:installDebug |
| 170 | +``` |
| 171 | + |
| 172 | +The sample demonstrates target measurement, step-specific styling, arrow variants, rounded and circular highlights, auto-scroll, and completion callbacks. |
0 commit comments