import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.VisibilityThreshold
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.tween
import androidx.compose.animation.expandVertically
import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.LocalIndication
import androidx.compose.foundation.background
import androidx.compose.foundation.border
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.foundation.layout.widthIn
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicText
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.alpha
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import com.composables.icons.lucide.ChevronDown
import com.composables.icons.lucide.Lucide
import com.composeunstyled.DisclosedContent
import com.composeunstyled.DisclosureButton
import com.composeunstyled.UnstyledDisclosure
import com.composeunstyled.UnstyledIcon
@Composable
fun DisclosureDemo() {
var expanded by remember { mutableStateOf(false) }
UnstyledDisclosure(
expanded = expanded,
onExpandedChange = { expanded = it },
) {
Column(
modifier = Modifier
.widthIn(max = 560.dp)
.clip(RoundedCornerShape(12.dp))
.background(Color(0xFFF8FAFC))
.border(1.dp, Color(0xFFCACACA), RoundedCornerShape(12.dp)),
) {
DisclosureButton(
modifier = Modifier.fillMaxWidth(),
indication = LocalIndication.current,
) {
Row(
modifier = Modifier.fillMaxWidth().padding(vertical = 12.dp, horizontal = 16.dp),
verticalAlignment = Alignment.CenterVertically,
) {
BasicText("What is Compose Unstyled", modifier = Modifier.weight(1f))
val degrees by animateFloatAsState(if (expanded) -180f else 0f, tween())
UnstyledIcon(
imageVector = Lucide.ChevronDown,
contentDescription = null,
modifier = Modifier.rotate(degrees),
)
}
}
DisclosedContent(
enter = expandVertically(
spring(
stiffness = Spring.StiffnessMediumLow,
visibilityThreshold = IntSize.VisibilityThreshold,
),
),
exit = shrinkVertically(),
) {
BasicText(
"Compose Unstyled is a collection of unstyled, accessible UI components for Compose " +
"Multiplatform. It provides the building blocks for creating beautiful, consistent " +
"user interfaces.",
modifier = Modifier.padding(16.dp).alpha(0.66f),
)
}
}
}
}Installation
implementation("com.composables:composeunstyled-disclosure")
Anatomy
UnstyledDisclosure(
expanded = expanded,
onExpandedChange = onExpandedChange,
) {
DisclosureButton {
}
DisclosedContent {
}
}
Concepts
UnstyledDisclosurerepresents an expandable region.DisclosureButtonrenders the trigger that toggles the disclosure.DisclosedContentrenders content only while the disclosure is expanded.
Accessibility
Use DisclosureButton for the disclosure trigger so assistive technology receives expand and collapse actions.
Code Examples
Showing hidden content
Use the expanded parameter to control whether DisclosedContent is visible:
var expanded by remember { mutableStateOf(false) }
UnstyledDisclosure(
expanded = expanded,
onExpandedChange = { expanded = it },
) {
DisclosureButton {
BasicText(if (expanded) "Hide details" else "Show details")
}
DisclosedContent {
BasicText("Details")
}
}
Animating disclosed content
Use the enter and exit parameters on DisclosedContent to animate the disclosed content:
UnstyledDisclosure(
expanded = expanded,
onExpandedChange = { expanded = it },
) {
DisclosureButton {
BasicText("Details")
}
DisclosedContent(
enter = expandVertically(),
exit = shrinkVertically(),
) {
BasicText("Hidden content")
}
}
API Reference
UnstyledDisclosure
| Parameter | Type | Description |
|---|---|---|
expanded |
Boolean |
Controls whether the disclosure is expanded. |
onExpandedChange |
(Boolean) -> Unit |
|
modifier |
Modifier |
Modifier to be applied to the panel. |
content |
DisclosureScope.() -> Unit |
A composable function that defines the content of the panel. |
DisclosureScope.DisclosureButton
| Parameter | Type | Description |
|---|---|---|
modifier |
Modifier |
Modifier to be applied to the panel. |
enabled |
Boolean |
Indicates if the heading is enabled. |
contentPadding |
PaddingValues |
Padding values for the content. |
indication |
Indication? |
The indication to be shown when the heading is interacted with. |
interactionSource |
MutableInteractionSource? |
The interaction source for the heading. |
contentAlignment |
Alignment |
|
content |
() -> Unit |
A composable function that defines the content of the panel. |
DisclosureScope.DisclosedContent
| Parameter | Type | Description |
|---|---|---|
modifier |
Modifier |
Modifier to be applied to the panel. |
enter |
EnterTransition |
The enter transition for the panel. |
exit |
ExitTransition |
The exit transition for the panel. |
content |
() -> Unit |
A composable function that defines the content of the panel. |