Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit 19ee960d authored by Rafael Tonholo's avatar Rafael Tonholo
Browse files

feat(design-system): add snackbar host component

parent f952209a
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -8,6 +8,8 @@ import net.thunderbird.ui.catalog.ui.page.common.PagedContent
import net.thunderbird.ui.catalog.ui.page.organism.CatalogOrganismPage.APP_BAR
import net.thunderbird.ui.catalog.ui.page.organism.CatalogOrganismPage.BANNER
import net.thunderbird.ui.catalog.ui.page.organism.CatalogOrganismPage.DIALOG
import net.thunderbird.ui.catalog.ui.page.organism.CatalogOrganismPage.SNACKBAR
import net.thunderbird.ui.catalog.ui.page.organism.items.SnackbarItems
import net.thunderbird.ui.catalog.ui.page.organism.items.appBarItems
import net.thunderbird.ui.catalog.ui.page.organism.items.bannerItems
import net.thunderbird.ui.catalog.ui.page.organism.items.dialogItems
@@ -28,9 +30,15 @@ fun CatalogOrganismContent(
                APP_BAR -> appBarItems()
                DIALOG -> dialogItems()
                BANNER -> bannerItems()
                SNACKBAR -> Unit
            }
        },
        onRenderFullScreenPage = {
            when (it) {
                SNACKBAR -> SnackbarItems()
                else -> Unit
            }
        },
        onRenderFullScreenPage = {},
        onEvent = onEvent,
    )
}
+1 −0
Original line number Diff line number Diff line
@@ -10,6 +10,7 @@ enum class CatalogOrganismPage(
    APP_BAR("App Bars"),
    DIALOG("Dialogs"),
    BANNER("Banners"),
    SNACKBAR("Snackbars", isFullScreen = true),
    ;

    override fun toString(): String {
+99 −0
Original line number Diff line number Diff line
package net.thunderbird.ui.catalog.ui.page.organism.items

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import app.k9mail.core.ui.compose.designsystem.atom.DividerHorizontal
import app.k9mail.core.ui.compose.designsystem.atom.button.ButtonText
import app.k9mail.core.ui.compose.designsystem.atom.text.TextTitleMedium
import app.k9mail.core.ui.compose.designsystem.organism.snackbar.SnackbarDuration
import app.k9mail.core.ui.compose.designsystem.organism.snackbar.SnackbarHost
import app.k9mail.core.ui.compose.designsystem.organism.snackbar.rememberSnackbarHostState
import app.k9mail.core.ui.compose.designsystem.template.Scaffold
import app.k9mail.core.ui.compose.theme2.MainTheme
import kotlinx.coroutines.launch

@Composable
fun SnackbarItems(modifier: Modifier = Modifier) {
    val snackbarHostState = rememberSnackbarHostState()
    val coroutineScope = rememberCoroutineScope()
    Scaffold(
        snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
        modifier = modifier,
    ) {
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(it),
        ) {
            SnackbarSubsection(title = "Without action") {
                ButtonText(
                    text = "Show snackbar",
                    onClick = {
                        coroutineScope.launch {
                            snackbarHostState.showSnackbar(
                                message = "Snackbar message",
                                actionLabel = null,
                            )
                        }
                    },
                )
            }
            SnackbarSubsection(title = "With action") {
                ButtonText(
                    text = "Show snackbar",
                    onClick = {
                        coroutineScope.launch {
                            snackbarHostState.showSnackbar(
                                message = "Snackbar message",
                                actionLabel = "The action",
                            )
                        }
                    },
                )
            }
            SnackbarDuration.entries.forEach { duration ->
                SnackbarSubsection(title = "With ${duration.name} duration") {
                    ButtonText(
                        text = "Show snackbar",
                        onClick = {
                            coroutineScope.launch {
                                snackbarHostState.showSnackbar(
                                    message = "Snackbar message with ${duration.name} of duration",
                                    duration = duration,
                                )
                            }
                        },
                    )
                }
            }
            Spacer(modifier = Modifier.weight(1f))
        }
    }
}

@Composable
private fun SnackbarSubsection(
    title: String,
    modifier: Modifier = Modifier,
    content: @Composable () -> Unit,
) {
    Column(
        modifier = modifier
            .fillMaxWidth()
            .padding(
                start = MainTheme.spacings.double,
                top = MainTheme.spacings.default,
                end = MainTheme.spacings.double,
            ),
    ) {
        TextTitleMedium(text = title)
        DividerHorizontal()
        content()
    }
}
+21 −0
Original line number Diff line number Diff line
package app.k9mail.core.ui.compose.designsystem.organism.snackbar

import androidx.compose.material3.SnackbarDuration as Material3SnackbarDuration

/** Possible durations of the [Snackbar] in [SnackbarHost] */
enum class SnackbarDuration {
    /** Show the Snackbar for a short period of time */
    Short,

    /** Show the Snackbar for a long period of time */
    Long,

    /** Show the Snackbar indefinitely until explicitly dismissed or action is clicked */
    Indefinite,
}

internal fun SnackbarDuration.toMaterial3SnackbarDuration(): Material3SnackbarDuration = when (this) {
    SnackbarDuration.Short -> Material3SnackbarDuration.Short
    SnackbarDuration.Long -> Material3SnackbarDuration.Long
    SnackbarDuration.Indefinite -> Material3SnackbarDuration.Indefinite
}
+34 −0
Original line number Diff line number Diff line
package app.k9mail.core.ui.compose.designsystem.organism.snackbar

import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.material3.SnackbarHost as Material3SnackbarHost
import androidx.compose.material3.SnackbarHostState as Material3SnackbarHostState

/**
 * Snackbars provide brief messages about app processes at the bottom of the screen.
 *
 * It uses the Material 3 [SnackbarHost] implementation under the hood.
 *
 * @param hostState state of this component to manage Snackbar show/dismiss timings.
 * @param modifier the [Modifier] to be applied to this component.
 */
@Composable
fun SnackbarHost(
    hostState: SnackbarHostState,
    modifier: Modifier = Modifier,
) {
    Material3SnackbarHost(
        hostState = (hostState as Material3BackedSnackbarHostState).m3State,
        modifier = modifier,
    )
}

/**
 * Creates a [SnackbarHostState] that is remembered across compositions.
 */
@Composable
fun rememberSnackbarHostState(): SnackbarHostState {
    return remember { Material3BackedSnackbarHostState(m3State = Material3SnackbarHostState()) }
}
Loading