@marigold/system 0.3.0 → 0.4.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/CHANGELOG.md +25 -50
- package/dist/index.d.ts +364 -8
- package/dist/index.js +399 -5
- package/dist/index.mjs +361 -0
- package/package.json +32 -7
- package/dist/Box.d.ts +0 -14
- package/dist/Global.d.ts +0 -2
- package/dist/SVG.d.ts +0 -6
- package/dist/normalize.d.ts +0 -144
- package/dist/system.cjs.development.js +0 -409
- package/dist/system.cjs.development.js.map +0 -1
- package/dist/system.cjs.production.min.js +0 -2
- package/dist/system.cjs.production.min.js.map +0 -1
- package/dist/system.esm.js +0 -392
- package/dist/system.esm.js.map +0 -1
- package/dist/theme.d.ts +0 -136
- package/dist/types.d.ts +0 -8
- package/dist/useTheme.d.ts +0 -16
- package/dist/variant.d.ts +0 -29
- package/src/Box.test.tsx +0 -308
- package/src/Box.tsx +0 -199
- package/src/Colors.stories.mdx +0 -499
- package/src/Global.test.tsx +0 -57
- package/src/Global.tsx +0 -34
- package/src/SVG.stories.mdx +0 -55
- package/src/SVG.test.tsx +0 -82
- package/src/SVG.tsx +0 -24
- package/src/concepts-principles.mdx +0 -84
- package/src/index.ts +0 -8
- package/src/normalize.test.tsx +0 -15
- package/src/normalize.ts +0 -100
- package/src/theme.ts +0 -157
- package/src/types.ts +0 -14
- package/src/useTheme.test.tsx +0 -123
- package/src/useTheme.tsx +0 -50
- package/src/variant.test.ts +0 -93
- package/src/variant.ts +0 -54
- package/tsconfig.build.json +0 -3
package/src/SVG.test.tsx
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { render, screen } from '@testing-library/react';
|
|
3
|
-
import { SVG } from './SVG';
|
|
4
|
-
|
|
5
|
-
test('renders svg', () => {
|
|
6
|
-
render(<SVG data-testid="svg" />);
|
|
7
|
-
const svg = screen.getByTestId('svg');
|
|
8
|
-
expect(svg instanceof SVGElement).toBeTruthy();
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
test('normalizes <svg>', () => {
|
|
12
|
-
render(<SVG data-testid="svg" />);
|
|
13
|
-
const svg = screen.getByTestId('svg');
|
|
14
|
-
expect(svg).toHaveStyle('display: block');
|
|
15
|
-
expect(svg).toHaveStyle('max-width: 100%');
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
test('supports default fill color', () => {
|
|
19
|
-
render(
|
|
20
|
-
<SVG data-testid="svg">
|
|
21
|
-
<path d="M9.9 20.113V13.8415H14" />
|
|
22
|
-
</SVG>
|
|
23
|
-
);
|
|
24
|
-
const svg = screen.getByTestId(/svg/);
|
|
25
|
-
|
|
26
|
-
expect(svg.getAttribute('fill')).toEqual('currentcolor');
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
test('supports default size', () => {
|
|
30
|
-
render(
|
|
31
|
-
<SVG data-testid="svg">
|
|
32
|
-
<path d="M9.9 20.113V13.8415H14" />
|
|
33
|
-
</SVG>
|
|
34
|
-
);
|
|
35
|
-
const svg = screen.getByTestId(/svg/);
|
|
36
|
-
|
|
37
|
-
expect(svg.getAttribute('width')).toEqual('24');
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
test('supports size prop', () => {
|
|
41
|
-
render(
|
|
42
|
-
<SVG data-testid="svg" size={30}>
|
|
43
|
-
<path d="M9.9 20.113V13.8415H14" />
|
|
44
|
-
</SVG>
|
|
45
|
-
);
|
|
46
|
-
const svg = screen.getByTestId(/svg/);
|
|
47
|
-
|
|
48
|
-
expect(svg.getAttribute('width')).toEqual('30');
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
test('supports fill prop', () => {
|
|
52
|
-
render(
|
|
53
|
-
<SVG data-testid="svg" fill="#fafafa">
|
|
54
|
-
<path d="M9.9 20.113V13.8415H14" />
|
|
55
|
-
</SVG>
|
|
56
|
-
);
|
|
57
|
-
const svg = screen.getByTestId(/svg/);
|
|
58
|
-
|
|
59
|
-
expect(svg.getAttribute('fill')).toEqual('#fafafa');
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
test('accepts custom styles prop className', () => {
|
|
63
|
-
render(
|
|
64
|
-
<SVG data-testid="svg" className="custom-class-name">
|
|
65
|
-
<path d="M9.9 20.113V13.8415H14" />
|
|
66
|
-
</SVG>
|
|
67
|
-
);
|
|
68
|
-
const svg = screen.getByTestId(/svg/);
|
|
69
|
-
|
|
70
|
-
expect(svg.getAttribute('class')).toMatch(/custom-class-name/);
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
test('renders <svg> element', () => {
|
|
74
|
-
render(
|
|
75
|
-
<SVG data-testid="svg">
|
|
76
|
-
<path d="M9.9 20.113V13.8415H14" />
|
|
77
|
-
</SVG>
|
|
78
|
-
);
|
|
79
|
-
const svg = screen.getByTestId(/svg/);
|
|
80
|
-
|
|
81
|
-
expect(svg instanceof SVGElement).toBeTruthy();
|
|
82
|
-
});
|
package/src/SVG.tsx
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { jsx } from '@emotion/react';
|
|
3
|
-
import { ComponentProps } from '@marigold/types';
|
|
4
|
-
import { getNormalizedStyles } from '@marigold/system';
|
|
5
|
-
|
|
6
|
-
const css = getNormalizedStyles('svg');
|
|
7
|
-
|
|
8
|
-
export type SVGProps = {
|
|
9
|
-
size?: number;
|
|
10
|
-
} & ComponentProps<'svg'>;
|
|
11
|
-
|
|
12
|
-
export const SVG: React.FC<SVGProps> = ({ size = 24, children, ...props }) =>
|
|
13
|
-
jsx(
|
|
14
|
-
'svg',
|
|
15
|
-
{
|
|
16
|
-
width: size,
|
|
17
|
-
height: size,
|
|
18
|
-
viewBox: '0 0 24 24',
|
|
19
|
-
fill: 'currentcolor',
|
|
20
|
-
...props,
|
|
21
|
-
css,
|
|
22
|
-
},
|
|
23
|
-
children
|
|
24
|
-
);
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { Meta } from '@storybook/addon-docs';
|
|
2
|
-
|
|
3
|
-
<Meta title="Guides/Concepts & Principles" />
|
|
4
|
-
|
|
5
|
-
## Design Tokens
|
|
6
|
-
|
|
7
|
-
The term _design tokens_ originates from the [Lightning Design System](https://www.lightningdesignsystem.com/design-tokens/). They are the "visual design atoms" of a design system. Similar to variables in CSS or Sass, design tokens are used to capture low-level values and then used to create the look and feel of your product. This helps with maintaining a consistent and scalable visual system for UI development.
|
|
8
|
-
|
|
9
|
-
```css
|
|
10
|
-
/* button.css */
|
|
11
|
-
.button {
|
|
12
|
-
color: #1f1235;
|
|
13
|
-
background: #ff6e6c;
|
|
14
|
-
height: 24px;
|
|
15
|
-
}
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
```scss
|
|
19
|
-
/* colors.scss */
|
|
20
|
-
$color-primary: #ff6e6c;
|
|
21
|
-
$color-text: #1f1235;
|
|
22
|
-
|
|
23
|
-
/* sizes.scss */
|
|
24
|
-
$size-6: 24px;
|
|
25
|
-
|
|
26
|
-
/* button.scss */
|
|
27
|
-
.button {
|
|
28
|
-
color: $color-text;
|
|
29
|
-
background: $color-primary;
|
|
30
|
-
height: $size-6;
|
|
31
|
-
}
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
_Read more:_
|
|
35
|
-
|
|
36
|
-
- [Lightning Design System: Design Tokens](https://www.lightningdesignsystem.com/design-tokens/)
|
|
37
|
-
- [CSS Tricks: What are Design Tokens?](https://css-tricks.com/what-are-design-tokens/)
|
|
38
|
-
|
|
39
|
-
## Rhythm & Harmony
|
|
40
|
-
|
|
41
|
-
Instead of choosing arbitrary numbers for our typography, we make use of a _modular scale_. "By using culturally relevant, historically pleasing ratios to create modular scales and basing the measurements in our compositions on values from those scales, we can achieve a visual harmony not found in layouts that use arbitrary, conventional, or easily divisible numbers." ([_More Meaningful Typography_](https://alistapart.com/article/more-meaningful-typography/))
|
|
42
|
-
|
|
43
|
-
Applied to web typography, this means we choose a base font size and apply a ratio to it. The ratio is then squared to generate an ascending scale.
|
|
44
|
-
|
|
45
|
-
```scss
|
|
46
|
-
/* perfect fifth */
|
|
47
|
-
$ratio: 1.5;
|
|
48
|
-
|
|
49
|
-
/* browser default */
|
|
50
|
-
$base: 16px;
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* The formular is always "$base * $ratio ** $level", the level is a integer.
|
|
54
|
-
* The resulting value is usually rounded to avoid poor sub-pixel rendering.
|
|
55
|
-
*
|
|
56
|
-
* Note that in the below example the number is not equal to the $level in
|
|
57
|
-
* the formula.
|
|
58
|
-
*/
|
|
59
|
-
$fontSize-0: 10px;
|
|
60
|
-
$fontSize-1: 16px;
|
|
61
|
-
$fontSize-2: 24px;
|
|
62
|
-
$fontSize-3: 36px;
|
|
63
|
-
/* etc. */
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
A similar concept can be applied to spacing and sizing of elements. To maintain a aesthetically pleasing rhythm between elements, we adopt the _8pt grid_. This means that multiples of 8 are used to define dimensions, paddings and margins. As a result, all of our measurements follow the same rule and we automatically get a more consistent UI.
|
|
67
|
-
|
|
68
|
-
```scss
|
|
69
|
-
/* 8pt grid */
|
|
70
|
-
$size-0: 0px;
|
|
71
|
-
$size-1: 8px;
|
|
72
|
-
$size-2: 16px;
|
|
73
|
-
$size-3: 32px;
|
|
74
|
-
$size-4: 64px;
|
|
75
|
-
$size-5: 128px;
|
|
76
|
-
$size-6: 256px;
|
|
77
|
-
$size-7: 512px;
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
Read more:
|
|
81
|
-
|
|
82
|
-
- [A List Apart: More Meaningful Typography](https://alistapart.com/article/more-meaningful-typography/)
|
|
83
|
-
- [Type Scale Calculator](https://type-scale.com/)
|
|
84
|
-
- [Bryn Jackson's 8-Point Grid](https://spec.fm/specifics/8-pt-grid)
|
package/src/index.ts
DELETED
package/src/normalize.test.tsx
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { normalize, getNormalizedStyles } from './normalize';
|
|
2
|
-
|
|
3
|
-
test.each(Object.entries(normalize))('base is included in %p', (_, value) => {
|
|
4
|
-
expect(value).toMatchObject(normalize.base);
|
|
5
|
-
});
|
|
6
|
-
|
|
7
|
-
test('get normalized styles', () => {
|
|
8
|
-
expect(getNormalizedStyles('a')).toMatchObject(normalize.a);
|
|
9
|
-
expect(getNormalizedStyles('p')).toMatchObject(normalize.p);
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
test('return base normalzation for arbitrary components', () => {
|
|
13
|
-
const Component = () => null;
|
|
14
|
-
expect(getNormalizedStyles(Component)).toMatchObject(normalize.base);
|
|
15
|
-
});
|
package/src/normalize.ts
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Normalize styling of certain elements between browsers.
|
|
3
|
-
* Based on https://www.joshwcomeau.com/css/custom-css-reset/
|
|
4
|
-
*/
|
|
5
|
-
import { ElementType } from 'react';
|
|
6
|
-
|
|
7
|
-
const base = {
|
|
8
|
-
boxSizing: 'border-box',
|
|
9
|
-
margin: 0,
|
|
10
|
-
minWidth: 0,
|
|
11
|
-
} as const;
|
|
12
|
-
|
|
13
|
-
const a = {
|
|
14
|
-
...base,
|
|
15
|
-
textDecoration: 'none',
|
|
16
|
-
} as const;
|
|
17
|
-
|
|
18
|
-
const text = {
|
|
19
|
-
...base,
|
|
20
|
-
overflowWrap: 'break-word',
|
|
21
|
-
} as const;
|
|
22
|
-
|
|
23
|
-
const media = {
|
|
24
|
-
...base,
|
|
25
|
-
display: 'block',
|
|
26
|
-
maxWidth: '100%',
|
|
27
|
-
} as const;
|
|
28
|
-
|
|
29
|
-
const button = {
|
|
30
|
-
...base,
|
|
31
|
-
display: 'block',
|
|
32
|
-
appearance: 'none',
|
|
33
|
-
font: 'inherit',
|
|
34
|
-
background: 'transparent',
|
|
35
|
-
textAlign: 'center',
|
|
36
|
-
} as const;
|
|
37
|
-
|
|
38
|
-
const input = {
|
|
39
|
-
...base,
|
|
40
|
-
display: 'block',
|
|
41
|
-
appearance: 'none',
|
|
42
|
-
font: 'inherit',
|
|
43
|
-
'&::-ms-clear': {
|
|
44
|
-
display: 'none',
|
|
45
|
-
},
|
|
46
|
-
'&::-webkit-search-cancel-button': {
|
|
47
|
-
WebkitAppearance: 'none',
|
|
48
|
-
},
|
|
49
|
-
} as const;
|
|
50
|
-
|
|
51
|
-
const select = {
|
|
52
|
-
...base,
|
|
53
|
-
display: 'block',
|
|
54
|
-
appearance: 'none',
|
|
55
|
-
font: 'inherit',
|
|
56
|
-
'&::-ms-expand': {
|
|
57
|
-
display: 'none',
|
|
58
|
-
},
|
|
59
|
-
} as const;
|
|
60
|
-
|
|
61
|
-
const textarea = {
|
|
62
|
-
...base,
|
|
63
|
-
display: 'block',
|
|
64
|
-
appearance: 'none',
|
|
65
|
-
font: 'inherit',
|
|
66
|
-
} as const;
|
|
67
|
-
|
|
68
|
-
// Normalize
|
|
69
|
-
// ---------------
|
|
70
|
-
export const normalize = {
|
|
71
|
-
base,
|
|
72
|
-
a,
|
|
73
|
-
p: text,
|
|
74
|
-
h1: text,
|
|
75
|
-
h2: text,
|
|
76
|
-
h3: text,
|
|
77
|
-
h4: text,
|
|
78
|
-
h5: text,
|
|
79
|
-
h6: text,
|
|
80
|
-
img: media,
|
|
81
|
-
picture: media,
|
|
82
|
-
video: media,
|
|
83
|
-
canvas: media,
|
|
84
|
-
svg: media,
|
|
85
|
-
select,
|
|
86
|
-
button,
|
|
87
|
-
textarea,
|
|
88
|
-
input,
|
|
89
|
-
} as const;
|
|
90
|
-
|
|
91
|
-
export type NormalizedElement = keyof typeof normalize;
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Type-safe helper to get normalization. If no normalization is found,
|
|
95
|
-
* returns the *base* normalization.
|
|
96
|
-
*/
|
|
97
|
-
export const getNormalizedStyles = (val?: ElementType) =>
|
|
98
|
-
typeof val === 'string' && val in normalize
|
|
99
|
-
? normalize[val as NormalizedElement] // Typescript doesn't infer this correctly
|
|
100
|
-
: normalize.base;
|
package/src/theme.ts
DELETED
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import * as CSS from 'csstype';
|
|
2
|
-
import { NestedScaleDict } from '@theme-ui/css';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Value used to define a scale.
|
|
6
|
-
*
|
|
7
|
-
* Can be nested to support a default value.
|
|
8
|
-
*
|
|
9
|
-
* @example
|
|
10
|
-
* Given a theme
|
|
11
|
-
* ```
|
|
12
|
-
* {
|
|
13
|
-
* colors: {
|
|
14
|
-
* primary: { __default: '#00f', light: '#33f' }
|
|
15
|
-
* }
|
|
16
|
-
* }
|
|
17
|
-
* ```
|
|
18
|
-
* `css{{ color: 'primary' }}` resolves to `color: #00f`.
|
|
19
|
-
*/
|
|
20
|
-
export type ScaleValue<T> = T | T[] | NestedScaleDict<T> | undefined;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Scales are a set of named, pre-defined CSS values which are used
|
|
24
|
-
* to create consitency in sizing across visual elements. They give
|
|
25
|
-
* plain values semantics meaning.
|
|
26
|
-
*
|
|
27
|
-
* Marigold uses a plain object to define scales, where the key should be a
|
|
28
|
-
* descriptive name for the scale (e.g. `small`/`medium`/.. or `body`/`heading`/...),
|
|
29
|
-
* and the value is the CSS value.
|
|
30
|
-
*/
|
|
31
|
-
export type Scale<T> = {
|
|
32
|
-
[key: string]: ScaleValue<T>;
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Predefined {@link Scale} scale which uses size values.
|
|
37
|
-
*/
|
|
38
|
-
export type SizeScale<T> = {
|
|
39
|
-
xxsmall?: ScaleValue<T>;
|
|
40
|
-
xsmall?: ScaleValue<T>;
|
|
41
|
-
small?: ScaleValue<T>;
|
|
42
|
-
medium?: ScaleValue<T>;
|
|
43
|
-
large?: ScaleValue<T>;
|
|
44
|
-
xlarge?: ScaleValue<T>;
|
|
45
|
-
xxlarge?: ScaleValue<T>;
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* A {@link SizeScale} that also includes a required `none` value, which is
|
|
50
|
-
* usually used to define the blank value (e.g `0`).
|
|
51
|
-
*/
|
|
52
|
-
export type ZeroScale<T> = {
|
|
53
|
-
none: ScaleValue<T>;
|
|
54
|
-
} & Scale<T>;
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Base theme with typings for available scales properties.
|
|
58
|
-
*/
|
|
59
|
-
export interface Theme {
|
|
60
|
-
/**
|
|
61
|
-
* To configure the default breakpoints used in responsive array values,
|
|
62
|
-
* add a breakpoints array to your theme.
|
|
63
|
-
*
|
|
64
|
-
* Each breakpoint should be a string with a CSS length unit included or a
|
|
65
|
-
* string including a CSS media query. String values with a CSS length unit
|
|
66
|
-
* will be used to generate a mobile-first (i.e. min-width) media query.
|
|
67
|
-
*
|
|
68
|
-
* @example
|
|
69
|
-
* ```ts
|
|
70
|
-
* {
|
|
71
|
-
* breakpoints: [
|
|
72
|
-
* '40em', '@media (min-width: 56em) and (orientation: landscape)', '64em',
|
|
73
|
-
* ],
|
|
74
|
-
* }
|
|
75
|
-
* ```
|
|
76
|
-
*/
|
|
77
|
-
breakpoints?: Array<string>;
|
|
78
|
-
|
|
79
|
-
colors?: Scale<CSS.Property.Color | NestedScaleDict<CSS.Property.Color>>;
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Used to define a scale for whitspace values,
|
|
83
|
-
* like `padding`, `margin`, `gap`, etc.
|
|
84
|
-
*/
|
|
85
|
-
space?: ZeroScale<CSS.Property.Margin<number | string>>;
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Used to define a `font-size` scale.
|
|
89
|
-
*/
|
|
90
|
-
fontSizes?: Scale<CSS.Property.FontSize<number>>;
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Used to define a `font-family` scale.
|
|
94
|
-
*/
|
|
95
|
-
fonts?: Scale<CSS.Property.FontFamily>;
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* Used to define a `font-weight` scale.
|
|
99
|
-
*/
|
|
100
|
-
fontWeights?: Scale<CSS.Property.FontWeight>;
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Used to define a `line-height` scale.
|
|
104
|
-
*/
|
|
105
|
-
lineHeights?: Scale<CSS.Property.LineHeight<string | 0 | number>>;
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Used to define a `letter-spacing` scale.
|
|
109
|
-
*/
|
|
110
|
-
letterSpacings?: ZeroScale<CSS.Property.LetterSpacing<string | 0 | number>>;
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Used to define a scale for size values,
|
|
114
|
-
* like `height`, `width`, `flexBasis`, etc.
|
|
115
|
-
*/
|
|
116
|
-
sizes?: ZeroScale<CSS.Property.Height<{}> | CSS.Property.Width<{}>>;
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Used to define different `border` styles.
|
|
120
|
-
*/
|
|
121
|
-
borders?: ZeroScale<CSS.Property.Border<{}>>;
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Used to define `border-style` styles.
|
|
125
|
-
*/
|
|
126
|
-
borderStyles?: Scale<CSS.Property.Border<{}>>;
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Used to define `border-width` styles.
|
|
130
|
-
*/
|
|
131
|
-
borderWidths?: ZeroScale<CSS.Property.BorderWidth<string | 0 | number>>;
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Used to define `border-radius` styles.
|
|
135
|
-
*/
|
|
136
|
-
radii?: ZeroScale<CSS.Property.BorderRadius<string | 0 | number>>;
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Used to define `Shadow` styles.
|
|
140
|
-
*/
|
|
141
|
-
shadows?: ZeroScale<CSS.Property.BoxShadow>;
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Used to define a `z-index` scake.
|
|
145
|
-
*/
|
|
146
|
-
zIndices?: Scale<CSS.Property.ZIndex>;
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Used to define a `opacity` scale.
|
|
150
|
-
*/
|
|
151
|
-
opacities?: Scale<CSS.Property.Opacity>;
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* Used to define a `transition` styles.
|
|
155
|
-
*/
|
|
156
|
-
transitions?: ZeroScale<CSS.Property.Transition>;
|
|
157
|
-
}
|
package/src/types.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Create type aliases for `theme-ui` so that it doesn't leak too much into our code.
|
|
3
|
-
*/
|
|
4
|
-
import {
|
|
5
|
-
ThemeUIStyleObject,
|
|
6
|
-
ThemeUICSSObject,
|
|
7
|
-
ThemeUICSSProperties,
|
|
8
|
-
ResponsiveStyleValue as RSV,
|
|
9
|
-
} from '@theme-ui/css';
|
|
10
|
-
|
|
11
|
-
export type ResponsiveStyleValue<T> = RSV<T>;
|
|
12
|
-
export type StyleObject = ThemeUIStyleObject;
|
|
13
|
-
export type CSSObject = ThemeUICSSObject;
|
|
14
|
-
export type CSSProperties = ThemeUICSSProperties;
|
package/src/useTheme.test.tsx
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { jsx } from '@emotion/react';
|
|
3
|
-
import { render, screen } from '@testing-library/react';
|
|
4
|
-
import { renderHook } from '@testing-library/react-hooks';
|
|
5
|
-
|
|
6
|
-
import { ThemeProvider, useTheme } from './useTheme';
|
|
7
|
-
|
|
8
|
-
// Setup
|
|
9
|
-
// ---------------
|
|
10
|
-
const theme = {
|
|
11
|
-
colors: {
|
|
12
|
-
primary: 'hotpink',
|
|
13
|
-
black: '#000',
|
|
14
|
-
},
|
|
15
|
-
space: {
|
|
16
|
-
none: 0,
|
|
17
|
-
small: 16,
|
|
18
|
-
medium: 24,
|
|
19
|
-
large: 32,
|
|
20
|
-
},
|
|
21
|
-
text: {
|
|
22
|
-
body: {
|
|
23
|
-
fontSize: 1,
|
|
24
|
-
color: 'black',
|
|
25
|
-
},
|
|
26
|
-
heading: {
|
|
27
|
-
fontSize: 3,
|
|
28
|
-
color: 'primary',
|
|
29
|
-
},
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const wrapper: React.FC = ({ children }) => (
|
|
34
|
-
<ThemeProvider theme={theme}>{children}</ThemeProvider>
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
test('returns the theme', () => {
|
|
38
|
-
const { result } = renderHook(() => useTheme(), { wrapper });
|
|
39
|
-
expect(result.current.theme).toEqual(theme);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
test('returns a "css" function', () => {
|
|
43
|
-
const { result } = renderHook(() => useTheme(), { wrapper });
|
|
44
|
-
expect(result.current.css).toEqual(expect.any(Function));
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
test('transpile style object to css object', () => {
|
|
48
|
-
const { result } = renderHook(() => useTheme(), { wrapper });
|
|
49
|
-
const css = result.current.css;
|
|
50
|
-
|
|
51
|
-
expect(css({ p: 'small' })).toMatchInlineSnapshot(`
|
|
52
|
-
{
|
|
53
|
-
"padding": 16,
|
|
54
|
-
}
|
|
55
|
-
`);
|
|
56
|
-
expect(css({ color: 'primary', p: 'large' })).toMatchInlineSnapshot(`
|
|
57
|
-
{
|
|
58
|
-
"color": "hotpink",
|
|
59
|
-
"padding": 32,
|
|
60
|
-
}
|
|
61
|
-
`);
|
|
62
|
-
expect(css({ variant: 'text.body' })).toMatchInlineSnapshot(`
|
|
63
|
-
{
|
|
64
|
-
"color": "#000",
|
|
65
|
-
"fontSize": 14,
|
|
66
|
-
}
|
|
67
|
-
`);
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
test('themes can be cascaded', () => {
|
|
71
|
-
const outerTheme = {
|
|
72
|
-
colors: {
|
|
73
|
-
primary: 'coral',
|
|
74
|
-
},
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
const innerTheme = {
|
|
78
|
-
colors: {
|
|
79
|
-
primary: 'gainsboro',
|
|
80
|
-
},
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
const Theme = ({ testId }: { testId: string }) => {
|
|
84
|
-
const { theme } = useTheme();
|
|
85
|
-
return <div data-testid={testId}>{JSON.stringify(theme, null, 2)}</div>;
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
render(
|
|
89
|
-
<ThemeProvider theme={outerTheme}>
|
|
90
|
-
<>
|
|
91
|
-
<Theme testId="outer" />
|
|
92
|
-
<ThemeProvider theme={innerTheme}>
|
|
93
|
-
<Theme testId="inner" />
|
|
94
|
-
</ThemeProvider>
|
|
95
|
-
</>
|
|
96
|
-
</ThemeProvider>
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
const outer = screen.getByTestId('outer');
|
|
100
|
-
const inner = screen.getByTestId('inner');
|
|
101
|
-
|
|
102
|
-
expect(outer.innerHTML).toMatchInlineSnapshot(`
|
|
103
|
-
"{
|
|
104
|
-
\\"colors\\": {
|
|
105
|
-
\\"primary\\": \\"coral\\"
|
|
106
|
-
}
|
|
107
|
-
}"
|
|
108
|
-
`);
|
|
109
|
-
expect(inner.innerHTML).toMatchInlineSnapshot(`
|
|
110
|
-
"{
|
|
111
|
-
\\"colors\\": {
|
|
112
|
-
\\"primary\\": \\"gainsboro\\"
|
|
113
|
-
}
|
|
114
|
-
}"
|
|
115
|
-
`);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
test('theme is passed down to emotion', () => {
|
|
119
|
-
const css = jest.fn().mockReturnValue({});
|
|
120
|
-
render(<ThemeProvider theme={theme}>{jsx('div', { css })}</ThemeProvider>);
|
|
121
|
-
|
|
122
|
-
expect(css).toHaveBeenCalledWith(theme);
|
|
123
|
-
});
|
package/src/useTheme.tsx
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
createContext,
|
|
3
|
-
ReactNode,
|
|
4
|
-
useCallback,
|
|
5
|
-
useContext,
|
|
6
|
-
} from 'react';
|
|
7
|
-
import { css as transformStyleObject } from '@theme-ui/css';
|
|
8
|
-
import { ThemeProvider as EmotionProvider } from '@emotion/react';
|
|
9
|
-
|
|
10
|
-
import { Theme } from './theme';
|
|
11
|
-
import { StyleObject } from './types';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* @internal
|
|
15
|
-
*/
|
|
16
|
-
export const __defaultTheme: Theme = {};
|
|
17
|
-
|
|
18
|
-
const InternalContext = createContext<Theme>(__defaultTheme);
|
|
19
|
-
|
|
20
|
-
export const useTheme = () => {
|
|
21
|
-
const theme = useContext(InternalContext);
|
|
22
|
-
/**
|
|
23
|
-
* We cast the theme here to `any` since our subset is not
|
|
24
|
-
* compatible with the typings of `theme-ui`, since they
|
|
25
|
-
* also support arrays as scale values, while we don't.
|
|
26
|
-
*/
|
|
27
|
-
const css = useCallback(
|
|
28
|
-
(style: StyleObject) => transformStyleObject(style)(theme as any),
|
|
29
|
-
[theme]
|
|
30
|
-
);
|
|
31
|
-
return { theme, css };
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export type ThemeProviderProps<T extends Theme> = {
|
|
35
|
-
theme: T;
|
|
36
|
-
children: ReactNode;
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
export function ThemeProvider<T extends Theme>({
|
|
40
|
-
theme,
|
|
41
|
-
children,
|
|
42
|
-
}: ThemeProviderProps<T>) {
|
|
43
|
-
return (
|
|
44
|
-
<EmotionProvider theme={theme}>
|
|
45
|
-
<InternalContext.Provider value={theme}>
|
|
46
|
-
{children}
|
|
47
|
-
</InternalContext.Provider>
|
|
48
|
-
</EmotionProvider>
|
|
49
|
-
);
|
|
50
|
-
}
|