Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
@@ -0,0 +1,157 @@
package com.team.prezel.core.designsystem.component

import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.selection.toggleable
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.material3.ripple
import androidx.compose.runtime.Composable
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.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.team.prezel.core.designsystem.icon.PrezelIcons
import com.team.prezel.core.designsystem.preview.PreviewScaffold
import com.team.prezel.core.designsystem.preview.SectionTitle
import com.team.prezel.core.designsystem.preview.ThemePreview
import com.team.prezel.core.designsystem.theme.PrezelTheme

/**
* 라디오 버튼의 크기 정의.
*
* @property value 라디오 버튼의 터치 영역 크기
*/
enum class PrezelRadioSize(
val value: Dp,
) {
REGULAR(40.dp),
LARGE(48.dp),
}

/**
* 아이콘만 표시되는 라디오 버튼.
*
* @param checked 현재 선택 여부
* @param onCheckedChange 선택 상태 변경 콜백
* @param size 라디오 버튼 크기
*/
@Composable
fun PrezelRadio(
checked: Boolean,
onCheckedChange: (checked: Boolean) -> Unit,
modifier: Modifier = Modifier,
size: PrezelRadioSize = PrezelRadioSize.REGULAR,
) {
PrezelRadioIcon(
checked = checked,
size = size,
modifier = modifier
.toggleable(
value = checked,
onValueChange = onCheckedChange,
role = Role.RadioButton,
indication = null,
interactionSource = null,
),
)
}

/**
* 텍스트와 함께 표시되는 라디오 버튼.
*
* @param text 라디오 버튼 라벨 텍스트
* @param checked 현재 선택 여부
* @param onCheckedChange 선택 상태 변경 콜백
* @param size 라디오 버튼 크기
*/
@Composable
fun PrezelRadio(
text: String,
checked: Boolean,
onCheckedChange: (checked: Boolean) -> Unit,
modifier: Modifier = Modifier,
size: PrezelRadioSize = PrezelRadioSize.REGULAR,
textStyle: TextStyle = PrezelTheme.typography.body2Medium,
textColor: Color = PrezelTheme.colors.textLarge,
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = modifier
.fillMaxWidth()
.clip(PrezelTheme.shapes.V6)
.toggleable(
value = checked,
onValueChange = onCheckedChange,
role = Role.RadioButton,
indication = ripple(),
interactionSource = null,
),
) {
PrezelRadioIcon(checked = checked, size = size)
Spacer(modifier = Modifier.width(PrezelTheme.spacing.V4))
Text(text = text, style = textStyle, color = textColor)
}
}

@Composable
private fun PrezelRadioIcon(
checked: Boolean,
modifier: Modifier = Modifier,
size: PrezelRadioSize = PrezelRadioSize.REGULAR,
) {
val tintColor = if (checked) PrezelTheme.colors.interactiveRegular else PrezelTheme.colors.iconDisabled
val icon = if (checked) PrezelIcons.RadioCircleFilled else PrezelIcons.RadioCircleOutlined

Icon(
painter = painterResource(icon),
contentDescription = null,
tint = tintColor,
modifier = Modifier
.size(size.value)
.then(modifier)
.padding(PrezelTheme.spacing.V8),
)
}

@ThemePreview
@Composable
private fun PrezelRadioPreview() {
var checked by remember { mutableStateOf(false) }

PrezelTheme {
PreviewScaffold {
SectionTitle("PrezelRadioSize.REGULAR")
Text("Checked: true")
PrezelRadio(checked = true, onCheckedChange = {}, size = PrezelRadioSize.REGULAR)
Text("Checked: false")
PrezelRadio(checked = false, onCheckedChange = {}, size = PrezelRadioSize.REGULAR)
Text("PrezelRadio with text")
PrezelRadio(checked = checked, onCheckedChange = { checked = it }, text = "텍스트", size = PrezelRadioSize.REGULAR)

Spacer(modifier = Modifier.height(20.dp))

SectionTitle("PrezelRadioSize.LARGE")
Text("Checked: true")
PrezelRadio(checked = true, onCheckedChange = {}, size = PrezelRadioSize.LARGE)
Text("Checked: false")
PrezelRadio(checked = false, onCheckedChange = {}, size = PrezelRadioSize.LARGE)
Text("PrezelRadio with text")
PrezelRadio(checked = checked, onCheckedChange = { checked = it }, text = "텍스트", size = PrezelRadioSize.LARGE)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
Expand All @@ -25,15 +26,20 @@ import kotlinx.collections.immutable.ImmutableList

@Composable
internal fun PreviewScaffold(content: @Composable () -> Unit) {
Column(
modifier = Modifier
.fillMaxSize()
.background(PrezelTheme.colors.bgRegular)
.verticalScroll(rememberScrollState())
.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp),
) {
content()
Scaffold(
containerColor = PrezelTheme.colors.bgRegular,
contentColor = PrezelTheme.colors.textLarge,
) { innerPadding ->
Column(
modifier = Modifier
.padding(innerPadding)
.fillMaxSize()
.verticalScroll(rememberScrollState())
.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp),
) {
content()
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion Prezel/detekt-config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ complexity:
threshold: 40
LongParameterList:
active: true
functionThreshold: 7
functionThreshold: 8
constructorThreshold: 8
CyclomaticComplexMethod:
active: true
Expand Down