Skip to content

Commit b53425e

Browse files
added DSLink (#8)
* added DSLink and code documentation --------- Co-authored-by: Thomas Köcher <[email protected]>
1 parent 308a936 commit b53425e

File tree

8 files changed

+347
-2
lines changed

8 files changed

+347
-2
lines changed

components/src/main/java/com/dbsystel/designsystem/components/button/DSButton.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ import com.dbsystel.designsystem.foundation.theme.DesignSystemTheme
4646
* @param icon wrapper class to define the icon to be displayed
4747
* @param variant visual representation of the button
4848
* @param size size of the button
49-
* @param enabled controls the enabled state of this button. When false, this component will not respond to user input, and it will appear visually disabled and disabled to accessibility services.
49+
* @param enabled controls the enabled state of this button. When false, this component will not
50+
* respond to user input, and it will appear visually disabled and disabled to accessibility services.
5051
* @param width width of the button
5152
* @param onClick called when this button is clicked
5253
*
Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
package com.dbsystel.designsystem.components.link
2+
3+
import androidx.annotation.DrawableRes
4+
import androidx.compose.animation.animateColorAsState
5+
import androidx.compose.foundation.clickable
6+
import androidx.compose.foundation.interaction.MutableInteractionSource
7+
import androidx.compose.foundation.interaction.collectIsPressedAsState
8+
import androidx.compose.foundation.layout.Arrangement
9+
import androidx.compose.foundation.layout.Row
10+
import androidx.compose.foundation.layout.padding
11+
import androidx.compose.foundation.layout.size
12+
import androidx.compose.material3.Icon
13+
import androidx.compose.material3.Text
14+
import androidx.compose.runtime.Composable
15+
import androidx.compose.runtime.ReadOnlyComposable
16+
import androidx.compose.runtime.getValue
17+
import androidx.compose.runtime.remember
18+
import androidx.compose.ui.Alignment
19+
import androidx.compose.ui.Modifier
20+
import androidx.compose.ui.draw.alpha
21+
import androidx.compose.ui.graphics.Color
22+
import androidx.compose.ui.res.painterResource
23+
import androidx.compose.ui.text.TextStyle
24+
import androidx.compose.ui.text.style.TextDecoration
25+
import androidx.compose.ui.tooling.preview.Preview
26+
import androidx.compose.ui.unit.Dp
27+
import androidx.compose.ui.unit.dp
28+
import com.dbsystel.designsystem.components.link.preview.previewName
29+
import com.dbsystel.designsystem.foundation.R
30+
import com.dbsystel.designsystem.foundation.theme.DesignSystemTheme
31+
32+
/**
33+
* Links are used as navigation elements. They can stand alone, within a sentence or paragraph
34+
* or directly after the content to which they refer.
35+
*
36+
* @param modifier the Modifier to be applied to this link
37+
* @param text the text to be displayed
38+
* @param content content type of the link (external or internal link)
39+
* @param variant visual representation of the link
40+
* @param size size of the link
41+
* @param enabled controls the enabled state of this link. When false, this component will not
42+
* respond to user input, and it will appear visually disabled and disabled to accessibility services.
43+
* @param showIcon control the visibility of the content type icon
44+
* @param onClick called when this link is clicked
45+
*
46+
* @sample com.dbsystel.designsystem.components.samples.DSLinkSample
47+
*/
48+
@Composable
49+
fun DSLink(
50+
modifier: Modifier = Modifier,
51+
text: String,
52+
content: DSLinkContent = DSLinkContent.INTERNAL,
53+
variant: DSLinkVariant = DSLinkVariant.ADAPTIVE,
54+
size: DSLinkSize = DSLinkSize.MEDIUM,
55+
enabled: Boolean = true,
56+
showIcon: Boolean = true,
57+
onClick: () -> Unit,
58+
) {
59+
val interactionSource = remember { MutableInteractionSource() }
60+
val pressed by interactionSource.collectIsPressedAsState()
61+
62+
val linkColor by animateColorAsState(
63+
targetValue = if (pressed) variant.pressedColor else variant.color,
64+
label = "LinkColorAnimation",
65+
)
66+
67+
Row(
68+
modifier = Modifier
69+
.alpha(if (enabled) 1.0f else 0.4f)
70+
.clickable(
71+
enabled = enabled,
72+
onClick = onClick,
73+
interactionSource = interactionSource,
74+
indication = null
75+
)
76+
.then(modifier),
77+
horizontalArrangement = Arrangement.spacedBy(size.paddingH),
78+
verticalAlignment = Alignment.CenterVertically,
79+
) {
80+
Text(
81+
text = text,
82+
textDecoration = TextDecoration.Underline,
83+
style = size.textStyle,
84+
color = linkColor,
85+
)
86+
if (showIcon) Icon(
87+
modifier = Modifier.size(size.iconSize),
88+
painter = painterResource(content.iconRes),
89+
contentDescription = content.name,
90+
tint = linkColor,
91+
)
92+
}
93+
}
94+
95+
enum class DSLinkVariant {
96+
ADAPTIVE,
97+
BRAND;
98+
99+
internal val color: Color
100+
@Composable
101+
@ReadOnlyComposable
102+
get() = when (this) {
103+
ADAPTIVE -> DesignSystemTheme.activeColor.Basic.Text.Emphasis100.Default
104+
BRAND -> DesignSystemTheme.colors.brand.Basic.Text.Emphasis80.Default
105+
}
106+
107+
internal val pressedColor: Color
108+
@Composable
109+
@ReadOnlyComposable
110+
get() = when (this) {
111+
ADAPTIVE -> DesignSystemTheme.activeColor.Basic.Text.Emphasis100.Pressed
112+
BRAND -> DesignSystemTheme.colors.brand.Basic.Text.Emphasis80.Pressed
113+
}
114+
}
115+
116+
enum class DSLinkSize {
117+
MEDIUM,
118+
SMALL;
119+
120+
internal val paddingH: Dp
121+
@Composable
122+
@ReadOnlyComposable
123+
get() = when (this) {
124+
MEDIUM -> DesignSystemTheme.dimensions.spacing.fixed2xs
125+
SMALL -> DesignSystemTheme.dimensions.spacing.fixed3xs
126+
}
127+
128+
internal val iconSize: Dp
129+
@Composable
130+
@ReadOnlyComposable
131+
get() = when (this) {
132+
MEDIUM -> 24.dp
133+
SMALL -> 20.dp
134+
}
135+
136+
internal val textStyle: TextStyle
137+
@Composable
138+
@ReadOnlyComposable
139+
get() = when (this) {
140+
MEDIUM -> DesignSystemTheme.typography.bodyMd
141+
SMALL -> DesignSystemTheme.typography.bodySm
142+
}
143+
}
144+
145+
enum class DSLinkContent {
146+
INTERNAL,
147+
EXTERNAL;
148+
149+
internal val iconRes: Int
150+
@DrawableRes
151+
get() = when (this) {
152+
INTERNAL -> R.drawable.ds_ic_arrow_forward
153+
EXTERNAL -> R.drawable.ds_ic_link_external
154+
}
155+
}
156+
157+
@Composable
158+
@Preview(
159+
showBackground = true,
160+
group = "Content",
161+
)
162+
private fun DSLinkPreview_Content() {
163+
DesignSystemTheme {
164+
Row(
165+
modifier = Modifier
166+
.padding(12.dp),
167+
verticalAlignment = Alignment.CenterVertically,
168+
horizontalArrangement = Arrangement.spacedBy(24.dp),
169+
) {
170+
DSLinkContent.entries.forEach { content ->
171+
DSLink(
172+
text = content.previewName,
173+
content = content,
174+
onClick = {},
175+
)
176+
}
177+
}
178+
}
179+
}
180+
181+
@Composable
182+
@Preview(
183+
showBackground = true,
184+
group = "Variant",
185+
)
186+
private fun DSLinkPreview_Variant() {
187+
DesignSystemTheme {
188+
Row(
189+
modifier = Modifier
190+
.padding(12.dp),
191+
verticalAlignment = Alignment.CenterVertically,
192+
horizontalArrangement = Arrangement.spacedBy(24.dp),
193+
) {
194+
DSLinkVariant.entries.forEach { variant ->
195+
DSLink(
196+
text = variant.previewName,
197+
variant = variant,
198+
onClick = {},
199+
)
200+
}
201+
}
202+
}
203+
}
204+
205+
@Composable
206+
@Preview(
207+
showBackground = true,
208+
group = "Disabled",
209+
)
210+
private fun DSLinkPreview_Disabled() {
211+
DesignSystemTheme {
212+
Row(
213+
modifier = Modifier
214+
.padding(12.dp),
215+
verticalAlignment = Alignment.CenterVertically,
216+
horizontalArrangement = Arrangement.spacedBy(24.dp),
217+
) {
218+
listOf(false, true).forEach { disabled ->
219+
DSLink(
220+
text = if (!disabled) "(Def) False" else "True",
221+
enabled = !disabled,
222+
onClick = {},
223+
)
224+
}
225+
}
226+
}
227+
}
228+
229+
@Composable
230+
@Preview(
231+
showBackground = true,
232+
group = "Size",
233+
)
234+
private fun DSLinkPreview_Size() {
235+
DesignSystemTheme {
236+
Row(
237+
modifier = Modifier
238+
.padding(12.dp),
239+
verticalAlignment = Alignment.CenterVertically,
240+
horizontalArrangement = Arrangement.spacedBy(24.dp),
241+
) {
242+
DSLinkSize.entries.forEach { size ->
243+
DSLink(
244+
text = size.previewName,
245+
size = size,
246+
onClick = {},
247+
)
248+
}
249+
}
250+
}
251+
}
252+
253+
@Composable
254+
@Preview(
255+
showBackground = true,
256+
group = "ShowIcon",
257+
)
258+
private fun DSLinkPreview_ShowIcon() {
259+
DesignSystemTheme {
260+
Row(
261+
modifier = Modifier
262+
.padding(12.dp),
263+
verticalAlignment = Alignment.CenterVertically,
264+
horizontalArrangement = Arrangement.spacedBy(24.dp),
265+
) {
266+
listOf(true, false).forEach { showIcon ->
267+
DSLink(
268+
text = if (showIcon) "(Def) True" else "False",
269+
showIcon = showIcon,
270+
onClick = {},
271+
)
272+
}
273+
}
274+
}
275+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.dbsystel.designsystem.components.link.preview
2+
3+
import com.dbsystel.designsystem.components.link.DSLinkContent
4+
import com.dbsystel.designsystem.components.link.DSLinkSize
5+
import com.dbsystel.designsystem.components.link.DSLinkVariant
6+
7+
internal val DSLinkContent.previewName: String
8+
get() = when (this) {
9+
DSLinkContent.INTERNAL -> "(Def) Internal"
10+
DSLinkContent.EXTERNAL -> "External"
11+
}
12+
13+
internal val DSLinkVariant.previewName: String
14+
get() = when (this) {
15+
DSLinkVariant.ADAPTIVE -> "(Def) Adaptive"
16+
DSLinkVariant.BRAND -> "Brand"
17+
}
18+
19+
internal val DSLinkSize.previewName: String
20+
get() = when (this) {
21+
DSLinkSize.MEDIUM -> "(Def) Medium"
22+
DSLinkSize.SMALL -> "Small"
23+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.dbsystel.designsystem.components.samples
2+
3+
import androidx.compose.runtime.Composable
4+
import androidx.compose.ui.tooling.preview.Preview
5+
import com.dbsystel.designsystem.components.link.DSLink
6+
import com.dbsystel.designsystem.components.link.DSLinkContent
7+
import com.dbsystel.designsystem.components.link.DSLinkSize
8+
import com.dbsystel.designsystem.components.link.DSLinkVariant
9+
10+
@Preview
11+
@Composable
12+
private fun DSLinkSample() {
13+
DSLink(
14+
text = "More",
15+
variant = DSLinkVariant.BRAND,
16+
size = DSLinkSize.MEDIUM,
17+
content = DSLinkContent.INTERNAL,
18+
enabled = true,
19+
showIcon = true,
20+
onClick = { /* Do something! */ },
21+
)
22+
}

foundation/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ plugins {
66

77
android {
88
namespace = "com.dbsystel.designsystem.foundation"
9-
compileSdk = 34
9+
compileSdk = 35
1010

1111
defaultConfig {
1212
minSdk = 30

foundation/src/main/res/drawable/.gitkeep

Whitespace-only changes.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:viewportWidth="24"
5+
android:viewportHeight="24">
6+
<path
7+
android:pathData="M4,12C4,12.563 4.438,13 5,13L16.594,13L12.313,17.281C12.094,17.5 12,17.75 12,18C12,18.438 12.375,19 13.031,19C13.281,19 13.531,18.906 13.719,18.719L19.719,12.719C19.923,12.515 20,12.25 20,12C20.031,11.75 19.923,11.485 19.719,11.281L13.719,5.281C13.531,5.094 13.25,5 13.031,5C12.469,5 12,5.469 12,6C12,6.281 12.109,6.515 12.313,6.719L16.594,11L5,11C4.438,11 4,11.438 4,12Z"
8+
android:strokeWidth="1"
9+
android:fillColor="#282D37"
10+
android:fillType="evenOdd"
11+
android:strokeColor="#00000000"/>
12+
</vector>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:viewportWidth="24"
5+
android:viewportHeight="24">
6+
<path
7+
android:pathData="M6.031,18C6.25,18 6.5,17.906 6.688,17.719L15,9.406L15,15C15,15.594 15.469,16.031 16,16.031C16.531,16.031 17,15.563 17,15L17,6.906C17,6.375 16.531,6 16,6L8,6C7.406,6 7,6.469 7,7C7,7.5 7.469,8 8,8L13.594,8L5.219,16.375C5.063,16.531 5,16.781 5,16.969C5,17.563 5.438,18 6.031,18Z"
8+
android:strokeWidth="1"
9+
android:fillColor="#282D37"
10+
android:fillType="evenOdd"
11+
android:strokeColor="#00000000"/>
12+
</vector>

0 commit comments

Comments
 (0)