-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* fix: 주석 오타 수정 * feat: button pressed 상태 위한 interactionSource 추가 * feat: BaseButton 구현 * feat: BoxButton 구현 * feat: BoxButton horizontalPadding 파라미터 추가 * feat: BoxButton Preview 추가 * feat: Tertiary BoxButton border 색 지정 * feat: TextButtonSize, BoxButtonSize 분리 * feat: TextButtonSize, BoxButtonSize 분리 * feat: TextButton 구현 * feat: TextButton Preview * feat: 주석 추가 * fix: preview 정렬방식 수정 * fix: indication 기본 파라미터 추가 * fix: 주석 설명 수정 * del: 불필요한 코드 삭제 * del: isDisabled -> enable로 수정 * fix: ButtonSizeState data class 명ButtonStyleProperties로 수정 * del: 최소 사이즈 옵션 삭제 * del: delete FAB file * del: ButtonState와 FloatingActionButtonState 분리 * feat: FloatingActionButton 구현 * feat: FloatingActionButton Preview 파일 생성 * del: 불필요한 주석 삭제 * fix: solved conflict * del: delete FAB file * del: ButtonState와 FloatingActionButtonState 분리 * feat: FloatingActionButton 구현 * feat: FloatingActionButton Preview 파일 생성 * del: 불필요한 주석 삭제
- Loading branch information
1 parent
d769cab
commit 8667f4a
Showing
3 changed files
with
309 additions
and
11 deletions.
There are no files selected for viewing
118 changes: 118 additions & 0 deletions
118
app/src/main/kotlin/com/yourssu/handy/demo/FloatingActionButtonPreview.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
package com.yourssu.handy.demo | ||
|
||
import androidx.compose.foundation.background | ||
import androidx.compose.foundation.layout.Arrangement | ||
import androidx.compose.foundation.layout.Column | ||
import androidx.compose.foundation.layout.Row | ||
import androidx.compose.foundation.layout.fillMaxSize | ||
import androidx.compose.foundation.layout.padding | ||
import androidx.compose.foundation.layout.wrapContentSize | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.ui.Modifier | ||
import androidx.compose.ui.graphics.Color | ||
import androidx.compose.ui.tooling.preview.Preview | ||
import androidx.compose.ui.unit.dp | ||
import com.yourssu.handy.compose.FloatingActionButton | ||
import com.yourssu.handy.compose.FloatingActionButtonSize | ||
import com.yourssu.handy.compose.FloatingActionButtonType | ||
import com.yourssu.handy.compose.HandyTheme | ||
import com.yourssu.handy.compose.icons.HandyIcons | ||
import com.yourssu.handy.compose.icons.line.ArrowsChevronUp | ||
import com.yourssu.handy.compose.icons.line.ExternalLink | ||
|
||
@Composable | ||
@Preview | ||
fun FloatingActionButtonPreview() { | ||
HandyTheme { | ||
Column( | ||
modifier = Modifier | ||
.background(Color.White) | ||
.wrapContentSize() | ||
.padding(20.dp), | ||
verticalArrangement = Arrangement.spacedBy(10.dp) | ||
) { | ||
Row( | ||
horizontalArrangement = Arrangement.spacedBy(20.dp) | ||
) { | ||
Row( | ||
horizontalArrangement = Arrangement.spacedBy(10.dp) | ||
) { | ||
FloatingActionButton( | ||
onClick = {}, | ||
icon = HandyIcons.Line.ArrowsChevronUp, | ||
sizeType = FloatingActionButtonSize.S, | ||
floatingActionButtonType = FloatingActionButtonType.Primary | ||
) | ||
FloatingActionButton( | ||
onClick = {}, | ||
icon = HandyIcons.Line.ExternalLink, | ||
sizeType = FloatingActionButtonSize.S, | ||
floatingActionButtonType = FloatingActionButtonType.Primary, | ||
enabled = false | ||
) | ||
} | ||
|
||
Row( | ||
horizontalArrangement = Arrangement.spacedBy(10.dp) | ||
) { | ||
FloatingActionButton( | ||
onClick = {}, | ||
icon = HandyIcons.Line.ExternalLink, | ||
sizeType = FloatingActionButtonSize.S, | ||
floatingActionButtonType = FloatingActionButtonType.Secondary, | ||
) | ||
|
||
FloatingActionButton( | ||
onClick = {}, | ||
icon = HandyIcons.Line.ExternalLink, | ||
sizeType = FloatingActionButtonSize.S, | ||
floatingActionButtonType = FloatingActionButtonType.Secondary, | ||
enabled = false | ||
) | ||
} | ||
} | ||
|
||
Row( | ||
horizontalArrangement = Arrangement.spacedBy(20.dp) | ||
) { | ||
Row( | ||
horizontalArrangement = Arrangement.spacedBy(10.dp) | ||
) { | ||
FloatingActionButton( | ||
onClick = {}, | ||
icon = HandyIcons.Line.ExternalLink, | ||
sizeType = FloatingActionButtonSize.L, | ||
floatingActionButtonType = FloatingActionButtonType.Primary | ||
) | ||
|
||
FloatingActionButton( | ||
onClick = {}, | ||
icon = HandyIcons.Line.ExternalLink, | ||
sizeType = FloatingActionButtonSize.L, | ||
floatingActionButtonType = FloatingActionButtonType.Primary, | ||
enabled = false | ||
) | ||
} | ||
|
||
Row( | ||
horizontalArrangement = Arrangement.spacedBy(10.dp) | ||
) { | ||
FloatingActionButton( | ||
onClick = {}, | ||
icon = HandyIcons.Line.ExternalLink, | ||
sizeType = FloatingActionButtonSize.L, | ||
floatingActionButtonType = FloatingActionButtonType.Secondary, | ||
) | ||
|
||
FloatingActionButton( | ||
onClick = {}, | ||
icon = HandyIcons.Line.ExternalLink, | ||
sizeType = FloatingActionButtonSize.L, | ||
floatingActionButtonType = FloatingActionButtonType.Secondary, | ||
enabled = false | ||
) | ||
} | ||
} | ||
} | ||
} | ||
} |
191 changes: 191 additions & 0 deletions
191
compose/src/main/kotlin/com/yourssu/handy/compose/FloatingActionButton.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,191 @@ | ||
package com.yourssu.handy.compose | ||
|
||
import androidx.compose.foundation.border | ||
import androidx.compose.foundation.interaction.MutableInteractionSource | ||
import androidx.compose.foundation.interaction.collectIsPressedAsState | ||
import androidx.compose.foundation.layout.Box | ||
import androidx.compose.foundation.layout.size | ||
import androidx.compose.foundation.shape.CircleShape | ||
import androidx.compose.runtime.Composable | ||
import androidx.compose.runtime.Immutable | ||
import androidx.compose.runtime.State | ||
import androidx.compose.runtime.getValue | ||
import androidx.compose.runtime.mutableStateOf | ||
import androidx.compose.runtime.remember | ||
import androidx.compose.runtime.rememberUpdatedState | ||
import androidx.compose.runtime.setValue | ||
import androidx.compose.ui.Alignment | ||
import androidx.compose.ui.Modifier | ||
import androidx.compose.ui.graphics.Color | ||
import androidx.compose.ui.graphics.Shape | ||
import androidx.compose.ui.graphics.vector.ImageVector | ||
import androidx.compose.ui.semantics.Role | ||
import androidx.compose.ui.semantics.role | ||
import androidx.compose.ui.semantics.semantics | ||
import androidx.compose.ui.unit.Dp | ||
import androidx.compose.ui.unit.dp | ||
import com.yourssu.handy.compose.foundation.ColorFabPrimaryShadow | ||
import com.yourssu.handy.compose.foundation.ColorFabSecondaryShadow | ||
import com.yourssu.handy.compose.icons.HandyIcons | ||
import com.yourssu.handy.compose.icons.line.ExternalLink | ||
|
||
enum class FloatingActionButtonSize(internal val value: Dp) { | ||
S(40.dp), | ||
L(56.dp), | ||
} | ||
|
||
enum class FloatingActionButtonType { | ||
Primary, | ||
Secondary; | ||
} | ||
|
||
@Composable | ||
fun FloatingActionButton( | ||
onClick: () -> Unit, | ||
modifier: Modifier = Modifier, | ||
enabled: Boolean = true, | ||
shape: Shape = CircleShape, | ||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, | ||
icon: ImageVector = HandyIcons.Line.ExternalLink, | ||
sizeType: FloatingActionButtonSize = FloatingActionButtonSize.S, | ||
floatingActionButtonType: FloatingActionButtonType = FloatingActionButtonType.Primary, | ||
) { | ||
val colors = floatingActionButtonColorByType(type = floatingActionButtonType) | ||
val localPressed by interactionSource.collectIsPressedAsState() | ||
val containerColor = colors.apply { pressed = localPressed } | ||
val contentColor by containerColor.contentColor(enabled) | ||
val borderColor = containerColor.borderColor() | ||
|
||
val containerSize = boxButtonSizeStateBySize(size = sizeType) | ||
|
||
Surface( | ||
onClick = onClick, | ||
modifier = modifier.semantics { role = Role.Button }, | ||
shape = shape, | ||
backgroundColor = containerColor.backgroundColor(enabled).value, | ||
contentColor = contentColor, | ||
interactionSource = interactionSource, | ||
shadowColor = containerColor.shadowColor(enabled).value, | ||
shadowElevation = FloatingActionButtonDefaults.FloatingActionButtonShadowElevation, | ||
) { | ||
Box( | ||
modifier = Modifier | ||
.size(containerSize.containerSize.value) | ||
.border( | ||
width = FloatingActionButtonDefaults.FloatingActionButtonBorderSize, | ||
color = borderColor.value, | ||
shape = shape | ||
), | ||
contentAlignment = Alignment.Center, | ||
) { | ||
Icon( | ||
imageVector = icon, | ||
iconSize = FloatingActionButtonDefaults.iconSize, | ||
) | ||
} | ||
} | ||
} | ||
|
||
|
||
@Immutable | ||
data class FloatingActionButtonSizeState( | ||
val containerSize: FloatingActionButtonSize = FloatingActionButtonSize.S, | ||
) | ||
|
||
|
||
private fun boxButtonSizeStateBySize( | ||
size: FloatingActionButtonSize, | ||
): FloatingActionButtonSizeState = when (size) { | ||
FloatingActionButtonSize.S -> FloatingActionButtonSizeState( | ||
containerSize = FloatingActionButtonSize.S, | ||
) | ||
|
||
FloatingActionButtonSize.L -> FloatingActionButtonSizeState( | ||
containerSize = FloatingActionButtonSize.L, | ||
) | ||
} | ||
|
||
@Composable | ||
private fun floatingActionButtonColorByType( | ||
type: FloatingActionButtonType, | ||
): FloatingActionButtonColorState = when (type) { | ||
FloatingActionButtonType.Primary -> FloatingActionButtonColorState( | ||
contentColor = HandyTheme.colors.iconBasicWhite, | ||
disabledContentColor = HandyTheme.colors.iconBasicWhite, | ||
bgColor = HandyTheme.colors.buttonFabPrimaryEnabled, | ||
disabledBgColor = HandyTheme.colors.buttonFabPrimaryDisabled, | ||
shadowColor = ColorFabPrimaryShadow, | ||
borderColor = Color.Transparent | ||
) | ||
|
||
FloatingActionButtonType.Secondary -> FloatingActionButtonColorState( | ||
contentColor = HandyTheme.colors.iconBasicTertiary, | ||
disabledContentColor = HandyTheme.colors.iconBasicDisabled, | ||
bgColor = HandyTheme.colors.buttonFabSecondaryEnabled, | ||
disabledBgColor = HandyTheme.colors.buttonFabSecondaryDisabled, | ||
shadowColor = ColorFabSecondaryShadow, | ||
borderColor = HandyTheme.colors.lineBasicLight | ||
) | ||
} | ||
|
||
@Composable | ||
private fun pressedFloatingActionButtonColorFor(color: Color): Color { | ||
return when (color) { | ||
HandyTheme.colors.buttonFabPrimaryEnabled -> HandyTheme.colors.buttonFabPrimaryPressed | ||
HandyTheme.colors.buttonFabSecondaryEnabled -> HandyTheme.colors.buttonFabSecondaryPressed | ||
else -> color | ||
} | ||
} | ||
|
||
@Immutable | ||
class FloatingActionButtonColorState( | ||
val contentColor: Color = Color.Unspecified, | ||
val disabledContentColor: Color = Color.Unspecified, | ||
val bgColor: Color = Color.Transparent, | ||
val disabledBgColor: Color = Color.Transparent, | ||
val shadowColor: Color = Color.Transparent, | ||
val borderColor: Color = Color.Transparent, | ||
pressed: Boolean = false, | ||
) { | ||
var pressed by mutableStateOf(pressed) | ||
internal set | ||
|
||
@Composable | ||
fun contentColor(enabled: Boolean): State<Color> = | ||
rememberUpdatedState( | ||
when { | ||
!enabled -> disabledContentColor | ||
pressed -> pressedFloatingActionButtonColorFor(contentColor) | ||
else -> contentColor | ||
} | ||
) | ||
|
||
@Composable | ||
fun backgroundColor(enabled: Boolean): State<Color> = | ||
rememberUpdatedState( | ||
when { | ||
!enabled -> disabledBgColor | ||
pressed -> pressedFloatingActionButtonColorFor(bgColor) | ||
else -> bgColor | ||
} | ||
) | ||
|
||
@Composable | ||
fun shadowColor(enabled: Boolean): State<Color> = | ||
rememberUpdatedState( | ||
when { | ||
!enabled -> Color.Transparent | ||
else -> shadowColor | ||
} | ||
) | ||
|
||
@Composable | ||
fun borderColor(): State<Color> = | ||
rememberUpdatedState(borderColor) | ||
} | ||
|
||
object FloatingActionButtonDefaults { | ||
val iconSize: IconSize = IconSize.M // 24.dp | ||
val FloatingActionButtonBorderSize = 1.dp | ||
val FloatingActionButtonShadowElevation = 6.dp | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters