-
Notifications
You must be signed in to change notification settings - Fork 1
PrezelSnackBar 구현 #47
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 6 commits
620c1bf
f20165b
098ea6e
0e682ec
0e1dcba
db516c8
534b6a5
b5156b2
4f18842
2db93d3
14a69f1
f0c9d91
d867401
1af4cb9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,198 @@ | ||
| package com.team.prezel.core.designsystem.component.snackbar | ||
|
|
||
| import androidx.compose.foundation.background | ||
| import androidx.compose.foundation.clickable | ||
| import androidx.compose.foundation.layout.Arrangement | ||
| import androidx.compose.foundation.layout.Column | ||
| import androidx.compose.foundation.layout.PaddingValues | ||
| import androidx.compose.foundation.layout.Row | ||
| import androidx.compose.foundation.layout.Spacer | ||
| import androidx.compose.foundation.layout.fillMaxWidth | ||
| import androidx.compose.foundation.layout.heightIn | ||
| import androidx.compose.foundation.layout.padding | ||
| import androidx.compose.foundation.layout.size | ||
| import androidx.compose.foundation.layout.width | ||
| import androidx.compose.foundation.shape.RoundedCornerShape | ||
| import androidx.compose.material3.Icon | ||
| import androidx.compose.material3.SnackbarData | ||
| import androidx.compose.material3.SnackbarDuration | ||
| import androidx.compose.material3.SnackbarVisuals | ||
| import androidx.compose.material3.Surface | ||
| import androidx.compose.material3.Text | ||
| import androidx.compose.runtime.Composable | ||
| import androidx.compose.runtime.Immutable | ||
| import androidx.compose.ui.Alignment | ||
| import androidx.compose.ui.Modifier | ||
| import androidx.compose.ui.graphics.Shape | ||
| import androidx.compose.ui.semantics.Role | ||
| import androidx.compose.ui.unit.dp | ||
| import com.team.prezel.core.designsystem.foundation.typography.PrezelTextStyles | ||
| import com.team.prezel.core.designsystem.icon.DrawableIcon | ||
| import com.team.prezel.core.designsystem.icon.IconSource | ||
| import com.team.prezel.core.designsystem.icon.PrezelIcons | ||
| import com.team.prezel.core.designsystem.preview.ThemePreview | ||
| import com.team.prezel.core.designsystem.theme.PrezelColorScheme | ||
| import com.team.prezel.core.designsystem.theme.PrezelTheme | ||
|
|
||
| @Immutable | ||
| internal object PrezelSnackbarDefaults { | ||
| val IconSize = 20.dp | ||
|
|
||
| val ContentPadding = PaddingValues( | ||
| start = 16.dp, | ||
| end = 8.dp, | ||
| top = 6.dp, | ||
| bottom = 6.dp, | ||
| ) | ||
|
|
||
| val Shape: Shape = RoundedCornerShape(12.dp) | ||
|
|
||
| val IconMessageSpacing = 8.dp | ||
| val MessageActionSpacing = 16.dp | ||
|
|
||
| val ActionTouchPadding = PaddingValues( | ||
| horizontal = 12.dp, | ||
| vertical = 8.dp, | ||
| ) | ||
| } | ||
|
|
||
| @Composable | ||
| fun PrezelSnackbar( | ||
| data: SnackbarData, | ||
| modifier: Modifier = Modifier, | ||
| leadingIcon: IconSource? = null, | ||
| ) { | ||
| Surface( | ||
| modifier = modifier, | ||
| shape = PrezelSnackbarDefaults.Shape, | ||
| color = PrezelColorScheme.Dark.bgMedium, | ||
| ) { | ||
|
HamBeomJoon marked this conversation as resolved.
Outdated
|
||
| PrezelSnackbarContent( | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Snackbar(
...
컨테이너 글자 아이콘 등 색상 정의
...
content: @Composable () -> Unit
)해당 컴포넌트를 사용해서 디자인만 입혀도 될 것 같은데 스낵바 뷰 자체를 구현하신 이유가 궁금해요 지금 보면 기존 스낵바에서 처리해주고 있는 로직들이 모두 포함되고 있지 않아 보여요 디자인 제약 상 위 컴포넌트를 사용하지 못한다면 기존 스낵바에서 처리해주는 로직을 모두 포함하고 있는지 검토 부탁드려요.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 기존 Material Snackbar는 레이아웃과 spacing이 강하게 고정되어 있어서 Prezel 디자인 요구사항(leading icon, spacing, touch 영역, minHeight)을 구현하기 힘들다 생각해서 따로 만들었습니다.
은 다른 리뷰에서말한 action 클릭 결과같은걸 말하는걸까요? |
||
| data = data, | ||
| leadingIcon = leadingIcon, | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| @Composable | ||
| fun PrezelSnackbarContent( | ||
| data: SnackbarData, | ||
| modifier: Modifier = Modifier, | ||
| leadingIcon: IconSource? = null, | ||
| ) { | ||
| Row( | ||
| modifier = modifier | ||
| .fillMaxWidth() | ||
| .heightIn(min = 48.dp) | ||
| .padding(PrezelSnackbarDefaults.ContentPadding), | ||
| verticalAlignment = Alignment.CenterVertically, | ||
| ) { | ||
| leadingIcon?.let { | ||
| PrezelSnackbarLeadingIcon(icon = it) | ||
| Spacer(Modifier.width(PrezelSnackbarDefaults.IconMessageSpacing)) | ||
| } | ||
|
|
||
| Text( | ||
| text = data.visuals.message, | ||
| modifier = Modifier | ||
| .padding(top = 8.dp, bottom = 8.dp, end = 8.dp) | ||
|
HamBeomJoon marked this conversation as resolved.
Outdated
|
||
| .weight(1f), | ||
| color = PrezelColorScheme.Dark.textLarge, | ||
| style = PrezelTextStyles.Body3Regular.toTextStyle(), | ||
| ) | ||
|
|
||
| data.visuals.actionLabel?.let { label -> | ||
| Spacer(Modifier.width(PrezelSnackbarDefaults.MessageActionSpacing)) | ||
|
|
||
| Text( | ||
| text = label, | ||
| modifier = Modifier | ||
| .clickable(role = Role.Button, onClick = { data.performAction() }) | ||
| .padding(PrezelSnackbarDefaults.ActionTouchPadding), | ||
| color = PrezelColorScheme.Dark.interactiveRegular, | ||
| style = PrezelTextStyles.Body3Medium.toTextStyle(), | ||
| ) | ||
| } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log찍어본 결과 onClick = { data.performAction() }으로 잘 반환됩니다 |
||
| } | ||
| } | ||
|
|
||
| @Composable | ||
| private fun PrezelSnackbarLeadingIcon( | ||
| icon: IconSource, | ||
| modifier: Modifier = Modifier, | ||
| ) { | ||
| Icon( | ||
| painter = icon.painter(), | ||
| contentDescription = icon.contentDescription(), | ||
| modifier = modifier.size(PrezelSnackbarDefaults.IconSize), | ||
| tint = PrezelColorScheme.Dark.iconLarge, | ||
| ) | ||
| } | ||
|
|
||
| @ThemePreview | ||
| @Composable | ||
| private fun PrezelSnackBarPreview_Cases() { | ||
|
HamBeomJoon marked this conversation as resolved.
|
||
| PrezelTheme { | ||
| Column( | ||
| modifier = Modifier | ||
| .background(PrezelTheme.colors.bgRegular) | ||
| .padding(16.dp), | ||
| verticalArrangement = Arrangement.spacedBy(12.dp), | ||
| ) { | ||
|
HamBeomJoon marked this conversation as resolved.
Outdated
|
||
| Text("Action O / Icon O") | ||
| PrezelSnackbar( | ||
| data = previewData(message = "Message", actionLabel = "Action"), | ||
| leadingIcon = DrawableIcon(PrezelIcons.Blank), | ||
| modifier = Modifier.fillMaxWidth(), | ||
| ) | ||
|
|
||
| Text("Action O / Icon X") | ||
| PrezelSnackbar( | ||
| data = previewData(message = "Message Message Message Message Message", actionLabel = "Action"), | ||
| leadingIcon = null, | ||
| modifier = Modifier.fillMaxWidth(), | ||
| ) | ||
|
|
||
| Text("Action X / Icon O") | ||
| PrezelSnackbar( | ||
| data = previewData(message = "Message", actionLabel = null), | ||
| leadingIcon = DrawableIcon(PrezelIcons.Blank), | ||
| modifier = Modifier.fillMaxWidth(), | ||
| ) | ||
|
|
||
| Text("Action X / Icon X") | ||
| PrezelSnackbar( | ||
| data = previewData(message = "Message Message Message Message Message", actionLabel = null), | ||
| leadingIcon = null, | ||
| modifier = Modifier.fillMaxWidth(), | ||
| ) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| @Composable | ||
| private fun previewData( | ||
| message: String, | ||
| actionLabel: String?, | ||
| ): SnackbarData = | ||
| PreviewSnackbarData( | ||
| visuals = PreviewSnackbarVisuals( | ||
| message = message, | ||
| actionLabel = actionLabel, | ||
| ), | ||
| ) | ||
|
|
||
| private data class PreviewSnackbarVisuals( | ||
| override val message: String, | ||
| override val actionLabel: String? = null, | ||
| override val withDismissAction: Boolean = false, | ||
| override val duration: SnackbarDuration = SnackbarDuration.Short, | ||
| ) : SnackbarVisuals | ||
|
|
||
| private class PreviewSnackbarData( | ||
| override val visuals: SnackbarVisuals, | ||
| ) : SnackbarData { | ||
| override fun performAction() {} | ||
|
|
||
| override fun dismiss() {} | ||
| } | ||
|
coderabbitai[bot] marked this conversation as resolved.
coderabbitai[bot] marked this conversation as resolved.
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| package com.team.prezel.core.designsystem.component.snackbar | ||
|
|
||
| import androidx.compose.material3.SnackbarDuration | ||
| import androidx.compose.material3.SnackbarHost | ||
| import androidx.compose.material3.SnackbarHostState | ||
| import androidx.compose.material3.SnackbarVisuals | ||
| import androidx.compose.runtime.Composable | ||
| import androidx.compose.ui.Modifier | ||
| import com.team.prezel.core.designsystem.icon.IconSource | ||
|
|
||
| data class PrezelSnackbarVisuals( | ||
| override val message: String, | ||
| override val actionLabel: String?, | ||
| override val withDismissAction: Boolean, | ||
| override val duration: SnackbarDuration, | ||
| val leadingIcon: IconSource?, | ||
| ) : SnackbarVisuals | ||
|
|
||
| suspend fun SnackbarHostState.showPrezelSnackbar( | ||
| message: String, | ||
| leadingIcon: IconSource?, | ||
| actionLabel: String? = null, | ||
| withDismissAction: Boolean = false, | ||
|
HamBeomJoon marked this conversation as resolved.
Outdated
|
||
| duration: SnackbarDuration = SnackbarDuration.Short, | ||
| ) { | ||
|
HamBeomJoon marked this conversation as resolved.
|
||
| showSnackbar( | ||
| visuals = PrezelSnackbarVisuals( | ||
| message = message, | ||
| actionLabel = actionLabel, | ||
| withDismissAction = withDismissAction, | ||
| duration = duration, | ||
| leadingIcon = leadingIcon, | ||
| ), | ||
| ) | ||
| } | ||
|
|
||
| @Composable | ||
| fun PrezelSnackbarHost( | ||
| hostState: SnackbarHostState, | ||
| modifier: Modifier = Modifier, | ||
| ) { | ||
| SnackbarHost( | ||
| hostState = hostState, | ||
| modifier = modifier, | ||
| ) { data -> | ||
| val visuals = data.visuals | ||
| val leadingIcon = (visuals as? PrezelSnackbarVisuals)?.leadingIcon | ||
|
HamBeomJoon marked this conversation as resolved.
Outdated
|
||
|
|
||
| PrezelSnackbar( | ||
| data = data, | ||
| leadingIcon = leadingIcon, | ||
| ) | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.