paris 0.8.16 → 0.8.18
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 +18 -0
- package/README.md +1 -1
- package/package.json +1 -1
- package/src/stories/button/Button.tsx +10 -0
- package/src/stories/icon/Icon.tsx +3 -3
- package/src/stories/icon/NotificationDot.tsx +8 -0
- package/src/stories/menu/Menu.module.scss +21 -0
- package/src/stories/menu/Menu.stories.tsx +1 -1
- package/src/stories/menu/Menu.tsx +11 -6
- package/src/stories/styledlink/StyledLink.stories.ts +8 -3
- package/src/stories/styledlink/StyledLink.tsx +1 -1
- package/src/stories/table/Table.tsx +1 -1
- package/src/stories/tag/Tag.module.scss +4 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# paris
|
|
2
2
|
|
|
3
|
+
## 0.8.18
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 3a29baf: Menu: update category
|
|
8
|
+
- e9d24cf: Icon: fix typings for `as` prop
|
|
9
|
+
- e9d24cf: StyledLink: fix typings for `as` prop
|
|
10
|
+
- 9b29f1d: Table: update docs to mention `cells` instead of `nodes` for `rowRenderFn`
|
|
11
|
+
|
|
12
|
+
## 0.8.17
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- c1fd99a: feat(Tag): Add new Tag styling
|
|
17
|
+
- c1fd99a: feat: Update menu component to support new feature styling
|
|
18
|
+
- c1fd99a: chore: Update README typo
|
|
19
|
+
- c1fd99a: feat(Button): Add notification dot support
|
|
20
|
+
|
|
3
21
|
## 0.8.16
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Paris is Slingshot's React design system, meant to work universally across serve
|
|
|
4
4
|
|
|
5
5
|
Currently, Paris is provided as a set of *unbundled* `.tsx` components styled with SCSS modules. This means that you can import only the components you need, and you can use your own bundler to optimize your bundle size. As a result, Paris works best with frameworks like Next.js that have built-in support for TypeScript and SCSS modules.
|
|
6
6
|
|
|
7
|
-
Paris 1.x styling is heavily inspired by Uber's [Base Web](https://baseweb.design), which we previously used in our production apps. We built Paris
|
|
7
|
+
Paris 1.x styling is heavily inspired by Uber's [Base Web](https://baseweb.design), which we previously used in our production apps. We built Paris to move away from Styletron and CSS-in-JS, since we're now largely working with React 18, RSC, and the Next.js `app` directory.
|
|
8
8
|
|
|
9
9
|
<br />
|
|
10
10
|
|
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.8.
|
|
5
|
+
"version": "0.8.18",
|
|
6
6
|
"homepage": "https://paris.slingshot.fm",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"repository": {
|
|
@@ -13,6 +13,7 @@ import type { Enhancer } from '../../types/Enhancer';
|
|
|
13
13
|
import { MemoizedEnhancer } from '../../helpers/renderEnhancer';
|
|
14
14
|
import { pvar } from '../theme';
|
|
15
15
|
import { Spinner } from '../icon';
|
|
16
|
+
import { NotificationDot } from '../icon/NotificationDot';
|
|
16
17
|
|
|
17
18
|
const EnhancerSizes = {
|
|
18
19
|
large: 13,
|
|
@@ -104,6 +105,8 @@ export type ButtonProps = {
|
|
|
104
105
|
* This should be text. When Button shape is `circle` or `square`, the action description should still be passed here for screen readers.
|
|
105
106
|
*/
|
|
106
107
|
children?: ReactNode | ReactNode[];
|
|
108
|
+
|
|
109
|
+
displayNotificationDot?: boolean;
|
|
107
110
|
} & Omit<AriaButtonProps, 'children' | 'disabled' | 'onClick'>;
|
|
108
111
|
|
|
109
112
|
/**
|
|
@@ -133,6 +136,7 @@ export const Button: FC<ButtonProps> = ({
|
|
|
133
136
|
disabled,
|
|
134
137
|
loading,
|
|
135
138
|
href,
|
|
139
|
+
displayNotificationDot = false,
|
|
136
140
|
...props
|
|
137
141
|
}) => (
|
|
138
142
|
<AriaButton
|
|
@@ -145,6 +149,7 @@ export const Button: FC<ButtonProps> = ({
|
|
|
145
149
|
'--pte-colors-backgroundTertiary': theme ? ButtonThemes[theme].secondary : colors?.secondary,
|
|
146
150
|
} as CSSProperties : {}}
|
|
147
151
|
className={clsx(
|
|
152
|
+
'relative',
|
|
148
153
|
styles.button,
|
|
149
154
|
styles[kind],
|
|
150
155
|
styles[shape],
|
|
@@ -189,5 +194,10 @@ export const Button: FC<ButtonProps> = ({
|
|
|
189
194
|
size={EnhancerSizes[size]}
|
|
190
195
|
/>
|
|
191
196
|
)}
|
|
197
|
+
{!!displayNotificationDot && (
|
|
198
|
+
<div className="absolute top-0 right-0">
|
|
199
|
+
<NotificationDot size={8} />
|
|
200
|
+
</div>
|
|
201
|
+
)}
|
|
192
202
|
</AriaButton>
|
|
193
203
|
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ComponentPropsWithoutRef, NamedExoticComponent } from 'react';
|
|
1
|
+
import type { ComponentPropsWithoutRef, ElementType, NamedExoticComponent } from 'react';
|
|
2
2
|
import { createElement, memo } from 'react';
|
|
3
3
|
|
|
4
4
|
export type IconDefinitionProps = {
|
|
@@ -9,7 +9,7 @@ export type IconDefinitionProps = {
|
|
|
9
9
|
};
|
|
10
10
|
export type IconDefinition = NamedExoticComponent<IconDefinitionProps>;
|
|
11
11
|
|
|
12
|
-
export type IconProps<T extends
|
|
12
|
+
export type IconProps<T extends ElementType = 'span'> = IconDefinitionProps & {
|
|
13
13
|
icon: IconDefinition;
|
|
14
14
|
as?: T;
|
|
15
15
|
overrides?: {
|
|
@@ -31,7 +31,7 @@ export type IconProps<T extends keyof JSX.IntrinsicElements = 'span'> = IconDefi
|
|
|
31
31
|
* ```
|
|
32
32
|
* @constructor
|
|
33
33
|
*/
|
|
34
|
-
export const Icon = memo<IconProps
|
|
34
|
+
export const Icon = memo<IconProps<ElementType>>(({
|
|
35
35
|
as = 'span',
|
|
36
36
|
icon,
|
|
37
37
|
size,
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { memo } from 'react';
|
|
2
|
+
import type { IconDefinition } from './Icon';
|
|
3
|
+
|
|
4
|
+
export const NotificationDot: IconDefinition = memo(({ size }) => (
|
|
5
|
+
<svg xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 8 8" fill="none">
|
|
6
|
+
<circle cx="4" cy="4" r="3.5" fill="#1DEECD" stroke="#8EF7E6" />
|
|
7
|
+
</svg>
|
|
8
|
+
));
|
|
@@ -49,4 +49,25 @@
|
|
|
49
49
|
&:hover {
|
|
50
50
|
background-color: var(--pte-colors-backgroundSecondary);
|
|
51
51
|
}
|
|
52
|
+
|
|
53
|
+
@keyframes gradientFlow {
|
|
54
|
+
0% {
|
|
55
|
+
background-position: 0%;
|
|
56
|
+
}
|
|
57
|
+
100% {
|
|
58
|
+
background-position: 125%;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.newItem {
|
|
64
|
+
background: radial-gradient(circle, rgba(20,239,172,0.2) 0%, rgba(38,237,237,0.05) 75%);
|
|
65
|
+
background-size: 150% 100%;
|
|
66
|
+
animation: gradientFlow 2.5s ease-in-out infinite alternate;
|
|
67
|
+
background-position: 0%;
|
|
68
|
+
|
|
69
|
+
&:hover {
|
|
70
|
+
background-color: unset;
|
|
71
|
+
animation-play-state: paused;
|
|
72
|
+
}
|
|
52
73
|
}
|
|
@@ -31,9 +31,11 @@ export const Menu: FC<MenuProps<React.ElementType>> & {
|
|
|
31
31
|
Items: FC<MenuItemsProps<React.ElementType> & {
|
|
32
32
|
position?: 'left' | 'right';
|
|
33
33
|
}>;
|
|
34
|
-
Item: FC<MenuItemProps<React.ElementType
|
|
34
|
+
Item: FC<MenuItemProps<React.ElementType> & {
|
|
35
|
+
isNew?: boolean;
|
|
36
|
+
}>;
|
|
35
37
|
} = ({ className, children, ...props }) => (
|
|
36
|
-
<HeadlessMenu as="div" className={clsx(
|
|
38
|
+
<HeadlessMenu as="div" className={clsx(styles.menu, className)} {...props}>
|
|
37
39
|
{children}
|
|
38
40
|
</HeadlessMenu>
|
|
39
41
|
);
|
|
@@ -44,7 +46,7 @@ export const Menu: FC<MenuProps<React.ElementType>> & {
|
|
|
44
46
|
* Should be used inside a `Menu` component to serve as the toggle for `MenuItems`.
|
|
45
47
|
*/
|
|
46
48
|
Menu.Button = ({ className, children, ...props }) => (
|
|
47
|
-
<HeadlessMenu.Button className={clsx(
|
|
49
|
+
<HeadlessMenu.Button className={clsx(styles.menuButton, className)} {...props}>
|
|
48
50
|
{children}
|
|
49
51
|
</HeadlessMenu.Button>
|
|
50
52
|
);
|
|
@@ -59,7 +61,7 @@ Menu.Button = ({ className, children, ...props }) => (
|
|
|
59
61
|
Menu.Items = ({
|
|
60
62
|
className, children, position = 'left', ...props
|
|
61
63
|
}) => (
|
|
62
|
-
<HeadlessMenu.Items className={clsx(
|
|
64
|
+
<HeadlessMenu.Items className={clsx(styles.menuItems, position === 'left' && styles.leftPosition, position === 'right' && styles.rightPosition, className)} {...props}>
|
|
63
65
|
{children}
|
|
64
66
|
</HeadlessMenu.Items>
|
|
65
67
|
);
|
|
@@ -69,9 +71,12 @@ Menu.Items = ({
|
|
|
69
71
|
*
|
|
70
72
|
* Should be used inside `MenuItems` to represent selectable options in the menu.
|
|
71
73
|
*
|
|
74
|
+
* @param isNew - Whether the menu items should be styled as new items.
|
|
72
75
|
*/
|
|
73
|
-
Menu.Item = ({
|
|
74
|
-
|
|
76
|
+
Menu.Item = ({
|
|
77
|
+
className, children, isNew = false, ...props
|
|
78
|
+
}) => (
|
|
79
|
+
<HeadlessMenu.Item className={clsx(styles.menuItem, isNew && styles.newItem, className)} {...props}>
|
|
75
80
|
{children}
|
|
76
81
|
</HeadlessMenu.Item>
|
|
77
82
|
);
|
|
@@ -12,12 +12,17 @@ type Story = StoryObj<typeof StyledLink>;
|
|
|
12
12
|
|
|
13
13
|
export const Default: Story = {
|
|
14
14
|
args: {
|
|
15
|
-
|
|
15
|
+
href: 'https://slingshot.fm',
|
|
16
|
+
target: '_blank',
|
|
17
|
+
children: 'Hello world! This is a styled link.',
|
|
16
18
|
},
|
|
17
19
|
};
|
|
18
20
|
|
|
19
|
-
export const
|
|
21
|
+
export const AsButton: Story = {
|
|
20
22
|
args: {
|
|
21
|
-
|
|
23
|
+
as: 'button',
|
|
24
|
+
// eslint-disable-next-line no-alert
|
|
25
|
+
onClick: () => alert('Hello world!'),
|
|
26
|
+
children: 'Hello world! This is a StyledLink rendered as a button.',
|
|
22
27
|
},
|
|
23
28
|
};
|
|
@@ -42,7 +42,7 @@ export type TableProps<
|
|
|
42
42
|
*
|
|
43
43
|
* The function should return an object containing a property named `key` for the row's React key (should be a unique id), and a property named `nodes` containing an array of React nodes to be rendered as cells in the row.
|
|
44
44
|
* @param row - The data for the row being rendered.
|
|
45
|
-
* @returns An object containing a property named `key` for the row's React key (should be a unique id), and a property named `
|
|
45
|
+
* @returns An object containing a property named `key` for the row's React key (should be a unique id), and a property named `cells` containing an array of React nodes to be rendered as cells in the row.
|
|
46
46
|
* @see RowRenderData
|
|
47
47
|
*/
|
|
48
48
|
rowRenderFn?: (row: RowData[number]) => RowRenderData;
|