Skip to content

Design System

The app uses Tamagui for a consistent, themeable UI system with a warm, book-inspired aesthetic.

Configuration

The design system is defined in tamagui.config.ts.

Typography

Three font families:

FontUsageComponent
FrauncesHeadings, display<Heading>
Source Serif 4Body text<Body>
DM SansUI elements, labels<Label>

Typography Components

typescript
import { Heading, Body, Label } from "@/components/ui/typography"

<Heading size="$8">Welcome to Logbook</Heading>
<Body>Track your reading journey.</Body>
<Label>Email address</Label>

Colors

Light Theme

TokenValueUsage
$cream#FAF7F2Background
$paper#F5F1EASurface
$amber#C4883APrimary accent
$charcoal#3D3835Text
$sage#8B9A7DSecondary accent
$dust#D4CFC7Borders

Dark Theme

TokenValueUsage
$background#1A1817Background
$surface#252220Surface
$text#E8E4DDText

Using Colors

typescript
import { styled, useTheme } from "tamagui"

// In styled components
const Card = styled(View, {
	backgroundColor: "$cream",
	borderColor: "$dust",
})

// In components
const theme = useTheme()
<View style={{ backgroundColor: theme.cream.val }} />

Spacing

Tamagui uses a scale-based spacing system:

typescript
<View padding="$4" marginBottom="$2">
	<Text marginTop="$1">Content</Text>
</View>
TokenValue
$14px
$28px
$312px
$416px
$520px
$624px

Components

Button

typescript
import { Button } from "@/components/ui"

<Button variant="primary" onPress={handlePress}>
	Get Started
</Button>

<Button variant="secondary" size="small">
	Cancel
</Button>

Input

typescript
import { Input } from "@/components/ui"

<Input
	placeholder="Enter your email"
	value={email}
	onChangeText={setEmail}
	keyboardType="email-address"
/>

Card

typescript
import { Card } from "@/components/ui"

<Card>
	<Heading size="$4">Book Title</Heading>
	<Body>Author Name</Body>
</Card>

Theme Switching

typescript
import { useColorScheme } from "@/hooks/useColorScheme"

const { colorScheme, toggleColorScheme } = useColorScheme()

// colorScheme is "light" or "dark"

Built with VitePress