Layout

All layout components accept BoxStyleProps. See the Primitives page for the full shorthand reference.


Stack

Arranges children in a row or column with consistent token-based gaps.

PropTypeDefaultDescription
direction?'vertical' | 'horizontal''vertical'Maps to flexDirection column/row
gap?SpacingPropSpace between children, resolved from spacing tokens
align?'flex-start' | 'flex-end' | 'center' | 'stretch' | 'baseline'Cross-axis alignment (alignItems)
justify?'flex-start' | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly'Main-axis distribution (justifyContent)
wrap?booleanfalseEnable flex wrap
BoxStylePropsAll shorthand layout props
import { Stack, Text, Box } from '@objectifthunes/limestone-sdk';

function ProfileCard() {
  return (
    <Box bg="card" rounded="lg" shadow="md" p="lg">
      <Stack direction="horizontal" gap="md" align="center">
        <Box w={48} h={48} rounded="full" bg="muted" />
        <Stack gap="xs" flex={1}>
          <Text variant="label" weight="semibold">Alice Martin</Text>
          <Text variant="caption" color="mutedForeground">Product Designer</Text>
        </Stack>
      </Stack>
    </Box>
  );
}

Grid

Arranges children in an equal-width column grid. Always uses row + wrap layout.

PropTypeDefaultDescription
columns?number2Number of equal-width columns
gap?SpacingPropGap between grid items
itemMinWidth?numberWhen set, overrides columns-based sizing
BoxStylePropsAll shorthand layout props

The hook exposes a getItemWidth(containerWidth: number): number helper to compute item width relative to the container.

import { Grid, Box, Text } from '@objectifthunes/limestone-sdk';

const CATEGORIES = ['Food', 'Travel', 'Music', 'Sports', 'Tech', 'Art'];

function CategoryGrid() {
  return (
    <Grid columns={3} gap="sm" p="md">
      {CATEGORIES.map((cat) => (
        <Box key={cat} bg="muted" rounded="md" p="md" center h={80}>
          <Text variant="label" align="center">{cat}</Text>
        </Box>
      ))}
    </Grid>
  );
}

ScrollView

A scrollable container with pull-to-refresh support.

PropTypeDefaultDescription
contentPadding?SpacingPropInner padding on the scroll content
refreshing?booleanfalseControls the pull-to-refresh indicator
onRefresh?() => voidCalled when user pulls to refresh
horizontal?booleanfalseHorizontal scroll mode
showsScrollIndicator?booleantrueShow the native scroll indicator
BoxStylePropsApplied to the outer container

The hook returns separate containerStyle and contentContainerStyle objects.

import { ScrollView, Stack, Box, Text } from '@objectifthunes/limestone-sdk';
import { useState, useCallback } from 'react';

function FeedScreen() {
  const [refreshing, setRefreshing] = useState(false);

  const handleRefresh = useCallback(async () => {
    setRefreshing(true);
    await fetchLatestPosts();
    setRefreshing(false);
  }, []);

  return (
    <ScrollView
      flex={1}
      contentPadding="md"
      refreshing={refreshing}
      onRefresh={handleRefresh}
    >
      <Stack gap="md">
        {posts.map((post) => (
          <Box key={post.id} bg="card" rounded="lg" p="md">
            <Text variant="body">{post.title}</Text>
          </Box>
        ))}
      </Stack>
    </ScrollView>
  );
}

SafeArea

Adds padding or margin to avoid device notches, status bars, and home indicators. Designed for react-native-safe-area-context.

PropTypeDefaultDescription
edges?Array<'top' | 'bottom' | 'left' | 'right'>all fourWhich edges to apply safe area insets
mode?'padding' | 'margin''padding'Whether to apply as padding or margin
SafeAreaViewComponent?React.ComponentTypeViewInject SafeAreaView from react-native-safe-area-context
BoxStylePropsAll shorthand layout props
import { SafeArea, Stack } from '@objectifthunes/limestone-sdk';
import { SafeAreaView } from 'react-native-safe-area-context';

function Screen({ children }: { children: React.ReactNode }) {
  return (
    <SafeArea
      SafeAreaViewComponent={SafeAreaView}
      edges={['top', 'bottom']}
      flex={1}
      bg="background"
    >
      <Stack flex={1} gap="md" p="md">
        {children}
      </Stack>
    </SafeArea>
  );
}

KeyboardAvoidingView

Shifts content up when the software keyboard appears.

PropTypeDefaultDescription
behavior?'height' | 'padding' | 'position'auto-detectedManually override the avoidance strategy
keyboardVerticalOffset?number0Extra vertical offset, useful with headers
BoxStylePropsAll shorthand layout props

Auto-detection: iOS uses 'padding', Android uses 'height'. Pass behavior explicitly to override.

import { KeyboardAvoidingView, Stack, TextInput } from '@objectifthunes/limestone-sdk';

function CommentInput() {
  return (
    <KeyboardAvoidingView flex={1} bg="background">
      <Stack flex={1} justify="flex-end" p="md">
        <TextInput
          value={comment}
          onChangeText={setComment}
          label="Leave a comment"
          variant="outline"
        />
      </Stack>
    </KeyboardAvoidingView>
  );
}