Feedback & Status

How your app talks back — toasts, banners, loading skeletons, and the four full-screen state views. Import from dev.shipkaro.kit.core.designsystem.components (and …state for the state views).

📱Feedback & status — lightlight/docs/components/feedback-light.png
📱Feedback & status — darkdark/docs/components/feedback-dark.png

KitSnackbar — severity toasts

A snackbar system that reads like the intent. Get a controller, host it once, call .success() / .error() / .info() / .warning() from anywhere.

val snackbar = rememberKitSnackbarController()

Scaffold(
    snackbarHost = { KitSnackbarHost(snackbar.hostState) },
) { /* … */ }

// later, from a button or VM callback:
snackbar.success("Saved!")
snackbar.error("Couldn't reach the server")

Features

  • Four styles — info / success / warning / error — each with its semantic color + icon
  • error defaults to a longer duration; others short
  • Optional action label + callback (fires only on tap)
  • A new snackbar dismisses the previous one (no queue pile-up)
  • Plain String messages still use the Material default — unrelated callers keep working

KitBanner

An inline, dismissible message block — 4 styles.

KitBanner(
    title = "Offline",
    text = "Changes will sync when you reconnect.",
    style = KitBannerStyle.WARNING,    // INFO · SUCCESS · WARNING · ERROR
    onDismiss = { showBanner = false }, // omit for non-dismissible
)

State views

Four full-screen (or inline) views for the empty / error / success / loading moments. Import from …designsystem.state.

when (state) {
    Loading  -> KitLoadingState(label = "Loading…")
    Empty    -> KitEmptyState(
        title = "No habits yet",
        message = "Add your first habit to start a streak.",
        actionText = "Add habit",
        onAction = ::addHabit,
    )
    is Error -> KitErrorState(message = state.message, onAction = ::retry)
    Success  -> KitSuccessState(title = "All done!")
}

Features — each takes an optional message + action button; fullScreen = false renders an inline variant for use inside a list or card. KitInlineLoading is the compact spinner.


Loading placeholders — Shimmer & Skeleton

// Shimmer modifier on any box
Box(Modifier.size(120.dp, 16.dp).kitShimmer())

// Prebuilt skeletons
KitSkeleton(width = 200.dp, height = 20.dp)
KitSkeletonListItem()                       // avatar + two lines

KitLinearProgress · KitPullToRefresh

KitLinearProgress(progress = uploaded / total)   // determinate
KitIndeterminateLinearProgress()                 // unknown duration

KitPullToRefresh(isRefreshing = refreshing, onRefresh = ::reload) {
    LazyColumn { /* … */ }
}

KitBadge · KitRatingBar

// Count overlay on any composable
KitBadge(count = unread, maxCount = 99) { Icon(KitTheme.icons.bell, null) }

// Tappable 5-star rating (tap the same star to clear)
KitRatingBar(rating = stars, onRatingChange = { stars = it })

Next: Navigation & Media — bottom nav, FAB, avatar, web view.