Skip to content

Commit 34a87a9

Browse files
authored
library: Add 'Sink' and 'Tilt' press feedback effects to Card (#73)
1 parent 0433c3c commit 34a87a9

File tree

8 files changed

+543
-42
lines changed

8 files changed

+543
-42
lines changed

docs/components/card.md

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
# Card
22

3-
`Card` is a basic container component in Miuix, used to hold related content and actions. It provides a card container with Miuix style, suitable for scenarios such as information display and content grouping.
3+
`Card` is a basic container component in Miuix, used to hold related content and actions. It provides a card container with Miuix style, suitable for scenarios such as information display and content grouping. Supports both static display and interactive modes.
44

55
## Import
66

77
```kotlin
88
import top.yukonga.miuix.kmp.basic.Card
9+
import top.yukonga.miuix.kmp.utils.PressFeedbackType // If using interactive card
910
```
1011

1112
## Basic Usage
1213

13-
The Card component can be used to wrap and organize content:
14+
The Card component can be used to wrap and organize content (static card):
1415

1516
```kotlin
1617
Card {
@@ -22,30 +23,38 @@ Card {
2223

2324
### Card Properties
2425

25-
| Property Name | Type | Description | Default Value | Required |
26-
| ------------- | ---------------------------------- | ------------------------ | --------------------------- | -------- |
27-
| modifier | Modifier | Modifier applied to card | Modifier | No |
28-
| cornerRadius | Dp | Card corner radius | CardDefaults.CornerRadius | No |
29-
| insideMargin | PaddingValues | Card inner padding | CardDefaults.InsideMargin | No |
30-
| color | Color | Card background color | CardDefaults.DefaultColor() | No |
31-
| content | @Composable ColumnScope.() -> Unit | Composable function for card content area | - | Yes |
26+
| Property Name | Type | Description | Default Value | Required | Applies To |
27+
| ----------------- | ---------------------------------- | ----------------------------------------- | --------------------------- | -------- | ----------- |
28+
| modifier | Modifier | Modifier applied to the card | Modifier | No | All |
29+
| cornerRadius | Dp | Card corner radius | CardDefaults.CornerRadius | No | All |
30+
| insideMargin | PaddingValues | Card inner padding | CardDefaults.InsideMargin | No | All |
31+
| color | Color | Card background color | CardDefaults.DefaultColor() | No | All |
32+
| pressFeedbackType | PressFeedbackType | Feedback type when pressed | PressFeedbackType.None | No | Interactive |
33+
| showIndication | Boolean? | Show indication on interaction | false | No | Interactive |
34+
| onClick | (() -> Unit)? | Callback when clicked | null | No | Interactive |
35+
| onLongPress | (() -> Unit)? | Callback when long pressed | null | No | Interactive |
36+
| content | @Composable ColumnScope.() -> Unit | Composable function for card content area | - | Yes | All |
37+
38+
::: warning
39+
Some properties are only available when creating an interactive card!
40+
:::
3241

3342
### CardDefaults Object
3443

3544
The CardDefaults object provides default values and color configurations for the card component.
3645

3746
#### Constants
3847

39-
| Constant Name | Type | Description | Default Value |
40-
| ------------- | ------------- | ------------------ | --------------------- |
41-
| CornerRadius | Dp | Card corner radius | 16.dp |
42-
| InsideMargin | PaddingValues | Card inner padding | PaddingValues(0.dp) |
48+
| Constant Name | Type | Description | Default Value |
49+
| ------------- | ------------- | ------------------ | ------------------- |
50+
| CornerRadius | Dp | Card corner radius | 16.dp |
51+
| InsideMargin | PaddingValues | Card inner padding | PaddingValues(0.dp) |
4352

4453
#### Methods
4554

46-
| Method Name | Type | Description |
47-
| -------------- | ----- | ------------------------- |
48-
| DefaultColor() | Color | Creates the default color for the card |
55+
| Method Name | Type | Description |
56+
| -------------- | ----- | ----------------------------------------- |
57+
| DefaultColor() | Color | The default background color for the card |
4958

5059
## Advanced Usage
5160

@@ -111,3 +120,17 @@ LazyColumn {
111120
}
112121
}
113122
```
123+
124+
### Interactive Card
125+
126+
```kotlin
127+
Card(
128+
modifier = Modifier.padding(16.dp),
129+
pressFeedbackType = PressFeedbackType.Sink, // Set press feedback to sink effect
130+
showIndication = true, // Show indication on click
131+
onClick = {/* Handle click event */ },
132+
onLongPress = {/* Handle long press event */ }
133+
) {
134+
Text("Interactive Card")
135+
}
136+
```

docs/guide/utils.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,82 @@ LazyColumn(
105105
* `springDamp`: Float, defines the spring damping for the rebound animation. Higher values result in less oscillation. Defaults to `1f`.
106106
* `isEnabled`: A lambda expression returning a Boolean, used to dynamically control whether the overscroll effect is enabled. By default, it is enabled only on Android and iOS platforms.
107107

108+
## Press Feedback Effects
109+
110+
Miuix provides visual feedback effects to enhance user interaction experience, improving operability through tactile-like responses.
111+
112+
### Sink Effect
113+
114+
The `pressSink` modifier applies a "sink" visual feedback when the component is pressed, by smoothly scaling down the component.
115+
116+
```kotlin
117+
val interactionSource = remember { MutableInteractionSource() }
118+
119+
Box(
120+
modifier = Modifier
121+
.clickable(interactionSource = interactionSource, indication = null)
122+
.pressSink(interactionSource)
123+
.background(Color.Blue)
124+
.size(100.dp)
125+
)
126+
```
127+
128+
### Tilt Effect
129+
130+
The `pressTilt` modifier applies a "tilt" effect based on the position where the user pressed the component. The tilt direction is determined by touch offset, giving the effect that one corner "sinks" while the other "static".
131+
132+
```kotlin
133+
val interactionSource = remember { MutableInteractionSource() }
134+
135+
Box(
136+
modifier = Modifier
137+
.clickable(interactionSource = interactionSource, indication = null)
138+
.pressTilt(interactionSource)
139+
.background(Color.Green)
140+
.size(100.dp)
141+
)
142+
```
143+
144+
### Prerequisites for Triggering Press Feedback
145+
146+
Press feedback effects require detecting `interactionSource.collectIsPressedAsState()` to be triggered.
147+
148+
You can use responsive modifiers like `Modifier.clickable()` to add `PressInteraction.Press` to the `interactionSource` and trigger press feedback effects.
149+
150+
However, it's recommended to use the method below to add `PressInteraction.Press` to the `interactionSource` for faster response triggering of press feedback effects.
151+
152+
```kotlin
153+
val interactionSource = remember { MutableInteractionSource() }
154+
155+
Box(
156+
modifier = Modifier
157+
.pointerInput(Unit) {
158+
awaitEachGesture {
159+
val pressInteraction: PressInteraction.Press
160+
awaitFirstDown().also {
161+
pressInteraction = PressInteraction.Press(it.position)
162+
interactionSource.tryEmit(pressInteraction)
163+
}
164+
if (waitForUpOrCancellation() == null) {
165+
interactionSource.tryEmit(PressInteraction.Cancel(pressInteraction))
166+
} else {
167+
interactionSource.tryEmit(PressInteraction.Release(pressInteraction))
168+
}
169+
}
170+
}
171+
)
172+
```
173+
174+
### Press Feedback Type (`PressFeedbackType`)
175+
176+
The `PressFeedbackType` enum defines different types of visual feedback that can be applied when the component is pressed.
177+
178+
| Type | Description |
179+
|------|-------------|
180+
| None | No visual feedback |
181+
| Sink | Applies a sink effect, where the component scales down slightly when pressed |
182+
| Tilt | Applies a tilt effect, where the component tilts slightly based on the touch position |
183+
108184
## Smooth Rounded Corners (SmoothRoundedCornerShape)
109185

110186
`SmoothRoundedCornerShape` provides smoother rounded corners compared to the standard `RoundedCornerShape`.

docs/zh_CN/components/card.md

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
# Card
22

3-
`Card` 是 Miuix 中的基础容器组件,用于承载相关内容和操作。它提供了具有 Miuix 风格的卡片容器,适用于信息展示、内容分组等场景。
3+
`Card` 是 Miuix 中的基础容器组件,用于承载相关内容和操作。它提供了具有 Miuix 风格的卡片容器,适用于信息展示、内容分组等场景。支持静态显示和交互式两种模式。
44

55
## 引入
66

77
```kotlin
88
import top.yukonga.miuix.kmp.basic.Card
9+
import top.yukonga.miuix.kmp.utils.PressFeedbackType // 如果使用交互式卡片
910
```
1011

1112
## 基本用法
1213

13-
Card 组件可以用于包装和组织内容:
14+
Card 组件可以用于包装和组织内容(静态卡片)
1415

1516
```kotlin
1617
Card {
@@ -22,13 +23,22 @@ Card {
2223

2324
### Card 属性
2425

25-
| 属性名 | 类型 | 说明 | 默认值 | 是否必须 |
26-
| ------------ | ---------------------------------- | ------------------------ | --------------------------- | -------- |
27-
| modifier | Modifier | 应用于卡片的修饰符 | Modifier ||
28-
| cornerRadius | Dp | 卡片圆角半径 | CardDefaults.CornerRadius ||
29-
| insideMargin | PaddingValues | 卡片内部边距 | CardDefaults.InsideMargin ||
30-
| color | Color | 卡片背景颜色 | CardDefaults.DefaultColor() ||
31-
| content | @Composable ColumnScope.() -> Unit | 卡片内容区域的可组合函数 | - ||
26+
27+
| 属性名 | 类型 | 说明 | 默认值 | 是否必须 | 适用范围 |
28+
| ----------------- | ---------------------------------- | ------------------------ | --------------------------- | -------- | -------- |
29+
| modifier | Modifier | 应用于卡片的修饰符 | Modifier || 所有 |
30+
| cornerRadius | Dp | 卡片圆角半径 | CardDefaults.CornerRadius || 所有 |
31+
| insideMargin | PaddingValues | 卡片内部边距 | CardDefaults.InsideMargin || 所有 |
32+
| color | Color | 卡片背景颜色 | CardDefaults.DefaultColor() || 所有 |
33+
| pressFeedbackType | PressFeedbackType | 按压反馈类型 | PressFeedbackType.None || 交互式 |
34+
| showIndication | Boolean? | 显示点击指示效果 | false || 交互式 |
35+
| onClick | (() -> Unit)? | 点击事件回调 | null || 交互式 |
36+
| onLongPress | (() -> Unit)? | 长按事件回调 | null || 交互式 |
37+
| content | @Composable ColumnScope.() -> Unit | 卡片内容区域的可组合函数 | - || 所有 |
38+
39+
::: warning 注意
40+
部分属性仅在创建可交互的卡片时可用!
41+
:::
3242

3343
### CardDefaults 对象
3444

@@ -45,7 +55,7 @@ CardDefaults 对象提供了卡片组件的默认值和颜色配置。
4555

4656
| 方法名 | 类型 | 说明 |
4757
| -------------- | ----- | ------------------ |
48-
| DefaultColor() | Color | 创建卡片的默认颜色 |
58+
| DefaultColor() | Color | 卡片的默认背景颜色 |
4959

5060
## 进阶用法
5161

@@ -89,7 +99,7 @@ Card(
8999
TextButton(
90100
text = "确定",
91101
colors = ButtonDefaults.textButtonColorsPrimary(), // 使用主题颜色
92-
onClick = { /* 处理取消事件 */ }
102+
onClick = { /* 处理确认事件 */ }
93103
)
94104
}
95105
}
@@ -111,3 +121,17 @@ LazyColumn {
111121
}
112122
}
113123
```
124+
125+
### 可交互的卡片
126+
127+
```kotlin
128+
Card(
129+
modifier = Modifier.padding(16.dp),
130+
pressFeedbackType = PressFeedbackType.Sink, // 设置按压反馈为下沉动画效果
131+
showIndication = true, // 显示点击时的视觉反馈效果
132+
onClick = { /* 处理点击事件 */ },
133+
onLongPress = { /* 处理长按事件 */ }
134+
) {
135+
Text("可交互的卡片")
136+
}
137+
```

docs/zh_CN/guide/utils.md

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,82 @@ LazyColumn(
106106
* `springDamp`: 浮点数,定义回弹动画的弹簧阻尼。值越高,振荡越小。默认为 `1f`
107107
* `isEnabled`: 一个返回布尔值的 Lambda 表达式,用于动态控制是否启用越界回弹效果。默认情况下,仅在 Android 和 iOS 平台上启用。
108108

109+
## 按压反馈效果 (PressFeedback)
110+
111+
Miuix 提供了视觉反馈效果来增强用户交互体验,通过类似触觉的响应提升操作感。
112+
113+
### 下沉效果
114+
115+
`pressSink` 修饰符会在组件被按下时应用一种“下沉”视觉效果,通过平滑缩放组件实现。
116+
117+
```kotlin
118+
val interactionSource = remember { MutableInteractionSource() }
119+
120+
Box(
121+
modifier = Modifier
122+
.clickable(interactionSource = interactionSource, indication = null)
123+
.pressSink(interactionSource)
124+
.background(Color.Blue)
125+
.size(100.dp)
126+
)
127+
```
128+
129+
### 倾斜效果
130+
131+
`pressTilt` 修饰符会根据用户按压组件的位置应用一种“倾斜”效果。倾斜方向由触摸偏移决定,使一角“下沉”而另一角保持“静止”。
132+
133+
```kotlin
134+
val interactionSource = remember { MutableInteractionSource() }
135+
136+
Box(
137+
modifier = Modifier
138+
.clickable(interactionSource = interactionSource, indication = null)
139+
.pressTilt(interactionSource)
140+
.background(Color.Green)
141+
.size(100.dp)
142+
)
143+
```
144+
145+
### 触发按压反馈效果的前提
146+
147+
按压反馈效果需要检测 `interactionSource.collectIsPressedAsState()` 以触发。
148+
149+
可以使用 `Modifier.clickable()` 等响应式修饰符来为 `interactionSource` 添加 `PressInteraction.Press` 以触发按压反馈效果。
150+
151+
但更推荐使用下面的方法来为 `interactionSource` 添加 `PressInteraction.Press` 以获得更快响应的触发按压反馈效果。
152+
153+
```kotlin
154+
val interactionSource = remember { MutableInteractionSource() }
155+
156+
Box(
157+
modifier = Modifier
158+
.pointerInput(Unit) {
159+
awaitEachGesture {
160+
val pressInteraction: PressInteraction.Press
161+
awaitFirstDown().also {
162+
pressInteraction = PressInteraction.Press(it.position)
163+
interactionSource.tryEmit(pressInteraction)
164+
}
165+
if (waitForUpOrCancellation() == null) {
166+
interactionSource.tryEmit(PressInteraction.Cancel(pressInteraction))
167+
} else {
168+
interactionSource.tryEmit(PressInteraction.Release(pressInteraction))
169+
}
170+
}
171+
}
172+
)
173+
```
174+
175+
### 按压反馈类型 (PressFeedbackType)
176+
177+
`PressFeedbackType` 枚举定义了组件被按下时可以应用的不同类型的视觉反馈。
178+
179+
| 类型 | 说明 |
180+
|------|-------------|
181+
| None | 无视觉反馈 |
182+
| Sink | 应用下沉效果,组件在按下时轻微缩小 |
183+
| Tilt | 应用倾斜效果,组件根据触摸位置轻微倾斜 |
184+
109185
## 平滑圆角 (SmoothRoundedCornerShape)
110186

111187
`SmoothRoundedCornerShape` 提供了比标准 `RoundedCornerShape` 更加平滑的圆角效果。

example/src/commonMain/kotlin/UITest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ data class UIState(
8989
val showFloatingToolbar: Boolean = false,
9090
val floatingToolbarPosition: Int = 1,
9191
val floatingToolbarOrientation: Int = 1,
92-
val showFloatingActionButton: Boolean = true,
92+
val showFloatingActionButton: Boolean = false,
9393
val floatingActionButtonPosition: Int = 2,
9494
val enablePageUserScroll: Boolean = false,
9595
val isTopPopupExpanded: Boolean = false

0 commit comments

Comments
 (0)