paris 0.2.2 → 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.
Files changed (72) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +61 -5
  3. package/package.json +27 -15
  4. package/src/helpers/renderEnhancer.tsx +21 -0
  5. package/src/pages/_app.tsx +1 -1
  6. package/src/pages/index.tsx +1 -1
  7. package/src/stories/Pagination.mdx +73 -0
  8. package/src/stories/Tokens.mdx +0 -8
  9. package/src/stories/button/Button.module.scss +23 -7
  10. package/src/stories/button/Button.stories.ts +17 -0
  11. package/src/stories/button/Button.tsx +80 -20
  12. package/src/stories/card/Card.module.scss +14 -0
  13. package/src/stories/card/Card.stories.ts +33 -0
  14. package/src/stories/card/Card.tsx +60 -0
  15. package/src/stories/card/index.ts +1 -0
  16. package/src/stories/checkbox/Checkbox.module.scss +57 -0
  17. package/src/stories/checkbox/Checkbox.stories.ts +27 -0
  18. package/src/stories/checkbox/Checkbox.tsx +58 -0
  19. package/src/stories/checkbox/index.ts +1 -0
  20. package/src/stories/combobox/Combobox.module.scss +5 -0
  21. package/src/stories/combobox/Combobox.stories.ts +84 -0
  22. package/src/stories/combobox/Combobox.tsx +264 -0
  23. package/src/stories/combobox/index.ts +1 -0
  24. package/src/stories/dialog/Dialog.module.scss +187 -0
  25. package/src/stories/dialog/Dialog.stories.tsx +70 -0
  26. package/src/stories/dialog/Dialog.tsx +279 -0
  27. package/src/stories/dialog/index.ts +1 -0
  28. package/src/stories/drawer/Drawer.module.scss +284 -0
  29. package/src/stories/drawer/Drawer.stories.tsx +94 -0
  30. package/src/stories/drawer/Drawer.tsx +339 -0
  31. package/src/stories/drawer/index.ts +1 -0
  32. package/src/stories/dropdown/Dropdown.module.scss +23 -0
  33. package/src/stories/field/Field.module.scss +5 -0
  34. package/src/stories/field/Field.stories.ts +32 -0
  35. package/src/stories/field/Field.tsx +106 -0
  36. package/src/stories/field/index.ts +1 -0
  37. package/src/stories/icon/ChevronLeft.tsx +11 -0
  38. package/src/stories/icon/ChevronRight.tsx +11 -0
  39. package/src/stories/icon/Close.tsx +11 -0
  40. package/src/stories/icon/Icon.module.scss +5 -0
  41. package/src/stories/icon/Icon.stories.ts +28 -0
  42. package/src/stories/icon/Icon.tsx +46 -0
  43. package/src/stories/icon/index.ts +4 -0
  44. package/src/stories/input/Input.module.scss +135 -0
  45. package/src/stories/input/Input.stories.ts +89 -0
  46. package/src/stories/input/Input.tsx +137 -0
  47. package/src/stories/input/index.ts +1 -0
  48. package/src/stories/pagination/index.ts +1 -0
  49. package/src/stories/pagination/usePagination.ts +106 -0
  50. package/src/stories/select/Select.module.scss +74 -0
  51. package/src/stories/select/Select.stories.ts +73 -0
  52. package/src/stories/select/Select.tsx +176 -0
  53. package/src/stories/select/index.ts +1 -0
  54. package/src/stories/text/Text.module.scss +1 -1
  55. package/src/stories/text/Text.tsx +36 -14
  56. package/src/stories/textarea/TextArea.stories.ts +19 -0
  57. package/src/stories/textarea/TextArea.tsx +120 -0
  58. package/src/stories/textarea/index.ts +1 -0
  59. package/src/stories/theme/global.scss +2 -0
  60. package/src/stories/theme/index.ts +1 -0
  61. package/src/stories/theme/themes.ts +126 -7
  62. package/src/{styles → stories/theme}/tw-preflight.css +3 -1
  63. package/src/stories/theme/util.scss +8 -0
  64. package/src/stories/tilt/Tilt.module.scss +1 -0
  65. package/src/stories/tilt/Tilt.stories.tsx +43 -0
  66. package/src/stories/tilt/Tilt.tsx +63 -0
  67. package/src/stories/tilt/index.ts +1 -0
  68. package/src/stories/utility/RemoveFromDOM.tsx +19 -0
  69. package/src/stories/utility/TextWhenString.tsx +28 -0
  70. package/src/stories/utility/VisuallyHidden.tsx +25 -0
  71. package/src/types/Enhancer.ts +3 -0
  72. package/src/styles/util.scss +0 -4
@@ -0,0 +1,176 @@
1
+ 'use client';
2
+
3
+ import type { ReactNode, ComponentPropsWithoutRef } from 'react';
4
+ import { Listbox, Transition } from '@headlessui/react';
5
+ import clsx from 'clsx';
6
+ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
7
+ import { faChevronDown } from '@fortawesome/free-solid-svg-icons';
8
+ import { useId } from 'react';
9
+ import inputStyles from '../input/Input.module.scss';
10
+ import dropdownStyles from '../dropdown/Dropdown.module.scss';
11
+ import styles from './Select.module.scss';
12
+ import type { TextProps } from '../text';
13
+ import { Text } from '../text';
14
+ import type { InputProps } from '../input';
15
+ import { MemoizedEnhancer } from '../../helpers/renderEnhancer';
16
+ import { pget, theme } from '../theme';
17
+ import { Field } from '../field';
18
+
19
+ export type Option<T = Record<string, any>> = {
20
+ id: string,
21
+ node: ReactNode,
22
+ metadata?: T,
23
+ };
24
+ export type SelectProps<T = Record<string, any>> = {
25
+ /**
26
+ * The {@link Option}s to render in the select box.
27
+ *
28
+ * Each option should have an id (`string`) and node ({@link ReactNode}) property at minimum. You can also pass in any other metadata through the `metadata` attribute.
29
+ *
30
+ * For type safety, you can pass in a type parameter to `SelectProps` component. This will be used as the type for the `metadata` property of each option.
31
+ */
32
+ options: Option<T>[];
33
+ /**
34
+ * The option ID to render as selected in the select box.
35
+ *
36
+ * This should exactly match one of the option IDs passed in the `options` prop. If `null`, no option will be selected.
37
+ */
38
+ value?: string | null;
39
+ /**
40
+ * The interaction handler for the Select.
41
+ */
42
+ onChange?: (value: string | null) => void | Promise<void>;
43
+ /**
44
+ * Prop overrides for other rendered elements. Overrides for the input itself should be passed directly to the component.
45
+ */
46
+ overrides?: {
47
+ container?: ComponentPropsWithoutRef<'div'>;
48
+ selectInput?: ComponentPropsWithoutRef<'button'>;
49
+ optionsContainer?: ComponentPropsWithoutRef<'div'>;
50
+ option?: ComponentPropsWithoutRef<'div'>;
51
+ label?: TextProps<'label'>;
52
+ description?: TextProps<'p'>;
53
+ startEnhancerContainer?: ComponentPropsWithoutRef<'div'>;
54
+ endEnhancerContainer?: ComponentPropsWithoutRef<'div'>;
55
+ }
56
+ } & Omit<InputProps, 'type' | 'overrides'>;
57
+
58
+ /**
59
+ * A Select component is used to render a `select` box.
60
+ *
61
+ * <hr />
62
+ *
63
+ * To use this component, import it as follows:
64
+ *
65
+ * ```js
66
+ * import { Select } from 'paris/select';
67
+ * ```
68
+ * @constructor
69
+ */
70
+ export function Select<T = Record<string, any>>({
71
+ options,
72
+ value,
73
+ onChange,
74
+ label,
75
+ status,
76
+ hideLabel,
77
+ description,
78
+ hideDescription,
79
+ placeholder,
80
+ startEnhancer,
81
+ endEnhancer,
82
+ disabled,
83
+ overrides,
84
+ }: SelectProps<T>) {
85
+ const inputID = useId();
86
+ return (
87
+ <Field
88
+ htmlFor={inputID}
89
+ label={label}
90
+ hideLabel={hideLabel}
91
+ description={description}
92
+ hideDescription={hideDescription}
93
+ disabled={disabled}
94
+ overrides={{
95
+ container: overrides?.container,
96
+ label: overrides?.label,
97
+ description: overrides?.description,
98
+ }}
99
+ >
100
+ <Listbox
101
+ as="div"
102
+ value={value}
103
+ onChange={onChange}
104
+ >
105
+ <Listbox.Button
106
+ id={inputID}
107
+ {...overrides?.selectInput}
108
+ aria-disabled={disabled}
109
+ data-status={disabled ? 'disabled' : (status || 'default')}
110
+ className={clsx(
111
+ overrides?.selectInput?.className,
112
+ inputStyles.inputContainer,
113
+ styles.field,
114
+ )}
115
+ >
116
+ {!!startEnhancer && (
117
+ <div {...overrides?.startEnhancerContainer} className={clsx(inputStyles.enhancer, overrides?.startEnhancerContainer?.className)}>
118
+ {!!startEnhancer && (
119
+ <MemoizedEnhancer
120
+ enhancer={startEnhancer}
121
+ size={parseInt(pget('typography.styles.paragraphSmall.fontSize') || theme.typography.styles.paragraphSmall.fontSize, 10)}
122
+ />
123
+ )}
124
+ </div>
125
+ )}
126
+ {options?.find((o) => o.id === value)?.node || placeholder || 'Select an option'}
127
+ {endEnhancer ? (
128
+ <div {...overrides?.endEnhancerContainer} className={clsx(inputStyles.enhancer, overrides?.endEnhancerContainer?.className)}>
129
+ {!!endEnhancer && (
130
+ <MemoizedEnhancer
131
+ enhancer={endEnhancer}
132
+ size={parseInt(pget('typography.styles.paragraphSmall.fontSize') || theme.typography.styles.paragraphSmall.fontSize, 10)}
133
+ />
134
+ )}
135
+ </div>
136
+ ) : (
137
+ <FontAwesomeIcon className={inputStyles.enhancer} width="10px" icon={faChevronDown} />
138
+ )}
139
+ </Listbox.Button>
140
+ <Transition
141
+ enter={dropdownStyles.transition}
142
+ enterFrom={dropdownStyles.enterFrom}
143
+ enterTo={dropdownStyles.enterTo}
144
+ leave={dropdownStyles.transition}
145
+ leaveFrom={dropdownStyles.leaveFrom}
146
+ leaveTo={dropdownStyles.leaveTo}
147
+ >
148
+ <Listbox.Options
149
+ className={clsx(
150
+ overrides?.optionsContainer,
151
+ styles.options,
152
+ )}
153
+ >
154
+ {(options || []).map((option) => (
155
+ <Listbox.Option
156
+ key={option.id}
157
+ value={option.id}
158
+ data-selected={option.id === value}
159
+ className={clsx(
160
+ overrides?.option,
161
+ styles.option,
162
+ )}
163
+ >
164
+ {typeof option.node === 'string' ? (
165
+ <Text as="span" kind="paragraphSmall">
166
+ {option.node}
167
+ </Text>
168
+ ) : option.node}
169
+ </Listbox.Option>
170
+ ))}
171
+ </Listbox.Options>
172
+ </Transition>
173
+ </Listbox>
174
+ </Field>
175
+ );
176
+ }
@@ -0,0 +1 @@
1
+ export * from './Select';
@@ -1,3 +1,3 @@
1
1
  .text {
2
- //color: var(--pte-colors-contentPrimary);
2
+ font-family: var(--pte-typography-fontFamily);
3
3
  }
@@ -1,40 +1,62 @@
1
- import type { FC, HTMLProps, ReactNode } from 'react';
1
+ import type { ComponentProps, FC, ReactNode } from 'react';
2
2
  import { createElement } from 'react';
3
+ import clsx from 'clsx';
4
+ import styles from './Text.module.scss';
3
5
  import typography from './Typography.module.css';
4
6
  import type { LightTheme } from '../theme';
5
7
 
6
- export type TextProps = {
8
+ export type TextElement = 'p' | 'span' | 'div' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'label' | 'legend' | 'caption' | 'small';
9
+ export type TextProps<T extends TextElement = 'span'> = {
7
10
  /**
8
11
  * The font class to use.
9
12
  * @default paragraphMedium
10
13
  */
11
- kind: keyof typeof LightTheme.typography.styles;
14
+ kind?: keyof typeof LightTheme.typography.styles;
12
15
  /**
13
16
  * The HTML text tag to use.
14
17
  * @default span
15
18
  */
16
- as?: 'p' | 'span' | 'div' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'label' | 'legend' | 'caption' | 'small';
19
+ as?: T;
17
20
  /** The contents of the Text element. */
18
21
  children: ReactNode;
19
- };
22
+ } & ComponentProps<T>;
20
23
 
21
24
  /**
22
25
  * A `Text` component is used to render text with one of our theme formats.
26
+ *
27
+ * <hr />
28
+ *
29
+ * To use the `Text` component, import it as follows:
30
+ *
31
+ * ```tsx
32
+ * import { Text } from 'paris/text';
33
+ *
34
+ * export const ExampleHeading: FC = () => (
35
+ * <Text as="h1" format="headingLarge">Hello World!</Text>
36
+ * );
37
+ * ```
38
+ *
23
39
  * @example ```tsx
24
40
  * <Text as="h1" format="headingLarge">Hello World!</Text>
25
41
  * ```
26
42
  * @constructor
27
43
  */
28
- export const Text: FC<TextProps & HTMLProps<HTMLParagraphElement>> = ({
44
+ export function Text<T extends TextElement>({
29
45
  kind,
30
46
  as,
31
47
  children,
32
48
  ...props
33
- }) => createElement(
34
- as || 'span',
35
- {
36
- ...props,
37
- className: `${props.className || ''} ${typography[kind]}`,
38
- },
39
- children,
40
- );
49
+ }: TextProps<T>): JSX.Element {
50
+ return createElement(
51
+ as || 'span',
52
+ {
53
+ ...props,
54
+ className: clsx(
55
+ styles.text,
56
+ typography[kind || 'paragraphMedium'],
57
+ props?.className,
58
+ ),
59
+ },
60
+ children,
61
+ );
62
+ }
@@ -0,0 +1,19 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { TextArea } from './TextArea';
3
+
4
+ const meta: Meta<typeof TextArea> = {
5
+ title: 'Inputs/TextArea',
6
+ component: TextArea,
7
+ tags: ['autodocs'],
8
+ };
9
+
10
+ export default meta;
11
+ type Story = StoryObj<typeof TextArea>;
12
+
13
+ export const Default: Story = {
14
+ args: {
15
+ placeholder: 'Billie Eilish',
16
+ label: 'Name',
17
+ description: 'Type your full name here.',
18
+ },
19
+ };
@@ -0,0 +1,120 @@
1
+ import type { ComponentPropsWithoutRef, FC } from 'react';
2
+ import { useId } from 'react';
3
+ import clsx from 'clsx';
4
+ import type { InputProps } from '../input';
5
+ import styles from '../input/Input.module.scss';
6
+ import { Text } from '../text';
7
+ import { MemoizedEnhancer } from '../../helpers/renderEnhancer';
8
+ import { pget, theme } from '../theme';
9
+
10
+ /**
11
+ * A `textarea` input field.
12
+ *
13
+ * <hr />
14
+ *
15
+ * To use this component in your app, import it as follows:
16
+ *
17
+ * ```js
18
+ * import { TextArea } from 'paris/textarea';
19
+ * ```
20
+ * @constructor
21
+ */
22
+ export const TextArea: FC<InputProps & ComponentPropsWithoutRef<'textarea'>> = ({ status, disabled, ...props }) => {
23
+ const inputID = useId();
24
+ return (
25
+ // Disable a11y rules because the container doesn't need to be focusable for screen readers; the input itself should receive focus instead.
26
+ // The container is only made clickable for usability purposes.
27
+ // eslint-disable-next-line jsx-a11y/click-events-have-key-events,jsx-a11y/no-static-element-interactions
28
+ <div
29
+ {...props.overrides?.container}
30
+ className={clsx(
31
+ props.overrides?.container?.className,
32
+ styles.container,
33
+ )}
34
+ onClick={(e) => {
35
+ if (disabled) e.preventDefault();
36
+ if (typeof window !== 'undefined') {
37
+ const input = document.getElementById(inputID);
38
+ if (input && !disabled) {
39
+ input.focus();
40
+ }
41
+ }
42
+ }}
43
+ >
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
+ <div
57
+ className={styles.inputContainer}
58
+ data-status={status}
59
+ data-disabled={disabled}
60
+ >
61
+ {!!props.startEnhancer && (
62
+ <div {...props.overrides?.startEnhancerContainer} className={clsx(styles.enhancer, props.overrides?.startEnhancerContainer?.className)}>
63
+ {!!props.startEnhancer && (
64
+ <MemoizedEnhancer
65
+ enhancer={props.startEnhancer}
66
+ size={parseInt(pget('typography.styles.paragraphSmall.fontSize') || theme.typography.styles.paragraphSmall.fontSize, 10)}
67
+ />
68
+ )}
69
+ </div>
70
+ )}
71
+ <textarea
72
+ {...props}
73
+ id={inputID}
74
+ aria-label={props.label}
75
+ aria-describedby={`${inputID}-description`}
76
+ aria-disabled={disabled}
77
+ readOnly={disabled}
78
+ className={clsx(
79
+ props.className,
80
+ styles.input,
81
+ )}
82
+ />
83
+ {!!props.endEnhancer && (
84
+ <div {...props.overrides?.endEnhancerContainer} className={clsx(styles.enhancer, props.overrides?.endEnhancerContainer?.className)}>
85
+ {!!props.endEnhancer && (
86
+ <MemoizedEnhancer
87
+ enhancer={props.endEnhancer}
88
+ size={parseInt(pget('typography.styles.paragraphSmall.fontSize') || theme.typography.styles.paragraphSmall.fontSize, 10)}
89
+ />
90
+ )}
91
+ </div>
92
+ )}
93
+ </div>
94
+ <Text
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>
108
+ );
109
+ // return (
110
+ // <div
111
+ // className={clsx(
112
+ // styles.inputContainer,
113
+ // )}
114
+ // >
115
+ // <textarea
116
+ // {...props}
117
+ // />
118
+ // </div>
119
+ // );
120
+ };
@@ -0,0 +1 @@
1
+ export * from './TextArea';
@@ -0,0 +1,2 @@
1
+ @use 'tw-preflight.css';
2
+ @use 'util.scss';
@@ -1,2 +1,3 @@
1
1
  export * from './themes';
2
2
  export * from './tokens';
3
+ export { generateCSS } from 'pte';
@@ -2,6 +2,7 @@ import { createTheme } from 'pte';
2
2
  import type { CSSColor, CSSLength } from '@ssh/csstypes';
3
3
  import type { Property } from 'csstype';
4
4
  import type { PartialDeep } from 'type-fest';
5
+ import merge from 'ts-deepmerge';
5
6
  import { Tokens as T } from './tokens';
6
7
  import type { TokensT } from './tokens';
7
8
 
@@ -16,8 +17,36 @@ export type FontDefinition = {
16
17
 
17
18
  export type FontClassDefinition = Omit<FontDefinition, 'fontSize' | 'lineHeight'>;
18
19
 
20
+ export type ShadowDefinition = `${CSSLength} ${CSSLength} ${CSSLength} ${CSSColor}` | 'none';
21
+
22
+ const Shadows = {
23
+ shallowBelow: '0px 4px 20px rgba(0, 0, 0, 0.2)',
24
+ deepBelow: '0px 8px 20px rgba(0, 0, 0, 0.2)',
25
+ shallowAbove: '0px -4px 20px rgba(0, 0, 0, 0.2)',
26
+ deepAbove: '0px -8px 20px rgba(0, 0, 0, 0.2)',
27
+ shallowPopup: '0px 0px 30px rgba(0, 0, 0, 0.2)',
28
+ deepPopup: '0px 0px 40px rgba(0, 0, 0, 0.2)',
29
+ subtlePopup: '0px 0px 10px rgba(0, 0, 0, 0.1)',
30
+ shallowLeft: '-20px 0px 40px rgba(0, 0, 0, 0.1)',
31
+ shallowRight: '20px 0px 40px rgba(0, 0, 0, 0.1)',
32
+ } as const;
33
+
34
+ export type TimingFunction = `cubic-bezier(${number}, ${number}, ${number}, ${number})` | 'ease' | 'ease-in' | 'ease-out' | 'ease-in-out' | 'linear';
35
+ export type Duration = `${number}ms` | `${number}s`;
36
+
37
+ const TimingFunctions: Omit<Theme['animations']['timing'], 'default'> = {
38
+ easeInOut: 'cubic-bezier(0.42, 0.0, 0.58, 1.0)',
39
+ easeOut: 'cubic-bezier(0.0, 0.0, 0.58, 1.0)',
40
+ easeIn: 'cubic-bezier(0.42, 0.0, 1.0, 1.0)',
41
+ easeOutQuad: 'cubic-bezier(0.5, 1, 0.89, 1)',
42
+ easeInQuad: 'cubic-bezier(0.11, 0, 0.5, 0)',
43
+ };
44
+
19
45
  export type Theme = {
20
46
  tokens: TokensT,
47
+ utils: {
48
+ defaultUserSelect: Property.UserSelect,
49
+ }
21
50
  colors: {
22
51
  // Primary
23
52
 
@@ -71,6 +100,7 @@ export type Theme = {
71
100
  backgroundOverlayLight: CSSColor,
72
101
  backgroundOverlayXLight: CSSColor,
73
102
  backgroundOverlayGrey: CSSColor,
103
+ backgroundOverlayDark: CSSColor,
74
104
  backgroundOverlayTeal: CSSColor,
75
105
 
76
106
  // Border
@@ -91,6 +121,7 @@ export type Theme = {
91
121
  fontFamily: string,
92
122
  boldFontWeight: number,
93
123
  italicLetterSpacing: CSSLength,
124
+ verticalMetricsAdjust: CSSLength;
94
125
 
95
126
  styles: {
96
127
  // Display
@@ -124,6 +155,17 @@ export type Theme = {
124
155
  paragraphXXSmall: FontDefinition,
125
156
  }
126
157
  },
158
+ lighting: {
159
+ shallowBelow: ShadowDefinition,
160
+ deepBelow: ShadowDefinition,
161
+ shallowAbove: ShadowDefinition,
162
+ deepAbove: ShadowDefinition,
163
+ shallowPopup: ShadowDefinition,
164
+ deepPopup: ShadowDefinition,
165
+ subtlePopup: ShadowDefinition,
166
+ shallowLeft: ShadowDefinition,
167
+ shallowRight: ShadowDefinition,
168
+ },
127
169
  borders: {
128
170
  // Border Radius
129
171
  radius: {
@@ -133,10 +175,42 @@ export type Theme = {
133
175
  rounded: CSSLength,
134
176
  roundedSmall: CSSLength,
135
177
  roundedLarge: CSSLength,
178
+ roundedXL: CSSLength,
179
+ },
180
+
181
+ // Dropdowns (Select, Menu, Popovers, etc.)
182
+
183
+ dropdown: {
184
+ color: CSSColor,
185
+ shadow: ShadowDefinition,
136
186
  },
137
187
  },
188
+ surfaces: {
189
+ dialog: {
190
+ border: `${number}px ${string} ${CSSColor}`,
191
+ outline: `${number}px ${string} ${CSSColor}`,
192
+ background: CSSColor,
193
+ backdropFilter: string,
194
+ },
195
+ }
138
196
  animations: {
139
197
  interaction: string,
198
+ timing: {
199
+ easeInOut: TimingFunction,
200
+ easeOut: TimingFunction,
201
+ easeIn: TimingFunction,
202
+ easeOutQuad: TimingFunction,
203
+ easeInQuad: TimingFunction,
204
+ default: TimingFunction,
205
+ },
206
+ duration: {
207
+ rapid: Duration,
208
+ fast: Duration,
209
+ normal: Duration,
210
+ relaxed: Duration,
211
+ slow: Duration,
212
+ gradual: Duration,
213
+ },
140
214
  }
141
215
  };
142
216
 
@@ -172,6 +246,9 @@ export const ParagraphFontClass: FontClassDefinition = {
172
246
 
173
247
  export const LightTheme: Theme = {
174
248
  tokens: T,
249
+ utils: {
250
+ defaultUserSelect: 'none',
251
+ },
175
252
  colors: {
176
253
  // Primary
177
254
 
@@ -225,6 +302,7 @@ export const LightTheme: Theme = {
225
302
  backgroundOverlayLight: 'rgba(255, 255, 255, 0.07)',
226
303
  backgroundOverlayXLight: 'rgba(255, 255, 255, 0.1)',
227
304
  backgroundOverlayGrey: 'rgba(175, 175, 175, 0.8)',
305
+ backgroundOverlayDark: 'rgba(0, 0, 0, 0.1)',
228
306
  backgroundOverlayTeal: 'rgba(29, 238, 205, 0.1)',
229
307
 
230
308
  // Border
@@ -245,6 +323,7 @@ export const LightTheme: Theme = {
245
323
  fontFamily: '"Graphik Web", -apple-system, BlinkMacSystemFont, Helvetica, Arial, sans-serif',
246
324
  boldFontWeight: 500,
247
325
  italicLetterSpacing: '-0.01em',
326
+ verticalMetricsAdjust: '1px',
248
327
 
249
328
  styles: {
250
329
  // Display
@@ -350,6 +429,9 @@ export const LightTheme: Theme = {
350
429
  },
351
430
  },
352
431
  },
432
+ lighting: {
433
+ ...Shadows,
434
+ },
353
435
  borders: {
354
436
  radius: {
355
437
  pill: '1000px',
@@ -358,18 +440,41 @@ export const LightTheme: Theme = {
358
440
  rounded: '8px',
359
441
  roundedSmall: '4px',
360
442
  roundedLarge: '12px',
443
+ roundedXL: '16px',
444
+ },
445
+
446
+ dropdown: {
447
+ shadow: Shadows.deepBelow,
448
+ color: 'transparent',
449
+ },
450
+ },
451
+ surfaces: {
452
+ dialog: {
453
+ border: '8px solid rgba(0, 0, 0, 0.2)',
454
+ outline: '1px solid rgba(0, 0, 0, 0.25)',
455
+ background: 'rgba(255, 255, 255, 0.9)',
456
+ backdropFilter: 'blur(6px)',
361
457
  },
362
458
  },
363
459
  animations: {
364
- interaction: '0.2s cubic-bezier(0.25, 1, 0.5, 1)',
460
+ interaction: '200ms cubic-bezier(0.5, 1, 0.89, 1)',
461
+ timing: {
462
+ ...TimingFunctions,
463
+ default: TimingFunctions.easeOut,
464
+ },
465
+ duration: {
466
+ rapid: '50ms',
467
+ fast: '100ms',
468
+ normal: '200ms',
469
+ relaxed: '300ms',
470
+ slow: '400ms',
471
+ gradual: '600ms',
472
+ },
365
473
  },
366
474
  };
367
475
 
368
- export const DarkTheme: Theme = {
369
- ...LightTheme,
476
+ export const DarkTheme: Theme = merge(LightTheme, {
370
477
  colors: {
371
- ...LightTheme.colors,
372
-
373
478
  // Reverse all inverse colors
374
479
 
375
480
  contentPrimary: LightTheme.colors.contentInversePrimary,
@@ -397,7 +502,21 @@ export const DarkTheme: Theme = {
397
502
  borderInverseOpaque: LightTheme.colors.borderOpaque,
398
503
  borderInverseSelected: LightTheme.colors.borderSelected,
399
504
  },
400
- };
505
+ borders: {
506
+ dropdown: {
507
+ shadow: 'none',
508
+ color: T.colors.grey600,
509
+ },
510
+ },
511
+ surfaces: {
512
+ dialog: {
513
+ border: '8px solid rgba(255, 255, 255, 0.2)',
514
+ outline: '1px solid rgba(255, 255, 255, 0.25)',
515
+ background: 'rgba(0, 0, 0, 0.6)',
516
+ backdropFilter: 'blur(6px)',
517
+ },
518
+ },
519
+ } as PartialDeep<Theme>) as Theme;
401
520
 
402
521
  export const {
403
522
  theme,
@@ -406,4 +525,4 @@ export const {
406
525
  updateTheme,
407
526
  injectTheme,
408
527
  generateThemeInjection,
409
- } = createTheme(LightTheme);
528
+ } = createTheme<Theme>(LightTheme);
@@ -15,6 +15,8 @@
15
15
  border-width: 0; /* 2 */
16
16
  border-style: solid; /* 2 */
17
17
  border-color: var(--pte-colors-borderSelected); /* 2 */
18
+
19
+ -webkit-tap-highlight-color: transparent;
18
20
  }
19
21
 
20
22
  /*
@@ -325,7 +327,7 @@ Set the default cursor for buttons.
325
327
 
326
328
  button,
327
329
  [role="button"] {
328
- cursor: pointer;
330
+ cursor: default;
329
331
  }
330
332
 
331
333
  /*
@@ -0,0 +1,8 @@
1
+ @mixin flex-row {
2
+ display: flex;
3
+ flex-direction: row;
4
+ }
5
+
6
+ .bold {
7
+ font-weight: var(--pte-typography-boldFontWeight);
8
+ }
@@ -0,0 +1 @@
1
+ .container {}