diff --git a/components/src/main/kotlin/de/jeanlucmakiola/floret/components/OptionPicker.kt b/components/src/main/kotlin/de/jeanlucmakiola/floret/components/OptionPicker.kt index 6c0d984..dd5e550 100644 --- a/components/src/main/kotlin/de/jeanlucmakiola/floret/components/OptionPicker.kt +++ b/components/src/main/kotlin/de/jeanlucmakiola/floret/components/OptionPicker.kt @@ -26,6 +26,20 @@ import de.jeanlucmakiola.floret.identity.LocalFloretDarkTheme * [scrollable] forwards to [CollapsingScaffold]: leave it on unless [content] * scrolls itself, which a picker only needs for an option list long enough to * warrant a lazy container. + * + * **Picker richness.** Three shapes, in ascending order — take the cheapest one + * that makes the choice obvious: + * 1. plain option rows, when the label *is* the meaning ("English", "Dark"); + * 2. rows plus a per-option summary of the concrete effect, when the meaning is + * a date, a time or a number the label only names ("Next 7 days" → + * "30 Jul – 5 Aug"). [OptionPicker]'s `summary` covers this; + * 3. a live preview above the rows, when the effect is *visual* and no words + * carry it (month grid style, dimmed past events, week start). + * + * A picker of the third kind **must not close when an option is tapped** — it + * applies immediately and stays open, because closing would hide the very thing + * the screen exists to show. The user leaves via back. The first two kinds close + * on tap as usual. */ @Composable fun FullScreenPicker( @@ -82,6 +96,15 @@ fun FullScreenPicker( * General single-select picker, full-screen: each option is a connected grouped * row and the current one carries a check. The drop-in for the family's option * dialogs (theme, default list, reminder offset, …). + * + * [summary] adds a second line per option — reserve it for the option's + * *concrete effect*, the thing its label names but doesn't spell out: the dates + * a range resolves to, the time a format renders as, what "follow the system" + * currently means. Returning null leaves that row single-line, so one option + * (typically the automatic one) can carry a note the others don't need. It is + * the cheap middle rung of the richness ladder described on [FullScreenPicker]: + * every option shows its effect at once and stays comparable, without the cost + * of a live preview. */ @Composable fun OptionPicker( @@ -91,6 +114,7 @@ fun OptionPicker( label: @Composable (T) -> String, onSelect: (T) -> Unit, onDismiss: () -> Unit, + summary: (@Composable (T) -> String?)? = null, leading: (@Composable (T) -> Unit)? = null, header: (@Composable ColumnScope.() -> Unit)? = null, predictiveBack: Boolean = false, @@ -101,6 +125,7 @@ fun OptionPicker( val isSelected = option == selected GroupedRow( title = label(option), + summary = summary?.invoke(option), position = positionOf(index, options.size), selected = isSelected, leading = leading?.let { { it(option) } },