@purpurds/tabs 4.3.0 → 4.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.
@@ -1,4 +1,5 @@
1
- import { TabContent } from "./tab-content";
1
+ import { TabContent } from './tab-content';
2
+
2
3
  export type TabsCmp<P> = React.FunctionComponent<P> & {
3
4
  Content: typeof TabContent;
4
5
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@purpurds/tabs",
3
- "version": "4.3.0",
3
+ "version": "4.4.0",
4
4
  "license": "AGPL-3.0-only",
5
5
  "main": "./dist/tabs.cjs.js",
6
6
  "types": "./dist/tabs.d.ts",
@@ -16,32 +16,32 @@
16
16
  "dependencies": {
17
17
  "classnames": "~2.5.0",
18
18
  "@radix-ui/react-tabs": "~1.0.4",
19
- "@purpurds/icon": "4.3.0",
20
- "@purpurds/paragraph": "4.3.0",
21
- "@purpurds/tokens": "4.3.0"
19
+ "@purpurds/tokens": "4.4.0",
20
+ "@purpurds/icon": "4.4.0",
21
+ "@purpurds/paragraph": "4.4.0"
22
22
  },
23
23
  "devDependencies": {
24
- "@rushstack/eslint-patch": "~1.7.0",
24
+ "@rushstack/eslint-patch": "~1.10.0",
25
25
  "@storybook/blocks": "~7.6.0",
26
26
  "@storybook/react": "~7.6.0",
27
27
  "@telia/base-rig": "~8.2.0",
28
28
  "@telia/react-rig": "~3.2.0",
29
29
  "@testing-library/dom": "~9.3.3",
30
30
  "@testing-library/jest-dom": "~6.4.0",
31
- "@testing-library/react": "~14.2.0",
31
+ "@testing-library/react": "~14.3.0",
32
32
  "@types/node": "18",
33
- "@types/react-dom": "~18.2.17",
34
- "@types/react": "~18.2.42",
33
+ "@types/react-dom": "~18.3.0",
34
+ "@types/react": "~18.3.0",
35
35
  "eslint-plugin-testing-library": "~6.2.0",
36
36
  "eslint": "~8.57.0",
37
37
  "jsdom": "~22.1.0",
38
38
  "lint-staged": "~10.5.3",
39
39
  "prettier": "~2.8.8",
40
- "react-dom": "~18.2.0",
41
- "react": "~18.2.0",
40
+ "react-dom": "~18.3.0",
41
+ "react": "~18.3.0",
42
42
  "typescript": "~5.4.2",
43
43
  "vite": "~5.2.2",
44
- "vitest": "~1.4.0",
44
+ "vitest": "~1.5.0",
45
45
  "@purpurds/component-rig": "1.0.0"
46
46
  },
47
47
  "scripts": {
@@ -30,6 +30,57 @@ 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
+
33
84
  export const Showcase: Story = {
34
85
  args: {
35
86
  variant: tabsVariants[0],
@@ -68,8 +119,8 @@ export const Showcase: Story = {
68
119
  background: args.variant?.includes("negative")
69
120
  ? "var(--purpur-color-purple-900)"
70
121
  : args.variant === "contained"
71
- ? "var(--purpur-color-gray-50)"
72
- : "transparent",
122
+ ? "var(--purpur-color-gray-50)"
123
+ : "transparent",
73
124
  color: `var(--purpur-color-text-default${
74
125
  args.variant === "line-negative" ? "-negative" : ""
75
126
  }`,
package/src/tabs.test.tsx CHANGED
@@ -3,9 +3,9 @@ import * as matchers from "@testing-library/jest-dom/matchers";
3
3
  import { cleanup, render, screen } from "@testing-library/react";
4
4
  import { afterEach, describe, expect, it } from "vitest";
5
5
 
6
- import { Tabs } from "./tabs";
7
- import { TabContent } from "./tab-content";
8
6
  import "./__mocks__/intersectionObserverMock";
7
+ import { TabContent } from "./tab-content";
8
+ import { Tabs } from "./tabs";
9
9
 
10
10
  const rootClassName = "purpur-tabs";
11
11
 
@@ -71,6 +71,24 @@ describe("Tabs", () => {
71
71
  expect(screen.getAllByTestId(testId).length).toEqual(2);
72
72
  });
73
73
 
74
+ it("should render second tab active if defaultValue prop provided", () => {
75
+ const testId = "tab-content";
76
+
77
+ render(
78
+ <Tabs defaultValue="tab-2">
79
+ <TabContent tabId="tab-1" name="Tab name 1" data-testid={`${testId}-1`}>
80
+ <div>Content</div>
81
+ </TabContent>
82
+ <TabContent tabId="tab-2" name="Tab name 2" data-testid={`${testId}-2`}>
83
+ <div>Content 2</div>
84
+ </TabContent>
85
+ </Tabs>
86
+ );
87
+
88
+ expect(screen.queryByTestId(`${testId}-1`)?.getAttribute("data-state")).toBe("inactive");
89
+ expect(screen.queryByTestId(`${testId}-2`)?.getAttribute("data-state")).toBe("active");
90
+ });
91
+
74
92
  it("should render two scroll buttons", () => {
75
93
  render(
76
94
  <Tabs data-testid="tabs-test">
package/src/tabs.tsx CHANGED
@@ -17,6 +17,7 @@ type TabsProps = {
17
17
  * */
18
18
  onChange?: (event: CustomEvent<TabChangeDetail>) => void;
19
19
  className?: string;
20
+ defaultValue?: string;
20
21
  "data-testid"?: string;
21
22
  };
22
23
 
@@ -68,10 +69,10 @@ export const Tabs: TabsCmp<TabsProps> = ({
68
69
  fullWidth = false,
69
70
  onChange,
70
71
  className,
72
+ defaultValue,
71
73
  "data-testid": dataTestId,
72
74
  ...props
73
75
  }) => {
74
- const [activeIndex, setActiveIndex] = useState(0);
75
76
  const [scrollClasses, setScrollClasses] = useState<{ [key: string]: boolean }>({});
76
77
  const [selectedTriggerOffset, setSelectedTriggerOffset] = useState(0);
77
78
  const [selectedTriggerWidth, setSelectedTriggerWidth] = useState(0);
@@ -90,6 +91,9 @@ export const Tabs: TabsCmp<TabsProps> = ({
90
91
 
91
92
  const tabIds = Children.map(tabContentChildren, ({ props: { tabId } }) => tabId);
92
93
 
94
+ const getDefaultTabIndex = () => tabIds.findIndex((tabIndex) => tabIndex === defaultValue) || 0;
95
+ const [activeIndex, setActiveIndex] = useState(getDefaultTabIndex);
96
+
93
97
  if (new Set(tabIds).size !== tabIds.length) {
94
98
  throw new Error("tabId must be unique");
95
99
  }
@@ -191,7 +195,7 @@ export const Tabs: TabsCmp<TabsProps> = ({
191
195
 
192
196
  return (
193
197
  <Root
194
- defaultValue={tabContentChildren[0].props.tabId}
198
+ defaultValue={defaultValue}
195
199
  onValueChange={handleTabChange}
196
200
  data-testid={dataTestId}
197
201
  className={classNames}