Skip to content

Commit 46c8e2d

Browse files
authored
fix: text alignment and stack alignment (#74)
This pull request makes several improvements: a) Adds missing support for textAlign in the flexbox layout b) Aliases multilineTextAlignment to textAlign c) Fixes VStack and HStack alignment, which was previously incorrect because their content boxes were not filling the outer frame
1 parent 04618e5 commit 46c8e2d

7 files changed

Lines changed: 73 additions & 3 deletions

File tree

example/screens/testing-grounds/flex-playground/FlexPlaygroundScreen.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,40 @@ export default function FlexPlaygroundScreen() {
180180
</VoltraView>
181181
</Card>
182182

183+
{/* Text Align Test */}
184+
<Card>
185+
<Card.Title>Text Align in Flex</Card.Title>
186+
<Text style={styles.previewSubtext}>Text alignment within stretched flex children</Text>
187+
188+
<VoltraView style={{ width: '100%', height: 200, backgroundColor: '#1E293B', padding: 8, marginTop: 12 }}>
189+
<Voltra.View
190+
style={{
191+
backgroundColor: '#334155',
192+
padding: 8,
193+
width: '100%',
194+
height: '100%',
195+
flexDirection: 'column',
196+
alignItems: 'stretch',
197+
gap: 8,
198+
}}
199+
>
200+
<Voltra.View style={{ backgroundColor: '#1E293B', padding: 8, flex: 1 }}>
201+
<Voltra.Text style={{ color: '#FFFFFF', fontSize: 14, textAlign: 'left' }}>textAlign: left</Voltra.Text>
202+
</Voltra.View>
203+
<Voltra.View style={{ backgroundColor: '#1E293B', padding: 8, flex: 1 }}>
204+
<Voltra.Text style={{ color: '#FFFFFF', fontSize: 14, textAlign: 'center' }}>
205+
textAlign: center
206+
</Voltra.Text>
207+
</Voltra.View>
208+
<Voltra.View style={{ backgroundColor: '#1E293B', padding: 8, flex: 1 }}>
209+
<Voltra.Text style={{ color: '#FFFFFF', fontSize: 14, textAlign: 'right' }}>
210+
textAlign: right
211+
</Voltra.Text>
212+
</Voltra.View>
213+
</Voltra.View>
214+
</VoltraView>
215+
</Card>
216+
183217
<View style={styles.footer}>
184218
<Link href="/testing-grounds" asChild>
185219
<Button title="Back to Testing Grounds" variant="ghost" />

ios/ui/Style/CompositeStyle.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ struct CompositeStyleModifier: ViewModifier {
66
let layout: LayoutStyle
77
let decoration: DecorationStyle
88
let rendering: RenderingStyle
9+
var contentAlignment: Alignment = .topLeading
910

1011
func body(content: Content) -> some View {
1112
Group {
@@ -18,7 +19,7 @@ struct CompositeStyleModifier: ViewModifier {
1819

1920
content
2021
.voltraIfLet(layout.padding) { c, p in c.padding(p) }
21-
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
22+
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: contentAlignment)
2223
.modifier(DecorationModifier(style: decoration))
2324
.modifier(RenderingModifier(style: rendering))
2425
.layoutValue(key: FlexItemLayoutKey.self, value: FlexItemValues(

ios/ui/Style/View+applyStyle.swift

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
import SwiftUI
22

3+
// MARK: - TextAlignment Extension
4+
5+
extension TextAlignment {
6+
var horizontalAlignment: HorizontalAlignment {
7+
switch self {
8+
case .leading: return .leading
9+
case .center: return .center
10+
case .trailing: return .trailing
11+
}
12+
}
13+
}
14+
315
// MARK: - View Extension
416

517
extension View {
@@ -13,10 +25,14 @@ extension View {
1325

1426
func applyStyle(_ style: (LayoutStyle, DecorationStyle, RenderingStyle, TextStyle)) -> some View {
1527
let (layout, decoration, rendering, text) = style
28+
let frameAlignment = Alignment(horizontal: text.alignment.horizontalAlignment, vertical: .top)
1629
return self
1730
// 1. Text Properties (Propagate font size for measurement)
1831
.modifier(TextStyleModifier(style: text))
1932
// 2. Standard Box Model
20-
.modifier(CompositeStyleModifier(layout: layout, decoration: decoration, rendering: rendering))
33+
.modifier(CompositeStyleModifier(
34+
layout: layout, decoration: decoration, rendering: rendering,
35+
contentAlignment: frameAlignment
36+
))
2137
}
2238
}

ios/ui/Views/VoltraHStack.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,14 @@ public struct VoltraHStack: VoltraView {
3434
let (layout, _, _, _) = StyleConverter.convert(anyStyle)
3535
let gap = layout.gap ?? 0
3636

37+
let hasFillHeight = layout.height == .fill
38+
3739
HStack(alignment: alignment, spacing: gap) {
3840
element.children ?? .empty
3941
}
42+
.voltraIf(hasFillHeight) { content in
43+
content.frame(maxHeight: .infinity, alignment: Alignment(horizontal: .center, vertical: alignment))
44+
}
4045
.applyStyle(element.style)
4146
}
4247

ios/ui/Views/VoltraText.swift

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,22 @@ public struct VoltraText: VoltraView {
5050
return baseFont
5151
}
5252

53+
let alignment: TextAlignment = {
54+
// Parameter takes precedence over style
55+
if let mta = params.multilineTextAlignment {
56+
return JSStyleParser.textAlignment(mta)
57+
}
58+
return textStyle.alignment
59+
}()
60+
5361
Text(.init(textContent))
5462
.kerning(textStyle.letterSpacing)
5563
.underline(textStyle.decoration == .underline || textStyle.decoration == .underlineLineThrough)
5664
.strikethrough(textStyle.decoration == .lineThrough || textStyle.decoration == .underlineLineThrough)
5765
// These technically work on View, but good to keep close
5866
.font(font)
5967
.foregroundColor(textStyle.color)
60-
.multilineTextAlignment(textStyle.alignment)
68+
.multilineTextAlignment(alignment)
6169
.lineSpacing(textStyle.lineSpacing)
6270
.voltraIfLet(params.numberOfLines) { view, numberOfLines in
6371
view.lineLimit(Int(numberOfLines))

ios/ui/Views/VoltraVStack.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,14 @@ public struct VoltraVStack: View {
3232
let (layout, _, _, _) = StyleConverter.convert(anyStyle)
3333
let gap = layout.gap ?? 0
3434

35+
let hasFillWidth = layout.width == .fill
36+
3537
VStack(alignment: alignment, spacing: gap) {
3638
element.children ?? .empty
3739
}
40+
.voltraIf(hasFillWidth) { content in
41+
content.frame(maxWidth: .infinity, alignment: Alignment(horizontal: alignment, vertical: .center))
42+
}
3843
.applyStyle(element.style)
3944
}
4045

src/styles/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ export type VoltraTextStyle = VoltraViewStyle &
6262
| 'fontVariant'
6363
| 'textDecorationLine'
6464
| 'lineHeight'
65+
| 'textAlign'
6566
>
6667

6768
export type VoltraStyleProp = StyleProp<VoltraViewStyle>

0 commit comments

Comments
 (0)