Skip to content

Commit

Permalink
Merge pull request #390 from kiwicom/collapse-fixes
Browse files Browse the repository at this point in the history
Collapse visual updates & fixes
  • Loading branch information
hrach committed Mar 29, 2023
2 parents 9cf141e + f921257 commit dc119a5
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ private fun CollapseScreenInner() {
Column(modifier = Modifier.padding(16.dp)) {
Collapse(
expanded = isFirstCollapseExpanded,
onExpandClick = { isFirstCollapseExpanded = it },
onExpandChange = { isFirstCollapseExpanded = it },
title = {
Text(text = "Title 1")
},
Expand All @@ -60,7 +60,7 @@ private fun CollapseScreenInner() {

Collapse(
expanded = isSecondCollapseExpanded,
onExpandClick = { isSecondCollapseExpanded = it },
onExpandChange = { isSecondCollapseExpanded = it },
withSeparator = false,
title = {
Text(text = "Title 2")
Expand Down
8 changes: 4 additions & 4 deletions docs/03-components/07-interaction/collapse.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ fun Example() {
expanded = expanded,
onExpandClick = { expanded = it },
title = {
Text(text = "This the title")
Text(text = "Collapse title")
},
content = {
Text(text = "This is the collapsible content")
Expand All @@ -43,7 +43,7 @@ fun Example() {
expanded = expanded,
onExpandClick = { expanded = it },
title = {
Text(text = "This the title")
Text(text = "Collapse title")
},
content = {
Text(text = "This is the collapsible content")
Expand All @@ -64,7 +64,7 @@ composeTestRule.setContent {
expanded = expanded,
onExpandClick = { expanded = it },
title = {
Text(text = "This the title", modifier = Modifier.testTag("title"))
Text(text = "Collapse title", modifier = Modifier.testTag("title"))
},
content = {
Text(text = "This is the collapsible content", modifier = Modifier.testTag("content"))
Expand All @@ -73,7 +73,7 @@ composeTestRule.setContent {
)
}

composeTestRule.onNodeWithTag("title").assertIsDisplayed()
composeTestRule.onNodeWithTag("title", useUnmergedTree = true).assertIsDisplayed()
composeTestRule.onNodeWithTag("content").assertDoesNotExist()

composeTestRule.onNodeWithTag("collapse").performSemanticsAction(SemanticsActions.Expand)
Expand Down
78 changes: 49 additions & 29 deletions ui/src/main/java/kiwi/orbit/compose/ui/controls/Collapse.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,67 +2,70 @@ package kiwi.orbit.compose.ui.controls

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Divider
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.semantics.AccessibilityAction
import androidx.compose.ui.semantics.SemanticsActions
import androidx.compose.ui.semantics.collapse
import androidx.compose.ui.semantics.expand
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp
import kiwi.orbit.compose.icons.Icons
import kiwi.orbit.compose.ui.OrbitTheme
import kiwi.orbit.compose.ui.controls.internal.OrbitPreviews
import kiwi.orbit.compose.ui.controls.internal.Preview
import kiwi.orbit.compose.ui.foundation.ProvideMergedTextStyle

/**
* Hides long or complex information under a block that can be hidden.
*
* Example :
*
* var expanded by remember { mutableStateOf(false) }
*
* ```
* var expanded by rememberSaveable { mutableStateOf(false) }
* Collapse(
* expanded = expanded,
* onExpandClick = { expanded = it },
* title = {
* Text(text = "This the title")
* },
* content = {
* Text(text = "This is the collapsible content")
* },
* title = { Text("Title") },
* content = { Text(text = "This is the collapsible content") },
* )
* ```
*/
@Composable
public fun Collapse(
expanded: Boolean,
onExpandClick: (Boolean) -> Unit,
onExpandChange: (Boolean) -> Unit,
title: @Composable () -> Unit,
content: @Composable () -> Unit,
modifier: Modifier = Modifier,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
withSeparator: Boolean = true,
) {
Column(
modifier = modifier.semantics {
this[SemanticsActions.Expand] = AccessibilityAction(SemanticsActions.Expand.name) {
expand {
if (!expanded) {
onExpandClick(true)
onExpandChange(true)
true
} else {
false
}
}
this[SemanticsActions.Collapse] = AccessibilityAction(SemanticsActions.Collapse.name) {
collapse {
if (expanded) {
onExpandClick(false)
onExpandChange(false)
true
} else {
false
Expand All @@ -72,17 +75,33 @@ public fun Collapse(
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
Row(
modifier = Modifier.fillMaxWidth(),
modifier = Modifier
.clickable(
enabled = true,
onClick = { onExpandChange(!expanded) },
indication = null,
interactionSource = interactionSource,
)
.padding(vertical = 12.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
) {
title()
CollapseArrow(expanded = expanded, onClick = { onExpandClick(!expanded) })
ProvideMergedTextStyle(OrbitTheme.typography.bodyNormalMedium) {
Box(Modifier.weight(1f)) {
title()
}
}
CollapseArrow(
expanded = expanded,
interactionSource = interactionSource,
onClick = { onExpandChange(!expanded) },
)
}
AnimatedVisibility(visible = expanded, modifier = Modifier.fillMaxWidth()) {
content()
AnimatedVisibility(visible = expanded) {
ProvideMergedTextStyle(OrbitTheme.typography.bodyNormal) {
content()
}
}

if (withSeparator) {
Divider()
}
Expand All @@ -92,16 +111,17 @@ public fun Collapse(
@Composable
private fun CollapseArrow(
expanded: Boolean,
interactionSource: MutableInteractionSource,
onClick: () -> Unit,
) {
val arrowRotationDegree by animateFloatAsState(
targetValue = if (expanded) 180f else 0f,
)

IconButton(
onClick = onClick,
modifier = Modifier
.rotate(arrowRotationDegree),
modifier = Modifier.rotate(arrowRotationDegree),
interactionSource = interactionSource,
minimumInteractiveComponentEnforcement = false,
) {
Icon(
painter = Icons.ChevronDown,
Expand All @@ -113,13 +133,13 @@ private fun CollapseArrow(
@OrbitPreviews
@Composable
internal fun CollapsePreview() {
var expanded by remember { mutableStateOf(true) }
var expanded by rememberSaveable { mutableStateOf(true) }
Preview {
Collapse(
expanded = expanded,
onExpandClick = { expanded = it },
onExpandChange = { expanded = it },
title = {
Text(text = "This the title")
Text(text = "Collapse title")
},
content = {
Text(text = "This is the collapsible content")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public fun IconButton(
modifier: Modifier = Modifier,
enabled: Boolean = true,
rippleRadius: Dp = RippleRadius,
minimumInteractiveComponentEnforcement: Boolean = true,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
content: @Composable () -> Unit,
) {
Expand All @@ -34,7 +35,13 @@ public fun IconButton(
interactionSource = interactionSource,
indication = rememberRipple(bounded = false, radius = rippleRadius),
)
.size(rippleRadius * 2),
.run {
if (minimumInteractiveComponentEnforcement) {
size(rippleRadius * 2)
} else {
this
}
},
contentAlignment = Alignment.Center,
) {
val contentEmphasis = if (enabled) LocalContentEmphasis.current else ContentEmphasis.Disabled
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ internal class CollapseTest {
var expanded by remember { mutableStateOf(false) }
Collapse(
expanded = expanded,
onExpandClick = { expanded = it },
onExpandChange = { expanded = it },
title = {
Text(text = "This the title", modifier = Modifier.testTag("title"))
Text(text = "Collapse title", modifier = Modifier.testTag("title"))
},
content = {
Text(text = "This is the collapsible content", modifier = Modifier.testTag("content"))
Expand All @@ -38,7 +38,7 @@ internal class CollapseTest {
)
}

composeTestRule.onNodeWithTag("title").assertIsDisplayed()
composeTestRule.onNodeWithTag("title", useUnmergedTree = true).assertIsDisplayed()
composeTestRule.onNodeWithTag("content").assertDoesNotExist()

composeTestRule.onNodeWithTag("collapse").performSemanticsAction(SemanticsActions.Expand)
Expand Down
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.

0 comments on commit dc119a5

Please sign in to comment.