Merge pull request #527 from vector-im/feature/bma/designSystem

Preparatory work to integrate new FTUE screen
This commit is contained in:
Benoit Marty 2023-06-07 08:59:13 +02:00 committed by GitHub
commit 6b264a6397
17 changed files with 410 additions and 103 deletions

View file

@ -14,19 +14,14 @@
* limitations under the License. * limitations under the License.
*/ */
@file:OptIn(ExperimentalMaterial3Api::class)
package io.element.android.features.messages.impl.attachments.preview package io.element.android.features.messages.impl.attachments.preview
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
@ -39,6 +34,7 @@ import io.element.android.features.messages.impl.attachments.Attachment
import io.element.android.features.messages.impl.attachments.preview.error.sendAttachmentError import io.element.android.features.messages.impl.attachments.preview.error.sendAttachmentError
import io.element.android.features.messages.impl.media.local.LocalMediaView import io.element.android.features.messages.impl.media.local.LocalMediaView
import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.atomic.molecules.ButtonRowMolecule
import io.element.android.libraries.designsystem.components.ProgressDialog import io.element.android.libraries.designsystem.components.ProgressDialog
import io.element.android.libraries.designsystem.components.dialogs.RetryDialog import io.element.android.libraries.designsystem.components.dialogs.RetryDialog
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
@ -150,9 +146,8 @@ private fun AttachmentsPreviewBottomActions(
onSendClicked: () -> Unit, onSendClicked: () -> Unit,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
Row( ButtonRowMolecule(
modifier = modifier, modifier = modifier,
horizontalArrangement = Arrangement.SpaceBetween
) { ) {
TextButton(onClick = onCancelClicked) { TextButton(onClick = onCancelClicked) {
Text(stringResource(id = StringsR.string.action_cancel)) Text(stringResource(id = StringsR.string.action_cancel))

View file

@ -17,7 +17,6 @@
package io.element.android.features.onboarding.impl package io.element.android.features.onboarding.impl
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
@ -40,6 +39,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule
import io.element.android.libraries.designsystem.atomic.pages.OnBoardingPage import io.element.android.libraries.designsystem.atomic.pages.OnBoardingPage
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
@ -117,12 +117,7 @@ private fun OnBoardingButtons(
onCreateAccount: () -> Unit, onCreateAccount: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
Column( ButtonColumnMolecule(modifier = modifier) {
modifier = modifier
.fillMaxWidth(),
horizontalAlignment = CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
if (state.canLoginWithQrCode) { if (state.canLoginWithQrCode) {
Button( Button(
onClick = { onClick = {

View file

@ -17,19 +17,15 @@
package io.element.android.features.verifysession.impl package io.element.android.features.verifysession.impl
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.TextButton import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -38,25 +34,21 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Async
import io.element.android.libraries.designsystem.ElementTextStyles import io.element.android.libraries.designsystem.ElementTextStyles
import io.element.android.libraries.designsystem.atomic.molecules.ButtonColumnMolecule
import io.element.android.libraries.designsystem.atomic.molecules.IconTitleSubtitleMolecule
import io.element.android.libraries.designsystem.atomic.pages.HeaderFooterPage
import io.element.android.libraries.designsystem.components.button.ButtonWithProgress import io.element.android.libraries.designsystem.components.button.ButtonWithProgress
import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.LocalColors
import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Surface
import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.matrix.api.verification.VerificationEmoji import io.element.android.libraries.matrix.api.verification.VerificationEmoji
import io.element.android.features.verifysession.impl.VerifySelfSessionState.VerificationStep as FlowStep import io.element.android.features.verifysession.impl.VerifySelfSessionState.VerificationStep as FlowStep
@ -82,21 +74,18 @@ fun VerifySelfSessionView(
val buttonsVisible by remember(verificationFlowStep) { val buttonsVisible by remember(verificationFlowStep) {
derivedStateOf { verificationFlowStep != FlowStep.AwaitingOtherDeviceResponse && verificationFlowStep != FlowStep.Completed } derivedStateOf { verificationFlowStep != FlowStep.AwaitingOtherDeviceResponse && verificationFlowStep != FlowStep.Completed }
} }
Surface { HeaderFooterPage(
Column(modifier = modifier.systemBarsPadding()) { modifier = modifier,
Column( header = {
modifier = Modifier HeaderContent(verificationFlowStep = verificationFlowStep)
.fillMaxWidth() },
.weight(1f) footer = {
.padding(horizontal = 20.dp)
) {
HeaderContent(verificationFlowStep = verificationFlowStep)
Content(modifier = Modifier.weight(1f), flowState = verificationFlowStep)
}
if (buttonsVisible) { if (buttonsVisible) {
BottomMenu(screenState = state, goBack = ::goBackAndCancelIfNeeded) BottomMenu(screenState = state, goBack = ::goBackAndCancelIfNeeded)
} }
} }
) {
Content(flowState = verificationFlowStep)
} }
} }
@ -121,58 +110,22 @@ internal fun HeaderContent(verificationFlowStep: FlowStep, modifier: Modifier =
FlowStep.Ready, is FlowStep.Verifying, FlowStep.Completed -> R.string.screen_session_verification_compare_emojis_subtitle FlowStep.Ready, is FlowStep.Verifying, FlowStep.Completed -> R.string.screen_session_verification_compare_emojis_subtitle
} }
Column(modifier) { IconTitleSubtitleMolecule(
Spacer(Modifier.height(80.dp)) modifier = modifier.padding(top = 60.dp),
Box( iconResourceId = iconResourceId,
modifier = Modifier title = stringResource(id = titleTextId),
.size(width = 70.dp, height = 70.dp) subTitle = stringResource(id = subtitleTextId)
.align(Alignment.CenterHorizontally) )
.background(
color = LocalColors.current.quinary,
shape = RoundedCornerShape(14.dp)
)
) {
Spacer(modifier = Modifier.height(68.dp))
Icon(
modifier = Modifier
.align(Alignment.Center)
.size(width = 48.dp, height = 48.dp),
tint = MaterialTheme.colorScheme.secondary,
resourceId = iconResourceId,
contentDescription = "",
)
}
Spacer(modifier = Modifier.height(16.dp))
Text(
text = stringResource(id = titleTextId),
modifier = Modifier
.fillMaxWidth()
.align(Alignment.CenterHorizontally),
textAlign = TextAlign.Center,
style = ElementTextStyles.Bold.title2,
color = MaterialTheme.colorScheme.primary,
)
Spacer(Modifier.height(8.dp))
Text(
text = stringResource(id = subtitleTextId),
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center,
style = ElementTextStyles.Regular.subheadline,
color = MaterialTheme.colorScheme.secondary,
)
}
} }
@Composable @Composable
internal fun Content(flowState: FlowStep, modifier: Modifier = Modifier) { internal fun Content(flowState: FlowStep, modifier: Modifier = Modifier) {
Column(modifier, verticalArrangement = Arrangement.Center) { Column(modifier.fillMaxHeight(), verticalArrangement = Arrangement.Center) {
Spacer(Modifier.shrinkableHeight(min = 20.dp, max = 56.dp))
when (flowState) { when (flowState) {
FlowStep.Initial, FlowStep.Ready, FlowStep.Canceled, FlowStep.Completed -> Unit FlowStep.Initial, FlowStep.Ready, FlowStep.Canceled, FlowStep.Completed -> Unit
FlowStep.AwaitingOtherDeviceResponse -> ContentWaiting() FlowStep.AwaitingOtherDeviceResponse -> ContentWaiting()
is FlowStep.Verifying -> ContentVerifying(flowState) is FlowStep.Verifying -> ContentVerifying(flowState)
} }
Spacer(Modifier.shrinkableHeight(min = 20.dp, max = 56.dp))
} }
} }
@ -259,11 +212,8 @@ internal fun BottomMenu(screenState: VerifySelfSessionState, goBack: () -> Unit)
else -> goBack else -> goBack
} }
Column( ButtonColumnMolecule(
modifier = Modifier modifier = Modifier.padding(bottom = 20.dp)
.fillMaxWidth()
.padding(horizontal = 20.dp),
horizontalAlignment = Alignment.CenterHorizontally
) { ) {
ButtonWithProgress( ButtonWithProgress(
text = positiveButtonTitle?.let { stringResource(it) }, text = positiveButtonTitle?.let { stringResource(it) },
@ -272,7 +222,6 @@ internal fun BottomMenu(screenState: VerifySelfSessionState, goBack: () -> Unit)
onClick = { positiveButtonEvent?.let { eventSink(it) } } onClick = { positiveButtonEvent?.let { eventSink(it) } }
) )
if (negativeButtonTitle != null) { if (negativeButtonTitle != null) {
Spacer(modifier = Modifier.height(16.dp))
TextButton( TextButton(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
onClick = negativeButtonCallback, onClick = negativeButtonCallback,
@ -281,7 +230,6 @@ internal fun BottomMenu(screenState: VerifySelfSessionState, goBack: () -> Unit)
Text(stringResource(negativeButtonTitle), fontSize = 16.sp) Text(stringResource(negativeButtonTitle), fontSize = 16.sp)
} }
} }
Spacer(Modifier.height(40.dp))
} }
} }
@ -302,15 +250,3 @@ private fun ContentToPreview(state: VerifySelfSessionState) {
goBack = {}, goBack = {},
) )
} }
private fun Modifier.shrinkableHeight(
min: Dp,
max: Dp,
minScreenHeight: Int = 720
): Modifier = composed {
if (LocalConfiguration.current.screenHeightDp >= minScreenHeight) {
then(Modifier.height(max))
} else {
then(Modifier.height(min))
}
}

View file

@ -0,0 +1,69 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.designsystem.atomic.molecules
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.components.Button
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TextButton
@Composable
fun ButtonColumnMolecule(
modifier: Modifier = Modifier,
content: @Composable ColumnScope.() -> Unit
) {
Column(
modifier = modifier
.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.spacedBy(16.dp),
) {
content()
}
}
@Preview
@Composable
internal fun ButtonColumnMoleculeLightPreview() =
ElementPreviewLight { ContentToPreview() }
@Preview
@Composable
internal fun ButtonColumnMoleculeDarkPreview() =
ElementPreviewDark { ContentToPreview() }
@Composable
private fun ContentToPreview() {
ButtonColumnMolecule {
Button(onClick = {}, modifier = Modifier.fillMaxWidth()) {
Text(text = "Button")
}
TextButton(onClick = {}, modifier = Modifier.fillMaxWidth()) {
Text(text = "TextButton")
}
}
}

View file

@ -0,0 +1,64 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.designsystem.atomic.molecules
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TextButton
@Composable
fun ButtonRowMolecule(
modifier: Modifier = Modifier,
content: @Composable RowScope.() -> Unit
) {
Row(
modifier = modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween
) {
content()
}
}
@Preview
@Composable
internal fun ButtonRowMoleculeLightPreview() =
ElementPreviewLight { ContentToPreview() }
@Preview
@Composable
internal fun ButtonRowMoleculeDarkPreview() =
ElementPreviewDark { ContentToPreview() }
@Composable
private fun ContentToPreview() {
ButtonRowMolecule {
TextButton(onClick = { }) {
Text("Button 1")
}
TextButton(onClick = { }) {
Text("Button 2")
}
}
}

View file

@ -0,0 +1,105 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.designsystem.atomic.molecules
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.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import io.element.android.libraries.designsystem.ElementTextStyles
import io.element.android.libraries.designsystem.R
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.LocalColors
import io.element.android.libraries.designsystem.theme.components.Icon
import io.element.android.libraries.designsystem.theme.components.Text
@Composable
fun IconTitleSubtitleMolecule(
iconResourceId: Int,
title: String,
subTitle: String,
modifier: Modifier = Modifier,
) {
Column(modifier) {
Box(
modifier = Modifier
.size(width = 70.dp, height = 70.dp)
.align(Alignment.CenterHorizontally)
.background(
color = LocalColors.current.quinary,
shape = RoundedCornerShape(14.dp)
)
) {
Icon(
modifier = Modifier
.align(Alignment.Center)
.size(width = 48.dp, height = 48.dp),
tint = MaterialTheme.colorScheme.secondary,
resourceId = iconResourceId,
contentDescription = "",
)
}
Spacer(modifier = Modifier.height(16.dp))
Text(
text = title,
modifier = Modifier
.fillMaxWidth(),
textAlign = TextAlign.Center,
style = ElementTextStyles.Bold.title2,
color = MaterialTheme.colorScheme.primary,
)
Spacer(Modifier.height(8.dp))
Text(
text = subTitle,
modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center,
style = ElementTextStyles.Regular.subheadline,
color = MaterialTheme.colorScheme.secondary,
)
}
}
@Preview
@Composable
internal fun IconTitleSubtitleMoleculeLightPreview() =
ElementPreviewLight { ContentToPreview() }
@Preview
@Composable
internal fun IconTitleSubtitleMoleculeDarkPreview() =
ElementPreviewDark { ContentToPreview() }
@Composable
private fun ContentToPreview() {
IconTitleSubtitleMolecule(
iconResourceId = R.drawable.ic_edit,
title = "Title",
subTitle = "Sub iitle",
)
}

View file

@ -0,0 +1,119 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.libraries.designsystem.atomic.pages
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import io.element.android.libraries.designsystem.preview.ElementPreviewDark
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
import io.element.android.libraries.designsystem.theme.components.Text
/**
* @param modifier Classical modifier.
* @param header optional header.
* @param footer optional footer.
* @param content main content.
*/
@Composable
fun HeaderFooterPage(
modifier: Modifier = Modifier,
header: @Composable () -> Unit = {},
footer: @Composable () -> Unit = {},
content: @Composable () -> Unit = {},
) {
Column(
modifier = modifier
.fillMaxSize()
.systemBarsPadding()
.padding(all = 20.dp),
) {
// Header
header()
// Content
Column(
modifier = Modifier
.weight(1f)
.fillMaxWidth(),
) {
content()
}
// Footer
footer()
}
}
@Preview
@Composable
internal fun HeaderFooterPageLightPreview() =
ElementPreviewLight { ContentToPreview() }
@Preview
@Composable
internal fun HeaderFooterPageDarkPreview() =
ElementPreviewDark { ContentToPreview() }
@Composable
private fun ContentToPreview() {
HeaderFooterPage(
content = {
Box(
Modifier
.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Text(
text = "Content",
fontSize = 40.sp
)
}
},
header = {
Box(
Modifier
.fillMaxWidth(),
contentAlignment = Alignment.Center
) {
Text(
text = "Header",
fontSize = 40.sp
)
}
},
footer = {
Box(
Modifier
.fillMaxWidth(),
contentAlignment = Alignment.Center
) {
Text(
text = "Footer",
fontSize = 40.sp
)
}
}
)
}

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:0162d20f04bfdd0fdd6eb6e00b18b5774f83f07a5c7a72d20d0f51988b05dc66 oid sha256:bff3aaf96ea36cd876e0bb262155f7da0a5e110ab5308872bf43d80fa50da414
size 26899 size 26909

View file

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:dd0c4a8485e00b917265b6061ee901a9f131883069621d55f3f5c9a42673046c oid sha256:ff5f22bda0c7deaaba6e8006abdd7e0c9ba1562016ae62ad41b6a70e67737fdc
size 26182 size 26179

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9042cbbca031bfd3e5ad357e1794a9b709448eb9194437dca51d8013d2e35028
size 9624

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3c402ba186ccaaefdc4994985867d33e2d877268b1a31a27d3c8e1b9d57f31fb
size 9547

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:21bce29c6b994eea9ba101871ef7d86d73283f4d5275ff1b68ffce7544a6ec44
size 7780

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:77e755537de1798e91b29a039e9dbea843f0680ef4a4599afab16f0cab83ab3c
size 7560

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:73d4db2c6cdd12c05672affc584c75161aa481fd0065c1b084f32ed4c3481c66
size 10605

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7aadaccb2874346a08bbdcf2cd8d51fd1490319e10c22065611c70543ce8d28d
size 9695

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a42089270cb47006962e1d953cc44c827cfb6928d17af8d071d3dd3a9907892c
size 17125

View file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:196ba6c67c3f586b0e5ec2c8feb5a345ecc4fba0df0ad49a38b097b12f5c96ea
size 16017