@marigold/components 0.0.3 → 0.3.1
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 +174 -0
- package/dist/ActionGroup/ActionGroup.d.ts +8 -0
- package/dist/ActionGroup/ActionGroup.stories.d.ts +5 -0
- package/dist/ActionGroup/index.d.ts +1 -0
- package/dist/Alert/Alert.d.ts +22 -1
- package/dist/Alert/Alert.stories.d.ts +5 -0
- package/dist/Badge/Badge.d.ts +5 -0
- package/dist/Badge/Badge.stories.d.ts +5 -0
- package/dist/Box.d.ts +2 -0
- package/dist/Button/Button.d.ts +9 -6
- package/dist/Button/Button.stories.d.ts +5 -0
- package/dist/Card/Card.d.ts +14 -0
- package/dist/Card/Card.stories.d.ts +5 -0
- package/dist/Card/index.d.ts +1 -0
- package/dist/Checkbox/Checkbox.d.ts +15 -3
- package/dist/Checkbox/Checkbox.stories.d.ts +5 -0
- package/dist/Checkbox/CheckboxIcons.d.ts +9 -0
- package/dist/Column/Column.d.ts +3 -1
- package/dist/Column/Column.stories.d.ts +5 -0
- package/dist/Columns/Columns.d.ts +2 -2
- package/dist/Columns/Columns.stories.d.ts +5 -0
- package/dist/Container/Container.stories.d.ts +5 -0
- package/dist/Dialog/Dialog.d.ts +12 -2
- package/dist/Dialog/Dialog.stories.d.ts +5 -0
- package/dist/Dialog/ModalDialog.d.ts +8 -0
- package/dist/Divider/Divider.d.ts +5 -0
- package/dist/Divider/Divider.stories.d.ts +5 -0
- package/dist/Field/Field.d.ts +5 -1
- package/dist/Field/Field.stories.d.ts +5 -0
- package/dist/Image/Image.d.ts +5 -0
- package/dist/Image/Image.stories.d.ts +5 -0
- package/dist/Inline/Inline.d.ts +7 -0
- package/dist/Inline/Inline.stories.d.ts +5 -0
- package/dist/Inline/index.d.ts +1 -0
- package/dist/Input/Input.d.ts +5 -0
- package/dist/Input/Input.stories.d.ts +5 -0
- package/dist/Label/Label.d.ts +14 -2
- package/dist/Label/Label.stories.d.ts +5 -0
- package/dist/Link/Link.d.ts +10 -6
- package/dist/Link/Link.stories.d.ts +5 -0
- package/dist/Menu/Menu.d.ts +3 -0
- package/dist/Menu/Menu.stories.d.ts +5 -0
- package/dist/MenuItem/MenuItem.d.ts +5 -0
- package/dist/MenuItem/MenuItem.stories.d.ts +5 -0
- package/dist/Message/Message.d.ts +5 -0
- package/dist/Message/Message.stories.d.ts +5 -0
- package/dist/Provider/MarigoldProvider.d.ts +11 -0
- package/dist/Provider/index.d.ts +3 -0
- package/dist/Radio/Radio.d.ts +11 -4
- package/dist/Radio/Radio.stories.d.ts +5 -0
- package/dist/Radio/RadioIcon.d.ts +9 -0
- package/dist/Select/ListBox.d.ts +9 -0
- package/dist/Select/ListBoxSection.d.ts +9 -0
- package/dist/Select/Option.d.ts +9 -0
- package/dist/Select/Popover.d.ts +9 -0
- package/dist/Select/Select.d.ts +25 -4
- package/dist/Select/Select.stories.d.ts +5 -0
- package/dist/Slider/Slider.d.ts +5 -0
- package/dist/Slider/Slider.stories.d.ts +5 -0
- package/dist/Stack/Stack.d.ts +1 -3
- package/dist/Stack/Stack.stories.d.ts +5 -0
- package/dist/Text/Text.d.ts +17 -10
- package/dist/Text/Text.stories.d.ts +5 -0
- package/dist/Textarea/Textarea.d.ts +7 -1
- package/dist/Textarea/Textarea.stories.d.ts +5 -0
- package/dist/ValidationMessage/ValidationMessage.d.ts +5 -0
- package/dist/ValidationMessage/ValidationMessage.stories.d.ts +5 -0
- package/dist/VisuallyHidden/VisuallyHidden.d.ts +1 -0
- package/dist/VisuallyHidden/VisuallyHidden.stories.d.ts +5 -0
- package/dist/VisuallyHidden/index.d.ts +1 -0
- package/dist/components.cjs.development.js +1075 -562
- package/dist/components.cjs.development.js.map +1 -1
- package/dist/components.cjs.production.min.js +1 -1
- package/dist/components.cjs.production.min.js.map +1 -1
- package/dist/components.esm.js +1012 -542
- package/dist/components.esm.js.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/theme.d.ts +23 -48
- package/package.json +21 -2
- package/src/ActionGroup/ActionGroup.stories.tsx +47 -0
- package/src/ActionGroup/ActionGroup.test.tsx +83 -0
- package/src/ActionGroup/ActionGroup.tsx +32 -0
- package/src/ActionGroup/index.ts +1 -0
- package/src/Alert/Alert.stories.tsx +32 -0
- package/src/Alert/Alert.test.tsx +5 -2
- package/src/Alert/Alert.tsx +27 -34
- package/src/Badge/Badge.stories.tsx +38 -0
- package/src/Badge/Badge.test.tsx +12 -16
- package/src/Badge/Badge.tsx +14 -3
- package/src/Box.ts +2 -0
- package/src/Button/Button.stories.tsx +57 -0
- package/src/Button/Button.test.tsx +76 -13
- package/src/Button/Button.tsx +61 -18
- package/src/Card/Card.stories.tsx +41 -0
- package/src/Card/Card.test.tsx +71 -0
- package/src/Card/Card.tsx +48 -0
- package/src/Card/index.ts +1 -0
- package/src/Checkbox/Checkbox.stories.tsx +78 -0
- package/src/Checkbox/Checkbox.test.tsx +138 -23
- package/src/Checkbox/Checkbox.tsx +81 -52
- package/src/Checkbox/CheckboxIcons.tsx +59 -0
- package/src/Column/Column.stories.tsx +33 -0
- package/src/Column/Column.test.tsx +8 -0
- package/src/Column/Column.tsx +12 -2
- package/src/Columns/Columns.stories.tsx +75 -0
- package/src/Columns/Columns.test.tsx +34 -23
- package/src/Columns/Columns.tsx +30 -30
- package/src/Container/Container.stories.tsx +14 -0
- package/src/Dialog/Dialog.stories.tsx +88 -0
- package/src/Dialog/Dialog.test.tsx +129 -18
- package/src/Dialog/Dialog.tsx +113 -15
- package/src/Dialog/ModalDialog.tsx +76 -0
- package/src/Divider/Divider.stories.tsx +30 -0
- package/src/Divider/Divider.test.tsx +13 -5
- package/src/Divider/Divider.tsx +12 -0
- package/src/Field/Field.stories.tsx +110 -0
- package/src/Field/Field.test.tsx +74 -33
- package/src/Field/Field.tsx +27 -20
- package/src/Image/Image.stories.tsx +34 -0
- package/src/Image/Image.test.tsx +4 -1
- package/src/Image/Image.tsx +13 -1
- package/src/Inline/Inline.stories.tsx +39 -0
- package/src/Inline/Inline.test.tsx +99 -0
- package/src/Inline/Inline.tsx +38 -0
- package/src/Inline/index.ts +1 -0
- package/src/Input/Input.stories.tsx +54 -0
- package/src/Input/Input.test.tsx +7 -3
- package/src/Input/Input.tsx +13 -1
- package/src/Label/Label.stories.tsx +41 -0
- package/src/Label/Label.test.tsx +40 -5
- package/src/Label/Label.tsx +54 -8
- package/src/Link/Link.stories.tsx +35 -0
- package/src/Link/Link.test.tsx +51 -21
- package/src/Link/Link.tsx +39 -13
- package/src/Menu/Menu.stories.tsx +62 -0
- package/src/Menu/Menu.test.tsx +11 -6
- package/src/Menu/Menu.tsx +22 -14
- package/src/MenuItem/MenuItem.stories.tsx +30 -0
- package/src/MenuItem/MenuItem.test.tsx +22 -13
- package/src/MenuItem/MenuItem.tsx +19 -10
- package/src/Message/Message.stories.tsx +30 -0
- package/src/Message/Message.test.tsx +4 -1
- package/src/Message/Message.tsx +18 -14
- package/src/Provider/MarigoldProvider.test.tsx +136 -0
- package/src/Provider/MarigoldProvider.tsx +47 -0
- package/src/Provider/index.ts +4 -0
- package/src/Radio/Radio.stories.tsx +78 -0
- package/src/Radio/Radio.test.tsx +129 -18
- package/src/Radio/Radio.tsx +62 -71
- package/src/Radio/RadioIcon.tsx +49 -0
- package/src/Select/ListBox.tsx +40 -0
- package/src/Select/ListBoxSection.tsx +40 -0
- package/src/Select/Option.tsx +48 -0
- package/src/Select/Popover.tsx +50 -0
- package/src/Select/Select.stories.tsx +81 -0
- package/src/Select/Select.test.tsx +317 -35
- package/src/Select/Select.tsx +162 -18
- package/src/Slider/Slider.stories.tsx +24 -0
- package/src/Slider/Slider.test.tsx +10 -6
- package/src/Slider/Slider.tsx +25 -13
- package/src/Stack/Stack.stories.tsx +57 -0
- package/src/Stack/Stack.test.tsx +93 -65
- package/src/Stack/Stack.tsx +27 -32
- package/src/Text/Text.stories.tsx +61 -0
- package/src/Text/Text.test.tsx +41 -36
- package/src/Text/Text.tsx +56 -31
- package/src/Textarea/Textarea.stories.tsx +64 -0
- package/src/Textarea/Textarea.test.tsx +11 -8
- package/src/Textarea/Textarea.tsx +41 -38
- package/src/ValidationMessage/ValidationMessage.stories.tsx +27 -0
- package/src/ValidationMessage/ValidationMessage.test.tsx +9 -4
- package/src/ValidationMessage/ValidationMessage.tsx +23 -12
- package/src/VisuallyHidden/VisuallyHidden.stories.tsx +19 -0
- package/src/VisuallyHidden/VisuallyHidden.test.tsx +10 -0
- package/src/VisuallyHidden/VisuallyHidden.tsx +1 -0
- package/src/VisuallyHidden/index.ts +1 -0
- package/src/index.ts +7 -2
- package/src/theme.ts +49 -48
- package/dist/Box/Box.d.ts +0 -45
- package/dist/Box/index.d.ts +0 -1
- package/dist/Heading/Heading.d.ts +0 -7
- package/dist/Heading/index.d.ts +0 -1
- package/dist/Hidden/Hidden.d.ts +0 -5
- package/dist/Hidden/index.d.ts +0 -1
- package/src/Alert/Alert.stories.mdx +0 -45
- package/src/Badge/Badge.stories.mdx +0 -43
- package/src/Box/Box.stories.mdx +0 -38
- package/src/Box/Box.test.tsx +0 -133
- package/src/Box/Box.tsx +0 -152
- package/src/Box/index.ts +0 -1
- package/src/Button/Button.stories.mdx +0 -176
- package/src/Checkbox/Checkbox.stories.mdx +0 -119
- package/src/Column/Column.stories.mdx +0 -74
- package/src/Columns/Columns.stories.mdx +0 -247
- package/src/Container/Container.stories.mdx +0 -36
- package/src/Dialog/Dialog.stories.mdx +0 -64
- package/src/Divider/Divider.stories.mdx +0 -43
- package/src/Field/Field.stories.mdx +0 -57
- package/src/Heading/Heading.stories.mdx +0 -91
- package/src/Heading/Heading.test.tsx +0 -77
- package/src/Heading/Heading.tsx +0 -19
- package/src/Heading/index.ts +0 -1
- package/src/Hidden/Hidden.stories.mdx +0 -64
- package/src/Hidden/Hidden.test.tsx +0 -24
- package/src/Hidden/Hidden.tsx +0 -16
- package/src/Hidden/index.ts +0 -1
- package/src/Image/Image.stories.mdx +0 -40
- package/src/Input/Input.stories.mdx +0 -45
- package/src/Label/Label.stories.mdx +0 -34
- package/src/Link/Link.stories.mdx +0 -38
- package/src/Menu/Menu.stories.mdx +0 -49
- package/src/MenuItem/MenuItem.stories.mdx +0 -32
- package/src/Message/Message.stories.mdx +0 -44
- package/src/Radio/Radio.stories.mdx +0 -100
- package/src/Select/Select.stories.mdx +0 -44
- package/src/Slider/Slider.stories.mdx +0 -58
- package/src/Stack/Stack.stories.mdx +0 -105
- package/src/Text/Text.stories.mdx +0 -60
- package/src/Textarea/Textarea.stories.mdx +0 -65
- package/src/ValidationMessage/ValidationMessage.stories.mdx +0 -36
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, screen } from '@testing-library/react';
|
|
3
|
+
import { ThemeProvider } from '@marigold/system';
|
|
4
|
+
|
|
5
|
+
import { Inline } from './Inline';
|
|
6
|
+
import { Text } from '../Text';
|
|
7
|
+
|
|
8
|
+
// Setup
|
|
9
|
+
// ---------------
|
|
10
|
+
const theme = {
|
|
11
|
+
space: {
|
|
12
|
+
none: 0,
|
|
13
|
+
small: 2,
|
|
14
|
+
medium: 4,
|
|
15
|
+
large: 8,
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const getLeftPadding = (element: HTMLElement) =>
|
|
20
|
+
getComputedStyle(element).getPropertyValue('padding-left');
|
|
21
|
+
|
|
22
|
+
test('default space is "none"', () => {
|
|
23
|
+
render(
|
|
24
|
+
<ThemeProvider theme={theme}>
|
|
25
|
+
<Inline>
|
|
26
|
+
<Text>first</Text>
|
|
27
|
+
<Text>second</Text>
|
|
28
|
+
</Inline>
|
|
29
|
+
</ThemeProvider>
|
|
30
|
+
);
|
|
31
|
+
const first = screen.getByText(/first/).parentElement!;
|
|
32
|
+
const second = screen.getByText(/second/).parentElement!;
|
|
33
|
+
|
|
34
|
+
expect(getLeftPadding(first)).toEqual('');
|
|
35
|
+
expect(second).toHaveStyle(`padding-left: 0px`);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test('accepts and uses spacing from theme', () => {
|
|
39
|
+
render(
|
|
40
|
+
<ThemeProvider theme={theme}>
|
|
41
|
+
<Inline space="small">
|
|
42
|
+
<Text>first</Text>
|
|
43
|
+
<Text>second</Text>
|
|
44
|
+
</Inline>
|
|
45
|
+
</ThemeProvider>
|
|
46
|
+
);
|
|
47
|
+
const first = screen.getByText(/first/);
|
|
48
|
+
const second = screen.getByText(/second/);
|
|
49
|
+
|
|
50
|
+
expect(getLeftPadding(first)).toEqual('');
|
|
51
|
+
expect(second.parentElement).toHaveStyle(`padding-left: 2px`);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('supports nesting', () => {
|
|
55
|
+
render(
|
|
56
|
+
<ThemeProvider theme={theme}>
|
|
57
|
+
<Inline space="large">
|
|
58
|
+
<Inline space="small" data-testid="leftInline">
|
|
59
|
+
<Text>first</Text>
|
|
60
|
+
<Text>second</Text>
|
|
61
|
+
</Inline>
|
|
62
|
+
<Inline space="small" data-testid="rightInline">
|
|
63
|
+
<Text>third</Text>
|
|
64
|
+
<Text>fourth</Text>
|
|
65
|
+
</Inline>
|
|
66
|
+
</Inline>
|
|
67
|
+
</ThemeProvider>
|
|
68
|
+
);
|
|
69
|
+
const first = screen.getByText(/first/);
|
|
70
|
+
const second = screen.getByText(/second/);
|
|
71
|
+
const leftInline = screen.getByTestId('leftInline');
|
|
72
|
+
|
|
73
|
+
const third = screen.getByText(/third/);
|
|
74
|
+
const fourth = screen.getByText(/fourth/);
|
|
75
|
+
const rightInline = screen.getByTestId('rightInline');
|
|
76
|
+
|
|
77
|
+
expect(getLeftPadding(leftInline.parentElement!)).toEqual('');
|
|
78
|
+
expect(rightInline.parentElement).toHaveStyle(`padding-left: 8px`);
|
|
79
|
+
|
|
80
|
+
expect(getLeftPadding(first.parentElement!)).toEqual('');
|
|
81
|
+
expect(second.parentElement).toHaveStyle(`padding-left: 2px`);
|
|
82
|
+
|
|
83
|
+
expect(getLeftPadding(third.parentElement!)).toEqual('');
|
|
84
|
+
expect(fourth.parentElement).toHaveStyle(`padding-left: 2px`);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test('renders div per default', () => {
|
|
88
|
+
render(
|
|
89
|
+
<ThemeProvider theme={theme}>
|
|
90
|
+
<Inline data-testid="inline">
|
|
91
|
+
<Text>first</Text>
|
|
92
|
+
<Text>second</Text>
|
|
93
|
+
</Inline>
|
|
94
|
+
</ThemeProvider>
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
const inline = screen.getByTestId('inline');
|
|
98
|
+
expect(inline instanceof HTMLDivElement).toBeTruthy();
|
|
99
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React, { Children } from 'react';
|
|
2
|
+
import flattenChildren from 'react-keyed-flatten-children';
|
|
3
|
+
|
|
4
|
+
import { ResponsiveStyleValue } from '@marigold/system';
|
|
5
|
+
|
|
6
|
+
import { Box } from '../Box';
|
|
7
|
+
|
|
8
|
+
export type InlineProps = {
|
|
9
|
+
space?: ResponsiveStyleValue<string>;
|
|
10
|
+
align?: 'top' | 'center' | 'bottom';
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const ALIGNMENT = {
|
|
14
|
+
top: 'flex-start',
|
|
15
|
+
center: 'center',
|
|
16
|
+
bottom: 'flex-end',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const Inline: React.FC<InlineProps> = ({
|
|
20
|
+
space = 'none',
|
|
21
|
+
align = 'center',
|
|
22
|
+
children,
|
|
23
|
+
...props
|
|
24
|
+
}) => (
|
|
25
|
+
<Box
|
|
26
|
+
display="inline-flex"
|
|
27
|
+
css={{ '> * + *': { pl: space } }}
|
|
28
|
+
alignItems={ALIGNMENT[align]}
|
|
29
|
+
{...props}
|
|
30
|
+
>
|
|
31
|
+
{Children.map(
|
|
32
|
+
flattenChildren(children) as unknown as React.ReactElement,
|
|
33
|
+
(child: React.ReactElement) => (
|
|
34
|
+
<Box>{React.cloneElement(child, {}, child.props.children)}</Box>
|
|
35
|
+
)
|
|
36
|
+
)}
|
|
37
|
+
</Box>
|
|
38
|
+
);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Inline';
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Meta, ComponentStory } from '@storybook/react';
|
|
3
|
+
import { Input } from './Input';
|
|
4
|
+
import { Label } from '../Label';
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
title: 'Components/Input',
|
|
8
|
+
argTypes: {
|
|
9
|
+
variant: {
|
|
10
|
+
control: {
|
|
11
|
+
type: 'text',
|
|
12
|
+
},
|
|
13
|
+
description: '?',
|
|
14
|
+
table: {
|
|
15
|
+
defaultValue: {
|
|
16
|
+
summary: '__default',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
type: {
|
|
21
|
+
control: {
|
|
22
|
+
type: 'select',
|
|
23
|
+
},
|
|
24
|
+
options: [
|
|
25
|
+
'date',
|
|
26
|
+
'datetime-local',
|
|
27
|
+
'email',
|
|
28
|
+
'month',
|
|
29
|
+
'number',
|
|
30
|
+
'password',
|
|
31
|
+
'search',
|
|
32
|
+
'tel',
|
|
33
|
+
'text',
|
|
34
|
+
'time',
|
|
35
|
+
'time',
|
|
36
|
+
'url',
|
|
37
|
+
'week',
|
|
38
|
+
],
|
|
39
|
+
defaultValue: 'text',
|
|
40
|
+
table: {
|
|
41
|
+
defaultValue: {
|
|
42
|
+
summary: 'text',
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
} as Meta;
|
|
48
|
+
|
|
49
|
+
export const Basic: ComponentStory<typeof Input> = args => (
|
|
50
|
+
<Label htmlFor="input">
|
|
51
|
+
Label
|
|
52
|
+
<Input id="input" placeholder="Placeholder..." {...args} />
|
|
53
|
+
</Label>
|
|
54
|
+
);
|
package/src/Input/Input.test.tsx
CHANGED
|
@@ -4,12 +4,16 @@ import { ThemeProvider } from '@marigold/system';
|
|
|
4
4
|
import { Input } from './Input';
|
|
5
5
|
|
|
6
6
|
const theme = {
|
|
7
|
+
fonts: {
|
|
8
|
+
body: 'Inter',
|
|
9
|
+
forms: 'Roboto',
|
|
10
|
+
},
|
|
7
11
|
input: {
|
|
8
|
-
|
|
9
|
-
fontFamily: '
|
|
12
|
+
__default: {
|
|
13
|
+
fontFamily: 'body',
|
|
10
14
|
},
|
|
11
15
|
input2: {
|
|
12
|
-
fontFamily: '
|
|
16
|
+
fontFamily: 'forms',
|
|
13
17
|
},
|
|
14
18
|
},
|
|
15
19
|
};
|
package/src/Input/Input.tsx
CHANGED
|
@@ -2,12 +2,24 @@ import React from 'react';
|
|
|
2
2
|
import { ComponentProps } from '@marigold/types';
|
|
3
3
|
import { Box } from '../Box';
|
|
4
4
|
|
|
5
|
+
// Theme Extension
|
|
6
|
+
// ---------------
|
|
7
|
+
export interface InputThemeExtension<Value> {
|
|
8
|
+
input?: {
|
|
9
|
+
[key: string]: Value;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Props
|
|
14
|
+
// ---------------
|
|
5
15
|
export type InputProps = {
|
|
6
16
|
variant?: string;
|
|
7
17
|
} & ComponentProps<'input'>;
|
|
8
18
|
|
|
19
|
+
// Component
|
|
20
|
+
// ---------------
|
|
9
21
|
export const Input: React.FC<InputProps> = ({
|
|
10
|
-
variant = '
|
|
22
|
+
variant = '',
|
|
11
23
|
type = 'text',
|
|
12
24
|
...props
|
|
13
25
|
}) => <Box {...props} as="input" type={type} variant={`input.${variant}`} />;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Meta, ComponentStory } from '@storybook/react';
|
|
3
|
+
import { Label } from './Label';
|
|
4
|
+
|
|
5
|
+
export default {
|
|
6
|
+
title: 'Components/Label',
|
|
7
|
+
argTypes: {
|
|
8
|
+
variant: {
|
|
9
|
+
control: {
|
|
10
|
+
type: 'text',
|
|
11
|
+
},
|
|
12
|
+
description: '?',
|
|
13
|
+
table: {
|
|
14
|
+
defaultValue: {
|
|
15
|
+
summary: 'above',
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
htmlFor: {
|
|
20
|
+
control: {
|
|
21
|
+
type: 'text',
|
|
22
|
+
},
|
|
23
|
+
defaultValue: 'input',
|
|
24
|
+
},
|
|
25
|
+
required: {
|
|
26
|
+
control: {
|
|
27
|
+
type: 'boolean',
|
|
28
|
+
},
|
|
29
|
+
description: 'Adds required Icon to label',
|
|
30
|
+
table: {
|
|
31
|
+
defaultValue: {
|
|
32
|
+
summary: false,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
} as Meta;
|
|
38
|
+
|
|
39
|
+
export const Basic: ComponentStory<typeof Label> = args => (
|
|
40
|
+
<Label {...args}>Label</Label>
|
|
41
|
+
);
|
package/src/Label/Label.test.tsx
CHANGED
|
@@ -4,17 +4,25 @@ import { ThemeProvider } from '@marigold/system';
|
|
|
4
4
|
import { Label } from './Label';
|
|
5
5
|
|
|
6
6
|
const theme = {
|
|
7
|
+
fonts: {
|
|
8
|
+
body: 'Inter Regular',
|
|
9
|
+
label: 'Oswald',
|
|
10
|
+
},
|
|
7
11
|
label: {
|
|
8
|
-
|
|
9
|
-
fontFamily: '
|
|
12
|
+
above: {
|
|
13
|
+
fontFamily: 'body',
|
|
10
14
|
},
|
|
11
15
|
myLabel: {
|
|
12
|
-
fontFamily: '
|
|
16
|
+
fontFamily: 'label',
|
|
13
17
|
},
|
|
14
18
|
},
|
|
19
|
+
colors: {
|
|
20
|
+
text: 'black',
|
|
21
|
+
disabled: 'gray',
|
|
22
|
+
},
|
|
15
23
|
};
|
|
16
24
|
|
|
17
|
-
test('supports default variant and
|
|
25
|
+
test('supports default variant and styles', () => {
|
|
18
26
|
render(
|
|
19
27
|
<ThemeProvider theme={theme}>
|
|
20
28
|
<Label htmlFor="labelId">label</Label>
|
|
@@ -23,6 +31,7 @@ test('supports default variant and themeSection', () => {
|
|
|
23
31
|
const label = screen.getByText(/label/);
|
|
24
32
|
|
|
25
33
|
expect(label).toHaveStyle(`font-family: Inter Regular`);
|
|
34
|
+
expect(label).toHaveStyle(`color: black`);
|
|
26
35
|
});
|
|
27
36
|
|
|
28
37
|
test('supports other variant than default', () => {
|
|
@@ -35,7 +44,7 @@ test('supports other variant than default', () => {
|
|
|
35
44
|
);
|
|
36
45
|
const label = screen.getByText(/label/);
|
|
37
46
|
|
|
38
|
-
expect(label).toHaveStyle(`font-family: Oswald
|
|
47
|
+
expect(label).toHaveStyle(`font-family: Oswald`);
|
|
39
48
|
});
|
|
40
49
|
|
|
41
50
|
test('supports htmlFor prop', () => {
|
|
@@ -49,6 +58,32 @@ test('supports htmlFor prop', () => {
|
|
|
49
58
|
expect(label).toHaveAttribute('for');
|
|
50
59
|
});
|
|
51
60
|
|
|
61
|
+
test('supports required prop', () => {
|
|
62
|
+
render(
|
|
63
|
+
<ThemeProvider theme={theme}>
|
|
64
|
+
<Label htmlFor="labelId" required>
|
|
65
|
+
label
|
|
66
|
+
</Label>
|
|
67
|
+
</ThemeProvider>
|
|
68
|
+
);
|
|
69
|
+
const label = screen.getByText(/label/);
|
|
70
|
+
const parent = label.parentElement;
|
|
71
|
+
|
|
72
|
+
expect(parent instanceof HTMLSpanElement).toBeTruthy();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
test('supports color prop', () => {
|
|
76
|
+
render(
|
|
77
|
+
<ThemeProvider theme={theme}>
|
|
78
|
+
<Label htmlFor="labelId" color="disabled">
|
|
79
|
+
label
|
|
80
|
+
</Label>
|
|
81
|
+
</ThemeProvider>
|
|
82
|
+
);
|
|
83
|
+
const label = screen.getByText(/label/);
|
|
84
|
+
expect(label).toHaveStyle(`color: gray`);
|
|
85
|
+
});
|
|
86
|
+
|
|
52
87
|
test('renders <label> element', () => {
|
|
53
88
|
render(
|
|
54
89
|
<ThemeProvider theme={theme}>
|
package/src/Label/Label.tsx
CHANGED
|
@@ -1,18 +1,64 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
|
|
2
3
|
import { ComponentProps } from '@marigold/types';
|
|
4
|
+
import { Required } from '@marigold/icons';
|
|
5
|
+
import { ResponsiveStyleValue } from '@marigold/system';
|
|
6
|
+
|
|
3
7
|
import { Box } from '../Box';
|
|
4
8
|
|
|
5
|
-
|
|
6
|
-
|
|
9
|
+
// Theme Extension
|
|
10
|
+
// ---------------
|
|
11
|
+
export interface LabelThemeExtension<Value> {
|
|
12
|
+
label?: {
|
|
13
|
+
[key: string]: Value;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// LabelBase
|
|
18
|
+
// ---------------
|
|
19
|
+
export type LabelBaseProps = {
|
|
20
|
+
htmlFor?: string;
|
|
7
21
|
variant?: string;
|
|
22
|
+
required?: boolean;
|
|
23
|
+
color?: ResponsiveStyleValue<string>;
|
|
8
24
|
} & ComponentProps<'label'>;
|
|
9
25
|
|
|
26
|
+
export const LabelBase: React.FC<LabelProps> = ({
|
|
27
|
+
variant = 'above',
|
|
28
|
+
required,
|
|
29
|
+
color = 'text',
|
|
30
|
+
children,
|
|
31
|
+
...props
|
|
32
|
+
}) => {
|
|
33
|
+
return (
|
|
34
|
+
<Box
|
|
35
|
+
{...props}
|
|
36
|
+
as="label"
|
|
37
|
+
__baseCSS={{ color: color }}
|
|
38
|
+
variant={`label.${variant}`}
|
|
39
|
+
>
|
|
40
|
+
{children}
|
|
41
|
+
</Box>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Label
|
|
46
|
+
// ---------------
|
|
47
|
+
export type LabelProps = {
|
|
48
|
+
required?: boolean;
|
|
49
|
+
} & LabelBaseProps;
|
|
50
|
+
|
|
10
51
|
export const Label: React.FC<LabelProps> = ({
|
|
11
|
-
|
|
52
|
+
required,
|
|
12
53
|
children,
|
|
13
54
|
...props
|
|
14
|
-
}) =>
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
55
|
+
}) => {
|
|
56
|
+
return required ? (
|
|
57
|
+
<Box as="span" display="inline-flex" alignItems="center">
|
|
58
|
+
<LabelBase {...props}>{children}</LabelBase>
|
|
59
|
+
{required && <Box as={Required} size={16} css={{ color: 'error' }} />}
|
|
60
|
+
</Box>
|
|
61
|
+
) : (
|
|
62
|
+
<LabelBase {...props}>{children}</LabelBase>
|
|
63
|
+
);
|
|
64
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Meta, ComponentStory } from '@storybook/react';
|
|
3
|
+
import { Link } from './Link';
|
|
4
|
+
import { Text } from '../Text';
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
title: 'Components/Link',
|
|
8
|
+
argTypes: {
|
|
9
|
+
variant: {
|
|
10
|
+
control: {
|
|
11
|
+
type: 'text',
|
|
12
|
+
},
|
|
13
|
+
description: '?',
|
|
14
|
+
table: {
|
|
15
|
+
defaultValue: {
|
|
16
|
+
summary: 'link',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
href: {
|
|
21
|
+
control: {
|
|
22
|
+
type: 'text',
|
|
23
|
+
},
|
|
24
|
+
description: 'The URL to direct to',
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
} as Meta;
|
|
28
|
+
|
|
29
|
+
export const Basic: ComponentStory<typeof Link> = args => (
|
|
30
|
+
<Text>
|
|
31
|
+
<Link href="https://marigold-ui.io" target="_blank" {...args}>
|
|
32
|
+
Marigold Docs
|
|
33
|
+
</Link>
|
|
34
|
+
</Text>
|
|
35
|
+
);
|
package/src/Link/Link.test.tsx
CHANGED
|
@@ -4,64 +4,94 @@ import { ThemeProvider } from '@marigold/system';
|
|
|
4
4
|
import { Link } from './Link';
|
|
5
5
|
|
|
6
6
|
const theme = {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
fonts: {
|
|
8
|
+
link: 'Inter',
|
|
9
|
+
body: 'Oswald',
|
|
10
|
+
},
|
|
11
|
+
text: {
|
|
12
|
+
link: {
|
|
13
|
+
fontFamily: 'link',
|
|
10
14
|
},
|
|
11
15
|
second: {
|
|
12
|
-
fontFamily: '
|
|
16
|
+
fontFamily: 'body',
|
|
13
17
|
},
|
|
14
18
|
},
|
|
15
19
|
};
|
|
16
20
|
|
|
17
|
-
test('
|
|
21
|
+
test('uses `text.link` as default variant', () => {
|
|
18
22
|
render(
|
|
19
23
|
<ThemeProvider theme={theme}>
|
|
20
|
-
<Link href="#!"
|
|
21
|
-
Link
|
|
22
|
-
</Link>
|
|
24
|
+
<Link href="#!">Link</Link>
|
|
23
25
|
</ThemeProvider>
|
|
24
26
|
);
|
|
25
|
-
const link = screen.
|
|
27
|
+
const link = screen.getByText(/Link/);
|
|
26
28
|
|
|
27
29
|
expect(link).toHaveStyle(`font-family: Inter`);
|
|
28
30
|
});
|
|
29
31
|
|
|
30
|
-
test('
|
|
32
|
+
test('allows to change variants via `variant` prop (with "text" prefix)', () => {
|
|
31
33
|
render(
|
|
32
34
|
<ThemeProvider theme={theme}>
|
|
33
|
-
<Link href="#!"
|
|
35
|
+
<Link href="#!" variant="second">
|
|
34
36
|
Link
|
|
35
37
|
</Link>
|
|
36
38
|
</ThemeProvider>
|
|
37
39
|
);
|
|
38
|
-
const link = screen.
|
|
40
|
+
const link = screen.getByText(/Link/);
|
|
39
41
|
|
|
40
42
|
expect(link).toHaveStyle(`font-family: Oswald`);
|
|
41
43
|
});
|
|
42
44
|
|
|
43
|
-
test('renders
|
|
45
|
+
test('renders a <a> element by default', () => {
|
|
44
46
|
render(
|
|
45
47
|
<ThemeProvider theme={theme}>
|
|
46
|
-
<Link href="#!"
|
|
47
|
-
Link
|
|
48
|
-
</Link>
|
|
48
|
+
<Link href="#!">Link</Link>
|
|
49
49
|
</ThemeProvider>
|
|
50
50
|
);
|
|
51
|
-
const link = screen.
|
|
51
|
+
const link = screen.getByText(/Link/);
|
|
52
52
|
|
|
53
53
|
expect(link instanceof HTMLAnchorElement).toBeTruthy();
|
|
54
54
|
});
|
|
55
55
|
|
|
56
|
-
test('accepts custom
|
|
56
|
+
test('accepts custom className', () => {
|
|
57
57
|
render(
|
|
58
58
|
<ThemeProvider theme={theme}>
|
|
59
|
-
<Link href="#!" className="custom-class-name"
|
|
60
|
-
|
|
59
|
+
<Link href="#!" className="custom-class-name">
|
|
60
|
+
Link
|
|
61
61
|
</Link>
|
|
62
62
|
</ThemeProvider>
|
|
63
63
|
);
|
|
64
|
-
const link = screen.
|
|
64
|
+
const link = screen.getByText(/Link/);
|
|
65
65
|
|
|
66
66
|
expect(link.className).toMatch('custom-class-name');
|
|
67
67
|
});
|
|
68
|
+
|
|
69
|
+
test('accepts other routing components', () => {
|
|
70
|
+
const RouterLink = React.forwardRef<
|
|
71
|
+
HTMLSpanElement,
|
|
72
|
+
{ to: string; children?: React.ReactNode }
|
|
73
|
+
>(() => <span>I am a Router Link!</span>);
|
|
74
|
+
|
|
75
|
+
render(
|
|
76
|
+
<ThemeProvider theme={theme}>
|
|
77
|
+
<Link as={RouterLink} to="/Home">
|
|
78
|
+
Link
|
|
79
|
+
</Link>
|
|
80
|
+
</ThemeProvider>
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
const link = screen.getByText('I am a Router Link!');
|
|
84
|
+
expect(link).toBeTruthy();
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test('a link can be disabled via aria attributes', () => {
|
|
88
|
+
render(
|
|
89
|
+
<ThemeProvider theme={theme}>
|
|
90
|
+
<Link href="#!" disabled={true}>
|
|
91
|
+
Link
|
|
92
|
+
</Link>
|
|
93
|
+
</ThemeProvider>
|
|
94
|
+
);
|
|
95
|
+
const link = screen.getByText(/Link/);
|
|
96
|
+
expect(link.getAttribute('aria-disabled')).toEqual('true');
|
|
97
|
+
});
|
package/src/Link/Link.tsx
CHANGED
|
@@ -1,17 +1,43 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
import React, { useRef } from 'react';
|
|
2
|
+
import { useLink } from '@react-aria/link';
|
|
3
|
+
import { PolymorphicComponent, PolymorphicProps } from '@marigold/types';
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
variant?: string;
|
|
7
|
-
} & ComponentProps<'a'>;
|
|
5
|
+
import { Text, TextOwnProps } from '../Text';
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
// Theme Extension
|
|
8
|
+
// ---------------
|
|
9
|
+
export interface LinkThemeExtension<Value> {
|
|
10
|
+
link?: Value;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Props
|
|
14
|
+
// ---------------
|
|
15
|
+
export type LinkOwnProps = { disabled?: boolean } & TextOwnProps;
|
|
16
|
+
export type LinkProps = PolymorphicProps<LinkOwnProps, 'a'>;
|
|
17
|
+
|
|
18
|
+
// Component
|
|
19
|
+
// ---------------
|
|
20
|
+
export const Link = (({
|
|
21
|
+
as = 'a',
|
|
22
|
+
variant = 'link',
|
|
11
23
|
children,
|
|
24
|
+
disabled,
|
|
12
25
|
...props
|
|
13
|
-
}) =>
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
26
|
+
}: LinkProps) => {
|
|
27
|
+
const ref = useRef<any>();
|
|
28
|
+
const { linkProps } = useLink(
|
|
29
|
+
{
|
|
30
|
+
// We typecast here because the element could very well be a `span`
|
|
31
|
+
...(props as PolymorphicProps<LinkOwnProps, any>),
|
|
32
|
+
elementType: typeof as === 'string' ? as : 'span',
|
|
33
|
+
isDisabled: disabled,
|
|
34
|
+
},
|
|
35
|
+
ref
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<Text {...props} {...linkProps} as={as} variant={variant} ref={ref}>
|
|
40
|
+
{children}
|
|
41
|
+
</Text>
|
|
42
|
+
);
|
|
43
|
+
}) as PolymorphicComponent<LinkOwnProps, 'a'>;
|