@purpurds/tabs 4.6.0 → 5.0.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.
@@ -3,7 +3,7 @@ import { TabContent } from './tab-content';
3
3
  export type TabsCmp<P> = React.FunctionComponent<P> & {
4
4
  Content: typeof TabContent;
5
5
  };
6
- export declare const tabsVariants: readonly ["line", "line-negative", "contained", "contained-negative"];
6
+ export declare const tabsVariants: readonly ["line", "contained"];
7
7
  export type TabsVariant = (typeof tabsVariants)[number];
8
8
  export declare const createTabChangeDetailEvent: (value: string) => CustomEvent<TabChangeDetail>;
9
9
  export type TabChangeDetail = {
@@ -1 +1 @@
1
- {"version":3,"file":"tabs.utils.d.ts","sourceRoot":"","sources":["../src/tabs.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC,GAAG;IACpD,OAAO,EAAE,OAAO,UAAU,CAAC;CAC5B,CAAC;AAEF,eAAO,MAAM,YAAY,uEAAwE,CAAC;AAElG,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAExD,eAAO,MAAM,0BAA0B,UAAW,MAAM,iCACoB,CAAC;AAE7E,MAAM,MAAM,eAAe,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC"}
1
+ {"version":3,"file":"tabs.utils.d.ts","sourceRoot":"","sources":["../src/tabs.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC,GAAG;IACpD,OAAO,EAAE,OAAO,UAAU,CAAC;CAC5B,CAAC;AAEF,eAAO,MAAM,YAAY,gCAAiC,CAAC;AAE3D,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAExD,eAAO,MAAM,0BAA0B,UAAW,MAAM,iCACoB,CAAC;AAE7E,MAAM,MAAM,eAAe,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@purpurds/tabs",
3
- "version": "4.6.0",
3
+ "version": "5.0.0",
4
4
  "license": "AGPL-3.0-only",
5
5
  "main": "./dist/tabs.cjs.js",
6
6
  "types": "./dist/tabs.d.ts",
@@ -16,9 +16,9 @@
16
16
  "dependencies": {
17
17
  "classnames": "~2.5.0",
18
18
  "@radix-ui/react-tabs": "~1.0.4",
19
- "@purpurds/tokens": "4.6.0",
20
- "@purpurds/paragraph": "4.6.0",
21
- "@purpurds/icon": "4.6.0"
19
+ "@purpurds/icon": "5.0.0",
20
+ "@purpurds/tokens": "5.0.0",
21
+ "@purpurds/paragraph": "5.0.0"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@rushstack/eslint-patch": "~1.10.0",
@@ -10,6 +10,7 @@ type TabHeaderProps = {
10
10
  index: number;
11
11
  tabId: string;
12
12
  variant: TabsVariant;
13
+ negative?: boolean;
13
14
  onFocus: FocusEventHandler<HTMLButtonElement>;
14
15
  children: ReactNode;
15
16
  };
@@ -19,12 +20,20 @@ const rootClassName = "purpur-tab-header";
19
20
 
20
21
  export const TabHeader = forwardRef(
21
22
  <T extends HTMLButtonElement>(
22
- { index, tabId, variant, onFocus, "data-testid": dataTestId, children }: TabHeaderProps,
23
+ {
24
+ index,
25
+ tabId,
26
+ variant,
27
+ negative,
28
+ onFocus,
29
+ "data-testid": dataTestId,
30
+ children,
31
+ }: TabHeaderProps,
23
32
  ref: ForwardedRef<T>
24
33
  ) => (
25
34
  <Trigger
26
35
  id={`${tabId}-trigger`}
27
- className={cx([rootClassName, `${rootClassName}--${variant}`])}
36
+ className={cx([rootClassName, `${rootClassName}--${variant}${negative ? "-negative" : ""}`])}
28
37
  value={tabId}
29
38
  data-testid={dataTestId}
30
39
  data-index={index}
@@ -30,57 +30,6 @@ type Story = StoryObj<typeof Tabs>;
30
30
  const tabId = "tab";
31
31
  const name = "Tab name";
32
32
 
33
- export const ActiveTab: Story = {
34
- args: {
35
- variant: tabsVariants[0],
36
- defaultValue: `${tabId}-2`,
37
- fullWidth: false,
38
- children: [
39
- <Tabs.Content
40
- key="1"
41
- tabId={`${tabId}-1`}
42
- name={`${name}-1`}
43
- style={{ padding: "var(--purpur-spacing-250" }}
44
- >
45
- <div>Content 1</div>
46
- </Tabs.Content>,
47
- <Tabs.Content
48
- key="2"
49
- tabId={`${tabId}-2`}
50
- name={`${name}-2`}
51
- style={{ padding: "var(--purpur-spacing-250" }}
52
- >
53
- <div>Content 2</div>
54
- </Tabs.Content>,
55
- <Tabs.Content
56
- key="3"
57
- tabId={`${tabId}-3`}
58
- name={`${name}-3`}
59
- style={{ padding: "var(--purpur-spacing-250" }}
60
- >
61
- <div>Content 3</div>
62
- </Tabs.Content>,
63
- ],
64
- },
65
- render: ({ children, ...args }) => (
66
- <div
67
- style={{
68
- padding: "var(--purpur-spacing-250)",
69
- background: args.variant?.includes("negative")
70
- ? "var(--purpur-color-purple-900)"
71
- : args.variant === "contained"
72
- ? "var(--purpur-color-gray-50)"
73
- : "transparent",
74
- color: `var(--purpur-color-text-default${
75
- args.variant === "line-negative" ? "-negative" : ""
76
- }`,
77
- }}
78
- >
79
- <Tabs {...args}>{children}</Tabs>
80
- </div>
81
- ),
82
- };
83
-
84
33
  export const Showcase: Story = {
85
34
  args: {
86
35
  variant: tabsVariants[0],
@@ -111,19 +60,18 @@ export const Showcase: Story = {
111
60
  <div>Content 3</div>
112
61
  </Tabs.Content>,
113
62
  ],
63
+ negative: false,
114
64
  },
115
65
  render: ({ children, ...args }) => (
116
66
  <div
117
67
  style={{
118
68
  padding: "var(--purpur-spacing-250)",
119
- background: args.variant?.includes("negative")
69
+ background: args.negative
120
70
  ? "var(--purpur-color-purple-900)"
121
71
  : args.variant === "contained"
122
72
  ? "var(--purpur-color-gray-50)"
123
73
  : "transparent",
124
- color: `var(--purpur-color-text-default${
125
- args.variant === "line-negative" ? "-negative" : ""
126
- }`,
74
+ color: `var(--purpur-color-text-default${args.negative ? "-negative" : ""}`,
127
75
  }}
128
76
  >
129
77
  <Tabs {...args}>{children}</Tabs>
package/src/tabs.test.tsx CHANGED
@@ -119,21 +119,6 @@ describe("Tabs", () => {
119
119
  expect(screen.getByTestId("tabs-test-selected-border")).toBeInTheDocument();
120
120
  });
121
121
 
122
- it("should render selected border for line-negative variant", () => {
123
- render(
124
- <Tabs variant="line-negative" data-testid="tabs-test">
125
- <TabContent tabId="tab-1" name="Tab name 1">
126
- <div>Content</div>
127
- </TabContent>
128
- <TabContent tabId="tab-2" name="Tab name 2">
129
- <div>Content</div>
130
- </TabContent>
131
- </Tabs>
132
- );
133
-
134
- expect(screen.getByTestId("tabs-test-selected-border")).toBeInTheDocument();
135
- });
136
-
137
122
  it("should not render selected border for contained variant", () => {
138
123
  render(
139
124
  <Tabs variant="contained" data-testid="tabs-test">
@@ -149,21 +134,6 @@ describe("Tabs", () => {
149
134
  expect(screen.queryByTestId("tabs-test-selected-border")).not.toBeInTheDocument();
150
135
  });
151
136
 
152
- it("should not render selected border for contained-negative variant", () => {
153
- render(
154
- <Tabs variant="contained-negative" data-testid="tabs-test">
155
- <TabContent tabId="tab-1" name="Tab name 1">
156
- <div>Content</div>
157
- </TabContent>
158
- <TabContent tabId="tab-2" name="Tab name 2">
159
- <div>Content</div>
160
- </TabContent>
161
- </Tabs>
162
- );
163
-
164
- expect(screen.queryByTestId("tabs-test-selected-border")).not.toBeInTheDocument();
165
- });
166
-
167
137
  it("should throw error if duplicate tabId is found", () => {
168
138
  expect(() => {
169
139
  render(
package/src/tabs.tsx CHANGED
@@ -11,6 +11,7 @@ import { createTabChangeDetailEvent, TabChangeDetail, TabsCmp, TabsVariant } fro
11
11
  type TabsProps = {
12
12
  children: Array<ReactElement<typeof TabContent>> | ReactElement<typeof TabContent>;
13
13
  variant?: TabsVariant;
14
+ negative?: boolean;
14
15
  fullWidth?: boolean;
15
16
  /**
16
17
  * Event handler called when the value changes.
@@ -66,6 +67,7 @@ const scrollToTarget = (target: HTMLElement, tabList?: HTMLDivElement | null) =>
66
67
  export const Tabs: TabsCmp<TabsProps> = ({
67
68
  children,
68
69
  variant = "line",
70
+ negative = false,
69
71
  fullWidth = false,
70
72
  onChange,
71
73
  className,
@@ -80,11 +82,11 @@ export const Tabs: TabsCmp<TabsProps> = ({
80
82
  const tabList = useRef<HTMLDivElement | null>();
81
83
  const tabChildren = useRef<HTMLButtonElement[]>(new Array(tabContentChildren.length));
82
84
  const sideScrollAdjustmentSize = 200;
83
- const isLineVariant = variant === "line" || variant === "line-negative";
85
+ const isLineVariant = variant === "line";
84
86
 
85
87
  const classNames = cx([
86
88
  rootClassName,
87
- `${rootClassName}--${variant}`,
89
+ `${rootClassName}--${variant}${negative ? "-negative" : ""}`,
88
90
  { [`${rootClassName}--fullWidth`]: fullWidth },
89
91
  className,
90
92
  ]);
@@ -147,11 +149,11 @@ export const Tabs: TabsCmp<TabsProps> = ({
147
149
  return () => {
148
150
  window.removeEventListener("resize", handleLinePosition);
149
151
  };
150
- }, []);
152
+ }, []); // eslint-disable-line react-hooks/exhaustive-deps
151
153
 
152
154
  useEffect(() => {
153
155
  handleLinePosition();
154
- }, [activeIndex, fullWidth, tabContentChildren, variant]);
156
+ }, [activeIndex, fullWidth, tabContentChildren.length, variant]); // eslint-disable-line react-hooks/exhaustive-deps
155
157
 
156
158
  useEffect(() => {
157
159
  const onIntersection = (entries: IntersectionObserverEntry[]): void => {
@@ -186,10 +188,12 @@ export const Tabs: TabsCmp<TabsProps> = ({
186
188
  root: tabList.current,
187
189
  });
188
190
 
189
- tabChildren.current.forEach((el) => observer.observe(el));
191
+ const currentTabChildren = tabChildren.current;
192
+
193
+ currentTabChildren.forEach((el) => observer.observe(el));
190
194
 
191
195
  return () => {
192
- tabChildren.current.forEach((el) => observer.unobserve(el));
196
+ currentTabChildren.forEach((el) => observer.unobserve(el));
193
197
  };
194
198
  }, [tabContentChildren.length]);
195
199
 
@@ -225,6 +229,7 @@ export const Tabs: TabsCmp<TabsProps> = ({
225
229
  scrollToTarget(e.target as HTMLElement, tabList.current);
226
230
  }}
227
231
  variant={variant}
232
+ negative={negative}
228
233
  >
229
234
  {name}
230
235
  </TabHeader>
package/src/tabs.utils.ts CHANGED
@@ -4,7 +4,7 @@ export type TabsCmp<P> = React.FunctionComponent<P> & {
4
4
  Content: typeof TabContent;
5
5
  };
6
6
 
7
- export const tabsVariants = ["line", "line-negative", "contained", "contained-negative"] as const;
7
+ export const tabsVariants = ["line", "contained"] as const;
8
8
 
9
9
  export type TabsVariant = (typeof tabsVariants)[number];
10
10