diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/PrezelButtonStyle.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/PrezelButtonStyle.kt index f98193e..6691d93 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/PrezelButtonStyle.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/PrezelButtonStyle.kt @@ -54,7 +54,7 @@ internal fun PrezelButtonIcon( if (icon == null) return Icon( painter = icon.painter(), - contentDescription = icon.contentDescription, + contentDescription = icon.contentDescription(), modifier = modifier.size( when (size) { PrezelButtonSize.XSMALL -> 14.dp diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/floating/PrezelFloatingButton.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/floating/PrezelFloatingButton.kt new file mode 100644 index 0000000..9ed408d --- /dev/null +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/floating/PrezelFloatingButton.kt @@ -0,0 +1,80 @@ +package com.team.prezel.core.designsystem.component.button.floating + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material3.FloatingActionButton +import androidx.compose.material3.FloatingActionButtonDefaults +import androidx.compose.material3.Icon +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +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.PrezelTheme + +@Composable +fun PrezelFloatingButton( + iconSource: IconSource, + onClick: () -> Unit, + modifier: Modifier = Modifier, + style: PrezelFloatingButtonStyle = PrezelFloatingButtonStyle(), +) { + FloatingActionButton( + onClick = onClick, + modifier = modifier + .applyPrezelFloatingButtonShadow() + .size(prezelFloatingButtonSize(style.size)), + shape = PrezelTheme.shapes.V1000, + containerColor = prezelFloatingButtonContainerColor(style.hierarchy), + contentColor = prezelFloatingButtonContentColor(style.hierarchy), + elevation = FloatingActionButtonDefaults.bottomAppBarFabElevation(), + ) { + Icon( + painter = iconSource.painter(), + contentDescription = iconSource.contentDescription(), + modifier = Modifier.size(prezelFloatingButtonIconSize(style.size)), + ) + } +} + +@ThemePreview +@Composable +private fun PrezelFloatingButtonPreview() { + PrezelTheme { + Column( + modifier = Modifier + .background(PrezelTheme.colors.bgRegular) + .padding(12.dp), + verticalArrangement = Arrangement.spacedBy(8.dp), + ) { + PrezelFloatingButton( + iconSource = DrawableIcon(resId = PrezelIcons.Blank), + style = PrezelFloatingButtonStyle(hierarchy = PrezelFloatingButtonHierarchy.PRIMARY, size = PrezelFloatingButtonSize.REGULAR), + onClick = {}, + ) + + PrezelFloatingButton( + iconSource = DrawableIcon(resId = PrezelIcons.Blank), + style = PrezelFloatingButtonStyle(hierarchy = PrezelFloatingButtonHierarchy.PRIMARY, size = PrezelFloatingButtonSize.SMALL), + onClick = {}, + ) + + PrezelFloatingButton( + iconSource = DrawableIcon(resId = PrezelIcons.Blank), + style = PrezelFloatingButtonStyle(hierarchy = PrezelFloatingButtonHierarchy.SECONDARY, size = PrezelFloatingButtonSize.REGULAR), + onClick = {}, + ) + + PrezelFloatingButton( + iconSource = DrawableIcon(resId = PrezelIcons.Blank), + style = PrezelFloatingButtonStyle(hierarchy = PrezelFloatingButtonHierarchy.SECONDARY, size = PrezelFloatingButtonSize.SMALL), + onClick = {}, + ) + } + } +} diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/floating/PrezelFloatingButtonMenuItem.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/floating/PrezelFloatingButtonMenuItem.kt new file mode 100644 index 0000000..5b198d2 --- /dev/null +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/floating/PrezelFloatingButtonMenuItem.kt @@ -0,0 +1,84 @@ +package com.team.prezel.core.designsystem.component.button.floating + +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.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.material3.ripple +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.unit.dp +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.PrezelTheme + +@Composable +fun PrezelFloatingButtonMenuItem( + label: String, + onClick: () -> Unit, + modifier: Modifier = Modifier, + iconSource: IconSource? = null, +) { + Row( + modifier = modifier + .fillMaxWidth() + .clip(PrezelTheme.shapes.V6) + .clickable( + indication = ripple(), + interactionSource = null, + onClick = onClick, + ).padding(prezelFloatingButtonMenuItemPaddingValues()), + verticalAlignment = Alignment.CenterVertically, + ) { + iconSource?.let { source -> PrezelFloatingButtonMenuItemIcon(iconSource = source) } + Text(text = label, style = prezelFloatingButtonMenuItemTextStyle()) + } +} + +@Composable +private fun PrezelFloatingButtonMenuItemIcon(iconSource: IconSource) { + Icon( + painter = iconSource.painter(), + contentDescription = iconSource.contentDescription(), + modifier = Modifier.size(prezelFloatingButtonMenuItemIconSize()), + ) + + Spacer(modifier = Modifier.width(prezelFloatingButtonMenuItemSpaceDp())) +} + +@ThemePreview +@Composable +private fun PrezelFloatingButtonMenuItemPreview() { + PrezelTheme { + Column( + verticalArrangement = Arrangement.spacedBy(8.dp), + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .background(PrezelTheme.colors.bgRegular) + .padding(16.dp), + ) { + PrezelFloatingButtonMenuItem( + label = "Label", + onClick = {}, + iconSource = DrawableIcon(resId = PrezelIcons.Blank), + ) + + PrezelFloatingButtonMenuItem( + label = "Label", + onClick = {}, + ) + } + } +} diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/floating/PrezelFloatingButtonMenuItemStyle.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/floating/PrezelFloatingButtonMenuItemStyle.kt new file mode 100644 index 0000000..8371677 --- /dev/null +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/floating/PrezelFloatingButtonMenuItemStyle.kt @@ -0,0 +1,64 @@ +package com.team.prezel.core.designsystem.component.button.floating + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.runtime.Composable +import androidx.compose.runtime.compositionLocalOf +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import com.team.prezel.core.designsystem.foundation.number.PrezelSpacing +import com.team.prezel.core.designsystem.foundation.typography.PrezelTypography +import com.team.prezel.core.designsystem.theme.PrezelTheme + +enum class PrezelFloatingButtonMenuItemSize { + SMALL, + REGULAR, + ; + + companion object { + fun buttonMenuItemSize(size: PrezelFloatingButtonSize): PrezelFloatingButtonMenuItemSize = + when (size) { + PrezelFloatingButtonSize.SMALL -> SMALL + PrezelFloatingButtonSize.REGULAR -> REGULAR + } + } +} + +internal val LocalPrezelFloatingButtonMenuItemSize = compositionLocalOf { PrezelFloatingButtonMenuItemSize.REGULAR } + +@Composable +internal fun prezelFloatingButtonMenuItemTextStyle( + size: PrezelFloatingButtonMenuItemSize = LocalPrezelFloatingButtonMenuItemSize.current, + typography: PrezelTypography = PrezelTheme.typography, +): TextStyle = + when (size) { + PrezelFloatingButtonMenuItemSize.SMALL -> typography.body3Regular + PrezelFloatingButtonMenuItemSize.REGULAR -> typography.body2Regular + } + +@Composable +internal fun prezelFloatingButtonMenuItemPaddingValues( + size: PrezelFloatingButtonMenuItemSize = LocalPrezelFloatingButtonMenuItemSize.current, + spacing: PrezelSpacing = PrezelTheme.spacing, +): PaddingValues = + when (size) { + PrezelFloatingButtonMenuItemSize.SMALL -> spacing.V8 to spacing.V4 + PrezelFloatingButtonMenuItemSize.REGULAR -> spacing.V12 to spacing.V8 + }.let { (horizontal, vertical) -> PaddingValues(horizontal = horizontal, vertical = vertical) } + +@Composable +internal fun prezelFloatingButtonMenuItemIconSize(size: PrezelFloatingButtonMenuItemSize = LocalPrezelFloatingButtonMenuItemSize.current): Dp = + when (size) { + PrezelFloatingButtonMenuItemSize.SMALL -> 16.dp + PrezelFloatingButtonMenuItemSize.REGULAR -> 20.dp + } + +@Composable +internal fun prezelFloatingButtonMenuItemSpaceDp( + size: PrezelFloatingButtonMenuItemSize = LocalPrezelFloatingButtonMenuItemSize.current, + spacing: PrezelSpacing = PrezelTheme.spacing, +): Dp = + when (size) { + PrezelFloatingButtonMenuItemSize.SMALL -> spacing.V4 + PrezelFloatingButtonMenuItemSize.REGULAR -> spacing.V8 + } diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/floating/PrezelFloatingButtonStyle.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/floating/PrezelFloatingButtonStyle.kt new file mode 100644 index 0000000..d9774d4 --- /dev/null +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/floating/PrezelFloatingButtonStyle.kt @@ -0,0 +1,101 @@ +package com.team.prezel.core.designsystem.component.button.floating + +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import com.team.prezel.core.designsystem.foundation.color.PrezelColors +import com.team.prezel.core.designsystem.foundation.number.PrezelSpacing +import com.team.prezel.core.designsystem.theme.PrezelColorScheme +import com.team.prezel.core.designsystem.theme.PrezelTheme +import com.team.prezel.core.designsystem.util.dropShadowCache + +enum class PrezelFloatingButtonHierarchy { + PRIMARY, + SECONDARY, +} + +enum class PrezelFloatingButtonSize { + SMALL, + REGULAR, +} + +@Immutable +data class PrezelFloatingButtonStyle( + val hierarchy: PrezelFloatingButtonHierarchy = PrezelFloatingButtonHierarchy.PRIMARY, + val size: PrezelFloatingButtonSize = PrezelFloatingButtonSize.REGULAR, +) + +internal fun prezelFloatingButtonSize(size: PrezelFloatingButtonSize): Dp = + when (size) { + PrezelFloatingButtonSize.SMALL -> 36.dp + PrezelFloatingButtonSize.REGULAR -> 48.dp + } + +internal fun prezelFloatingButtonIconSize(size: PrezelFloatingButtonSize): Dp = + when (size) { + PrezelFloatingButtonSize.SMALL -> 16.dp + PrezelFloatingButtonSize.REGULAR -> 20.dp + } + +@Composable +internal fun Modifier.applyPrezelFloatingButtonShadow(): Modifier = + this.dropShadowCache( + color = Color(0x1F000713), + shape = PrezelTheme.shapes.V1000, + offsetY = 2.dp, + blurRadius = 4.dp, + ) + +@Composable +internal fun prezelFloatingButtonContentColor( + hierarchy: PrezelFloatingButtonHierarchy, + colors: PrezelColors = PrezelTheme.colors, +): Color = + when (hierarchy) { + PrezelFloatingButtonHierarchy.PRIMARY -> colors.solidWhite + PrezelFloatingButtonHierarchy.SECONDARY -> colors.iconRegular + } + +@Composable +internal fun prezelFloatingButtonContainerColor( + hierarchy: PrezelFloatingButtonHierarchy, + colors: PrezelColors = PrezelTheme.colors, +): Color = + when (hierarchy) { + PrezelFloatingButtonHierarchy.PRIMARY -> colors.interactiveRegular + PrezelFloatingButtonHierarchy.SECONDARY -> colors.bgLarge + } + +@Composable +internal fun prezelFloatingMenuButtonContentColor( + hierarchy: PrezelFloatingButtonHierarchy, + colors: PrezelColors = PrezelTheme.colors, +): Color = + when (hierarchy) { + PrezelFloatingButtonHierarchy.PRIMARY -> PrezelColorScheme.Light.textMedium + PrezelFloatingButtonHierarchy.SECONDARY -> colors.textMedium + } + +@Composable +internal fun prezelFloatingMenuButtonContainerColor( + hierarchy: PrezelFloatingButtonHierarchy, + colors: PrezelColors = PrezelTheme.colors, +): Color = + when (hierarchy) { + PrezelFloatingButtonHierarchy.PRIMARY -> colors.solidWhite + PrezelFloatingButtonHierarchy.SECONDARY -> colors.bgRegular + } + +@Composable +internal fun prezelFloatingMenuButtonPaddingValues( + size: PrezelFloatingButtonSize, + spacing: PrezelSpacing = PrezelTheme.spacing, +): PaddingValues = + when (size) { + PrezelFloatingButtonSize.SMALL -> spacing.V4 + PrezelFloatingButtonSize.REGULAR -> spacing.V6 + }.let { padding -> PaddingValues(padding) } diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/floating/PrezelFloatingMenuButton.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/floating/PrezelFloatingMenuButton.kt new file mode 100644 index 0000000..d2c1002 --- /dev/null +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/component/button/floating/PrezelFloatingMenuButton.kt @@ -0,0 +1,228 @@ +package com.team.prezel.core.designsystem.component.button.floating + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.IntrinsicSize +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.requiredHeightIn +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.material3.LocalContentColor +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.team.prezel.core.designsystem.R +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.PrezelTheme + +@Composable +fun PrezelFloatingMenuButton( + iconSource: IconSource, + isExpanded: Boolean, + onClick: () -> Unit, + modifier: Modifier = Modifier, + style: PrezelFloatingButtonStyle = PrezelFloatingButtonStyle(), + content: @Composable (ColumnScope.() -> Unit), +) { + CompositionLocalProvider( + LocalContentColor provides prezelFloatingMenuButtonContentColor(style.hierarchy), + ) { + Column( + modifier = modifier, + horizontalAlignment = Alignment.End, + verticalArrangement = Arrangement.spacedBy(PrezelTheme.spacing.V16), + ) { + PrezelFloatingButtonMenu( + isExpanded = isExpanded, + style = style, + content = content, + ) + + PrezelMainFloatingButton( + iconSource = iconSource, + style = style, + isExpanded = isExpanded, + onClick = onClick, + ) + } + } +} + +@Composable +private fun PrezelMainFloatingButton( + iconSource: IconSource, + style: PrezelFloatingButtonStyle, + isExpanded: Boolean, + onClick: () -> Unit, + modifier: Modifier = Modifier, +) { + val currentIconSource = + if (isExpanded) DrawableIcon(resId = PrezelIcons.Cancel, contentDescTextId = R.string.close_floating_btn_content_desc) else iconSource + + PrezelFloatingButton( + iconSource = currentIconSource, + onClick = onClick, + modifier = modifier, + style = style, + ) +} + +@Composable +private fun PrezelFloatingButtonMenu( + isExpanded: Boolean, + modifier: Modifier = Modifier, + style: PrezelFloatingButtonStyle, + content: @Composable ColumnScope.() -> Unit, +) { + AnimatedVisibility( + visible = isExpanded, + enter = fadeIn(), + exit = fadeOut(), + ) { + Column( + modifier = modifier + .width(IntrinsicSize.Max) + .background( + shape = PrezelTheme.shapes.V12, + color = prezelFloatingMenuButtonContainerColor(style.hierarchy), + ).padding(prezelFloatingMenuButtonPaddingValues(style.size)), + horizontalAlignment = Alignment.Start, + verticalArrangement = Arrangement.spacedBy(PrezelTheme.spacing.V4), + ) { + CompositionLocalProvider( + LocalPrezelFloatingButtonMenuItemSize provides PrezelFloatingButtonMenuItemSize.buttonMenuItemSize(style.size), + ) { + content() + } + } + } +} + +@ThemePreview +@Composable +private fun PrimaryPrezelFloatingMenuButtonPreview() { + PrezelTheme { + Row( + modifier = Modifier + .wrapContentHeight() + .requiredHeightIn(200.dp) + .background(PrezelTheme.colors.bgScrim) + .padding(12.dp), + verticalAlignment = Alignment.Bottom, + horizontalArrangement = Arrangement.spacedBy(12.dp), + ) { + PreviewFloatingMenuButton( + initialExpanded = false, + style = PrezelFloatingButtonStyle(hierarchy = PrezelFloatingButtonHierarchy.PRIMARY, size = PrezelFloatingButtonSize.REGULAR), + ) + PreviewFloatingMenuButton( + initialExpanded = true, + style = PrezelFloatingButtonStyle(hierarchy = PrezelFloatingButtonHierarchy.PRIMARY, size = PrezelFloatingButtonSize.REGULAR), + ) + PreviewFloatingMenuButton( + initialExpanded = false, + style = PrezelFloatingButtonStyle(hierarchy = PrezelFloatingButtonHierarchy.PRIMARY, size = PrezelFloatingButtonSize.SMALL), + ) + PreviewFloatingMenuButton( + initialExpanded = true, + style = PrezelFloatingButtonStyle(hierarchy = PrezelFloatingButtonHierarchy.PRIMARY, size = PrezelFloatingButtonSize.SMALL), + ) + } + } +} + +@ThemePreview +@Composable +private fun SecondaryPrezelFloatingMenuButtonPreview() { + PrezelTheme { + Row( + modifier = Modifier + .wrapContentHeight() + .requiredHeightIn(200.dp) + .background(PrezelTheme.colors.bgScrim) + .padding(12.dp), + verticalAlignment = Alignment.Bottom, + horizontalArrangement = Arrangement.spacedBy(12.dp), + ) { + PreviewFloatingMenuButton( + initialExpanded = false, + style = PrezelFloatingButtonStyle(hierarchy = PrezelFloatingButtonHierarchy.SECONDARY, size = PrezelFloatingButtonSize.REGULAR), + ) + PreviewFloatingMenuButton( + initialExpanded = true, + style = PrezelFloatingButtonStyle(hierarchy = PrezelFloatingButtonHierarchy.SECONDARY, size = PrezelFloatingButtonSize.REGULAR), + ) + PreviewFloatingMenuButton( + initialExpanded = false, + style = PrezelFloatingButtonStyle(hierarchy = PrezelFloatingButtonHierarchy.SECONDARY, size = PrezelFloatingButtonSize.SMALL), + ) + PreviewFloatingMenuButton( + initialExpanded = true, + style = PrezelFloatingButtonStyle(hierarchy = PrezelFloatingButtonHierarchy.SECONDARY, size = PrezelFloatingButtonSize.SMALL), + ) + } + } +} + +@Composable +private fun PreviewFloatingMenuButton( + initialExpanded: Boolean, + style: PrezelFloatingButtonStyle, +) { + var isExpanded by remember { mutableStateOf(initialExpanded) } + + PrezelFloatingMenuButton( + iconSource = DrawableIcon(resId = PrezelIcons.Blank), + isExpanded = isExpanded, + onClick = { isExpanded = !isExpanded }, + style = style, + ) { + PrezelFloatingButtonMenuItem(label = "LongLabel", onClick = {}) + PrezelFloatingButtonMenuItem(label = "Label", onClick = {}) + PrezelFloatingButtonMenuItem(label = "Label", onClick = {}) + } +} + +@ThemePreview +@Composable +private fun PrezelFloatingMenuButtonPreview() { + PrezelTheme { + Row { + PreviewFloatingMenuButton(true) + PreviewFloatingMenuButton(false) + } + } +} + +@Composable +private fun PreviewFloatingMenuButton(isShowIcon: Boolean) { + val iconSource = if (isShowIcon) DrawableIcon(resId = PrezelIcons.Blank) else null + + PrezelFloatingMenuButton( + modifier = Modifier + .background(PrezelTheme.colors.bgScrim) + .padding(16.dp), + iconSource = DrawableIcon(resId = PrezelIcons.Blank), + isExpanded = true, + onClick = {}, + ) { + PrezelFloatingButtonMenuItem(label = "LongLabel", onClick = {}, iconSource = iconSource) + PrezelFloatingButtonMenuItem(label = "Label", onClick = {}, iconSource = iconSource) + PrezelFloatingButtonMenuItem(label = "Label", onClick = {}, iconSource = iconSource) + } +} diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/icon/IconSource.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/icon/IconSource.kt index 40d8ecf..223c8d9 100644 --- a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/icon/IconSource.kt +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/icon/IconSource.kt @@ -1,24 +1,30 @@ package com.team.prezel.core.designsystem.icon import androidx.annotation.DrawableRes +import androidx.annotation.StringRes import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource @Immutable interface IconSource { - val contentDescription: String? - @Composable fun painter(): Painter + + @Composable + fun contentDescription(vararg args: String): String? } @Immutable data class DrawableIcon( - override val contentDescription: String? = null, @param:DrawableRes val resId: Int, + @param:StringRes val contentDescTextId: Int? = null, ) : IconSource { @Composable override fun painter(): Painter = painterResource(resId) + + @Composable + override fun contentDescription(vararg args: String): String? = contentDescTextId?.let { resId -> stringResource(resId, *args) } } diff --git a/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/util/DropShadowCache.kt b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/util/DropShadowCache.kt new file mode 100644 index 0000000..dd5a61f --- /dev/null +++ b/Prezel/core/designsystem/src/main/java/com/team/prezel/core/designsystem/util/DropShadowCache.kt @@ -0,0 +1,46 @@ +package com.team.prezel.core.designsystem.util + +import android.graphics.BlurMaskFilter +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.drawWithCache +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Paint +import androidx.compose.ui.graphics.Path +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.graphics.addOutline +import androidx.compose.ui.graphics.drawscope.drawIntoCanvas +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp + +fun Modifier.dropShadowCache( + color: Color = Color.Black, + offsetX: Dp = 0.dp, + offsetY: Dp = 0.dp, + blurRadius: Dp = 0.dp, + shape: Shape, + blurStyle: BlurMaskFilter.Blur = BlurMaskFilter.Blur.NORMAL, +): Modifier = + drawWithCache { + val paint = Paint() + val frameworkPaint = paint.asFrameworkPaint() + if (blurRadius != 0.dp) { + frameworkPaint.maskFilter = (BlurMaskFilter(blurRadius.toPx(), blurStyle)) + } + frameworkPaint.color = color.toArgb() + + val leftPixel = offsetX.toPx() + val topPixel = offsetY.toPx() + + val path = Path().apply { + addOutline(shape.createOutline(size, layoutDirection, this@drawWithCache)) + } + + onDrawBehind { + drawIntoCanvas { canvas -> + canvas.translate(leftPixel, topPixel) + canvas.drawPath(path, paint) + canvas.translate(-leftPixel, -topPixel) + } + } + } diff --git a/Prezel/core/designsystem/src/main/res/values/strings.xml b/Prezel/core/designsystem/src/main/res/values/strings.xml new file mode 100644 index 0000000..370c924 --- /dev/null +++ b/Prezel/core/designsystem/src/main/res/values/strings.xml @@ -0,0 +1,4 @@ + + + 플로팅 버튼 닫기 + diff --git a/Prezel/detekt-config.yml b/Prezel/detekt-config.yml index 3f97a7a..4829866 100644 --- a/Prezel/detekt-config.yml +++ b/Prezel/detekt-config.yml @@ -47,6 +47,8 @@ complexity: naming: active: true + MatchingDeclarationName: + active: false FunctionNaming: active: true ignoreAnnotated: