Skip to content

Layout Components ​

Core layout containers that provide SwiftUI-style layout with flexbox implementation. These components form the foundation of tachUI's layout system.

Overview ​

tachUI provides three fundamental layout components:

  • VStack - Vertical stack layout (column direction)
  • HStack - Horizontal stack layout (row direction)
  • ZStack - Overlay/depth stack layout (absolute positioning)

All layout components support modifier chaining and can contain any tachUI components as children.

VStack ​

Arranges child components vertically in a column layout.

Basic Usage ​

typescript
import { VStack, Text } from '@tachui/core'

VStack({
  children: [
    Text("First item"),
    Text("Second item"), 
    Text("Third item")
  ]
})

Props ​

typescript
interface VStackProps {
  children?: ComponentInstance[]
  spacing?: number
  alignment?: 'leading' | 'center' | 'trailing'
  debugLabel?: string
}
PropertyTypeDefaultDescription
childrenComponentInstance[][]Array of child components
spacingnumber0Space between items in pixels
alignment'leading' | 'center' | 'trailing''center'Cross-axis alignment
debugLabelstring-Debug identifier for development

Alignment Options ​

typescript
import { VStack, Text } from '@tachui/core'

// Leading alignment (left-aligned)
VStack({
  children: [Text("Left"), Text("Aligned")],
  alignment: 'leading'
})

// Center alignment (default)
VStack({
  children: [Text("Center"), Text("Aligned")],
  alignment: 'center'
})

// Trailing alignment (right-aligned)
VStack({
  children: [Text("Right"), Text("Aligned")],
  alignment: 'trailing'
})

With Spacing ​

typescript
import { VStack, Button } from '@tachui/core'

VStack({
  children: [
    Button("First Button"),
    Button("Second Button"),
    Button("Third Button")
  ],
  spacing: 16 // 16px between each button
})

With Modifiers ​

typescript
import { VStack, Text } from '@tachui/core'

VStack({
  children: [
    Text("Styled Stack"),
    Text("With padding and background")
  ],
  spacing: 12
})
.modifier
.padding(20)
.backgroundColor('#f5f5f5')
.cornerRadius(12)
.shadow({ x: 0, y: 2, blur: 8, color: 'rgba(0,0,0,0.1)' })
.build()

HStack ​

Arranges child components horizontally in a row layout.

Basic Usage ​

typescript
import { HStack, Button } from '@tachui/core'

HStack({
  children: [
    Button("Cancel"),
    Button("OK")
  ]
})

Props ​

typescript
interface HStackProps {
  children?: ComponentInstance[]
  spacing?: number
  alignment?: 'top' | 'center' | 'bottom'
  debugLabel?: string
}
PropertyTypeDefaultDescription
childrenComponentInstance[][]Array of child components
spacingnumber0Space between items in pixels
alignment'top' | 'center' | 'bottom''center'Cross-axis alignment
debugLabelstring-Debug identifier for development

Alignment Options ​

typescript
import { HStack, Text, Button } from '@tachui/core'

// Top alignment
HStack({
  children: [
    Text("Top").modifier.font({ size: 12 }).build(),
    Button("Aligned"),
    Text("Content").modifier.font({ size: 20 }).build()
  ],
  alignment: 'top'
})

// Center alignment (default)
HStack({
  children: [
    Text("Center").modifier.font({ size: 12 }).build(), 
    Button("Aligned"),
    Text("Content").modifier.font({ size: 20 }).build()
  ],
  alignment: 'center'
})

// Bottom alignment
HStack({
  children: [
    Text("Bottom").modifier.font({ size: 12 }).build(),
    Button("Aligned"), 
    Text("Content").modifier.font({ size: 20 }).build()
  ],
  alignment: 'bottom'
})
typescript
import { HStack, Button, Text, Spacer } from '@tachui/core'

const NavigationBar = () =>
  HStack({
    children: [
      Button("Back"),
      Text("Page Title")
        .modifier
        .font({ size: 18, weight: 'bold' })
        .build(),
      Spacer(),
      Button("More")
    ],
    spacing: 12
  })
  .modifier
  .padding({ horizontal: 16, vertical: 12 })
  .backgroundColor('white')
  .shadow({ x: 0, y: 1, blur: 2, color: 'rgba(0,0,0,0.1)' })
  .build()

ZStack ​

Overlays child components with absolute positioning and z-index control.

Basic Usage ​

typescript
import { ZStack, Image, Text } from '@tachui/core'

ZStack({
  children: [
    Image({ src: 'background.jpg' }), // Bottom layer
    Text("Overlay Text")               // Top layer
      .modifier
      .foregroundColor('white')
      .build()
  ]
})

Props ​

typescript
interface ZStackProps {
  children?: ComponentInstance[]
  alignment?: 'center' | 'top' | 'bottom' | 'leading' | 'trailing' | 
              'topLeading' | 'topTrailing' | 'bottomLeading' | 'bottomTrailing'
  debugLabel?: string
}
PropertyTypeDefaultDescription
childrenComponentInstance[][]Array of child components (back to front)
alignmentZStackAlignment'center'Alignment of all children
debugLabelstring-Debug identifier for development

Alignment Options ​

typescript
import { ZStack, Text, VStack } from '@tachui/core'

// Center alignment (default)
ZStack({
  children: [
    VStack().modifier.backgroundColor('blue').size({ width: 200, height: 200 }).build(),
    Text("Centered")
  ],
  alignment: 'center'
})

// Corner alignments
ZStack({
  children: [
    VStack().modifier.backgroundColor('blue').size({ width: 200, height: 200 }).build(),
    Text("Top Left")
  ],
  alignment: 'topLeading'
})

ZStack({
  children: [
    VStack().modifier.backgroundColor('blue').size({ width: 200, height: 200 }).build(), 
    Text("Bottom Right")
  ],
  alignment: 'bottomTrailing'
})

Card with Overlay ​

typescript
import { ZStack, Image, VStack, Text, Button } from '@tachui/core'

const ImageCard = ({ src, title, description }: {
  src: string
  title: string
  description: string
}) => 
  ZStack({
    children: [
      // Background image
      Image({ src })
        .modifier
        .css({ 
          width: '100%', 
          height: '300px', 
          objectFit: 'cover' 
        })
        .build(),
      
      // Dark overlay
      VStack()
        .modifier
        .backgroundColor('rgba(0,0,0,0.4)')
        .css({ position: 'absolute', inset: '0' })
        .build(),
      
      // Content overlay
      VStack({
        children: [
          Text(title)
            .modifier
            .font({ size: 24, weight: 'bold' })
            .foregroundColor('white')
            .textAlign('center')
            .build(),
          
          Text(description)
            .modifier
            .foregroundColor('rgba(255,255,255,0.9)')
            .textAlign('center')
            .build(),
          
          Button("Learn More")
            .modifier
            .backgroundColor('rgba(255,255,255,0.2)')
            .foregroundColor('white')
            .border({ width: 1, color: 'rgba(255,255,255,0.3)' })
            .cornerRadius(8)
            .padding({ horizontal: 20, vertical: 10 })
            .build()
        ],
        spacing: 12
      })
    ],
    alignment: 'center'
  })
  .modifier
  .cornerRadius(16)
  .overflow('hidden')
  .build()

Layout Composition ​

Layout components can be nested to create complex layouts:

typescript
import { HStack, VStack, Text, Button, Spacer } from '@tachui/core'

const SidebarLayout = () =>
  HStack({
    children: [
      // Sidebar
      VStack({
        children: [
          Text("Navigation")
            .modifier
            .font({ size: 18, weight: 'bold' })
            .build(),
          
          Button("Home"),
          Button("About"), 
          Button("Contact"),
          
          Spacer(),
          
          Button("Settings")
        ],
        spacing: 8
      })
      .modifier
      .width(200)
      .padding(16)
      .backgroundColor('#f5f5f5')
      .build(),
      
      // Main content
      VStack({
        children: [
          Text("Main Content Area")
            .modifier
            .font({ size: 24, weight: 'bold' })
            .build(),
          
          Text("This is the main content area")
        ],
        spacing: 16
      })
      .modifier
      .padding(24)
      .flexGrow(1)
      .build()
    ]
  })
  .modifier
  .css({ minHeight: '100vh' })
  .build()

Card Grid ​

typescript
import { VStack, HStack, Text } from '@tachui/core'

const CardGrid = ({ items }: { items: string[] }) => {
  const rows: string[][] = []
  for (let i = 0; i < items.length; i += 3) {
    rows.push(items.slice(i, i + 3))
  }
  
  return VStack({
    children: rows.map(row =>
      HStack({
        children: row.map(item =>
          VStack({
            children: [
              Text(item)
                .modifier
                .font({ weight: 'bold' })
                .build()
            ]
          })
          .modifier
          .padding(20)
          .backgroundColor('white')
          .cornerRadius(8)
          .shadow({ x: 0, y: 2, blur: 4, color: 'rgba(0,0,0,0.1)' })
          .flexGrow(1)
          .build()
        ),
        spacing: 16
      })
    ),
    spacing: 16
  })
  .modifier
  .padding(16)
  .build()
}

Best Practices ​

Performance ​

typescript
// ✅ Good - Use specific alignments when needed
VStack({
  children: [...],
  alignment: 'leading' // Explicit alignment
})

// ✅ Good - Set appropriate spacing
HStack({
  children: [...],
  spacing: 12 // Consistent spacing
})

// ❌ Avoid - Excessive nesting without purpose
VStack({
  children: [
    HStack({
      children: [
        VStack({ children: [Text("Overly nested")] }) // Unnecessary nesting
      ]
    })
  ]
})

Responsive Design ​

typescript
import { VStack, HStack } from '@tachui/core'

// Use responsive modifiers for layout adaptation
VStack({
  children: [...],
  spacing: 16
})
.modifier
.responsive()
.xs(() => padding(8))
.md(() => padding(16))
.lg(() => padding(24))
.build()

Accessibility ​

typescript
import { VStack, Text } from '@tachui/core'

// Provide semantic structure
VStack({
  children: [
    Text("Section Title"),
    Text("Section content")
  ],
  debugLabel: "Article Section" // Helps with debugging
})
.modifier
.aria({ role: 'section' })
.build()

Integration with Other Components ​

Layout components work seamlessly with all tachUI components:

typescript
import { VStack, HStack, Text, Button, Image, Form, TextField } from '@tachui/core'

const ProfileForm = () =>
  VStack({
    children: [
      // Profile image section
      HStack({
        children: [
          Image({ src: 'avatar.jpg' })
            .modifier
            .css({ width: '80px', height: '80px', borderRadius: '50%' })
            .build(),
          
          VStack({
            children: [
              Text("Profile Photo"),
              Button("Change Photo")
            ],
            spacing: 8
          })
        ],
        spacing: 16,
        alignment: 'center'
      }),
      
      // Form fields
      Form({
        children: [
          TextField({ placeholder: "Full Name" }),
          TextField({ placeholder: "Email" }),
          TextField({ placeholder: "Bio", multiline: true })
        ]
      }),
      
      // Action buttons
      HStack({
        children: [
          Button("Cancel"),
          Button("Save Changes")
        ],
        spacing: 12
      })
    ],
    spacing: 24
  })
  .modifier
  .padding(24)
  .maxWidth(400)
  .build()

See Also ​

Released under the MPL-2.0 License.