-
Notifications
You must be signed in to change notification settings - Fork 0
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
Top Bar 구현 #19
base: main
Are you sure you want to change the base?
Top Bar 구현 #19
Changes from 6 commits
ba38bbc
1d00f4e
f8676db
f331b04
14197b2
3a17cd5
bd1239e
e342649
dfabfcd
40da437
5aacd70
181f8c9
0c95789
5547b99
fd418bb
485705d
19c9829
2867d5f
f6ee7a9
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,10 @@ | ||
package com.yourssu.handy.demo | ||
|
||
import androidx.compose.runtime.Composable | ||
import androidx.compose.ui.tooling.preview.Preview | ||
|
||
@Preview(showBackground = true) | ||
@Composable | ||
fun TopBarPreview() { | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,259 @@ | ||
package com.yourssu.handy.compose | ||
|
||
import android.util.Log | ||
import androidx.compose.foundation.background | ||
import androidx.compose.foundation.clickable | ||
import androidx.compose.foundation.layout.Box | ||
import androidx.compose.foundation.layout.Column | ||
import androidx.compose.foundation.layout.Row | ||
import androidx.compose.foundation.layout.RowScope | ||
import androidx.compose.foundation.layout.Spacer | ||
import androidx.compose.foundation.layout.fillMaxHeight | ||
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.foundation.layout.width | ||
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 com.yourssu.handy.compose.TopBarDefaults.topBarHeight | ||
import com.yourssu.handy.compose.TopBarDefaults.topBarHorizontalPadding | ||
import com.yourssu.handy.compose.foundation.HandyTypography | ||
import com.yourssu.handy.compose.icons.HandyIcons | ||
import com.yourssu.handy.compose.icons.filled.Add | ||
import com.yourssu.handy.compose.icons.filled.ArrowsChevronLeft | ||
import com.yourssu.handy.compose.icons.filled.List | ||
import com.yourssu.handy.compose.icons.line.Add | ||
|
||
sealed interface NavIcon { | ||
data object None : NavIcon | ||
data class Back(val onClick: () -> Unit) : NavIcon | ||
data class Menu(val onClick: () -> Unit) : NavIcon | ||
} | ||
|
||
/** | ||
* Center-Aligned Top App Bar | ||
* | ||
* 타이틀이 중앙에 위치한 탑앱바입니다. 좌측에 메뉴 아이콘 및 뒤로 가기 아이콘이 요구될 경우 사용합니다. | ||
* 아이콘으로 기능을 명확하게 표현하지 못하거나 확실하게 기능을 설명하고 싶을 때 아이콘 대신 Text를 사용할 수 있습니다. | ||
* 이때, 텍스트의 사용은 한 개까지만 가능하며, 텍스트가 공백 포함 5자일 경우 우측에 아이콘을 같이 쓸 수 없습니다. | ||
* | ||
* | ||
* @param title headline or Logo 최대 9자(공백 포함) | ||
* @param navIcon 왼쪽 아이콘 NavIcon.None, NavIcon.Menu, NavIcon.Back | ||
* @param actions 오른쪽 아이콘 or 텍스트 (아이콘은 임의로 변경할 수 있으며 Center-aligned의 우측엔 최대 2개의 아이콘 버튼) | ||
**/ | ||
@Composable | ||
fun CenterAlignedTopAppBar( | ||
title: String, | ||
navIcon: NavIcon, | ||
actions: @Composable (RowScope.() -> Unit)? = null | ||
) { | ||
Box( | ||
modifier = Modifier | ||
.fillMaxWidth() | ||
.background(color = HandyTheme.colors.bgBasicDefault) | ||
.height(topBarHeight), //Top App Bar의 높이값을 임의로 변경하지 않습니다. | ||
contentAlignment = Alignment.Center | ||
) { | ||
Text( | ||
text = title, | ||
color = HandyTheme.colors.textBasicPrimary, | ||
style = HandyTypography.T2Sb18, | ||
textAlign = TextAlign.Center, | ||
) | ||
|
||
Row( | ||
modifier = Modifier | ||
.fillMaxSize() | ||
.padding(horizontal = topBarHorizontalPadding), | ||
verticalAlignment = Alignment.CenterVertically | ||
) { | ||
// Left Icon | ||
IconButton(navIcon) | ||
|
||
Spacer(modifier = Modifier.weight(1f)) | ||
|
||
// Actions | ||
if (actions != null) { | ||
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. 별건 아니지만 전 이런식의 표현이 좀 더 kotlin스러워서 선호합니다 actions?.let{
... // anctions가 null이 아닌경우
} |
||
Row( | ||
verticalAlignment = Alignment.CenterVertically, | ||
modifier = Modifier.fillMaxHeight() | ||
) { | ||
actions() | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
@Composable | ||
private fun RowScope.IconButton(navIcon: NavIcon) { | ||
when (navIcon) { | ||
is NavIcon.Back -> Icon( | ||
imageVector = HandyIcons.Filled.ArrowsChevronLeft, | ||
contentDescription = "Back", | ||
modifier = Modifier.clickable(onClick = navIcon.onClick) | ||
) | ||
|
||
is NavIcon.Menu -> Icon( | ||
imageVector = HandyIcons.Filled.List, | ||
contentDescription = "Menu", | ||
modifier = Modifier.clickable(onClick = navIcon.onClick) | ||
) | ||
|
||
NavIcon.None -> Spacer(modifier = Modifier.width(24.dp)) // 여백 확보 | ||
} | ||
} | ||
|
||
/** | ||
* Left-aligned | ||
* | ||
* 타이틀이 좌측에 위치한 탑앱바입니다. 기능의 첫 페이지에 사용되는 탑앱바로, | ||
* 현재 페이지의 제목을 나타낼 때 사용합니다. 아이콘으로 기능을 명확하게 표현하지 못하거나 확실하게 기능을 설명하고 싶을 때 아이콘 대신 Text를 사용할 수 있습니다. | ||
* | ||
* @param title headline or Logo 최대 9자(공백 포함) | ||
* @param actions 오른쪽 아이콘 or 텍스트 (아이콘은 임의로 변경할 수 있으며 Left-aligned의 우측엔 최대 3개의 아이콘 버튼) | ||
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. actions보다는 다른 명칭이 어떨까용 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. 오른쪽에 들어가는 친구들은 주로 공유하기나 더보기, 신고하기 등 사용자가 주도적으로 액션을 취한다고 생각해서 action이라고 하였습니다! 사실 머테리얼 보고 그렇게 한 걸로 기억하는데, 혹시 추천할만한 네이밍이 있을까요? 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. 흠... 그런 의미가 있다면 우선은 굳이 수정할 필요는 없을 것 같아요 |
||
**/ | ||
@Composable | ||
fun LeftAlignedTopAppBar( | ||
title: String, | ||
actions: @Composable (RowScope.() -> Unit)? = null | ||
Comment on lines
+101
to
+102
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. 여기서 modifier를 안넣은 이유가 있을까요?? 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. 놓친 것 같습니다! 수정했습니닷 🧐 |
||
) { | ||
Box( | ||
modifier = Modifier | ||
.fillMaxWidth() | ||
.background(color = HandyTheme.colors.bgBasicDefault) | ||
.height(topBarHeight), | ||
contentAlignment = Alignment.Center | ||
) { | ||
Row( | ||
modifier = Modifier | ||
.fillMaxSize() | ||
.padding(horizontal = topBarHorizontalPadding), | ||
verticalAlignment = Alignment.CenterVertically | ||
) { | ||
Text( | ||
text = title, | ||
style = HandyTypography.H3Sb24, | ||
color = HandyTheme.colors.textBasicPrimary, | ||
textAlign = TextAlign.Center, | ||
) | ||
|
||
Spacer(modifier = Modifier.weight(1f)) | ||
|
||
// Actions | ||
if (actions != null) { | ||
Row( | ||
verticalAlignment = Alignment.CenterVertically, | ||
modifier = Modifier | ||
.padding(10.dp) | ||
) { | ||
actions() | ||
} | ||
} | ||
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. |
||
} | ||
} | ||
} | ||
|
||
@Preview(showBackground = true) | ||
@Composable | ||
fun CenterAlignedTopAppBarPreview() { | ||
Column { | ||
CenterAlignedTopAppBar( | ||
title = "Centered", | ||
navIcon = NavIcon.None, | ||
actions = {} | ||
) | ||
|
||
CenterAlignedTopAppBar( | ||
title = "Back Example", | ||
navIcon = NavIcon.Back(onClick = { Log.d("TopBarPreview", "Back clicked") }), | ||
actions = { | ||
Text( | ||
text = "Share", | ||
color = HandyTheme.colors.textBrandPrimary, | ||
modifier = Modifier.clickable { Log.d("TopBarPreview", "Share clicked") }) | ||
} | ||
) | ||
|
||
CenterAlignedTopAppBar( | ||
title = "Menu Example", | ||
navIcon = NavIcon.Menu(onClick = { Log.d("TopBarPreview", "Menu clicked") }), | ||
actions = { | ||
Icon( | ||
imageVector = HandyIcons.Filled.Add, | ||
contentDescription = "Add", | ||
modifier = Modifier.clickable { Log.d("TopBarPreview", "Add clicked") } | ||
) | ||
} | ||
) | ||
} | ||
} | ||
|
||
|
||
@Preview(showBackground = true) | ||
@Composable | ||
fun LeftAlignedTopBarPreview() { | ||
Column { | ||
LeftAlignedTopAppBar( | ||
title = "Title", | ||
actions = {} | ||
) | ||
LeftAlignedTopAppBar( | ||
title = "Title", | ||
actions = { | ||
Icon( | ||
imageVector = HandyIcons.Line.Add, | ||
contentDescription = "Add", | ||
modifier = Modifier.clickable { Log.d("TopBarPreview", "Add clicked") } | ||
) | ||
} | ||
) | ||
LeftAlignedTopAppBar( | ||
title = "Title", | ||
actions = { | ||
Icon( | ||
imageVector = HandyIcons.Line.Add, | ||
contentDescription = "Add", | ||
modifier = Modifier.clickable { Log.d("TopBarPreview", "Add clicked") } | ||
) | ||
Icon( | ||
imageVector = HandyIcons.Line.Add, | ||
contentDescription = "Add", | ||
modifier = Modifier.clickable { Log.d("TopBarPreview", "Add clicked") } | ||
) | ||
} | ||
) | ||
LeftAlignedTopAppBar( | ||
title = "Title", | ||
actions = { | ||
Icon( | ||
imageVector = HandyIcons.Line.Add, | ||
contentDescription = "Add", | ||
modifier = Modifier.clickable { Log.d("TopBarPreview", "Add clicked") } | ||
) | ||
Icon( | ||
imageVector = HandyIcons.Line.Add, | ||
contentDescription = "Add", | ||
modifier = Modifier.clickable { Log.d("TopBarPreview", "Add clicked") } | ||
) | ||
Icon( | ||
imageVector = HandyIcons.Line.Add, | ||
contentDescription = "Add", | ||
modifier = Modifier.clickable { Log.d("TopBarPreview", "Add clicked") } | ||
) | ||
} | ||
) | ||
} | ||
} | ||
|
||
|
||
object TopBarDefaults { | ||
val topBarHeight = 56.dp | ||
val topBarHorizontalPadding = 16.dp | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아이콘 개수는 굳이 코드상에서 제한할 필요는 없을 것 같습니다..!
피그마 문서자체가 디자인 가이드이기도 해서요 디자인측에서 고려해서 넘겨주실 것 같아요
게일 PR에서는 require로 강제해주시긴 했는데, 의문이 있어 리뷰남겨둔 상황이라 한번 참고해주세요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이부분은 우선 강제하지 않는 걸로 가도 될 것 같습니다!