Skip to content

Latest commit

 

History

History
103 lines (79 loc) · 2.86 KB

Styling.md

File metadata and controls

103 lines (79 loc) · 2.86 KB
sidebar_position
80

Styling Ignite apps

Ignite's approach to styling individual components is, like many other things in Ignite, straightforward and direct.

If you're looking to set app-wide styles such as fonts/typography or colors, check out the Theming documentation.

We don't use StyleSheet.create() as a general rule, as it doesn't provide any real benefits over bare objects and functions.

We instead use a strategy of bare JS objects and functions that take a theme parameter, colocated with our components (usually below the component in the file), prefixed with $, and typed with TypeScript:

import { View, type ViewStyle } from "react-native"
import { useAppTheme } from "@/utils/useAppTheme"

const MyComponent = () => {
  const { themed } = useAppTheme()
  return (
    <View style={themed($container)}>
      <View style={$plainObjectStyle} />
    </View>
  )
}

const $container: ThemedStyle<ViewStyle> = (theme) => ({
  flex: 1,
  backgroundColor: theme.colors.background,
  paddingHorizontal: theme.spacing.small,
})

const $plainObjectStyle: ViewStyle = {
  marginBottom: 20,
}

We use components with presets to share styles across our whole app.

With this strategy, you can tell if a variable is a style when it has the $ prefix. You can also spread in other styles to compose styles:

const $bold: TextStyle = {
  fontWeight: "bold",
}
const $larger: TextStyle = {
  fontSize: 22,
}
const $title: TextStyle = {
  ...$bold,
  ...$larger,
}

Sharing Styles via Presets

Most of the components we include with Ignite include a preset property:

<View preset="heading" text="My Header" />

Presets are defined in the component file itself, usually something like this:

type Presets = "default" | "bold" | "heading" | "subheading"
const $presets: Record<Presets, ThemedStyleArray<TextStyle>> = {
  default: [$baseStyle],
  bold: [$baseStyle, $fontWeightStyles.bold],
  heading: [$baseStyle, $sizeStyles.xxl, $fontWeightStyles.bold],
  subheading: [$baseStyle, $sizeStyles.lg, $fontWeightStyles.medium],
}

These presets are usually composed of other styles, using arrays (which React Native will properly merge).

So, let's say we want a button that is a destructive action. We might add a "destructive" preset to the Button component.

The preset might look like this:

const $warning: ThemedStyle<ViewStyle> = (theme) => ({
  backgroundColor: theme.colors.alert,
  color: "white",
  padding: theme.spacing.lg,
})

const $viewPresets: Record<Presets, ThemedStyle<ViewStyle>> = {
  destructive: [$baseViewStyle, $warning],
}

You can then use it with your Button like this:

<Button
  text="Delete"
  // set the preset here
  preset="destructive"
  onPress={() => thisItem.destroy()}
/>