Disclosure

An unstyled Disclosure component that can be used to build disclosures with the styling of your choice in your Compose Multiplatform apps.

Comes with accessibility baked in, animation support and it is fully customizable.

Installation

repositories {
    mavenCentral()
}

dependencies {
    implementation("com.composables:core:1.37.0")
}

Basic Example

The Disclosure component consists of a Disclosure, a DisclosureHeading, and a DisclosurePanel.

The Disclosure component holds its state and the rest of the components. It also sets up important semantics for accessibility.

The DisclosureHeading is a button which will reveal or hide the DisclosurePanel when clicked, according to the disclosure's state:

Disclosure {
    DisclosureHeading {
        Text("What is the return policy?")
    }
    DisclosurePanel {
        Text("Our return policy allows returns within 30 days of purchase with a receipt.")
    }
}

Styling

The Disclosure renders nothing on the screen by default. It handles the UX pattern of a disclosure for you and leaves any styling for you to handle.

We provide some styling parameters to ensure that your content's interaction indicators look great according to the styling you need.

Changing the styling of the disclosure is done by passing the respective Modifiers to your DisclosureHeading and DisclosurePanel:

val state = rememberDisclosureState()

Disclosure(state = state) {
    DisclosureHeading(
        modifier = Modifier
            .background(Color.LightGray)
            .padding(16.dp)
            .shadow(4.dp),
        shape = RoundedCornerShape(8.dp),
        contentPadding = PaddingValues(vertical = 12.dp, horizontal = 16.dp)
    ) {
        val degrees by animateFloatAsState(if (state.expanded) -180f else 0f, tween())

        Text("What is Compose Unstyled?")

        // icon from composeicons.com/icons/lucide/chevron-down
        Icon(
            imageVector = ChevronDown,
            contentDescription = null,
            modifier = Modifier.rotate(degrees)
        )
    }
    DisclosurePanel(
        enter = expandVertically(
            spring(
                stiffness = Spring.StiffnessMediumLow,
                visibilityThreshold = IntSize.VisibilityThreshold
            )
        ),
        exit = shrinkVertically()
    ) {
        Text(
            "Compose Unstyled is a collection of unstyled, accessible UI components for Jetpack Compose and Compose Multiplatform.",
            modifier = Modifier.padding(16.dp).alpha(0.66f)
        )
    }
}

Code Examples

Showing/Hide the disclosure

To manually show or hide the disclosure panel, use the expanded property of the Disclosure state.

To create your own controlled state use the rememberDisclosureState() function and pass it to the Disclosure composable.

Then use the DisclosureHeading variant with the onClick parameter to toggle the state manually.

Important: the DisclosureHeading with the onClick parameter does not set the collapse/expanded actions to the heading as you might want to customize the behavior. These are important for accessibility and you would need to set them yourself, if you chose to use this variant.

val state = rememberDisclosureState()

Disclosure(state = state) {
    DisclosureHeading(onClick = { state.expanded = state.expanded.not() }) {
        Text("What is the return policy?")
    }
    DisclosurePanel {
        Text("Our return policy allows returns within 30 days of purchase with a receipt.")
    }
}

Adding transitions

You can add transitions to the disclosure panel to animate its expansion and collapse:

Disclosure {
    DisclosureHeading {
        Text("What is Compose Unstyled?")
    }
    DisclosurePanel(
        enter = expandVertically(
            spring(
                stiffness = Spring.StiffnessMediumLow,
                visibilityThreshold = IntSize.VisibilityThreshold
            )
        ),
        exit = shrinkVertically()
    ) {
        Text(
            "Compose Unstyled is a collection of unstyled, accessible UI components for Jetpack Compose and Compose Multiplatform.",
            modifier = Modifier.padding(16.dp).alpha(0.66f)
        )
    }
}

Keyboard Interactions

KeyDescription
Enter
Toggles the disclosure between expanded and collapsed states.
Space
Toggles the disclosure between expanded and collapsed states.

Component API

rememberDisclosureState

ParameterDescription
initiallyExpandedDetermines if the disclosure is expanded initially.

DisclosureState

ParameterDescription
expandedControls whether the disclosure is expanded.

Disclosure

ParameterDescription
stateThe DisclosureState object controlling the disclosure's expanded state.
modifierModifier to be applied to the disclosure.
contentA composable function that defines the content of the disclosure.

DisclosureHeading

ParameterDescription
modifierModifier to be applied to the heading.
enabledIndicates if the heading is enabled.
shapeThe shape of the heading.
backgroundColorThe background color of the heading.
contentColorThe color to apply to the contents of the heading.
contentPaddingPadding values for the content.
borderColorThe color of the border.
borderWidthThe width of the border.
indicationThe indication to be shown when the heading is interacted with.
interactionSourceThe interaction source for the heading.
contentA composable function that defines the content of the heading.

DisclosurePanel

ParameterDescription
modifierModifier to be applied to the panel.
enterThe enter transition for the panel.
exitThe exit transition for the panel.
contentA composable function that defines the content of the panel.

Chevron Icons and other icons

You can find the chevron icon used in our examples and many other icons at composeicons.com.