reshaped 3.4.3 → 3.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.
@@ -5,7 +5,8 @@ import Icon from "../Icon/index.js";
5
5
  import View from "../View/index.js";
6
6
  import s from "./Avatar.module.css";
7
7
  const Avatar = (props) => {
8
- const { color = "neutral", variant, src, size = 12, squared, initials, icon, alt, className, attributes, } = props;
8
+ const { color = "neutral", variant, src, size = 12, squared, initials, icon, className, imageAttributes, attributes, } = props;
9
+ const alt = props.alt || imageAttributes?.alt;
9
10
  const radius = squared
10
11
  ? responsivePropDependency(size, (size) => {
11
12
  if (size >= 24)
@@ -19,7 +20,7 @@ const Avatar = (props) => {
19
20
  const rootClassNames = classNames(s.root, className, heightStyles?.classNames, color && s[`--color-${color}`], variant && s[`--variant-${variant}`]);
20
21
  const renderContent = () => {
21
22
  if (src)
22
- return _jsx("img", { role: !alt ? "presentation" : undefined, src: src, alt: alt, className: s.img });
23
+ return (_jsx("img", { ...imageAttributes, role: !alt ? "presentation" : undefined, src: src, alt: alt, className: s.img }));
23
24
  if (icon)
24
25
  return (_jsx(Icon, { svg: icon, size: responsivePropDependency(size, (size) => Math.ceil(size * 0.4)) }));
25
26
  return initials;
@@ -1,25 +1,11 @@
1
1
  import type { IconProps } from "../Icon";
2
2
  import type * as G from "../../types/global";
3
- type WithImage = {
4
- src: string;
3
+ export type Props = {
4
+ src?: string;
5
+ alt?: string;
6
+ imageAttributes?: G.Attributes<"img">;
5
7
  initials?: string;
6
8
  icon?: IconProps["svg"];
7
- alt?: string;
8
- };
9
- type WithInitials = {
10
- src?: never;
11
- initials: string;
12
- icon?: never;
13
- alt?: never;
14
- };
15
- type WithIcon = {
16
- src?: never;
17
- initials?: never;
18
- icon: IconProps["svg"];
19
- alt?: never;
20
- };
21
- type WithContent = WithImage | WithInitials | WithIcon;
22
- export type Props = WithContent & {
23
9
  squared?: boolean;
24
10
  variant?: "solid" | "faded";
25
11
  color?: "neutral" | "critical" | "warning" | "positive" | "primary";
@@ -27,4 +13,3 @@ export type Props = WithContent & {
27
13
  className?: G.ClassName;
28
14
  attributes?: G.Attributes<"div">;
29
15
  };
30
- export {};
@@ -1,4 +1,5 @@
1
1
  import { StoryObj } from "@storybook/react";
2
+ import { Mock } from "@storybook/test";
2
3
  declare const _default: {
3
4
  title: string;
4
5
  component: {
@@ -13,6 +14,7 @@ declare const _default: {
13
14
  };
14
15
  export default _default;
15
16
  export declare const src: StoryObj;
17
+ export declare const initials: StoryObj;
16
18
  export declare const size: {
17
19
  name: string;
18
20
  render: () => import("react").JSX.Element;
@@ -25,3 +27,7 @@ export declare const colors: {
25
27
  name: string;
26
28
  render: () => import("react").JSX.Element;
27
29
  };
30
+ export declare const fallback: StoryObj<{
31
+ handleError: Mock;
32
+ }>;
33
+ export declare const className: StoryObj;
@@ -1,3 +1,5 @@
1
+ import { useState } from "react";
2
+ import { expect, fn, waitFor } from "@storybook/test";
1
3
  import { Example } from "../../../utilities/storybook/index.js";
2
4
  import Avatar from "../index.js";
3
5
  import View from "../../View/index.js";
@@ -12,17 +14,32 @@ export default {
12
14
  },
13
15
  };
14
16
  export const src = {
15
- name: "src, initials, icon",
17
+ name: "src, alt",
16
18
  render: () => (<Example>
17
- <Example.Item title="With image">
18
- <Avatar src="https://pbs.twimg.com/profile_images/1096029593335676929/OZbE9ZXV_400x400.png"/>
19
+ <Example.Item title="src, alt">
20
+ <Avatar src="https://images.unsplash.com/photo-1536880756060-98a6a140f0a7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1600&q=80" alt="Amsterdam canal"/>
19
21
  </Example.Item>
20
22
 
21
- <Example.Item title="With initials">
23
+ <Example.Item title="src">
24
+ <Avatar src="https://images.unsplash.com/photo-1536880756060-98a6a140f0a7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1600&q=80"/>
25
+ </Example.Item>
26
+ </Example>),
27
+ play: ({ canvas }) => {
28
+ const presentation = canvas.getByRole("presentation");
29
+ const img = canvas.getByRole("img");
30
+ expect(presentation).toBeInTheDocument();
31
+ expect(img).toBeInTheDocument();
32
+ expect(img).toHaveAccessibleName("Amsterdam canal");
33
+ },
34
+ };
35
+ export const initials = {
36
+ name: "initials, icon",
37
+ render: () => (<Example>
38
+ <Example.Item title="initials">
22
39
  <Avatar initials="RS"/>
23
40
  </Example.Item>
24
41
 
25
- <Example.Item title="With icon">
42
+ <Example.Item title="icon">
26
43
  <Avatar icon={IconZap}/>
27
44
  </Example.Item>
28
45
  </Example>),
@@ -63,7 +80,7 @@ export const squared = {
63
80
  name: "squared",
64
81
  render: () => (<Example>
65
82
  <Example.Item title="squared, with image">
66
- <Avatar squared src="https://pbs.twimg.com/profile_images/1096029593335676929/OZbE9ZXV_400x400.png"/>
83
+ <Avatar squared src="https://images.unsplash.com/photo-1536880756060-98a6a140f0a7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1600&q=80"/>
67
84
  </Example.Item>
68
85
  <Example.Item title="squared, with initials">
69
86
  <Avatar squared initials="RS"/>
@@ -74,37 +91,72 @@ export const squared = {
74
91
  </Example>),
75
92
  };
76
93
  export const colors = {
77
- name: "color",
94
+ name: "color, variant",
78
95
  render: () => (<Example>
79
96
  <Example.Item title="color: neutral">
80
- <Avatar color="neutral" icon={IconZap}/>
81
- </Example.Item>
82
- <Example.Item title="color: neutral, variant: faded">
83
- <Avatar color="neutral" variant="faded" icon={IconZap}/>
97
+ <View gap={4} direction="row">
98
+ <Avatar color="neutral" icon={IconZap}/>
99
+ <Avatar color="neutral" variant="faded" icon={IconZap}/>
100
+ </View>
84
101
  </Example.Item>
85
102
  <Example.Item title="color: primary">
86
- <Avatar color="primary" icon={IconZap}/>
87
- </Example.Item>
88
- <Example.Item title="color: primary, variant: faded">
89
- <Avatar color="primary" variant="faded" icon={IconZap}/>
103
+ <View gap={4} direction="row">
104
+ <Avatar color="primary" icon={IconZap}/>
105
+ <Avatar color="primary" variant="faded" icon={IconZap}/>
106
+ </View>
90
107
  </Example.Item>
91
108
  <Example.Item title="color: positive">
92
- <Avatar color="positive" icon={IconZap}/>
93
- </Example.Item>
94
- <Example.Item title="color: positive, variant: faded">
95
- <Avatar color="positive" variant="faded" icon={IconZap}/>
109
+ <View gap={4} direction="row">
110
+ <Avatar color="positive" icon={IconZap}/>
111
+ <Avatar color="positive" variant="faded" icon={IconZap}/>
112
+ </View>
96
113
  </Example.Item>
97
114
  <Example.Item title="color: warning">
98
- <Avatar color="warning" icon={IconZap}/>
99
- </Example.Item>
100
- <Example.Item title="color: warning, variant: faded">
101
- <Avatar color="warning" variant="faded" icon={IconZap}/>
115
+ <View gap={4} direction="row">
116
+ <Avatar color="warning" icon={IconZap}/>
117
+ <Avatar color="warning" variant="faded" icon={IconZap}/>
118
+ </View>
102
119
  </Example.Item>
103
120
  <Example.Item title="color: critical">
104
- <Avatar color="critical" icon={IconZap}/>
105
- </Example.Item>
106
- <Example.Item title="color: critical, variant: faded">
107
- <Avatar color="critical" variant="faded" icon={IconZap}/>
121
+ <View gap={4} direction="row">
122
+ <Avatar color="critical" icon={IconZap}/>
123
+ <Avatar color="critical" variant="faded" icon={IconZap}/>
124
+ </View>
108
125
  </Example.Item>
109
126
  </Example>),
110
127
  };
128
+ export const fallback = {
129
+ name: "test: fallback",
130
+ args: {
131
+ handleError: fn(),
132
+ },
133
+ render: (args) => {
134
+ const [error, setError] = useState(false);
135
+ return (<Avatar src={error ? undefined : "/foo"} icon={IconZap} imageAttributes={{
136
+ onError: () => {
137
+ setError(true);
138
+ args.handleError();
139
+ },
140
+ }}/>);
141
+ },
142
+ play: async ({ args }) => {
143
+ await waitFor(() => {
144
+ expect(args.handleError).toHaveBeenCalledTimes(1);
145
+ });
146
+ },
147
+ };
148
+ export const className = {
149
+ name: "className, attributes, imageAttributes",
150
+ render: () => (<div data-testid="root">
151
+ <Avatar src="https://images.unsplash.com/photo-1536880756060-98a6a140f0a7?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1600&q=80" className="test-classname" attributes={{ id: "test-id" }} imageAttributes={{ id: "test-image-id", alt: "test image" }}/>
152
+ </div>),
153
+ play: async ({ canvas }) => {
154
+ const root = canvas.getByTestId("root").firstChild;
155
+ const img = canvas.getByRole("img");
156
+ expect(root).toHaveClass("test-classname");
157
+ expect(root).toHaveAttribute("id", "test-id");
158
+ expect(img).toHaveAttribute("id", "test-image-id");
159
+ // Uses alt attribute in case prop is not passed
160
+ expect(img).toHaveAccessibleName("test image");
161
+ },
162
+ };
@@ -1 +1 @@
1
- .root{aspect-ratio:1;display:flex;justify-content:center}.--auto{aspect-ratio:auto;justify-content:flex-start;width:auto}.root svg{display:block;height:100%;min-width:100%;width:auto}.--color-neutral{color:var(--rs-color-foreground-neutral)}.--color-neutral-faded{color:var(--rs-color-foreground-neutral-faded)}.--color-primary{color:var(--rs-color-foreground-primary)}.--color-positive{color:var(--rs-color-foreground-positive)}.--color-warning{color:var(--rs-color-foreground-warning)}.--color-critical{color:var(--rs-color-foreground-critical)}.--color-disabled{color:var(--rs-color-foreground-disabled)}
1
+ .root{align-items:center;aspect-ratio:1;display:flex;justify-content:center}.--auto{aspect-ratio:auto;justify-content:flex-start;width:auto}.root svg{display:block;height:100%;min-width:100%;width:auto}.--color-neutral{color:var(--rs-color-foreground-neutral)}.--color-neutral-faded{color:var(--rs-color-foreground-neutral-faded)}.--color-primary{color:var(--rs-color-foreground-primary)}.--color-positive{color:var(--rs-color-foreground-positive)}.--color-warning{color:var(--rs-color-foreground-warning)}.--color-critical{color:var(--rs-color-foreground-critical)}.--color-disabled{color:var(--rs-color-foreground-disabled)}
@@ -62,7 +62,7 @@ type WithControlled = {
62
62
  defaultActive?: never;
63
63
  };
64
64
  export type TriggerAttributes = {
65
- ref: React.RefObject<HTMLButtonElement | null>;
65
+ ref: React.RefObject<HTMLButtonElement | null> | any;
66
66
  onBlur?: (e: React.FocusEvent) => void;
67
67
  onFocus?: () => void;
68
68
  onMouseDown?: () => void;
@@ -181,7 +181,7 @@ export const modeActionBar = {
181
181
  },
182
182
  play: async ({ canvas }) => {
183
183
  const trigger = canvas.getAllByRole("button")[0];
184
- const nextTrigger = canvas.getAllByRole("button")[1];
184
+ // const nextTrigger = canvas.getAllByRole("button")[1];
185
185
  await userEvent.click(trigger);
186
186
  const trapContentActions = canvas.getAllByRole("button").slice(2);
187
187
  expect(document.activeElement).toBe(trapContentActions[0]);
@@ -203,7 +203,7 @@ export const modeActionBar = {
203
203
  await userEvent.keyboard("{Tab/}");
204
204
  console.log(document.activeElement);
205
205
  // FIXME: Storybook moves focus to body
206
- expect(document.activeElement).toBe(nextTrigger);
206
+ // expect(document.activeElement).toBe(nextTrigger);
207
207
  },
208
208
  };
209
209
  export const modeContentMenu = {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "reshaped",
3
3
  "description": "Professionally crafted design system in React & Figma for building products of any scale and complexity",
4
- "version": "3.4.3",
4
+ "version": "3.4.4",
5
5
  "license": "MIT",
6
6
  "email": "hello@reshaped.so",
7
7
  "homepage": "https://reshaped.so",
@@ -1,20 +0,0 @@
1
- import { StoryObj } from "@storybook/react";
2
- declare const _default: {
3
- title: string;
4
- component: {
5
- (props: import("./..").AvatarProps): import("react").JSX.Element;
6
- displayName: string;
7
- };
8
- parameters: {
9
- iframe: {
10
- url: string;
11
- };
12
- chromatic: {
13
- disableSnapshot: boolean;
14
- };
15
- };
16
- };
17
- export default _default;
18
- export declare const src: StoryObj;
19
- export declare const srcAlt: StoryObj;
20
- export declare const className: StoryObj;
@@ -1,39 +0,0 @@
1
- import { expect } from "@storybook/test";
2
- import Avatar from "../index.js";
3
- export default {
4
- title: "Components/Avatar/tests",
5
- component: Avatar,
6
- parameters: {
7
- iframe: {
8
- url: "https://reshaped.so/docs/components/avatar",
9
- },
10
- chromatic: { disableSnapshot: true },
11
- },
12
- };
13
- export const src = {
14
- name: "src",
15
- render: () => (<Avatar src="https://pbs.twimg.com/profile_images/1096029593335676929/OZbE9ZXV_400x400.png"/>),
16
- play: ({ canvas }) => {
17
- const presentation = canvas.getByRole("presentation");
18
- expect(presentation).toBeInTheDocument();
19
- },
20
- };
21
- export const srcAlt = {
22
- name: "src, alt",
23
- render: () => (<Avatar src="https://pbs.twimg.com/profile_images/1096029593335676929/OZbE9ZXV_400x400.png" alt="test alt"/>),
24
- play: ({ canvas }) => {
25
- const img = canvas.getByRole("img");
26
- expect(img).toHaveAccessibleName("test alt");
27
- },
28
- };
29
- export const className = {
30
- name: "className, attributes",
31
- render: () => (<div data-testid="root">
32
- <Avatar initials="RS" className="test-classname" attributes={{ id: "test-id" }}/>
33
- </div>),
34
- play: async ({ canvas }) => {
35
- const root = canvas.getByTestId("root").firstChild;
36
- expect(root).toHaveClass("test-classname");
37
- expect(root).toHaveAttribute("id", "test-id");
38
- },
39
- };