paris 0.4.2 → 0.4.4
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 +15 -0
- package/README.md +0 -10
- package/package.json +23 -6
- package/src/stories/Tokens.mdx +1 -1
- package/src/stories/button/Button.tsx +2 -2
- package/src/stories/checkbox/Checkbox.tsx +2 -2
- package/src/stories/drawer/Drawer.module.scss +31 -4
- package/src/stories/drawer/Drawer.tsx +13 -1
- package/src/stories/field/Field.tsx +45 -26
- package/src/stories/input/Input.module.scss +4 -3
- package/src/stories/input/Input.stories.ts +26 -0
- package/src/stories/input/Input.tsx +3 -3
- package/src/stories/text/Text.module.scss +35 -0
- package/src/stories/text/Text.stories.ts +40 -0
- package/src/stories/text/Text.tsx +22 -4
- package/src/stories/text/Typography.module.css +1 -1
- package/src/stories/textarea/TextArea.stories.ts +27 -0
- package/src/stories/textarea/TextArea.tsx +38 -67
- package/src/stories/theme/themes.ts +36 -2
- package/src/stories/theme/util.scss +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# paris
|
|
2
2
|
|
|
3
|
+
## 0.4.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- fd52101: Explicitly define each component export in `package.json` for TypeScript support without needing a tsconfig update
|
|
8
|
+
- 94c847a: feat: Add weight and fontStyle props to Text component
|
|
9
|
+
- a90ddd3: Drawer: Add overlay greyed style option
|
|
10
|
+
Field: Allow for custom label and description components to be passed as props
|
|
11
|
+
|
|
12
|
+
## 0.4.3
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- 49f9ee4: Prop typing fixes
|
|
17
|
+
|
|
3
18
|
## 0.4.2
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -76,16 +76,6 @@ export default function RootLayout({
|
|
|
76
76
|
}
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
-
Finally, map our types in your `.tsconfig.json` file (this is a temporary workaround that we'll fix soon):
|
|
80
|
-
|
|
81
|
-
```json
|
|
82
|
-
{
|
|
83
|
-
"paths": {
|
|
84
|
-
"paris/*": ["./node_modules/paris/src/stories/*"]
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
```
|
|
88
|
-
|
|
89
79
|
That's it! You can now import any component from Paris:
|
|
90
80
|
|
|
91
81
|
```tsx
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "paris",
|
|
3
3
|
"author": "Sanil Chawla <sanil@slingshot.fm> (https://sanil.co)",
|
|
4
4
|
"description": "Paris is Slingshot's React design system. It's a collection of reusable components, design tokens, and guidelines that help us build consistent, accessible, and performant user interfaces.",
|
|
5
|
-
"version": "0.4.
|
|
5
|
+
"version": "0.4.4",
|
|
6
6
|
"homepage": "https://paris.slingshot.fm",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"repository": {
|
|
@@ -29,7 +29,24 @@
|
|
|
29
29
|
"pnpm": "^8.x"
|
|
30
30
|
},
|
|
31
31
|
"exports": {
|
|
32
|
-
"./*": "./src/stories/*"
|
|
32
|
+
"./*": "./src/stories/*",
|
|
33
|
+
"./button": "./src/stories/button/index.ts",
|
|
34
|
+
"./card": "./src/stories/card/index.ts",
|
|
35
|
+
"./checkbox": "./src/stories/checkbox/index.ts",
|
|
36
|
+
"./combobox": "./src/stories/combobox/index.ts",
|
|
37
|
+
"./dialog": "./src/stories/dialog/index.ts",
|
|
38
|
+
"./drawer": "./src/stories/drawer/index.ts",
|
|
39
|
+
"./dropdown": "./src/stories/dropdown/index.ts",
|
|
40
|
+
"./field": "./src/stories/field/index.ts",
|
|
41
|
+
"./icon": "./src/stories/icon/index.ts",
|
|
42
|
+
"./input": "./src/stories/input/index.ts",
|
|
43
|
+
"./pagination": "./src/stories/pagination/index.ts",
|
|
44
|
+
"./select": "./src/stories/select/index.ts",
|
|
45
|
+
"./text": "./src/stories/text/index.ts",
|
|
46
|
+
"./textarea": "./src/stories/textarea/index.ts",
|
|
47
|
+
"./theme": "./src/stories/theme/index.ts",
|
|
48
|
+
"./tilt": "./src/stories/tilt/index.ts",
|
|
49
|
+
"./utility": "./src/stories/utility/index.ts"
|
|
33
50
|
},
|
|
34
51
|
"dependencies": {
|
|
35
52
|
"@ariakit/react": "^0.2.3",
|
|
@@ -91,19 +108,19 @@
|
|
|
91
108
|
"ts-node": "^10.9.1",
|
|
92
109
|
"tsconfig-paths-webpack-plugin": "^4.0.1",
|
|
93
110
|
"type-fest": "^3.10.0",
|
|
94
|
-
"typescript": "^5.
|
|
111
|
+
"typescript": "^5.2.2"
|
|
95
112
|
},
|
|
96
113
|
"scripts": {
|
|
97
114
|
"dev": "next dev",
|
|
98
|
-
"build": "next build",
|
|
115
|
+
"build": "pnpm generate:exports && next build",
|
|
99
116
|
"start": "next start",
|
|
100
117
|
"lint": "next lint",
|
|
101
118
|
"storybook": "storybook dev -p 6006",
|
|
102
119
|
"build:storybook": "storybook build",
|
|
103
120
|
"create:component": "node ./scripts/createComponent.js",
|
|
104
|
-
"generate:
|
|
121
|
+
"generate:exports": "node ./scripts/generateExports.js",
|
|
105
122
|
"generate:theme": "pte export ./src/stories/theme/themes.ts LightTheme -o ./public/pte.css",
|
|
106
123
|
"generate:text": "ts-node --esm ./scripts/text.ts",
|
|
107
|
-
"release": "pnpm changeset publish"
|
|
124
|
+
"release": "pnpm generate:exports && pnpm changeset publish"
|
|
108
125
|
}
|
|
109
126
|
}
|
package/src/stories/Tokens.mdx
CHANGED
|
@@ -36,7 +36,7 @@ Tokens are the smallest pieces of design language that can be used to build comp
|
|
|
36
36
|
}}
|
|
37
37
|
/>
|
|
38
38
|
<div style={{ color: pvar('colors.contentPrimary') }}>
|
|
39
|
-
<span style={{ fontWeight: pvar('typography.
|
|
39
|
+
<span style={{ fontWeight: pvar('typography.fontWeights.medium') }}>{key}</span>
|
|
40
40
|
<br />
|
|
41
41
|
<pre style={{ fontSize: '14px' }}>{pget(`colors.${key}`)}</pre>
|
|
42
42
|
</div>
|
|
@@ -65,7 +65,7 @@ export type ButtonProps = {
|
|
|
65
65
|
*
|
|
66
66
|
* This should be text. When Button shape is `circle` or `square`, the action description should still be passed here for screen readers.
|
|
67
67
|
*/
|
|
68
|
-
children:
|
|
68
|
+
children: ReactNode | ReactNode[];
|
|
69
69
|
} & Omit<AriaButtonProps, 'children' | 'disabled' | 'onClick'>;
|
|
70
70
|
|
|
71
71
|
/**
|
|
@@ -105,7 +105,7 @@ export const Button: FC<ButtonProps> = ({
|
|
|
105
105
|
)}
|
|
106
106
|
aria-disabled={disabled ?? false}
|
|
107
107
|
type={type}
|
|
108
|
-
aria-details={children}
|
|
108
|
+
aria-details={typeof children === 'string' ? children : undefined}
|
|
109
109
|
onClick={!disabled && !href ? onClick : () => {}}
|
|
110
110
|
disabled={false}
|
|
111
111
|
{...href ? {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { FC } from 'react';
|
|
1
|
+
import type { FC, ReactNode } from 'react';
|
|
2
2
|
import { useId } from 'react';
|
|
3
3
|
import * as RadixCheckbox from '@radix-ui/react-checkbox';
|
|
4
4
|
import styles from './Checkbox.module.scss';
|
|
@@ -9,7 +9,7 @@ export type CheckboxProps = {
|
|
|
9
9
|
onChange?: (checked: boolean | 'indeterminate') => void;
|
|
10
10
|
disabled?: boolean;
|
|
11
11
|
/** The contents of the Checkbox. */
|
|
12
|
-
children?:
|
|
12
|
+
children?: ReactNode | ReactNode[];
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -26,12 +26,20 @@ $panelAnimationDelay: var(--pte-animations-duration-fast);
|
|
|
26
26
|
.overlay {
|
|
27
27
|
position: absolute;
|
|
28
28
|
inset: 0;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
|
|
30
|
+
&.overlayBlured {
|
|
31
|
+
backdrop-filter: blur(0);
|
|
32
|
+
background-color: var(--pte-colors-backgroundOverlayDark);
|
|
33
|
+
will-change: backdrop-filter, opacity;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
&.overlayGreyed {
|
|
37
|
+
background-color: rgba(175, 175, 175, 0); // Non-transparent backgroundOverlayGrey
|
|
38
|
+
will-change: background-color, opacity;
|
|
39
|
+
}
|
|
32
40
|
}
|
|
33
41
|
|
|
34
|
-
.
|
|
42
|
+
.overlayBluredContainer {
|
|
35
43
|
.enterFrom {
|
|
36
44
|
backdrop-filter: blur(0);
|
|
37
45
|
}
|
|
@@ -49,6 +57,25 @@ $panelAnimationDelay: var(--pte-animations-duration-fast);
|
|
|
49
57
|
}
|
|
50
58
|
}
|
|
51
59
|
|
|
60
|
+
.overlayGreyedContainer {
|
|
61
|
+
.enterFrom {
|
|
62
|
+
background-color: rgba(175, 175, 175, 0);
|
|
63
|
+
}
|
|
64
|
+
.enterTo {
|
|
65
|
+
background-color: var(--pte-colors-backgroundOverlayGrey);
|
|
66
|
+
}
|
|
67
|
+
.leave {
|
|
68
|
+
transition-delay: $panelAnimationDelay;
|
|
69
|
+
}
|
|
70
|
+
.leaveFrom {
|
|
71
|
+
background-color: var(--pte-colors-backgroundOverlayGrey);
|
|
72
|
+
}
|
|
73
|
+
.leaveTo {
|
|
74
|
+
background-color: rgba(175, 175, 175, 0);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
}
|
|
78
|
+
|
|
52
79
|
.panelContainer {
|
|
53
80
|
position: fixed;
|
|
54
81
|
|
|
@@ -91,6 +91,12 @@ export type DrawerProps<T extends string[] | readonly string[] = string[]> = {
|
|
|
91
91
|
* @default false
|
|
92
92
|
*/
|
|
93
93
|
pagination?: PaginationState<T>;
|
|
94
|
+
/**
|
|
95
|
+
* The overlay style of the Drawer, either 'greyed' or 'blur'.
|
|
96
|
+
*
|
|
97
|
+
* @default 'blur'
|
|
98
|
+
*/
|
|
99
|
+
overlayStyle?: 'greyed' | 'blur';
|
|
94
100
|
/** The contents of the Drawer. */
|
|
95
101
|
children?: ReactNode | ReactNode[];
|
|
96
102
|
};
|
|
@@ -116,6 +122,7 @@ export const Drawer = <T extends string[] | readonly string[] = string[]>({
|
|
|
116
122
|
from = 'right',
|
|
117
123
|
size = 'default',
|
|
118
124
|
pagination,
|
|
125
|
+
overlayStyle = 'blur',
|
|
119
126
|
children,
|
|
120
127
|
}: DrawerProps<T>) => {
|
|
121
128
|
// Check if the drawer is on the x-axis.
|
|
@@ -164,7 +171,10 @@ export const Drawer = <T extends string[] | readonly string[] = string[]>({
|
|
|
164
171
|
onClose={onClose}
|
|
165
172
|
>
|
|
166
173
|
<div
|
|
167
|
-
className={
|
|
174
|
+
className={clsx(
|
|
175
|
+
overlayStyle === 'blur' && styles.overlayBluredContainer,
|
|
176
|
+
overlayStyle === 'greyed' && styles.overlayGreyedContainer,
|
|
177
|
+
)}
|
|
168
178
|
>
|
|
169
179
|
<Transition.Child
|
|
170
180
|
as={Fragment}
|
|
@@ -178,6 +188,8 @@ export const Drawer = <T extends string[] | readonly string[] = string[]>({
|
|
|
178
188
|
<Dialog.Overlay
|
|
179
189
|
className={clsx(
|
|
180
190
|
styles.overlay,
|
|
191
|
+
overlayStyle === 'blur' && styles.overlayBlured,
|
|
192
|
+
overlayStyle === 'greyed' && styles.overlayGreyed,
|
|
181
193
|
)}
|
|
182
194
|
/>
|
|
183
195
|
</Transition.Child>
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
type FC, type PropsWithChildren, type ComponentPropsWithoutRef, cloneElement,
|
|
3
|
+
} from 'react';
|
|
2
4
|
import clsx from 'clsx';
|
|
5
|
+
import React from 'react';
|
|
3
6
|
import styles from '../input/Input.module.scss';
|
|
4
7
|
import type { TextProps } from '../text';
|
|
5
8
|
import { Text } from '../text';
|
|
@@ -12,7 +15,7 @@ export type FieldProps = {
|
|
|
12
15
|
/**
|
|
13
16
|
* A label for the field. Can be visually hidden using the `hideLabel` prop.
|
|
14
17
|
*/
|
|
15
|
-
label?:
|
|
18
|
+
label?: React.ReactNode;
|
|
16
19
|
/**
|
|
17
20
|
* Visually hide the label (while keeping it accessible to screen readers).
|
|
18
21
|
* @default false
|
|
@@ -21,7 +24,7 @@ export type FieldProps = {
|
|
|
21
24
|
/**
|
|
22
25
|
* A description of the field. Can be visually hidden using the `hideDescription` prop.
|
|
23
26
|
*/
|
|
24
|
-
description?:
|
|
27
|
+
description?: React.ReactNode;
|
|
25
28
|
/**
|
|
26
29
|
* Visually hide the description while keeping it accessible to screen readers.
|
|
27
30
|
* @default false
|
|
@@ -76,31 +79,47 @@ export const Field: FC<PropsWithChildren<FieldProps>> = ({
|
|
|
76
79
|
}
|
|
77
80
|
}}
|
|
78
81
|
>
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
82
|
+
{typeof props.label === 'string'
|
|
83
|
+
? (
|
|
84
|
+
<Text
|
|
85
|
+
{...props.overrides?.label}
|
|
86
|
+
as="label"
|
|
87
|
+
kind="paragraphSmall"
|
|
88
|
+
htmlFor={htmlFor}
|
|
89
|
+
className={clsx(
|
|
90
|
+
styles.label,
|
|
91
|
+
{ [styles.hidden]: props.hideLabel },
|
|
92
|
+
)}
|
|
93
|
+
>
|
|
94
|
+
{props.label}
|
|
95
|
+
</Text>
|
|
96
|
+
)
|
|
97
|
+
: (
|
|
98
|
+
<label htmlFor={htmlFor}>
|
|
99
|
+
{props.label}
|
|
100
|
+
</label>
|
|
87
101
|
)}
|
|
88
|
-
>
|
|
89
|
-
{props.label}
|
|
90
|
-
</Text>
|
|
91
102
|
{children}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
103
|
+
{typeof props.description === 'string'
|
|
104
|
+
? (
|
|
105
|
+
<Text
|
|
106
|
+
id={`${htmlFor}-description`}
|
|
107
|
+
{...props.overrides?.description}
|
|
108
|
+
as="p"
|
|
109
|
+
kind="paragraphXSmall"
|
|
110
|
+
className={clsx(
|
|
111
|
+
styles.description,
|
|
112
|
+
{ [styles.hidden]: !props.description || props.hideDescription },
|
|
113
|
+
props.overrides?.description?.className,
|
|
114
|
+
)}
|
|
115
|
+
>
|
|
116
|
+
{props.description}
|
|
117
|
+
</Text>
|
|
118
|
+
)
|
|
119
|
+
: (
|
|
120
|
+
<div id={`${htmlFor}-description`}>
|
|
121
|
+
{props.description}
|
|
122
|
+
</div>
|
|
101
123
|
)}
|
|
102
|
-
>
|
|
103
|
-
{props.description}
|
|
104
|
-
</Text>
|
|
105
124
|
</div>
|
|
106
125
|
);
|
|
@@ -63,7 +63,8 @@
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
& input,
|
|
66
|
+
& input,
|
|
67
|
+
& textarea {
|
|
67
68
|
width: 100%;
|
|
68
69
|
background-color: transparent;
|
|
69
70
|
padding: 0;
|
|
@@ -122,7 +123,7 @@
|
|
|
122
123
|
// Use double selector to ensure specificity is higher than the default styles
|
|
123
124
|
.label.label {
|
|
124
125
|
color: var(--pte-colors-contentPrimary);
|
|
125
|
-
font-weight: var(--pte-typography-
|
|
126
|
+
font-weight: var(--pte-typography-fontWeights-medium);
|
|
126
127
|
}
|
|
127
128
|
|
|
128
129
|
// Use double selector to ensure specificity is higher than the default styles
|
|
@@ -132,4 +133,4 @@
|
|
|
132
133
|
|
|
133
134
|
.hidden {
|
|
134
135
|
display: none;
|
|
135
|
-
}
|
|
136
|
+
}
|
|
@@ -87,3 +87,29 @@ export const WithEndEnhancer: Story = {
|
|
|
87
87
|
}),
|
|
88
88
|
},
|
|
89
89
|
};
|
|
90
|
+
|
|
91
|
+
export const WithCustomLabel: Story = {
|
|
92
|
+
args: {
|
|
93
|
+
placeholder: 'Billie Eilish',
|
|
94
|
+
label: createElement(
|
|
95
|
+
'span',
|
|
96
|
+
null,
|
|
97
|
+
[
|
|
98
|
+
createElement('b', null, 'Name'),
|
|
99
|
+
createElement('i', null, ' (optional)'),
|
|
100
|
+
],
|
|
101
|
+
),
|
|
102
|
+
'aria-label': 'Name (optional)',
|
|
103
|
+
description: createElement(
|
|
104
|
+
'span',
|
|
105
|
+
null,
|
|
106
|
+
[
|
|
107
|
+
createElement('b', {
|
|
108
|
+
style: {
|
|
109
|
+
color: 'red',
|
|
110
|
+
},
|
|
111
|
+
}, 'My custom description'),
|
|
112
|
+
],
|
|
113
|
+
),
|
|
114
|
+
},
|
|
115
|
+
};
|
|
@@ -14,9 +14,9 @@ import { Field } from '../field';
|
|
|
14
14
|
|
|
15
15
|
export type InputProps = {
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
17
|
+
* This is required for accessibility. If the label is not a string, you should provide an `aria-label` prop directly to specify the text used for accessibility
|
|
18
18
|
*/
|
|
19
|
-
label:
|
|
19
|
+
label: React.ReactNode;
|
|
20
20
|
/**
|
|
21
21
|
* The status of the input field.
|
|
22
22
|
* @default default
|
|
@@ -112,7 +112,7 @@ export const Input: FC<InputProps & ComponentPropsWithoutRef<'input'>> = ({
|
|
|
112
112
|
{...props}
|
|
113
113
|
id={inputID}
|
|
114
114
|
type={type || 'text'}
|
|
115
|
-
aria-label={label}
|
|
115
|
+
aria-label={typeof label === 'string' ? label : props['aria-label']}
|
|
116
116
|
aria-describedby={`${inputID}-description`}
|
|
117
117
|
aria-disabled={disabled}
|
|
118
118
|
readOnly={disabled}
|
|
@@ -1,3 +1,38 @@
|
|
|
1
1
|
.text {
|
|
2
2
|
font-family: var(--pte-typography-fontFamily);
|
|
3
3
|
}
|
|
4
|
+
|
|
5
|
+
/* Font weight theme values */
|
|
6
|
+
$text-weights: (
|
|
7
|
+
"thin": var(--pte-typography-fontWeights-thin),
|
|
8
|
+
"extraLight": var(--pte-typography-fontWeights-extraLight),
|
|
9
|
+
"light": var(--pte-typography-fontWeights-light),
|
|
10
|
+
"normal": var(--pte-typography-fontWeights-normal),
|
|
11
|
+
"medium": var(--pte-typography-fontWeights-medium),
|
|
12
|
+
"semiBold": var(--pte-typography-fontWeights-semiBold),
|
|
13
|
+
"bold": var(--pte-typography-fontWeights-bold),
|
|
14
|
+
"extraBold": var(--pte-typography-fontWeights-extraBold),
|
|
15
|
+
"black": var(--pte-typography-fontWeights-black),
|
|
16
|
+
"extraBlack": var(--pte-typography-fontWeights-extraBlack),
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@each $weight-name,
|
|
21
|
+
$weight-value in $text-weights {
|
|
22
|
+
.weight-#{$weight-name} {
|
|
23
|
+
font-weight: $weight-value;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* Font style theme values */
|
|
28
|
+
$font-styles: (
|
|
29
|
+
"normal": var(--pte-typography-fontStyles-normal),
|
|
30
|
+
"italic": var(--pte-typography-fontStyles-italic),
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
@each $style-name,
|
|
34
|
+
$style-value in $font-styles {
|
|
35
|
+
.fontStyle-#{$style-name} {
|
|
36
|
+
font-style: $style-value;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -152,4 +152,44 @@ export const ParagraphXXSmall: Story = {
|
|
|
152
152
|
},
|
|
153
153
|
};
|
|
154
154
|
|
|
155
|
+
export const ParagraphLargeBold: Story = {
|
|
156
|
+
args: {
|
|
157
|
+
children: 'In an alleyway, drinking champagne',
|
|
158
|
+
kind: 'paragraphLarge',
|
|
159
|
+
weight: 'medium',
|
|
160
|
+
},
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
export const ParagraphMediumBold: Story = {
|
|
164
|
+
args: {
|
|
165
|
+
children: 'In an alleyway, drinking champagne',
|
|
166
|
+
kind: 'paragraphMedium',
|
|
167
|
+
weight: 'medium',
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
export const ParagraphSmallBold: Story = {
|
|
172
|
+
args: {
|
|
173
|
+
children: 'In an alleyway, drinking champagne',
|
|
174
|
+
kind: 'paragraphSmall',
|
|
175
|
+
weight: 'medium',
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
export const ParagraphXSmallBold: Story = {
|
|
180
|
+
args: {
|
|
181
|
+
children: 'In an alleyway, drinking champagne',
|
|
182
|
+
kind: 'paragraphXSmall',
|
|
183
|
+
weight: 'medium',
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
export const ParagraphLargeItalic: Story = {
|
|
188
|
+
args: {
|
|
189
|
+
children: 'In an alleyway, drinking champagne',
|
|
190
|
+
kind: 'paragraphLarge',
|
|
191
|
+
fontStyle: 'italic',
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
|
|
155
195
|
// @auto-generated-end
|
|
@@ -1,22 +1,36 @@
|
|
|
1
1
|
import type { ComponentProps, FC, ReactNode } from 'react';
|
|
2
2
|
import { createElement } from 'react';
|
|
3
3
|
import clsx from 'clsx';
|
|
4
|
-
import styles from './Text.module.scss';
|
|
5
4
|
import typography from './Typography.module.css';
|
|
6
|
-
import
|
|
5
|
+
import styles from './Text.module.scss';
|
|
6
|
+
import type { LightTheme, Theme } from '../theme';
|
|
7
7
|
|
|
8
8
|
export type TextElement = 'p' | 'span' | 'div' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'label' | 'legend' | 'caption' | 'small';
|
|
9
|
+
export type GlobalCSSValues = 'inherit' | 'initial' | 'revert' | 'revert-layer' | 'unset';
|
|
10
|
+
|
|
9
11
|
export type TextProps<T extends TextElement = 'span'> = {
|
|
10
12
|
/**
|
|
11
13
|
* The font class to use.
|
|
12
14
|
* @default paragraphMedium
|
|
13
15
|
*/
|
|
14
16
|
kind?: keyof typeof LightTheme.typography.styles;
|
|
17
|
+
|
|
15
18
|
/**
|
|
16
19
|
* The HTML text tag to use.
|
|
17
20
|
* @default span
|
|
18
21
|
*/
|
|
19
22
|
as?: T;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The font weight to apply.
|
|
26
|
+
*/
|
|
27
|
+
weight?: keyof typeof LightTheme.typography.fontWeights;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The font style to apply.
|
|
31
|
+
*/
|
|
32
|
+
fontStyle?: keyof typeof LightTheme.typography.fontStyles;
|
|
33
|
+
|
|
20
34
|
/** The contents of the Text element. */
|
|
21
35
|
children: ReactNode;
|
|
22
36
|
} & ComponentProps<T>;
|
|
@@ -32,18 +46,20 @@ export type TextProps<T extends TextElement = 'span'> = {
|
|
|
32
46
|
* import { Text } from 'paris/text';
|
|
33
47
|
*
|
|
34
48
|
* export const ExampleHeading: FC = () => (
|
|
35
|
-
* <Text as="h1"
|
|
49
|
+
* <Text as="h1" kind="headingLarge" weight="bold" fontStyle="italic">Hello World!</Text>
|
|
36
50
|
* );
|
|
37
51
|
* ```
|
|
38
52
|
*
|
|
39
53
|
* @example ```tsx
|
|
40
|
-
* <Text as="h1"
|
|
54
|
+
* <Text as="h1" kind="headingLarge">Hello World!</Text>
|
|
41
55
|
* ```
|
|
42
56
|
* @constructor
|
|
43
57
|
*/
|
|
44
58
|
export function Text<T extends TextElement>({
|
|
45
59
|
kind,
|
|
46
60
|
as,
|
|
61
|
+
weight,
|
|
62
|
+
fontStyle,
|
|
47
63
|
children,
|
|
48
64
|
...props
|
|
49
65
|
}: TextProps<T>): JSX.Element {
|
|
@@ -54,6 +70,8 @@ export function Text<T extends TextElement>({
|
|
|
54
70
|
className: clsx(
|
|
55
71
|
styles.text,
|
|
56
72
|
typography[kind || 'paragraphMedium'],
|
|
73
|
+
weight && styles[`weight-${weight}`],
|
|
74
|
+
fontStyle && styles[`fontStyle-${fontStyle}`],
|
|
57
75
|
props?.className,
|
|
58
76
|
),
|
|
59
77
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* Auto-generated with `pnpm generate:text` on
|
|
1
|
+
/* Auto-generated with `pnpm generate:text` on Wed Jun 21 2023 15:22:53 GMT-0700 (Pacific Daylight Time) */
|
|
2
2
|
/* Do not edit manually; instead, edit the `generateTextClasses` function in `scripts/text.ts` and run `pnpm generate:text -c`. */
|
|
3
3
|
|
|
4
4
|
.displayLarge {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { createElement } from 'react';
|
|
2
3
|
import { TextArea } from './TextArea';
|
|
3
4
|
|
|
4
5
|
const meta: Meta<typeof TextArea> = {
|
|
@@ -17,3 +18,29 @@ export const Default: Story = {
|
|
|
17
18
|
description: 'Type your full name here.',
|
|
18
19
|
},
|
|
19
20
|
};
|
|
21
|
+
|
|
22
|
+
export const WithCustomLabel: Story = {
|
|
23
|
+
args: {
|
|
24
|
+
placeholder: 'Billie Eilish',
|
|
25
|
+
label: createElement(
|
|
26
|
+
'span',
|
|
27
|
+
{},
|
|
28
|
+
[
|
|
29
|
+
createElement('b', null, 'Name'),
|
|
30
|
+
createElement('i', null, ' (optional)'),
|
|
31
|
+
],
|
|
32
|
+
),
|
|
33
|
+
'aria-label': 'Name (optional)',
|
|
34
|
+
description: createElement(
|
|
35
|
+
'span',
|
|
36
|
+
null,
|
|
37
|
+
[
|
|
38
|
+
createElement('b', {
|
|
39
|
+
style: {
|
|
40
|
+
color: 'red',
|
|
41
|
+
},
|
|
42
|
+
}, 'My custom description'),
|
|
43
|
+
],
|
|
44
|
+
),
|
|
45
|
+
},
|
|
46
|
+
};
|
|
@@ -6,6 +6,7 @@ import styles from '../input/Input.module.scss';
|
|
|
6
6
|
import { Text } from '../text';
|
|
7
7
|
import { MemoizedEnhancer } from '../../helpers/renderEnhancer';
|
|
8
8
|
import { pget, theme } from '../theme';
|
|
9
|
+
import { Field } from '../field';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* A `textarea` input field.
|
|
@@ -19,50 +20,44 @@ import { pget, theme } from '../theme';
|
|
|
19
20
|
* ```
|
|
20
21
|
* @constructor
|
|
21
22
|
*/
|
|
22
|
-
export const TextArea: FC<InputProps & ComponentPropsWithoutRef<'textarea'>> = ({
|
|
23
|
-
|
|
23
|
+
export const TextArea: FC<InputProps & ComponentPropsWithoutRef<'textarea'>> = ({
|
|
24
|
+
label,
|
|
25
|
+
status,
|
|
26
|
+
type,
|
|
27
|
+
hideLabel,
|
|
28
|
+
description,
|
|
29
|
+
hideDescription,
|
|
30
|
+
startEnhancer,
|
|
31
|
+
endEnhancer,
|
|
32
|
+
disabled,
|
|
33
|
+
overrides,
|
|
34
|
+
...props
|
|
35
|
+
}) => {
|
|
36
|
+
const textareaID = useId();
|
|
24
37
|
return (
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
{
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
if (typeof window !== 'undefined') {
|
|
37
|
-
const input = document.getElementById(inputID);
|
|
38
|
-
if (input && !disabled) {
|
|
39
|
-
input.focus();
|
|
40
|
-
}
|
|
41
|
-
}
|
|
38
|
+
<Field
|
|
39
|
+
htmlFor={textareaID}
|
|
40
|
+
label={label}
|
|
41
|
+
hideLabel={hideLabel}
|
|
42
|
+
description={description}
|
|
43
|
+
hideDescription={hideDescription}
|
|
44
|
+
disabled={disabled}
|
|
45
|
+
overrides={{
|
|
46
|
+
container: overrides?.container,
|
|
47
|
+
label: overrides?.label,
|
|
48
|
+
description: overrides?.description,
|
|
42
49
|
}}
|
|
43
50
|
>
|
|
44
|
-
<Text
|
|
45
|
-
{...props.overrides?.label}
|
|
46
|
-
as="label"
|
|
47
|
-
kind="paragraphSmall"
|
|
48
|
-
htmlFor={inputID}
|
|
49
|
-
className={clsx(
|
|
50
|
-
styles.label,
|
|
51
|
-
{ [styles.hidden]: props.hideLabel },
|
|
52
|
-
)}
|
|
53
|
-
>
|
|
54
|
-
{props.label}
|
|
55
|
-
</Text>
|
|
56
51
|
<div
|
|
57
52
|
className={styles.inputContainer}
|
|
58
53
|
data-status={status}
|
|
59
54
|
data-disabled={disabled}
|
|
60
55
|
>
|
|
61
|
-
{!!
|
|
62
|
-
<div {...
|
|
63
|
-
{!!
|
|
56
|
+
{!!startEnhancer && (
|
|
57
|
+
<div {...overrides?.startEnhancerContainer} className={clsx(styles.enhancer, overrides?.startEnhancerContainer?.className)}>
|
|
58
|
+
{!!startEnhancer && (
|
|
64
59
|
<MemoizedEnhancer
|
|
65
|
-
enhancer={
|
|
60
|
+
enhancer={startEnhancer}
|
|
66
61
|
size={parseInt(pget('typography.styles.paragraphSmall.fontSize') || theme.typography.styles.paragraphSmall.fontSize, 10)}
|
|
67
62
|
/>
|
|
68
63
|
)}
|
|
@@ -70,9 +65,9 @@ export const TextArea: FC<InputProps & ComponentPropsWithoutRef<'textarea'>> = (
|
|
|
70
65
|
)}
|
|
71
66
|
<textarea
|
|
72
67
|
{...props}
|
|
73
|
-
id={
|
|
74
|
-
aria-label={props
|
|
75
|
-
aria-describedby={`${
|
|
68
|
+
id={textareaID}
|
|
69
|
+
aria-label={typeof label === 'string' ? label : props['aria-label']}
|
|
70
|
+
aria-describedby={`${textareaID}-description`}
|
|
76
71
|
aria-disabled={disabled}
|
|
77
72
|
readOnly={disabled}
|
|
78
73
|
className={clsx(
|
|
@@ -80,41 +75,17 @@ export const TextArea: FC<InputProps & ComponentPropsWithoutRef<'textarea'>> = (
|
|
|
80
75
|
styles.input,
|
|
81
76
|
)}
|
|
82
77
|
/>
|
|
83
|
-
{!!
|
|
84
|
-
<div {...
|
|
85
|
-
{!!
|
|
78
|
+
{!!endEnhancer && (
|
|
79
|
+
<div {...overrides?.endEnhancerContainer} className={clsx(styles.enhancer, overrides?.endEnhancerContainer?.className)}>
|
|
80
|
+
{!!endEnhancer && (
|
|
86
81
|
<MemoizedEnhancer
|
|
87
|
-
enhancer={
|
|
82
|
+
enhancer={endEnhancer}
|
|
88
83
|
size={parseInt(pget('typography.styles.paragraphSmall.fontSize') || theme.typography.styles.paragraphSmall.fontSize, 10)}
|
|
89
84
|
/>
|
|
90
85
|
)}
|
|
91
86
|
</div>
|
|
92
87
|
)}
|
|
93
88
|
</div>
|
|
94
|
-
|
|
95
|
-
id={`${inputID}-description`}
|
|
96
|
-
{...props.overrides?.description}
|
|
97
|
-
as="p"
|
|
98
|
-
kind="paragraphXSmall"
|
|
99
|
-
className={clsx(
|
|
100
|
-
styles.description,
|
|
101
|
-
{ [styles.hidden]: !props.description || props.hideDescription },
|
|
102
|
-
props.overrides?.description?.className,
|
|
103
|
-
)}
|
|
104
|
-
>
|
|
105
|
-
{props.description}
|
|
106
|
-
</Text>
|
|
107
|
-
</div>
|
|
89
|
+
</Field>
|
|
108
90
|
);
|
|
109
|
-
// return (
|
|
110
|
-
// <div
|
|
111
|
-
// className={clsx(
|
|
112
|
-
// styles.inputContainer,
|
|
113
|
-
// )}
|
|
114
|
-
// >
|
|
115
|
-
// <textarea
|
|
116
|
-
// {...props}
|
|
117
|
-
// />
|
|
118
|
-
// </div>
|
|
119
|
-
// );
|
|
120
91
|
};
|
|
@@ -119,10 +119,27 @@ export type Theme = {
|
|
|
119
119
|
},
|
|
120
120
|
typography: {
|
|
121
121
|
fontFamily: string,
|
|
122
|
-
boldFontWeight: number,
|
|
123
122
|
italicLetterSpacing: CSSLength,
|
|
124
123
|
verticalMetricsAdjust: CSSLength;
|
|
125
124
|
|
|
125
|
+
fontWeights: {
|
|
126
|
+
thin: number,
|
|
127
|
+
extraLight: number,
|
|
128
|
+
light: number,
|
|
129
|
+
normal: number,
|
|
130
|
+
medium: number,
|
|
131
|
+
semiBold: number,
|
|
132
|
+
bold: number,
|
|
133
|
+
extraBold: number,
|
|
134
|
+
black: number,
|
|
135
|
+
extraBlack: number,
|
|
136
|
+
},
|
|
137
|
+
|
|
138
|
+
fontStyles: {
|
|
139
|
+
normal: string,
|
|
140
|
+
italic: string,
|
|
141
|
+
}
|
|
142
|
+
|
|
126
143
|
styles: {
|
|
127
144
|
// Display
|
|
128
145
|
|
|
@@ -321,10 +338,27 @@ export const LightTheme: Theme = {
|
|
|
321
338
|
},
|
|
322
339
|
typography: {
|
|
323
340
|
fontFamily: '"Graphik Web", -apple-system, BlinkMacSystemFont, Helvetica, Arial, sans-serif',
|
|
324
|
-
boldFontWeight: 500,
|
|
325
341
|
italicLetterSpacing: '-0.01em',
|
|
326
342
|
verticalMetricsAdjust: '1px',
|
|
327
343
|
|
|
344
|
+
fontWeights: {
|
|
345
|
+
thin: 100,
|
|
346
|
+
extraLight: 200,
|
|
347
|
+
light: 300,
|
|
348
|
+
normal: 400,
|
|
349
|
+
medium: 500,
|
|
350
|
+
semiBold: 600,
|
|
351
|
+
bold: 700,
|
|
352
|
+
extraBold: 800,
|
|
353
|
+
black: 900,
|
|
354
|
+
extraBlack: 950,
|
|
355
|
+
},
|
|
356
|
+
|
|
357
|
+
fontStyles: {
|
|
358
|
+
italic: 'italic',
|
|
359
|
+
normal: 'normal',
|
|
360
|
+
},
|
|
361
|
+
|
|
328
362
|
styles: {
|
|
329
363
|
// Display
|
|
330
364
|
|