Skip to content

Commit 562a9a5

Browse files
committed
Propagate font, color, and disabled through the view tree
1 parent 2bc1ae7 commit 562a9a5

1 file changed

Lines changed: 45 additions & 5 deletions

File tree

  • Demo/swiftui/src/commonMain/kotlin/com/pureswift/swiftui

Demo/swiftui/src/commonMain/kotlin/com/pureswift/swiftui/Render.kt

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,15 @@ internal data class AnimSpec(val curve: String, val durationMs: Int)
138138

139139
internal val LocalAnimationSpec = compositionLocalOf<AnimSpec?> { null }
140140

141+
// Inherited style environment (SwiftUI's `.font`/`.foregroundColor`/`.disabled`
142+
// set values for a whole subtree). A node folds its own such modifiers into
143+
// these before rendering its children; leaves consume them as defaults that
144+
// their own modifiers still override.
145+
internal val LocalInheritedFontSize = compositionLocalOf { TextUnit.Unspecified }
146+
internal val LocalInheritedFontWeight = compositionLocalOf<FontWeight?> { null }
147+
internal val LocalInheritedColor = compositionLocalOf { Color.Unspecified }
148+
internal val LocalInheritedDisabled = compositionLocalOf { false }
149+
141150
/// Interprets a Swift-evaluated node tree into Material 3 composables.
142151
///
143152
/// One `when` per node type; unknown types render a diagnostic so schema
@@ -152,7 +161,36 @@ fun Render(node: ViewNode) {
152161
val spec = node.string("animationCurve")?.let {
153162
AnimSpec(it, (node.double("animationDurationMs") ?: 350.0).toInt())
154163
} ?: LocalAnimationSpec.current
155-
CompositionLocalProvider(LocalAnimationSpec provides spec) { RenderResolved(node) }
164+
165+
// Fold this node's own style modifiers into the inherited environment so
166+
// its subtree sees them.
167+
var fontSize = LocalInheritedFontSize.current
168+
var fontWeight = LocalInheritedFontWeight.current
169+
var color = LocalInheritedColor.current
170+
var disabled = LocalInheritedDisabled.current
171+
for (m in node.modifiers) {
172+
when (m.kind) {
173+
"font" -> {
174+
m.args.string("style")?.let {
175+
fontSize = fontSizeForStyle(it).sp
176+
fontWeight = defaultWeightForStyle(it)
177+
}
178+
m.args.double("size")?.let { fontSize = it.sp }
179+
m.args.string("weight")?.let { fontWeight = fontWeightFor(it) }
180+
}
181+
"fontWeight" -> m.args.string("weight")?.let { fontWeight = fontWeightFor(it) }
182+
"foregroundColor" -> m.args.long("color")?.let { color = Color(it.toInt()) }
183+
"disabled" -> if ((m.args["value"] as? kotlinx.serialization.json.JsonPrimitive)?.content == "true") disabled = true
184+
}
185+
}
186+
187+
CompositionLocalProvider(
188+
LocalAnimationSpec provides spec,
189+
LocalInheritedFontSize provides fontSize,
190+
LocalInheritedFontWeight provides fontWeight,
191+
LocalInheritedColor provides color,
192+
LocalInheritedDisabled provides disabled,
193+
) { RenderResolved(node) }
156194
}
157195

158196
@Composable
@@ -165,8 +203,9 @@ private fun RenderResolved(node: ViewNode) {
165203
"Button" -> {
166204
val onTap = node.long("onTap")
167205
Button(
206+
// own disabled and any inherited `.disabled` both apply
168207
onClick = { onTap?.let { SwiftBridge.sink.invokeVoid(it) } },
169-
enabled = !node.isDisabled(),
208+
enabled = !node.isDisabled() && !LocalInheritedDisabled.current,
170209
modifier = node.composeModifiers(),
171210
) {
172211
RenderChildren(node)
@@ -744,9 +783,10 @@ private fun materialIcon(name: String): ImageVector? = when (name) {
744783
// attributes. Layout modifiers in the same chain still apply via composeModifiers().
745784
@Composable
746785
private fun RenderText(node: ViewNode) {
747-
var color = Color.Unspecified
748-
var fontSize: TextUnit = TextUnit.Unspecified
749-
var weight: FontWeight? = null
786+
// Start from the inherited environment; the node's own modifiers override.
787+
var color = LocalInheritedColor.current
788+
var fontSize: TextUnit = LocalInheritedFontSize.current
789+
var weight: FontWeight? = LocalInheritedFontWeight.current
750790
var fontStyle: FontStyle? = null
751791
var maxLines = Int.MAX_VALUE
752792
var textAlign: TextAlign? = null

0 commit comments

Comments
 (0)