Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
f5f558b
feat: 그림자 효과를 위한 `dropShadowCache` Modifier 추가
moondev03 Jan 23, 2026
9a34d13
feat: FloatingActionButton 스타일 정의 추가
moondev03 Jan 23, 2026
b2390aa
feat: FloatingActionButton 스타일 정의 추가
moondev03 Jan 23, 2026
655f237
feat: FloatingActionButton 스타일 정의 추가
moondev03 Jan 23, 2026
faafd41
feat: 플로팅 메뉴 버튼 컴포넌트 추가
moondev03 Jan 23, 2026
ff94a47
feat: `PrezelFloatingMenuButton`의 메뉴 아이템 컴포넌트 추가
moondev03 Jan 23, 2026
c81b55f
style: detekt `MatchingDeclarationName` 규칙 비활성화
moondev03 Jan 23, 2026
fb32bb0
feat: `PrezelFloatingMenuButton` 스타일 확장 및 계층 구조 지원
moondev03 Jan 23, 2026
d31441f
refactor: `PrezelFloatingButtonMenuItem` 스타일 로직 개선 및 의존성 분리
moondev03 Jan 23, 2026
ec4d560
refactor: `PrezelFloatingMenuButton` 레이아웃 너비 동작 개선
moondev03 Jan 23, 2026
8ef0a62
fix: 플로팅 버튼 메뉴 아이템에 clip 적용
moondev03 Jan 23, 2026
6615ffb
feat: `PrezelFloatingMenuButton` 프리뷰 동작 추가
moondev03 Jan 23, 2026
96b280a
refactor: IconSource 구조 개선 및 contentDescription 지원 강화
moondev03 Jan 24, 2026
a1e09a5
refactor: 플로팅 버튼의 Content Description을 리소스화
moondev03 Jan 24, 2026
619ab11
refactor: `IconSource`의 contentDescription을 함수 호출로 변경
moondev03 Jan 24, 2026
4743280
refactor: `IconSource`의 `contentDescription` 기능 확장
moondev03 Jan 24, 2026
c7990a0
refactor: PrezelFloatingMenuButton의 Preview 파라미터명 변경
moondev03 Jan 24, 2026
46c85db
fix: spread 연산자 추가
moondev03 Jan 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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 = {},
)
}
}
}
Original file line number Diff line number Diff line change
@@ -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 = {},
)
}
}
}
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
@@ -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) }
Loading