UNPKG

4.95 kBMarkdownView Raw
1---
2title: Box
3storybookPath: page-layout-box--default
4isExperimentalPackage: false
5---
6
7The Box component is our lowest-level primitive. The goal of the Box component
8is to map props to our tokens so that consumers should be able to use these
9props for all of their styling needs. Ideally, you shouldn't need to use the
10`className` or `style` prop at all. Internally, all Spark Web components are
11composed using the Box component.
12
13Box is a polymorphic component (meaning it will render different elements
14depending on what is provided to the `as` prop). If no `as` prop is provided,
15Box will render a `div`.
16
17We also spread in consumer props, so any valid HTML attributes are also valid
18for Box. Due to some clever TypeScript we can even warn you when you use an
19invalid combination of props.
20
21```jsx
22<Box as="input" href="https://spark.brighte.com.au" />
23```
24
25In the example above, you should see a "red squiggly" under the `href` element
26with the following error:
27
28```console
29Type '{ as: "input"; href: string; }' is not assignable to type 'IntrinsicAttributes & { as?: "input" | undefined; ref?: Ref<HTMLInputElement> | undefined; } & Omit<Pick<DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "key" | keyof InputHTMLAttributes<...>>, "as"> & { ...; } & UnresponsiveBoxProps & ResponsiveBoxProps'.
30 Property 'href' does not exist on type 'IntrinsicAttributes & { as?: "input" | undefined; ref?: Ref<HTMLInputElement> | undefined; } & Omit<Pick<DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "key" | keyof InputHTMLAttributes<...>>, "as"> & { ...; } & UnresponsiveBoxProps & ResponsiveBoxProps'. Did you mean 'ref'?
31```
32
33Unfortunately TypeScript errors can be pretty cryptic sometimes 🙃.
34
35**Pro tip**: copying the error message and pasting it into
36[TypeScript Error Translator](https://ts-error-translator.vercel.app/) can
37sometimes help make these errors easier to understand.
38
39A minimal CSS reset is also applied to each element rendered with Box. This
40helps prevent styles from "leaking" out and effecting other elements (which
41should make it easier to incrementally adopt Spark Web into existing projects).
42If you provide a non-Spark component to the `as` prop instead of an element, it
43is recommended that you also use the `asElement` prop so the appropriate styles
44can be applied.
45
46## Examples
47
48### Responsive styles
49
50Most of Box's props accept a string value (usually corresponding to a token), we
51also accept an object for responsive styles.
52
53```jsx live
54const items = [1, 2, 3];
55
56return (
57 <Box
58 background="primaryLow"
59 display="inline-flex"
60 flexDirection={{ mobile: 'row', tablet: 'column', desktop: 'rowReverse' }}
61 gap={{ mobile: 'small', tablet: 'medium', desktop: 'large' }}
62 padding={{ mobile: 'small', tablet: 'medium', desktop: 'large' }}
63 >
64 {items.map(item => (
65 <Row
66 key={item}
67 align="center"
68 alignY="center"
69 background="primary"
70 height={{ mobile: 'small', tablet: 'medium', desktop: 'large' }}
71 width={{ mobile: 'small', tablet: 'medium', desktop: 'large' }}
72 >
73 <Text>{item}</Text>
74 </Row>
75 ))}
76 </Box>
77);
78```
79
80Resize your browser to see the example above change at different breakpoints.
81
82### Backgrounds
83
84Box stores the background in a provider. We can use this to work out what colour
85to use by default for text elements.
86
87```jsx live
88const backgroundTones = [
89 // Light
90 ['surface', 'positiveLight', 'infoLight', 'cautionLight', 'criticalLight'],
91 // Dark
92 ['muted', 'positive', 'info', 'caution', 'critical'],
93];
94
95return (
96 <Stack gap="large">
97 {backgroundTones.map((backgrounds, index) => (
98 <Columns
99 key={index}
100 collapseBelow="tablet"
101 gap="large"
102 template={[1, 1, 1]}
103 >
104 {backgrounds.map(background => (
105 <Box
106 key={background}
107 shadow="medium"
108 background={background}
109 height="large"
110 display="flex"
111 flexShrink={0}
112 alignItems="center"
113 justifyContent="center"
114 >
115 <Text weight="semibold">{background}</Text>
116 </Box>
117 ))}
118 </Columns>
119 ))}
120 </Stack>
121);
122```
123
124Notice that the Text in the example above doesn't use the tone prop, the colour
125is worked out using the BackgroundProvider in Box.
126
127**Note:** this will only work if you use the `background` prop. If you try to
128style the background colour in any other way the Text component will not know
129what colour the background is and so cannot invert its colour to make sure that
130its contents are readable.
131
132```jsx
133<Box style={{ background: 'midnightblue' }} padding="large">
134 <Text>Good luck reading this!</Text>
135</Box>
136```
137
138## Props
139
140<PropsTable displayName="Box" />
141
142By default, Box renders a `div` element. You can customise this via the `as`
143prop. Extra props will also be forwarded to the underlying element.