react-native-spacing-system
react-native-spacing-system copied to clipboard
Standardizing how components are spaced in ReactNative.
React Native Spacing System
Warning, you are currently looking at the v2 documentation. For v1 documentation please go over here.
What Is It?
Using margin and padding to control spacing between components introduces too many ways to accomplish the same goal. React Native Spacing System seeks to standardize your React Native code, increase legibility, and separate the concern of layouting though the usage of spacing components.
Stack:
Queue:
Inset:
Factory method are provided so that you can use your own spacing key and values instead of raw values.
and
are both supported!
Installation
npm install react-native-spacing-system
or
yarn add react-native-spacing-system
Features
Stack
Stack
is a vertical spacing component, think of a pile of plates at a buffet.
Usage
Stack Props:
-
size: number
-
_debug?: boolean
-
_debugOptions?: {color?: string, border?: boolean, borderColor?: string, opacity?: number}
import React from "react";
import { View } from 'react-native';
import { Stack } from "react-native-spacing-system";
import { BuffetPlates } from "./BuffetPlates";
import { KitchenCounter } from "./KitchenCounter";
/*
Creates a vertical space with size of 16 between
<BuffetPlates /> and <KitchenCounter /> components.
*/
const QueueExample = () => {
return (
<View>
<BuffetPlates />
<Stack size={16} />
<BuffetPlates />
<Stack size={16} />
<KitchenCounter />
</View>
);
Queue
Queue
is a horizontal spacing component, think of people queueing for that new bubbletea joint.
Usage
Queue Props:
-
size: number
-
_debug?: boolean
-
_debugOptions?: {color?: string, border?: boolean, borderColor?: string, opacity?: number}
import React from "react";
import { View } from "react-native";
import { Queue } from "react-native-spacing-system";
import { BubbleTeaJoint } from "./BubbleTeaJoint";
import { PatientPatron } from "./PatientPatron";
/*
Creates a horizontal space with size of 16 between
<BubbleTeaJoint /> and <PatientPatron /> components.
Only works when flex direction is row.
*/
const StackExample = () => {
return (
<View style={{ flexDirection: "row" }}>
<BubbleTeaJoint />
<Queue size={16} />
<PatientPatron />
<Queue size={16} />
<PatientPatron />
</View>
);
};
Inset
Inset
is a boundary spacing component, think of adding frames around a picture (the child).
Usage
Inset Props:
-
children: ReactNode
-
layout?: LayoutStyle
-
onLayout?: (event: LayoutChangeEvent) => void
-
_debug?: boolean
-
_debugOptions?: {color?: string}
-
PaddingCombinations
The allowed PaddingCombinations
are as follows:
-
{all: number}
-
{horizontal: number, vertical: number}
-
{horizontal: number, bottom?: number, top?: number}
-
{vertical: number, left?: number, right?: number}
-
{left: number, top?: number, right?: number, bottom?: number}
-
{left?: number, top: number, right?: number, bottom?: number}
-
{left?: number, top?: number, right: number, bottom?: number}
-
{left?: number, top?: number, right? :number, bottom: number}
The allowed LayoutStyle
can be found HERE
import React from "react";
import { Inset } from "react-native-spacing-system";
import { PictureNeedingAFrame } from "./PictureNeedingAFrame";
/*
Creates a padding of size 16 around
the <PictureNeedingAFrame /> component.
*/
const InsetExample = () => {
return (
<Inset all={16}>
<PictureNeedingAFrame />
</Inset>
);
};
Factory Methods
Create your own spacing component with custom keys by passing in the space mapping object into the factory method provided.
-
stackFactory()
-
queueFactory()
-
insetFactory()
import { stackFactory } from "react-native-spacing-system";
const spacing = {
tall: 8,
grande: 12,
venti: 16
};
const Stack = stackFactory(spacing);
<Stack size={16}/> // TS Error
<Stack size="venti"/> // Works
spacingFactory
If the spacing object is expected to be used in all Stack
, Queue
, and Inset
, spacingFactory
can be used to create the components in one function.
import { spacingFactory } from "react-native-spacing-system";
const spacing = {
tall: 8,
grande: 12,
venti: 16,
};
const { Stack, Queue, Inset } = spacingFactory(spacing);
Flow
/* @flow */
import { stackFactory } from "react-native-spacing-system";
type SpacingKey = 'tall' | 'grande' | 'venti'
type Spacing = {[key: SpacingKey]: number}
const spacing: Spacing = {
tall: 8,
grande: 12,
venti: 16
};
const Stack = stackFactory<Spacing>(spacing);
<Stack size={16}/> // Flow Error
<Stack size="venti"/> // Works
DisallowLayout
For insetFactory
and spacingFactory
, you can declare if you would like to allow the layout
prop to be able to be passed into Inset
.
TypeScript
/* @flow */
import { insetFactory } from "react-native-spacing-system";
const spacing = {
tall: 8,
grande: 12,
venti: 16
};
const disallowLayout = true;
const NoLayoutInset = insetFactory(spacing, disallowLayout);
<NoLayoutInset all='tall' layout={{flex: 1}}/> // TS Error
<NoLayoutInset all='tall'/> // Works
Flow
For flow
, you must specify the type arguments.
/* @flow */
import { insetFactory } from "react-native-spacing-system";
type SpacingKey = 'tall' | 'grande' | 'venti'
type Spacing = {[key: SpacingKey]: number}
const spacing: Spacing = {
tall: 8,
grande: 12,
venti: 16
};}
type DisallowLayout = true;
const disallowLayout = true;
const NoLayoutInset = insetFactory<Spacing, DisallowLayout>(spacing, disallowLayout);
<NoLayoutInset all='tall' layout={{flex: 1}}/> // Flow Error
<NoLayoutInset all='tall'/> // Works
Debug Mode
Each component supports a debug mode where their spacing is highlighted.
Import the DebugContext
and use the Provider
to toggle debug mode on and off.
import React from "react";
import { DebugContext } from "react-native-spacing-system";
import ComponentWithSpacingSystemComponents from "./ComponentWithSpacingSystemComponents";
const SomeComponent = () => {
return (
<DebugContext.Provider value={{ debug: booleanValue }}>
<ComponentWithSpacingSystemComponents />
</DebugContext.Provider>
);
};
You can also control debug mode of each type of spacing component as well as their border highlighting.
Expected Type (TypeScript)
type DebugContextProps = {
debug: boolean;
inset?: {
debug?: boolean;
color?: string;
};
queue?: {
debug?: boolean;
color?: string;
border?: boolean;
borderColor?: string;
opacity?: number;
};
stack?: {
debug?: boolean;
color?: string;
border?: boolean;
borderColor?: string;
opacity?: number;
};
};
Expected Type (Flow)
type DebugContextProps = {|
debug: boolean,
inset?: {|
debug?: boolean,
color?: string,
|},
queue?: {|
debug?: boolean,
color?: string,
border?: boolean,
borderColor?: string,
opacity?: number,
|},
stack?: {|
debug?: boolean,
color?: string,
border?: boolean,
borderColor?: string,
opacity?: number,
|},
|};
Sentiment & Rationalization
Inspired by Nathan Curtis's Medium article Space In Design Systems and this react-spacing library by Nathan Winder, I figured I'd do something similar for React Native with slight tweaks.
For the full sentiment and rationalization, please check out my Medium blog post: Enforcing Component Spacing in React & React Native.