@marigold/system 0.0.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Element.d.ts +8 -0
- package/dist/cache.d.ts +4 -0
- package/dist/index.d.ts +6 -4
- package/dist/normalize.d.ts +110 -0
- package/dist/reset.d.ts +24 -0
- package/dist/system.cjs.development.js +332 -95
- package/dist/system.cjs.development.js.map +1 -1
- package/dist/system.cjs.production.min.js +1 -1
- package/dist/system.cjs.production.min.js.map +1 -1
- package/dist/system.esm.js +323 -92
- package/dist/system.esm.js.map +1 -1
- package/dist/types.d.ts +9 -0
- package/dist/useClassname.d.ts +2 -0
- package/dist/useStyles.d.ts +15 -0
- package/dist/useTheme.d.ts +10 -0
- package/package.json +7 -10
- package/src/Colors.stories.mdx +616 -448
- package/src/Element.test.tsx +203 -0
- package/src/Element.tsx +59 -0
- package/src/cache.ts +4 -0
- package/src/concepts-principles.mdx +1 -1
- package/src/index.ts +6 -4
- package/src/normalize.test.tsx +42 -0
- package/src/normalize.ts +131 -0
- package/src/reset.ts +108 -0
- package/src/types.ts +16 -0
- package/src/useClassname.test.tsx +70 -0
- package/src/useClassname.ts +23 -0
- package/src/useStyles.stories.mdx +24 -0
- package/src/useStyles.test.tsx +286 -0
- package/src/useStyles.ts +63 -0
- package/src/useTheme.test.tsx +115 -0
- package/src/useTheme.tsx +22 -0
- package/dist/Box/Box.d.ts +0 -6
- package/dist/Box/index.d.ts +0 -1
- package/dist/MarigoldProvider.d.ts +0 -7
- package/dist/categories.d.ts +0 -169
- package/dist/emotion.d.ts +0 -7
- package/dist/system.d.ts +0 -37
- package/src/Box/Box.stories.mdx +0 -148
- package/src/Box/Box.test.tsx +0 -215
- package/src/Box/Box.tsx +0 -58
- package/src/Box/index.ts +0 -1
- package/src/MarigoldProvider.test.tsx +0 -80
- package/src/MarigoldProvider.tsx +0 -37
- package/src/categories.ts +0 -203
- package/src/emotion.ts +0 -39
- package/src/system.test.tsx +0 -84
- package/src/system.tsx +0 -55
- package/src/writeComponent.stories.mdx +0 -114
package/dist/system.d.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Typings are based on [Reach UI](https://github.com/reach/reach-ui/blob/4cb497f530b0f83f80c6f6f2da46ab55b1160cb6/packages/utils/src/types.tsx).
|
|
3
|
-
*/
|
|
4
|
-
import { ComponentPropsWithRef, ElementType, ReactElement, ValidationMap, WeakValidationMap } from 'react';
|
|
5
|
-
/**
|
|
6
|
-
* SystemProps support the `as` and `variant` prop. The former
|
|
7
|
-
* is used to changed the rendered root element of a component.
|
|
8
|
-
*
|
|
9
|
-
* These props also infer additional allowed props based on the
|
|
10
|
-
* value of the `as` prop. For example, setting `as="button"` will
|
|
11
|
-
* allow to use HTMLButtonAttributes on the component.
|
|
12
|
-
*/
|
|
13
|
-
export declare type SystemProps<P, T extends ElementType> = P & Omit<ComponentPropsWithRef<T>, 'as' | keyof P> & {
|
|
14
|
-
as?: T;
|
|
15
|
-
variant?: string;
|
|
16
|
-
};
|
|
17
|
-
/**
|
|
18
|
-
* Enhanced version of `React.FunctionComponent` that accepts `SystemProps`
|
|
19
|
-
* and infers allowed properties based on the `as` prop.
|
|
20
|
-
*/
|
|
21
|
-
export interface SystemComponent<P, T extends ElementType> {
|
|
22
|
-
/**
|
|
23
|
-
* These types are a bit of a hack, but cover us in cases where the `as` prop
|
|
24
|
-
* is not a JSX string type. Makes the compiler happy so 🤷♂️
|
|
25
|
-
*/
|
|
26
|
-
<TT extends ElementType>(props: SystemProps<P, TT>): ReactElement | null;
|
|
27
|
-
(props: SystemProps<P, T>): ReactElement | null;
|
|
28
|
-
displayName?: string;
|
|
29
|
-
propTypes?: WeakValidationMap<SystemProps<P, T>>;
|
|
30
|
-
contextTypes?: ValidationMap<any>;
|
|
31
|
-
defaultProps?: Partial<SystemProps<P, T>>;
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Helper to write components that adhere to a common design system API,
|
|
35
|
-
* which includes the `as` and `variant` prop.
|
|
36
|
-
*/
|
|
37
|
-
export declare function system<P, T extends ElementType>(render: (props: SystemProps<P, T>) => ReactElement | null): SystemComponent<P, T>;
|
package/src/Box/Box.stories.mdx
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import { Meta, Story, Preview } from '@storybook/addon-docs/blocks';
|
|
2
|
-
import { Box } from './Box';
|
|
3
|
-
import { Label, Button } from '@marigold/components';
|
|
4
|
-
|
|
5
|
-
<Meta title="Components/Box Component" />
|
|
6
|
-
|
|
7
|
-
# Box-Component
|
|
8
|
-
|
|
9
|
-
## Description
|
|
10
|
-
|
|
11
|
-
`Box` is the most abstract component on top of which all other Marigold components are build.
|
|
12
|
-
The `Box` allows us to apply styling via a dedicated prop (`css`) while respecting the rules and constraints of our design system.
|
|
13
|
-
Instead of exposing the underlying tools that will create CSS, the `Box` component wraps them and exposes a more React-like API to style components.
|
|
14
|
-
|
|
15
|
-
### Style components
|
|
16
|
-
|
|
17
|
-
The style of components is defined by three different layers that are structured hierarchically. A layer can overwrite the attributes of the previous layer.
|
|
18
|
-
|
|
19
|
-
**Default styles, theme styles and style props**
|
|
20
|
-
|
|
21
|
-
- **default styles**
|
|
22
|
-
|
|
23
|
-
- add default styling to a component, even without a theme
|
|
24
|
-
- should be used to achieve minimal level of consistency between browsers
|
|
25
|
-
|
|
26
|
-
<Preview>
|
|
27
|
-
<Story name="label">
|
|
28
|
-
<Label variant="" htmlFor="labelId">
|
|
29
|
-
A simple Label
|
|
30
|
-
</Label>
|
|
31
|
-
</Story>
|
|
32
|
-
<Story name="button">
|
|
33
|
-
<Button>Click me!</Button>
|
|
34
|
-
</Story>
|
|
35
|
-
</Preview>
|
|
36
|
-
|
|
37
|
-
- **theme styles**
|
|
38
|
-
|
|
39
|
-
- style values from a specific theme can be easily used with the box
|
|
40
|
-
- the theme can overwrite the default styles
|
|
41
|
-
- in this way you can stay inside the boundaries of the design system.
|
|
42
|
-
|
|
43
|
-
<Preview>
|
|
44
|
-
<Story name="label-theme-styled">
|
|
45
|
-
<Label htmlFor="labelId">A simple Label</Label>
|
|
46
|
-
</Story>
|
|
47
|
-
<Story name="button-theme-styled">
|
|
48
|
-
<Button variant="primary.large">Click me!</Button>
|
|
49
|
-
</Story>
|
|
50
|
-
</Preview>
|
|
51
|
-
|
|
52
|
-
- **style props**
|
|
53
|
-
|
|
54
|
-
- style props can be used to add and modify component styles beyond the boundaries of the design system
|
|
55
|
-
|
|
56
|
-
<Preview>
|
|
57
|
-
<Story name="label-css-styled">
|
|
58
|
-
<Label
|
|
59
|
-
htmlFor="labelId"
|
|
60
|
-
css={{ px: 64, fontSize: '24px', letterSpacing: '8px' }}
|
|
61
|
-
>
|
|
62
|
-
A simple Label
|
|
63
|
-
</Label>
|
|
64
|
-
</Story>
|
|
65
|
-
<Story name="button-css-styled">
|
|
66
|
-
<Button variant="primary.large" css={{ letterSpacing: '8px' }}>
|
|
67
|
-
Click me!
|
|
68
|
-
</Button>
|
|
69
|
-
</Story>
|
|
70
|
-
</Preview>
|
|
71
|
-
|
|
72
|
-
> Staying inside the boundaries of the design system and its contraints should be the norm. But limiting styling only to allowed values defined by the system can be very restrictive up to a point where the design system becomes an obstacle. This is why there is a an escape hatch for when it is absolutely necessary to apply styling from a third party or style it in a way that is non-compliant with the design system.
|
|
73
|
-
|
|
74
|
-
## Properties
|
|
75
|
-
|
|
76
|
-
| Property | Type | Default |
|
|
77
|
-
| :------------- | :--------------------------- | :------ |
|
|
78
|
-
| `as` | `HTMLTag`, `ComponentType` | `'div'` |
|
|
79
|
-
| `css` | [`css props`](#cssProps) | |
|
|
80
|
-
| `themeSection` | `string` | |
|
|
81
|
-
| `variant` | `string` | |
|
|
82
|
-
| `SpacingProps` | [`space props`](#spaceProps) | |
|
|
83
|
-
|
|
84
|
-
### as-Property
|
|
85
|
-
|
|
86
|
-
The HTML element used for the root node. Either a string to use a DOM element or a component. By default the `Box` component will render a `<div/>`. And while this might be fine most of the time, sometimes you would rather render a `<button/>` or an `<input/>`. To allow this, the `Box` component has a special prop called `as`, which accepts an HTML tag as input.
|
|
87
|
-
|
|
88
|
-
### css-Properties <a id="cssProps"></a>
|
|
89
|
-
|
|
90
|
-
The `css` props let you style elements inline, using values from your theme. The css prop allows all CSS properties and the below shorthands.
|
|
91
|
-
|
|
92
|
-
| Category | Prop |
|
|
93
|
-
| -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
94
|
-
| `css` | `fontFamily, fontSize, fontWeight, lineHeight, letterSpacing, color, backgroundColor, bg, margin, m, marginTop, mt, marginRight, mr, marginBottom, mb, marginLeft, ml, marginX, mx, marginY, my, padding, p, paddingTop, pt, paddingRight, pr, paddingBottom, pb, paddingLeft, pl, paddingX, px, paddingY, py, top, bottom, left, right, border, borderTop, borderRight, borderBottom, borderLeft, borderColor, borderWidth, borderStyle, borderRadius, boxShadow, textShadow, zIndex, width, minWidth, maxWidth, height, minHeight, maxHeight, size` |
|
|
95
|
-
|
|
96
|
-
### themeSection
|
|
97
|
-
|
|
98
|
-
With the `themeSection` proberty, users can define as a `string` the section from a theme which should be used. E.g. you defined in your theme explicitly colors, text or buttons with seperate styles for these elements.
|
|
99
|
-
|
|
100
|
-
### variant
|
|
101
|
-
|
|
102
|
-
The `variant` proberty is the next layer under themeSection. In a section like e.g. buttons there are two varaints: primary and secondary. With the variant prop you can define as a `string` a button with primary or secondary style from a theme.
|
|
103
|
-
|
|
104
|
-
### Spacing Props <a id="spaceProps"></a>
|
|
105
|
-
|
|
106
|
-
The `SpacingProps` are part of the style props which can be used to give your component custom css style. The values are usable with shortcuts which you can see in the Prop column. For more information click the space Doc link to Theme-Ui in the following table.
|
|
107
|
-
|
|
108
|
-
| Category | Prop |
|
|
109
|
-
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
110
|
-
| `SpacingProps` | `margin, m, marginTop, mt, marginRight, mr, marginBottom, mb, marginLeft, ml, marginX, mx, marginY, my, padding, p, paddingTop, pt, paddingRight, pr, paddingBottom, pb, paddingLeft, pl, paddingX, px, paddingY, py` |
|
|
111
|
-
|
|
112
|
-
## Import
|
|
113
|
-
|
|
114
|
-
```js
|
|
115
|
-
import { Box } from '@marigold/system';
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
## Usage
|
|
119
|
-
|
|
120
|
-
<Preview>
|
|
121
|
-
<Story name="div-box">
|
|
122
|
-
<Box>I am a div box!</Box>
|
|
123
|
-
</Story>
|
|
124
|
-
</Preview>
|
|
125
|
-
|
|
126
|
-
<Preview>
|
|
127
|
-
<Story name="text-box">
|
|
128
|
-
<Box as="span" css={{ color: 'orange' }}>
|
|
129
|
-
I am a text box!
|
|
130
|
-
</Box>
|
|
131
|
-
</Story>
|
|
132
|
-
</Preview>
|
|
133
|
-
|
|
134
|
-
<Preview>
|
|
135
|
-
<Story name="button-box">
|
|
136
|
-
<Box as="button" css={{ border: '1px solid black' }}>
|
|
137
|
-
I am a simple button!
|
|
138
|
-
</Box>
|
|
139
|
-
</Story>
|
|
140
|
-
</Preview>
|
|
141
|
-
|
|
142
|
-
<Preview>
|
|
143
|
-
<Story name="h1-box">
|
|
144
|
-
<Box as="h1" css={{ color: 'blue' }}>
|
|
145
|
-
I am a blue headline!
|
|
146
|
-
</Box>
|
|
147
|
-
</Story>
|
|
148
|
-
</Preview>
|
package/src/Box/Box.test.tsx
DELETED
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { render, screen } from '@testing-library/react';
|
|
3
|
-
import { ThemeContext } from '../emotion';
|
|
4
|
-
import { SpacingProps } from '../categories';
|
|
5
|
-
|
|
6
|
-
import { Box } from './Box';
|
|
7
|
-
|
|
8
|
-
// Setup
|
|
9
|
-
// ---------------
|
|
10
|
-
const theme = {
|
|
11
|
-
colors: {
|
|
12
|
-
primary: 'hotpink',
|
|
13
|
-
black: '#000',
|
|
14
|
-
white: '#FFF',
|
|
15
|
-
blue: '#2980b9',
|
|
16
|
-
},
|
|
17
|
-
text: {
|
|
18
|
-
body: {
|
|
19
|
-
fontSize: 1,
|
|
20
|
-
color: 'black',
|
|
21
|
-
},
|
|
22
|
-
heading: {
|
|
23
|
-
fontSize: 3,
|
|
24
|
-
color: 'primary',
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
buttons: {
|
|
28
|
-
primary: {
|
|
29
|
-
color: 'white',
|
|
30
|
-
bg: 'blue',
|
|
31
|
-
},
|
|
32
|
-
secondary: {
|
|
33
|
-
color: 'black',
|
|
34
|
-
bg: 'white',
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
// Tests
|
|
40
|
-
// ---------------
|
|
41
|
-
test('renders a <div> by default', () => {
|
|
42
|
-
render(<Box>box</Box>);
|
|
43
|
-
const box = screen.getByText(/box/);
|
|
44
|
-
|
|
45
|
-
expect(box instanceof HTMLDivElement).toBeTruthy();
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
test('changes rendered element via as prop', () => {
|
|
49
|
-
render(<Box as="span">box</Box>);
|
|
50
|
-
const box = screen.getByText(/box/);
|
|
51
|
-
|
|
52
|
-
expect(box instanceof HTMLSpanElement).toBeTruthy();
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
test('passes down all HTML attributes', () => {
|
|
56
|
-
render(
|
|
57
|
-
<Box id="box-id" disabled>
|
|
58
|
-
box
|
|
59
|
-
</Box>
|
|
60
|
-
);
|
|
61
|
-
const box = screen.getByText(/box/);
|
|
62
|
-
|
|
63
|
-
expect(box.getAttribute('id')).toEqual('box-id');
|
|
64
|
-
expect(box.getAttribute('disabled')).toMatch('');
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
test('apply some base css styling for normalization', () => {
|
|
68
|
-
render(<Box>box</Box>);
|
|
69
|
-
const box = screen.getByText(/box/);
|
|
70
|
-
|
|
71
|
-
expect(box).toHaveStyle(`box-sizing: border-box`);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
test('forward ref', () => {
|
|
75
|
-
const ref = React.createRef<HTMLButtonElement>();
|
|
76
|
-
render(
|
|
77
|
-
<Box as="button" ref={ref}>
|
|
78
|
-
button
|
|
79
|
-
</Box>
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
expect(ref.current instanceof HTMLButtonElement).toBeTruthy();
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
test('apply default styling via css prop', () => {
|
|
86
|
-
const Button: React.FC = ({ children }) => (
|
|
87
|
-
<Box as="button" css={{ border: '1px solid black' }}>
|
|
88
|
-
{children}
|
|
89
|
-
</Box>
|
|
90
|
-
);
|
|
91
|
-
render(<Button>button</Button>);
|
|
92
|
-
const button = screen.getByText(/button/);
|
|
93
|
-
|
|
94
|
-
expect(button).toHaveStyle(`border: 1px solid black`);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
test('use design tokens for scale values', () => {
|
|
98
|
-
render(<Box css={{ px: 1 }}>box</Box>);
|
|
99
|
-
const box = screen.getByText(/box/);
|
|
100
|
-
|
|
101
|
-
expect(box).toHaveStyle(`padding-left: 4px`);
|
|
102
|
-
expect(box).toHaveStyle(`padding-right: 4px`);
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
test('interpolate responsive values', () => {
|
|
106
|
-
render(<Box css={{ px: [1, 2] }}>box</Box>);
|
|
107
|
-
const box = screen.getByText(/box/);
|
|
108
|
-
|
|
109
|
-
expect(box).toHaveStyle(`padding-left: 4px`);
|
|
110
|
-
expect(box).toHaveStyle(`padding-right: 4px`);
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
test('support style props for spacing', () => {
|
|
114
|
-
const Button: React.FC = ({ children }) => (
|
|
115
|
-
<Box as="button" my="2">
|
|
116
|
-
{children}
|
|
117
|
-
</Box>
|
|
118
|
-
);
|
|
119
|
-
render(<Button>button</Button>);
|
|
120
|
-
const button = screen.getByText(/button/);
|
|
121
|
-
|
|
122
|
-
expect(button).toHaveStyle(`margin-top: 8px`);
|
|
123
|
-
expect(button).toHaveStyle(`margin-bottom: 8px`);
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
test('supports variants from theme', () => {
|
|
127
|
-
const Text: React.FC<{ variant?: keyof typeof theme.text }> = ({
|
|
128
|
-
variant = 'body',
|
|
129
|
-
children,
|
|
130
|
-
}) => (
|
|
131
|
-
<Box themeSection="text" variant={variant}>
|
|
132
|
-
{children}
|
|
133
|
-
</Box>
|
|
134
|
-
);
|
|
135
|
-
|
|
136
|
-
// Body Text
|
|
137
|
-
render(
|
|
138
|
-
<ThemeContext.Provider value={theme}>
|
|
139
|
-
<Text>body</Text>
|
|
140
|
-
</ThemeContext.Provider>
|
|
141
|
-
);
|
|
142
|
-
const body = screen.getByText(/body/);
|
|
143
|
-
|
|
144
|
-
expect(body).toHaveStyle(`font-size: 14px`);
|
|
145
|
-
expect(body).toHaveStyle(`color: ${theme.colors.black}`);
|
|
146
|
-
|
|
147
|
-
// Heading Text
|
|
148
|
-
render(
|
|
149
|
-
<ThemeContext.Provider value={theme}>
|
|
150
|
-
<Text variant="heading">heading</Text>
|
|
151
|
-
</ThemeContext.Provider>
|
|
152
|
-
);
|
|
153
|
-
const heading = screen.getByText(/heading/);
|
|
154
|
-
|
|
155
|
-
expect(heading).toHaveStyle(`font-size: 20px`);
|
|
156
|
-
expect(heading).toHaveStyle(`color: ${theme.colors.primary}`);
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
test('order of application: base < theme < style props', () => {
|
|
160
|
-
const Button: React.FC<
|
|
161
|
-
{
|
|
162
|
-
variant?: keyof typeof theme.buttons;
|
|
163
|
-
} & SpacingProps
|
|
164
|
-
> = ({ children, variant = 'secondary', ...props }) => (
|
|
165
|
-
<Box
|
|
166
|
-
{...props}
|
|
167
|
-
as="button"
|
|
168
|
-
themeSection="buttons"
|
|
169
|
-
variant={variant}
|
|
170
|
-
css={{
|
|
171
|
-
display: 'inline-block',
|
|
172
|
-
color: 'hotpink',
|
|
173
|
-
border: 0,
|
|
174
|
-
px: 2,
|
|
175
|
-
py: 1,
|
|
176
|
-
}}
|
|
177
|
-
>
|
|
178
|
-
{children}
|
|
179
|
-
</Box>
|
|
180
|
-
);
|
|
181
|
-
|
|
182
|
-
render(
|
|
183
|
-
<ThemeContext.Provider value={theme}>
|
|
184
|
-
<Button>button</Button>
|
|
185
|
-
</ThemeContext.Provider>
|
|
186
|
-
);
|
|
187
|
-
const button = screen.getByText(/button/);
|
|
188
|
-
|
|
189
|
-
// Added via css prop
|
|
190
|
-
expect(button).toHaveStyle(`display: inline-block`);
|
|
191
|
-
expect(button).toHaveStyle(`border: 0`);
|
|
192
|
-
expect(button).toHaveStyle(`padding-left: 8px`);
|
|
193
|
-
expect(button).toHaveStyle(`padding-right: 8px`);
|
|
194
|
-
expect(button).toHaveStyle(`padding-top: 4px`);
|
|
195
|
-
expect(button).toHaveStyle(`padding-bottom: 4px`);
|
|
196
|
-
|
|
197
|
-
// Added via variant
|
|
198
|
-
expect(button).toHaveStyle(`color: ${theme.colors.black}`); // overrides "hotpink"
|
|
199
|
-
expect(button).toHaveStyle(`background-color: ${theme.colors.white}`);
|
|
200
|
-
|
|
201
|
-
render(
|
|
202
|
-
<ThemeContext.Provider value={theme}>
|
|
203
|
-
<Button px="3" py="4">
|
|
204
|
-
variantbutton
|
|
205
|
-
</Button>
|
|
206
|
-
</ThemeContext.Provider>
|
|
207
|
-
);
|
|
208
|
-
const variantbutton = screen.getByText(/variantbutton/);
|
|
209
|
-
|
|
210
|
-
expect(variantbutton).toHaveStyle(`padding: 32px 16px 32px 16px`);
|
|
211
|
-
expect(variantbutton).not.toHaveStyle(`padding-left: 8px`);
|
|
212
|
-
expect(variantbutton).not.toHaveStyle(`padding-right: 8px`);
|
|
213
|
-
expect(variantbutton).not.toHaveStyle(`padding-top: 4px`);
|
|
214
|
-
expect(variantbutton).not.toHaveStyle(`padding-bottom: 4px`);
|
|
215
|
-
});
|
package/src/Box/Box.tsx
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
// @ts-ignore
|
|
2
|
-
import { css } from '@theme-ui/css';
|
|
3
|
-
import pick from 'lodash.pick';
|
|
4
|
-
import { SPACE_PROPS, SpacingProps } from '../categories';
|
|
5
|
-
import { jsx } from '../emotion';
|
|
6
|
-
import { system } from '../system';
|
|
7
|
-
|
|
8
|
-
export type BoxProps = {
|
|
9
|
-
css?: Object;
|
|
10
|
-
themeSection?: string;
|
|
11
|
-
} & SpacingProps;
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Props that we have to remove (because they are not valid HTML attributes)
|
|
15
|
-
* and want to process (for styling the component).
|
|
16
|
-
*/
|
|
17
|
-
const SKIP_PROPS = ['css', 'variant', 'themeSection', ...SPACE_PROPS];
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Gather styling related props (css, variant, space props, ...) and put them in a
|
|
21
|
-
* single `css` prop for emotion. All gathered props will be passed to `@theme-ui/css`
|
|
22
|
-
* before emotion will process them. This way CSS properties will interpolated based on
|
|
23
|
-
* the given theme.
|
|
24
|
-
*/
|
|
25
|
-
const parseProps = (props: { [key: string]: any }) => {
|
|
26
|
-
const next: any = {};
|
|
27
|
-
|
|
28
|
-
// TODO: optimize loop such that the style props are picked
|
|
29
|
-
// within the loop (and remove lodash.pick!)
|
|
30
|
-
for (let key in props) {
|
|
31
|
-
if (SKIP_PROPS.includes(key)) continue;
|
|
32
|
-
next[key] = props[key];
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const styles = {
|
|
36
|
-
...props.css,
|
|
37
|
-
...pick(props, SPACE_PROPS),
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const variant =
|
|
41
|
-
props.themeSection &&
|
|
42
|
-
props.variant &&
|
|
43
|
-
`${props.themeSection}.${props.variant}`;
|
|
44
|
-
|
|
45
|
-
next.css = (theme: any) => {
|
|
46
|
-
return [
|
|
47
|
-
{ boxSizing: 'border-box', margin: 0, minWidth: 0 },
|
|
48
|
-
css(styles)(theme),
|
|
49
|
-
css({ variant })(theme),
|
|
50
|
-
];
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
return next;
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
export const Box = system<BoxProps, 'div'>(
|
|
57
|
-
({ as = 'div', children, ...props }) => jsx(as, parseProps(props), children)
|
|
58
|
-
);
|
package/src/Box/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './Box';
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { render } from '@testing-library/react';
|
|
3
|
-
|
|
4
|
-
import { Global } from './emotion';
|
|
5
|
-
import { Box } from './Box';
|
|
6
|
-
import { MarigoldProvider } from './MarigoldProvider';
|
|
7
|
-
|
|
8
|
-
// Mock
|
|
9
|
-
// ---------------
|
|
10
|
-
/**
|
|
11
|
-
* We're mocking emotion's `<Global/>` here even though this will make us test
|
|
12
|
-
* implementation details. This is currently the only way to test CSS and
|
|
13
|
-
* media queries.
|
|
14
|
-
*/
|
|
15
|
-
jest.mock('@emotion/core', () => {
|
|
16
|
-
const original = jest.requireActual('@emotion/core');
|
|
17
|
-
return {
|
|
18
|
-
...original,
|
|
19
|
-
Global: jest.fn(() => null),
|
|
20
|
-
};
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
// Setup
|
|
24
|
-
// ---------------
|
|
25
|
-
const theme = {
|
|
26
|
-
colors: {
|
|
27
|
-
black: '#111',
|
|
28
|
-
},
|
|
29
|
-
text: {
|
|
30
|
-
body: {
|
|
31
|
-
fontSize: 1,
|
|
32
|
-
color: 'black',
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
// Tests
|
|
38
|
-
// ---------------
|
|
39
|
-
test('set theme context', () => {
|
|
40
|
-
const Text: React.FC<{
|
|
41
|
-
variant?: keyof typeof theme.text;
|
|
42
|
-
}> = ({ children }) => (
|
|
43
|
-
<Box themeSection="text" variant="body">
|
|
44
|
-
{children}
|
|
45
|
-
</Box>
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
const { getByText } = render(
|
|
49
|
-
<MarigoldProvider theme={theme}>
|
|
50
|
-
<Text>I am a body text!</Text>
|
|
51
|
-
</MarigoldProvider>
|
|
52
|
-
);
|
|
53
|
-
const element = getByText('I am a body text!');
|
|
54
|
-
|
|
55
|
-
expect(element).toHaveStyle(`color: ${theme.colors.black}`);
|
|
56
|
-
expect(element).toHaveStyle(`font-size: 14px`);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
test('removes animation when "reduce-motion" media query is set', () => {
|
|
60
|
-
const spy = Global as jest.Mock;
|
|
61
|
-
spy.mockClear();
|
|
62
|
-
|
|
63
|
-
render(<MarigoldProvider theme={theme} />);
|
|
64
|
-
expect((Global as jest.Mock).mock.calls[0]).toMatchInlineSnapshot(`
|
|
65
|
-
Array [
|
|
66
|
-
Object {
|
|
67
|
-
"styles": Object {
|
|
68
|
-
"@media screen and (prefers-reduced-motion: reduce), (update: slow)": Object {
|
|
69
|
-
"*": Object {
|
|
70
|
-
"animationDuration": "0.001ms !important",
|
|
71
|
-
"animationIterationCount": "1 !important",
|
|
72
|
-
"transitionDuration": "0.001ms !important",
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
Object {},
|
|
78
|
-
]
|
|
79
|
-
`);
|
|
80
|
-
});
|
package/src/MarigoldProvider.tsx
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { Global, ThemeContext } from './emotion';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* CSS snippet and idea from:
|
|
6
|
-
* https://css-tricks.com/revisiting-prefers-reduced-motion-the-reduced-motion-media-query/
|
|
7
|
-
*/
|
|
8
|
-
const ReduceMotion = () => (
|
|
9
|
-
<Global
|
|
10
|
-
styles={{
|
|
11
|
-
'@media screen and (prefers-reduced-motion: reduce), (update: slow)': {
|
|
12
|
-
'*': {
|
|
13
|
-
animationDuration: '0.001ms !important',
|
|
14
|
-
animationIterationCount: '1 !important',
|
|
15
|
-
transitionDuration: '0.001ms !important',
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
}}
|
|
19
|
-
/>
|
|
20
|
-
);
|
|
21
|
-
|
|
22
|
-
// TODO: change any to theme when theme component exists
|
|
23
|
-
export type MarigoldProviderProps<T extends any> = React.PropsWithChildren<{
|
|
24
|
-
theme: T;
|
|
25
|
-
}>;
|
|
26
|
-
|
|
27
|
-
export const MarigoldProvider = <T extends any>({
|
|
28
|
-
theme,
|
|
29
|
-
children,
|
|
30
|
-
}: MarigoldProviderProps<T>) => (
|
|
31
|
-
<ThemeContext.Provider value={theme}>
|
|
32
|
-
<>
|
|
33
|
-
<ReduceMotion />
|
|
34
|
-
{children}
|
|
35
|
-
</>
|
|
36
|
-
</ThemeContext.Provider>
|
|
37
|
-
);
|