Skip to content
Merged
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
34 changes: 24 additions & 10 deletions components/src/main/kotlin/se/seb/gds/atoms/cards/GdsCard.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import se.seb.gds.theme.GdsTheme
*
* @param modifier The [Modifier] to be applied to the card.
* @param containerColor The background color of the card. Defaults to `GdsTheme.colors.L1.Neutral01`.
* @param shape The shape of the card's corners. Defaults to [GdsInformationCardDefaults.shape].
* @param shape The shape of the card's corners. Defaults to [GdsCardDefaults.shape].
* @param border An optional border to draw around the card.
* @param content The content to be placed inside the card.
*
Expand All @@ -35,18 +35,32 @@ import se.seb.gds.theme.GdsTheme
@Composable
fun GdsCard(
modifier: Modifier = Modifier,
onClick: (() -> Unit)? = null,
containerColor: Color = GdsTheme.colors.L1.Neutral01,
shape: Shape = GdsCardDefaults.shape,
border: BorderStroke? = GdsCardDefaults.border,
content: @Composable ColumnScope.() -> Unit,
) {
Card(
modifier = Modifier
.fillMaxWidth()
.then(modifier),
colors = CardDefaults.cardColors(containerColor = containerColor),
shape = shape,
border = border,
content = content,
)
val cardModifier = Modifier
.fillMaxWidth()
.then(modifier)

if (onClick != null) {
Card(
onClick = onClick,
modifier = cardModifier,
colors = CardDefaults.cardColors(containerColor = containerColor),
shape = shape,
border = border,
content = content,
)
} else {
Card(
modifier = cardModifier,
colors = CardDefaults.cardColors(containerColor = containerColor),
shape = shape,
border = border,
content = content,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.Box
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.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
Expand Down Expand Up @@ -72,13 +73,8 @@ fun GdsInformationCard(
button: CardButton? = null,
) {
GdsCard(
modifier = modifier
.clickable(
enabled = onClick != null,
onClick = { onClick?.invoke() },
interactionSource = remember { MutableInteractionSource() },
indication = ripple(),
),
modifier = modifier,
onClick = onClick,
containerColor = style.colors.containerColor,
shape = style.shape,
border = style.border,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.tooling.preview.Preview
import se.seb.gds.theme.GdsTheme

Expand Down Expand Up @@ -51,12 +52,12 @@ fun GdsSwitch(
GdsTheme {
CompositionLocalProvider(
LocalRippleConfiguration provides RippleConfiguration(
color = GdsTheme.colors.State.Positive03,
color = style.rippleColor,
rippleAlpha = RippleAlpha(0.16f, 0.1f, 0.08f, 0.1f),
),
) {
Switch(
modifier = modifier,
modifier = modifier.alpha(if (enabled) 1f else style.disabledOpacity),
checked = checked,
enabled = enabled,
onCheckedChange = onCheckedChanged,
Expand All @@ -65,7 +66,7 @@ fun GdsSwitch(
if (checked || style.alwaysShowThumb) {
if (style.checkedIcon != null) {
Icon(
modifier = Modifier.size(SwitchDefaults.IconSize),
modifier = Modifier.size(GdsSwitchDefaults.IconSize),
imageVector = style.checkedIcon,
contentDescription = null,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import androidx.compose.material3.SwitchDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.unit.Dp
import se.seb.gds.icons.GdsIcons
import se.seb.gds.icons.custom.SolidCheckmark12
import se.seb.gds.theme.GdsTheme

/**
Expand All @@ -26,11 +28,16 @@ import se.seb.gds.theme.GdsTheme
* @property checkedIcon An optional icon to display inside the thumb when the switch is
* in the checked state. If `null`, no icon will be displayed in the checked thumb.
* This should be a [ImageVector].
* @property disabledOpacity The opacity to apply to the entire switch when it is in a disabled
* state.
* @property rippleColor The color to use for the ripple effect when the switch is interacted with.
*/
data class GdsSwitchStyle(
val colors: SwitchColors,
val alwaysShowThumb: Boolean,
val checkedIcon: ImageVector?,
val disabledOpacity: Float = 1f,
val rippleColor: Color,
)

object GdsSwitchDefaults {
Expand All @@ -40,7 +47,9 @@ object GdsSwitchDefaults {
GdsSwitchStyle(
colors = defaultColors(),
alwaysShowThumb = false,
checkedIcon = GdsIcons.Solid.Checkmark,
checkedIcon = SolidCheckmark12,
disabledOpacity = 0.5f,
rippleColor = GdsTheme.colors.State.Positive03,
)

// 2016
Expand All @@ -50,6 +59,7 @@ object GdsSwitchDefaults {
colors = legacyColors(),
alwaysShowThumb = false,
checkedIcon = GdsIcons.Solid.Checkmark,
rippleColor = GdsTheme.legacyColors.DarkBlue1,
)

@Composable
Expand All @@ -58,23 +68,25 @@ object GdsSwitchDefaults {
colors = neoColors(),
alwaysShowThumb = true,
checkedIcon = null,
rippleColor = Color(0xFF26BD3F),
)

@Composable
fun defaultColors(): SwitchColors =
SwitchDefaults.colors(
checkedThumbColor = GdsTheme.colors.L3.Neutral05,
checkedTrackColor = GdsTheme.colors.L3.Positive04,
checkedIconColor = GdsTheme.colors.Content.Positive01,
uncheckedThumbColor = GdsTheme.colors.Content.Neutral02,
uncheckedTrackColor = Color.Transparent,
uncheckedBorderColor = GdsTheme.colors.Border.Interactive,
checkedIconColor = GdsTheme.colors.Content.Positive01,
disabledCheckedIconColor = GdsTheme.colors.Content.Disabled01,
disabledCheckedTrackColor = GdsTheme.colors.L3.Disabled02,
disabledCheckedThumbColor = GdsTheme.colors.L3.Disabled03,
disabledUncheckedThumbColor = GdsTheme.colors.Content.Disabled01,
// The same colors are used for disabled states, but with reduced opacity applied to the entire switch
disabledCheckedThumbColor = GdsTheme.colors.L3.Neutral05,
disabledCheckedTrackColor = GdsTheme.colors.L3.Positive04,
disabledCheckedIconColor = GdsTheme.colors.Content.Positive01,
disabledUncheckedThumbColor = GdsTheme.colors.Content.Neutral02,
disabledUncheckedTrackColor = Color.Transparent,
disabledUncheckedBorderColor = GdsTheme.colors.L3.Disabled03,
disabledUncheckedBorderColor = GdsTheme.colors.Border.Interactive,
)

@Composable
Expand All @@ -99,4 +111,8 @@ object GdsSwitchDefaults {
checkedBorderColor = Color.Transparent,
uncheckedBorderColor = Color.Transparent,
)

val IconSize: Dp
@Composable
get() = GdsTheme.dimensions.spacing.SpaceS
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package se.seb.gds.icons.custom

import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.height
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.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.StrokeCap
import androidx.compose.ui.graphics.StrokeJoin
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.path
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import se.seb.gds.theme.GdsTheme

internal val SolidCheckmark12: ImageVector
get() {
val current = _solidCheckmark12
if (current != null) return current

return ImageVector.Builder(
name = "se.seb.gds.theme.GdsTheme.SolidCheckmark12",
defaultWidth = 12.0.dp,
defaultHeight = 12.0.dp,
viewportWidth = 12.0f,
viewportHeight = 12.0f,
).apply {
path(
stroke = SolidColor(Color(0xFF027839)),
strokeLineCap = StrokeCap.Round,
strokeLineJoin = StrokeJoin.Round,
strokeLineWidth = 1.5f,
) {
moveTo(x = 1.375f, y = 7.54688f)
lineTo(x = 4.5f, y = 10.125f)
lineTo(x = 10.625f, y = 1.875f)
}
}.build().also { _solidCheckmark12 = it }
}

@Preview
@Composable
private fun IconPreview() {
GdsTheme {
Column(
verticalArrangement = Arrangement.spacedBy(8.dp),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Image(
imageVector = SolidCheckmark12,
contentDescription = null,
modifier = Modifier
.width((12.0).dp)
.height((12.0).dp),
)
}
}
}

@Suppress("ObjectPropertyName")
private var _solidCheckmark12: ImageVector? = null
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package se.seb.gds.preview

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.Row
Expand Down Expand Up @@ -30,11 +29,8 @@ fun ExpandableCard(

GdsCard(
containerColor = GdsTheme.colors.L2.Neutral02,
modifier = modifier
.fillMaxWidth()
.clickable {
expanded = !expanded
},
modifier = modifier,
onClick = { expanded = !expanded },
) {
Column {
Row(
Expand Down
35 changes: 22 additions & 13 deletions components/src/main/kotlin/se/seb/gds/preview/SwitchesScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import se.seb.gds.atoms.switch.GdsSwitchDefaults
import se.seb.gds.components.SwitchRow

@Composable
Expand All @@ -25,27 +24,37 @@ internal fun SwitchesScreen(scrollState: ScrollState) {
.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp),
) {
var checked by remember { mutableStateOf(false) }
ComponentHeaderSection(
title = "GdsSwitch",
body = "Example usage:",
code = """
GdsSwitch(
checked = true,
onCheckedChanged = { },
enabled = true,
)
""".trimIndent(),
)

var checked by remember { mutableStateOf(true) }
SwitchRow(
title = "Green 2023",
title = "Enabled",
checked = checked,
onCheckedChanged = { checked = it },
)

var legacyChecked by remember { mutableStateOf(false) }
SwitchRow(
title = "Green 2016",
checked = legacyChecked,
style = GdsSwitchDefaults.legacyStyle(),
onCheckedChanged = { legacyChecked = it },
title = "Disabled - Checked",
checked = true,
enabled = false,
onCheckedChanged = { checked = it },
)

var neoChecked by remember { mutableStateOf(false) }
SwitchRow(
title = "Neo",
checked = neoChecked,
style = GdsSwitchDefaults.neoStyle(),
onCheckedChanged = { neoChecked = it },
title = "Disabled - Unchecked",
checked = false,
enabled = false,
onCheckedChanged = { checked = it },
)
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading