paris 0.8.15 → 0.8.17

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 CHANGED
@@ -1,5 +1,20 @@
1
1
  # paris
2
2
 
3
+ ## 0.8.17
4
+
5
+ ### Patch Changes
6
+
7
+ - c1fd99a: feat(Tag): Add new Tag styling
8
+ - c1fd99a: feat: Update menu component to support new feature styling
9
+ - c1fd99a: chore: Update README typo
10
+ - c1fd99a: feat(Button): Add notification dot support
11
+
12
+ ## 0.8.16
13
+
14
+ ### Patch Changes
15
+
16
+ - 616d1e6: fix: Remove New Tag styling and add teal700
17
+
3
18
  ## 0.8.15
4
19
 
5
20
  ### 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 because 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.
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.15",
5
+ "version": "0.8.17",
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
  );
@@ -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(className, styles.menu)} {...props}>
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(className, styles.menuButton)} {...props}>
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(className, styles.menuItems, position === 'left' && styles.leftPosition, position === 'right' && styles.rightPosition)} {...props}>
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 = ({ className, children, ...props }) => (
74
- <HeadlessMenu.Item className={clsx(className, styles.menuItem)} {...props}>
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
  );
@@ -16,6 +16,10 @@
16
16
  }
17
17
  }
18
18
 
19
+ .new {
20
+ padding: 4px 10px;
21
+ }
22
+
19
23
  .default {
20
24
  background-color: var(--pte-colors-backgroundTertiary);
21
25
  color: var(--pte-colors-contentTertiary);
@@ -43,10 +47,4 @@
43
47
  background-color: var(--pte-colors-backgroundNegative);
44
48
  color: var(--pte-colors-contentNegative);
45
49
  border-color: var(--pte-colors-contentNegative);
46
- }
47
-
48
- .new {
49
- border: 1px solid var(--pte-colors-borderAccent);
50
- background-color: var(--pte-tokens-colors-teal200);
51
- box-shadow: 0px 0px 10px 0px color-mix(in srgb, var(--pte-colors-contentAccent) 30%, transparent);
52
50
  }
@@ -1,4 +1,4 @@
1
- import type { FC, ReactNode } from 'react';
1
+ import type { ComponentPropsWithoutRef, FC, ReactNode } from 'react';
2
2
  import clsx from 'clsx';
3
3
  import styles from './Tag.module.scss';
4
4
  import typography from '../text/Typography.module.css';
@@ -10,7 +10,7 @@ export type TagProps = {
10
10
  kind?: 'default' | 'secondary' | 'positive' | 'warning' | 'negative' | 'new';
11
11
  /** The contents of the Tag. */
12
12
  children: ReactNode;
13
- };
13
+ } & Omit<ComponentPropsWithoutRef<'div'>, 'children'>;
14
14
 
15
15
  /**
16
16
  * A Tag component.
@@ -28,6 +28,7 @@ export const Tag: FC<TagProps> = ({
28
28
  size = 'normal',
29
29
  kind = 'default',
30
30
  children,
31
+ className,
31
32
  }) => (
32
33
  <div
33
34
  className={clsx(
@@ -36,6 +37,7 @@ export const Tag: FC<TagProps> = ({
36
37
  styles[kind],
37
38
  size === 'normal' && typography.labelXSmall,
38
39
  size === 'compact' && typography.labelXXSmall,
40
+ className,
39
41
  )}
40
42
  >
41
43
  {children}
@@ -23,6 +23,7 @@ export const Colors = {
23
23
  grey100: '#eeeeee',
24
24
  grey50: '#f6f6f6',
25
25
 
26
+ teal700: '#004136',
26
27
  teal600: '#18b199',
27
28
  teal500: '#1ad4b6',
28
29
  teal400: '#1deecd',