DRY pass #2, batch 6, F19: Sheet, the bottom sheet with its title (#5372)

EditorPickers.kt Sheet(title, onDismiss, modifier, verticalArrangement):
a ModalBottomSheet holding a full-width column with the screen margin,
clear of the navigation bar, under SheetTitle. The filter, tag picker,
reminder and share sheets each built that. A site's extra (a scroll, ime
padding, bottom space) is now applied after the navigation-bar inset
rather than before it. The total inset is the same either way.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 14:53:51 -04:00
co-authored by Claude Opus 5.5
parent f2fac1674b
commit 709ccca64c
3 changed files with 167 additions and 167 deletions
@@ -1,19 +1,16 @@
package com.fabledsword.inkwell.ui package com.fabledsword.inkwell.ui
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FilterChip import androidx.compose.material3.FilterChip
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@@ -115,17 +112,11 @@ internal fun FilterSheet(
onChange: (BoardFilters) -> Unit, onChange: (BoardFilters) -> Unit,
onDismiss: () -> Unit, onDismiss: () -> Unit,
) { ) {
ModalBottomSheet(onDismissRequest = onDismiss) { Sheet(
Column( title = R.string.filters,
modifier = onDismiss = onDismiss,
Modifier modifier = Modifier.verticalScroll(rememberScrollState()),
.fillMaxWidth()
.padding(horizontal = 16.dp)
.navigationBarsPadding()
.verticalScroll(rememberScrollState()),
) { ) {
SheetTitle(R.string.filters)
FilterHeading(R.string.filters_show) FilterHeading(R.string.filters_show)
FlowRow(horizontalArrangement = Arrangement.spacedBy(6.dp)) { FlowRow(horizontalArrangement = Arrangement.spacedBy(6.dp)) {
FilterChip( FilterChip(
@@ -165,7 +156,6 @@ internal fun FilterSheet(
} }
} }
} }
}
@Composable @Composable
private fun FilterHeading(labelRes: Int) { private fun FilterHeading(labelRes: Int) {
@@ -1,8 +1,10 @@
package com.fabledsword.inkwell.ui package com.fabledsword.inkwell.ui
import androidx.annotation.StringRes
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.heightIn
@@ -85,17 +87,11 @@ fun LabelSheet(
.map { it.id } .map { it.id }
.toSet() .toSet()
ModalBottomSheet(onDismissRequest = onDismiss) { Sheet(
Column( title = R.string.label_picker_title,
modifier = onDismiss = onDismiss,
Modifier modifier = Modifier.imePadding(),
.fillMaxWidth()
.padding(horizontal = 16.dp)
.imePadding()
.navigationBarsPadding(),
) { ) {
SheetTitle(R.string.label_picker_title)
PlainTextField( PlainTextField(
value = typed, value = typed,
onValueChange = { typed = it }, onValueChange = { typed = it },
@@ -150,7 +146,6 @@ fun LabelSheet(
} }
} }
} }
}
/** /**
* When to be reminded. * When to be reminded.
@@ -170,16 +165,10 @@ fun ReminderSheet(
) { ) {
var exact by remember { mutableStateOf(false) } var exact by remember { mutableStateOf(false) }
ModalBottomSheet(onDismissRequest = onDismiss) { Sheet(
Column( title = R.string.reminder_title,
modifier = onDismiss = onDismiss,
Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp)
.navigationBarsPadding(),
) { ) {
SheetTitle(R.string.reminder_title)
reminderPresets().forEach { (labelRes, at) -> reminderPresets().forEach { (labelRes, at) ->
Text( Text(
text = "${stringResource(labelRes)} · ${formatInstant(rfc3339(at))}", text = "${stringResource(labelRes)} · ${formatInstant(rfc3339(at))}",
@@ -225,7 +214,6 @@ fun ReminderSheet(
) )
} }
} }
}
if (exact) { if (exact) {
ExactReminderPicker( ExactReminderPicker(
@@ -337,6 +325,36 @@ private fun RecurrenceChips(
} }
} }
/**
* A bottom sheet with its title: full width, the screen's side margin, and clear of
* the navigation bar. [modifier] adds to that, after the inset (ime padding, a
* scroll, extra space at the bottom).
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
internal fun Sheet(
@StringRes title: Int,
onDismiss: () -> Unit,
modifier: Modifier = Modifier,
verticalArrangement: Arrangement.Vertical = Arrangement.Top,
content: @Composable ColumnScope.() -> Unit,
) {
ModalBottomSheet(onDismissRequest = onDismiss) {
Column(
modifier =
Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp)
.navigationBarsPadding()
.then(modifier),
verticalArrangement = verticalArrangement,
) {
SheetTitle(title)
content()
}
}
}
@Composable @Composable
internal fun SheetTitle(labelRes: Int) { internal fun SheetTitle(labelRes: Int) {
Text( Text(
@@ -7,7 +7,6 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
@@ -18,7 +17,6 @@ import androidx.compose.material3.FilterChip
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.RadioButton import androidx.compose.material3.RadioButton
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton import androidx.compose.material3.TextButton
@@ -75,17 +73,12 @@ fun ShareSheet(
onUnshare: (shareId: String) -> Unit, onUnshare: (shareId: String) -> Unit,
onDismiss: () -> Unit, onDismiss: () -> Unit,
) { ) {
ModalBottomSheet(onDismissRequest = onDismiss) { Sheet(
Column( title = R.string.share_title,
modifier = onDismiss = onDismiss,
Modifier modifier = Modifier.padding(bottom = 16.dp),
.fillMaxWidth()
.padding(horizontal = 16.dp)
.padding(bottom = 16.dp)
.navigationBarsPadding(),
verticalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp),
) { ) {
SheetTitle(R.string.share_title)
when { when {
state.loading -> Muted(stringResource(R.string.share_loading)) state.loading -> Muted(stringResource(R.string.share_loading))
state.needsServer -> Muted(stringResource(R.string.share_needs_server)) state.needsServer -> Muted(stringResource(R.string.share_needs_server))
@@ -94,7 +87,6 @@ fun ShareSheet(
} }
} }
} }
}
@Composable @Composable
private fun ShareBody( private fun ShareBody(