diff --git a/example/screens/testing-grounds/flex-playground/FlexPlaygroundScreen.tsx b/example/screens/testing-grounds/flex-playground/FlexPlaygroundScreen.tsx
index 50a34c8..72d90bc 100644
--- a/example/screens/testing-grounds/flex-playground/FlexPlaygroundScreen.tsx
+++ b/example/screens/testing-grounds/flex-playground/FlexPlaygroundScreen.tsx
@@ -180,6 +180,40 @@ export default function FlexPlaygroundScreen() {
+ {/* Text Align Test */}
+
+ Text Align in Flex
+ Text alignment within stretched flex children
+
+
+
+
+ textAlign: left
+
+
+
+ textAlign: center
+
+
+
+
+ textAlign: right
+
+
+
+
+
+
diff --git a/ios/ui/Style/CompositeStyle.swift b/ios/ui/Style/CompositeStyle.swift
index 0d0e487..b8f8e7e 100644
--- a/ios/ui/Style/CompositeStyle.swift
+++ b/ios/ui/Style/CompositeStyle.swift
@@ -6,6 +6,7 @@ struct CompositeStyleModifier: ViewModifier {
let layout: LayoutStyle
let decoration: DecorationStyle
let rendering: RenderingStyle
+ var contentAlignment: Alignment = .topLeading
func body(content: Content) -> some View {
Group {
@@ -18,7 +19,7 @@ struct CompositeStyleModifier: ViewModifier {
content
.voltraIfLet(layout.padding) { c, p in c.padding(p) }
- .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
+ .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: contentAlignment)
.modifier(DecorationModifier(style: decoration))
.modifier(RenderingModifier(style: rendering))
.layoutValue(key: FlexItemLayoutKey.self, value: FlexItemValues(
diff --git a/ios/ui/Style/View+applyStyle.swift b/ios/ui/Style/View+applyStyle.swift
index ba2f99a..9b7f29d 100644
--- a/ios/ui/Style/View+applyStyle.swift
+++ b/ios/ui/Style/View+applyStyle.swift
@@ -1,5 +1,17 @@
import SwiftUI
+// MARK: - TextAlignment Extension
+
+extension TextAlignment {
+ var horizontalAlignment: HorizontalAlignment {
+ switch self {
+ case .leading: return .leading
+ case .center: return .center
+ case .trailing: return .trailing
+ }
+ }
+}
+
// MARK: - View Extension
extension View {
@@ -13,10 +25,14 @@ extension View {
func applyStyle(_ style: (LayoutStyle, DecorationStyle, RenderingStyle, TextStyle)) -> some View {
let (layout, decoration, rendering, text) = style
+ let frameAlignment = Alignment(horizontal: text.alignment.horizontalAlignment, vertical: .top)
return self
// 1. Text Properties (Propagate font size for measurement)
.modifier(TextStyleModifier(style: text))
// 2. Standard Box Model
- .modifier(CompositeStyleModifier(layout: layout, decoration: decoration, rendering: rendering))
+ .modifier(CompositeStyleModifier(
+ layout: layout, decoration: decoration, rendering: rendering,
+ contentAlignment: frameAlignment
+ ))
}
}
diff --git a/ios/ui/Views/VoltraHStack.swift b/ios/ui/Views/VoltraHStack.swift
index 8f85ca1..335475a 100644
--- a/ios/ui/Views/VoltraHStack.swift
+++ b/ios/ui/Views/VoltraHStack.swift
@@ -34,9 +34,14 @@ public struct VoltraHStack: VoltraView {
let (layout, _, _, _) = StyleConverter.convert(anyStyle)
let gap = layout.gap ?? 0
+ let hasFillHeight = layout.height == .fill
+
HStack(alignment: alignment, spacing: gap) {
element.children ?? .empty
}
+ .voltraIf(hasFillHeight) { content in
+ content.frame(maxHeight: .infinity, alignment: Alignment(horizontal: .center, vertical: alignment))
+ }
.applyStyle(element.style)
}
diff --git a/ios/ui/Views/VoltraText.swift b/ios/ui/Views/VoltraText.swift
index 18948a2..fb3aad7 100644
--- a/ios/ui/Views/VoltraText.swift
+++ b/ios/ui/Views/VoltraText.swift
@@ -50,6 +50,14 @@ public struct VoltraText: VoltraView {
return baseFont
}
+ let alignment: TextAlignment = {
+ // Parameter takes precedence over style
+ if let mta = params.multilineTextAlignment {
+ return JSStyleParser.textAlignment(mta)
+ }
+ return textStyle.alignment
+ }()
+
Text(.init(textContent))
.kerning(textStyle.letterSpacing)
.underline(textStyle.decoration == .underline || textStyle.decoration == .underlineLineThrough)
@@ -57,7 +65,7 @@ public struct VoltraText: VoltraView {
// These technically work on View, but good to keep close
.font(font)
.foregroundColor(textStyle.color)
- .multilineTextAlignment(textStyle.alignment)
+ .multilineTextAlignment(alignment)
.lineSpacing(textStyle.lineSpacing)
.voltraIfLet(params.numberOfLines) { view, numberOfLines in
view.lineLimit(Int(numberOfLines))
diff --git a/ios/ui/Views/VoltraVStack.swift b/ios/ui/Views/VoltraVStack.swift
index 6cca679..905079b 100644
--- a/ios/ui/Views/VoltraVStack.swift
+++ b/ios/ui/Views/VoltraVStack.swift
@@ -32,9 +32,14 @@ public struct VoltraVStack: View {
let (layout, _, _, _) = StyleConverter.convert(anyStyle)
let gap = layout.gap ?? 0
+ let hasFillWidth = layout.width == .fill
+
VStack(alignment: alignment, spacing: gap) {
element.children ?? .empty
}
+ .voltraIf(hasFillWidth) { content in
+ content.frame(maxWidth: .infinity, alignment: Alignment(horizontal: alignment, vertical: .center))
+ }
.applyStyle(element.style)
}
diff --git a/src/styles/types.ts b/src/styles/types.ts
index deb088e..40a8549 100644
--- a/src/styles/types.ts
+++ b/src/styles/types.ts
@@ -62,6 +62,7 @@ export type VoltraTextStyle = VoltraViewStyle &
| 'fontVariant'
| 'textDecorationLine'
| 'lineHeight'
+ | 'textAlign'
>
export type VoltraStyleProp = StyleProp