Bug 1816743 - Create Tabs Tray banner container UI

fenix/112.0
Noah Bond 1 year ago committed by mergify[bot]
parent 66845c9c99
commit 1ac9bb70e6

@ -7,10 +7,7 @@ package org.mozilla.fenix.tabstray
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
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.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
@ -21,23 +18,28 @@ import com.google.accompanist.pager.ExperimentalPagerApi
import com.google.accompanist.pager.HorizontalPager
import com.google.accompanist.pager.rememberPagerState
import kotlinx.coroutines.launch
import mozilla.components.lib.state.ext.observeAsComposableState
import org.mozilla.fenix.compose.Divider
import org.mozilla.fenix.compose.annotation.LightDarkPreview
import org.mozilla.fenix.compose.button.PrimaryButton
import org.mozilla.fenix.theme.FirefoxTheme
/**
* Top-level UI for displaying the Tabs Tray feature.
*
* @param tabsTrayStore [TabsTrayStore] used to listen for changes to [TabsTrayState].
*/
@OptIn(ExperimentalPagerApi::class)
@Suppress("LongMethod")
@Composable
fun TabsTray() {
fun TabsTray(
tabsTrayStore: TabsTrayStore,
) {
val multiselectMode = tabsTrayStore
.observeAsComposableState { state -> state.mode }.value ?: TabsTrayState.Mode.Normal
val pagerState = rememberPagerState(initialPage = 0)
val scope = rememberCoroutineScope()
val animateScrollToPage: ((Int) -> Unit) = { pagePosition ->
val animateScrollToPage: ((Page) -> Unit) = { page ->
scope.launch {
pagerState.animateScrollToPage(pagePosition)
pagerState.animateScrollToPage(page.ordinal)
}
}
@ -46,35 +48,10 @@ fun TabsTray() {
.fillMaxSize()
.background(FirefoxTheme.colors.layer1),
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(all = 16.dp),
) {
Text(
text = "Temporary tab switchers",
color = FirefoxTheme.colors.textPrimary,
style = FirefoxTheme.typography.body1,
)
Spacer(modifier = Modifier.height(16.dp))
PrimaryButton(text = "Normal tabs") {
animateScrollToPage(Page.NormalTabs.ordinal)
}
Spacer(modifier = Modifier.height(16.dp))
PrimaryButton(text = "Private tabs") {
animateScrollToPage(Page.PrivateTabs.ordinal)
}
Spacer(modifier = Modifier.height(16.dp))
PrimaryButton(text = "Synced tabs") {
animateScrollToPage(Page.SyncedTabs.ordinal)
}
}
TabsTrayBanner(
isInMultiSelectMode = multiselectMode is TabsTrayState.Mode.Select,
onTabPageIndicatorClicked = animateScrollToPage,
)
Divider()
@ -120,6 +97,24 @@ fun TabsTray() {
@Composable
private fun TabsTrayPreview() {
FirefoxTheme {
TabsTray()
TabsTray(
tabsTrayStore = TabsTrayStore(),
)
}
}
@LightDarkPreview
@Composable
private fun TabsTrayMultiSelectPreview() {
val store = TabsTrayStore(
initialState = TabsTrayState(
mode = TabsTrayState.Mode.Select(setOf()),
),
)
FirefoxTheme {
TabsTray(
tabsTrayStore = store,
)
}
}

@ -0,0 +1,113 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.tabstray
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import org.mozilla.fenix.compose.annotation.LightDarkPreview
import org.mozilla.fenix.compose.button.PrimaryButton
import org.mozilla.fenix.theme.FirefoxTheme
/**
* Top-level UI for displaying the banner in [TabsTray].
*
* @param isInMultiSelectMode Whether the tab list is in multi-select mode.
* @param onTabPageIndicatorClicked Invoked when the user clicks on a tab page indicator.
*/
@Composable
fun TabsTrayBanner(
isInMultiSelectMode: Boolean,
onTabPageIndicatorClicked: (Page) -> Unit,
) {
if (isInMultiSelectMode) {
MultiSelectBanner()
} else {
SingleSelectBanner(
onTabPageIndicatorClicked = onTabPageIndicatorClicked,
)
}
}
@Composable
private fun SingleSelectBanner(
onTabPageIndicatorClicked: (Page) -> Unit,
) {
Row(
modifier = Modifier
.fillMaxWidth()
.height(80.dp)
.padding(all = 16.dp),
horizontalArrangement = Arrangement.spacedBy(16.dp),
) {
Box(modifier = Modifier.weight(1.0f)) {
PrimaryButton(text = "Normal tabs") {
onTabPageIndicatorClicked(Page.NormalTabs)
}
}
Box(modifier = Modifier.weight(1.0f)) {
PrimaryButton(text = "Private tabs") {
onTabPageIndicatorClicked(Page.PrivateTabs)
}
}
Box(modifier = Modifier.weight(1.0f)) {
PrimaryButton(text = "Synced tabs") {
onTabPageIndicatorClicked(Page.SyncedTabs)
}
}
}
}
@Composable
private fun MultiSelectBanner() {
Box(
modifier = Modifier
.fillMaxWidth()
.height(80.dp)
.background(color = FirefoxTheme.colors.layerAccent),
contentAlignment = Alignment.Center,
) {
Text(
text = "Multi selection mode",
color = FirefoxTheme.colors.textOnColorPrimary,
style = FirefoxTheme.typography.body1,
)
}
}
@LightDarkPreview
@Composable
private fun TabsTrayBannerPreview() {
FirefoxTheme {
Box(modifier = Modifier.background(color = FirefoxTheme.colors.layer1)) {
TabsTrayBanner(
isInMultiSelectMode = false,
onTabPageIndicatorClicked = {},
)
}
}
}
@LightDarkPreview
@Composable
private fun TabsTrayBannerMultiselectPreview() {
FirefoxTheme {
TabsTrayBanner(
isInMultiSelectMode = true,
onTabPageIndicatorClicked = {},
)
}
}

@ -206,7 +206,9 @@ class TabsTrayFragment : AppCompatDialogFragment() {
tabsTrayComposeBinding.root.setContent {
FirefoxTheme {
TabsTray()
TabsTray(
tabsTrayStore = tabsTrayStore,
)
}
}
} else {

Loading…
Cancel
Save