Skip to content

Forms: Add basic theming support #339

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions toolkit/featureforms/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,33 @@ FeatureForm(
)
```
*Note* : Once the `validationErrorVisibility` is set to `Visible`, changing it back to `Automatic` will have no effect since all the fields have now gained focus to show any errors.

## Theming and Customization

`FeatureForm` uses the material3 theming system. The following `colors` and `typography` are used by the respective fields.

#### Text Fields
- Outline color - `MaterialTheme.colorScheme.outline`
- Label TextStyle - `MaterialTheme.typography.bodyMedium`
- Input TextStyle - `MaterialTheme.typography.bodyLarge`
- SupportingText TextStyle - `MaterialTheme.typography.bodySmall`
- Error color - `MaterialTheme.colorScheme.error`

#### Radio Buttons
- Outline color - `MaterialTheme.colorScheme.outline`
- Label TextStyle - `MaterialTheme.typography.bodyMedium`
- Options TextStyle - `MaterialTheme.typography.bodyLarge`
- SupportingText TextStyle - `MaterialTheme.typography.bodySmall`
- Error color - `MaterialTheme.colorScheme.error`

#### Group Elements
- Outline Color - `MaterialTheme.colorScheme.outline`
- Header Color - `MaterialTheme.colorScheme.SurfaceVariant`
- Content background Color - `MaterialTheme.colorScheme.background`
- Label TextStyle - `MaterialTheme.typography.bodyMedium`
- Description TextStyle - `MaterialTheme.typography.bodySmall`

#### Read-Only Fields
Alpha values for read only fields cannot be customized at this time.

More information on the material 3 specs [here](https://m3.material.io/components/text-fields/specs#e4964192-72ad-414f-85b4-4b4357abb83c)
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@ import androidx.compose.material.icons.rounded.Clear
import androidx.compose.material.icons.rounded.TextFields
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
Expand Down Expand Up @@ -190,12 +192,14 @@ internal fun BaseTextField(
.semantics { contentDescription = "outlined text field" },
enabled = true,
readOnly = readOnly,
textStyle = MaterialTheme.typography.bodyLarge,
label = {
Text(
text = label,
modifier = Modifier.semantics { contentDescription = "label" },
overflow = TextOverflow.Ellipsis,
maxLines = 1
maxLines = 1,
style = MaterialTheme.typography.bodySmall
)
},
trailingIcon = trailingContent
Expand All @@ -209,13 +213,15 @@ internal fun BaseTextField(
onDone = { focusManager.clearFocus() }
),
supportingText = {
Column(
modifier = Modifier
.clickable {
focusManager.clearFocus()
}
) {
supportingText?.invoke(this)
CompositionLocalProvider(LocalTextStyle provides MaterialTheme.typography.bodySmall) {
Column(
modifier = Modifier
.clickable {
focusManager.clearFocus()
}
) {
supportingText?.invoke(this)
}
}
},
visualTransformation = visualTransformation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import androidx.compose.foundation.selection.selectable
import androidx.compose.foundation.selection.selectableGroup
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Text
Expand Down Expand Up @@ -101,8 +102,7 @@ private fun RadioButtonField(
} else {
label
},
style = MaterialTheme.typography.bodyMedium,
color = colors.labelColor
style = RadioButtonFieldDefaults.labelTextStyle,
)
Column(
modifier = Modifier
Expand All @@ -114,7 +114,7 @@ private fun RadioButtonField(
)
) {
CompositionLocalProvider(
LocalContentColor provides colors.textColor
LocalTextStyle provides RadioButtonFieldDefaults.textStyle
) {
options.forEach { (code, name) ->
RadioButtonRow(
Expand All @@ -129,8 +129,7 @@ private fun RadioButtonField(
if (description.isNotEmpty()) {
Text(
text = description,
style = MaterialTheme.typography.bodySmall,
color = colors.supportingTextColor
style = RadioButtonFieldDefaults.supportingTextStyle
)
}
}
Expand Down Expand Up @@ -164,8 +163,7 @@ private fun RadioButtonRow(
enabled = enabled
)
Text(
text = value,
style = MaterialTheme.typography.bodyMedium
text = value
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,36 +16,32 @@

package com.arcgismaps.toolkit.featureforms.components.codedvalue

import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextStyle

internal object RadioButtonFieldDefaults {

val textStyle : TextStyle @Composable get() = MaterialTheme.typography.bodyLarge
val labelTextStyle : TextStyle @Composable get() = MaterialTheme.typography.bodyMedium
val supportingTextStyle : TextStyle @Composable get() = MaterialTheme.typography.bodySmall

@Composable
fun colors(): RadioButtonFieldColors = RadioButtonFieldColors(
labelColor = MaterialTheme.colorScheme.onSurfaceVariant,
supportingTextColor = MaterialTheme.colorScheme.onSurfaceVariant,
errorColor = MaterialTheme.colorScheme.error,
containerBorderColor = MaterialTheme.colorScheme.outline,
textColor = LocalContentColor.current
)
}

/**
* Color properties of a radio button field.
*
* @property labelColor The color used for the label of this radio button field.
* @property supportingTextColor The color used for the supporting text of this radio button field.
* @property errorColor The color used for the supporting text of this radio button field when the value is considered
* invalid.
* @property containerBorderColor The color used for the container border of this radio button field.
* @property textColor The color used for the text of this radio button field options.
*/
internal data class RadioButtonFieldColors(
val labelColor: Color,
val supportingTextColor: Color,
val errorColor: Color,
val containerBorderColor: Color,
val textColor: Color
)