@rovula/ui 0.0.51 → 0.0.53

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.
Files changed (63) hide show
  1. package/dist/cjs/bundle.css +50 -11
  2. package/dist/cjs/bundle.js +2 -2
  3. package/dist/cjs/bundle.js.map +1 -1
  4. package/dist/cjs/types/components/Tabs/Tabs.d.ts +14 -1
  5. package/dist/cjs/types/components/Tabs/Tabs.stories.d.ts +81 -2
  6. package/dist/cjs/types/components/Tree/Tree.stories.d.ts +3 -0
  7. package/dist/cjs/types/components/Tree/example-data.d.ts +5 -0
  8. package/dist/cjs/types/components/Tree/type.d.ts +14 -4
  9. package/dist/components/Tabs/Tabs.js +35 -18
  10. package/dist/components/Tabs/Tabs.stories.js +70 -3
  11. package/dist/components/Tree/Tree.js +7 -4
  12. package/dist/components/Tree/Tree.stories.js +34 -2090
  13. package/dist/components/Tree/TreeItem.js +16 -8
  14. package/dist/components/Tree/example-data.js +2125 -0
  15. package/dist/esm/bundle.css +50 -11
  16. package/dist/esm/bundle.js +2 -2
  17. package/dist/esm/bundle.js.map +1 -1
  18. package/dist/esm/types/components/Tabs/Tabs.d.ts +14 -1
  19. package/dist/esm/types/components/Tabs/Tabs.stories.d.ts +81 -2
  20. package/dist/esm/types/components/Tree/Tree.stories.d.ts +3 -0
  21. package/dist/esm/types/components/Tree/example-data.d.ts +5 -0
  22. package/dist/esm/types/components/Tree/type.d.ts +14 -4
  23. package/dist/index.d.ts +27 -5
  24. package/dist/src/theme/global.css +36 -1164
  25. package/dist/theme/global.css +0 -1
  26. package/package.json +6 -1
  27. package/src/components/Tabs/Tabs.css +21 -0
  28. package/src/components/Tabs/Tabs.stories.tsx +140 -4
  29. package/src/components/Tabs/Tabs.tsx +134 -50
  30. package/src/components/Tree/Tree.stories.tsx +58 -2124
  31. package/src/components/Tree/Tree.tsx +17 -3
  32. package/src/components/Tree/TreeItem.tsx +47 -17
  33. package/src/components/Tree/example-data.ts +2162 -0
  34. package/src/components/Tree/type.ts +18 -4
  35. package/src/theme/global.css +0 -1
  36. package/dist/theme/themes/SKL/baseline.css +0 -12
  37. package/dist/theme/themes/SKL/color.css +0 -78
  38. package/dist/theme/themes/SKL/components/action-button.css +0 -127
  39. package/dist/theme/themes/SKL/components/button.css +0 -512
  40. package/dist/theme/themes/SKL/components/dropdown-menu.css +0 -27
  41. package/dist/theme/themes/SKL/components/loading.css +0 -11
  42. package/dist/theme/themes/SKL/components/navbar.css +0 -8
  43. package/dist/theme/themes/SKL/components/progress-bar.css +0 -8
  44. package/dist/theme/themes/SKL/components/switch.css +0 -30
  45. package/dist/theme/themes/SKL/palette.css +0 -145
  46. package/dist/theme/themes/SKL/state.css +0 -86
  47. package/dist/theme/themes/SKL/transparent.css +0 -68
  48. package/dist/theme/themes/SKL/typography.css +0 -199
  49. package/dist/theme/themes/SKL/variables.css +0 -28
  50. package/src/theme/themes/SKL/baseline.css +0 -12
  51. package/src/theme/themes/SKL/color.css +0 -78
  52. package/src/theme/themes/SKL/components/action-button.css +0 -127
  53. package/src/theme/themes/SKL/components/button.css +0 -512
  54. package/src/theme/themes/SKL/components/dropdown-menu.css +0 -27
  55. package/src/theme/themes/SKL/components/loading.css +0 -11
  56. package/src/theme/themes/SKL/components/navbar.css +0 -8
  57. package/src/theme/themes/SKL/components/progress-bar.css +0 -8
  58. package/src/theme/themes/SKL/components/switch.css +0 -30
  59. package/src/theme/themes/SKL/palette.css +0 -145
  60. package/src/theme/themes/SKL/state.css +0 -86
  61. package/src/theme/themes/SKL/transparent.css +0 -68
  62. package/src/theme/themes/SKL/typography.css +0 -199
  63. package/src/theme/themes/SKL/variables.css +0 -28
@@ -1,7 +1,6 @@
1
1
 
2
2
  @import "./tokens/baseline.css";
3
3
  @import "./themes/xspector/baseline.css";
4
- @import "./themes/SKL/baseline.css";
5
4
 
6
5
  @tailwind base;
7
6
  @tailwind components;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rovula/ui",
3
- "version": "0.0.51",
3
+ "version": "0.0.53",
4
4
  "main": "dist/cjs/bundle.js",
5
5
  "module": "dist/esm/bundle.js",
6
6
  "types": "dist/index.d.ts",
@@ -15,6 +15,7 @@
15
15
  "public": "npm run build:package && npm publish --access=public",
16
16
  "storybook:serve-css": "npx tailwindcss -i ./src/theme/global.css -o ./dist/src/theme/global.css",
17
17
  "storybook": "storybook dev -p 6006",
18
+ "storybook:docker": "storybook dev -p 6006 --no-open",
18
19
  "build-storybook": "storybook build",
19
20
  "chromatic": "npx chromatic --project-token=chpt_cee098dd3b9b3ee",
20
21
  "deploy-storybook": "npx wrangler pages deploy storybook-static --project-name=rovula-ui --branch=main"
@@ -105,6 +106,10 @@
105
106
  "react": "^17.0.0 || ^18.0.0",
106
107
  "react-dom": "^17.0.0 || ^18.0.0"
107
108
  },
109
+ "overrides": {
110
+ "rimraf": "^4.4.1",
111
+ "glob": "^9.3.5"
112
+ },
108
113
  "repository": {
109
114
  "type": "git",
110
115
  "url": ""
@@ -0,0 +1,21 @@
1
+ /* Scroll bar */
2
+ .tabs-scrollbar::-webkit-scrollbar {
3
+ height: 4px;
4
+ width: 4px;
5
+ background: rgba(0, 0, 0, 0.08);
6
+ }
7
+
8
+ .tabs-scrollbar::-webkit-scrollbar-thumb {
9
+ border-radius: 4px;
10
+ background: rgba(121, 141, 150, 0.48);
11
+ width: 4px;
12
+ }
13
+
14
+ .tabs-scrollbar::-webkit-scrollbar-thumb:hover {
15
+ background: rgba(251, 252, 253, 0.48);
16
+ cursor: pointer
17
+ }
18
+
19
+ .tabs-scrollbar::-webkit-scrollbar-corner {
20
+ display: none;
21
+ }
@@ -1,7 +1,10 @@
1
- import React from "react";
1
+ import React, { useState } from "react";
2
2
  import type { Meta, StoryObj } from "@storybook/react";
3
3
  import Tabs from "./Tabs";
4
4
  import { ChevronDownIcon, ArchiveBoxIcon } from "@heroicons/react/16/solid";
5
+ import ActionButton from "../ActionButton/ActionButton";
6
+ import Icon from "../Icon/Icon";
7
+ import { useArgs } from "@storybook/preview-api";
5
8
 
6
9
  const meta = {
7
10
  title: "Components/Tabs",
@@ -12,7 +15,7 @@ const meta = {
12
15
  },
13
16
  decorators: [
14
17
  (Story) => (
15
- <div className="p-5 flex w-full">
18
+ <div className="p-5 flex w-full bg-base-bg2">
16
19
  <Story />
17
20
  </div>
18
21
  ),
@@ -58,8 +61,8 @@ export const CustomTab = {
58
61
  initialTab: 0,
59
62
  tabs: tabs.map((tab) => ({
60
63
  ...tab,
61
- startTabContent: <ArchiveBoxIcon className="size-3 " />,
62
- endTabContent: <ChevronDownIcon className="size-3" />,
64
+ startTabContent: <ArchiveBoxIcon />,
65
+ endTabContent: <ChevronDownIcon />,
63
66
  })),
64
67
  },
65
68
  render: (args) => {
@@ -73,3 +76,136 @@ export const CustomTab = {
73
76
  );
74
77
  },
75
78
  } satisfies StoryObj;
79
+
80
+ // variant="scrollable"
81
+ export const TabWithLeftRightAction = {
82
+ args: {
83
+ initialTab: 0,
84
+ tabs: tabs.map((tab) => ({
85
+ ...tab,
86
+ })),
87
+ },
88
+ render: (args) => {
89
+ const props: typeof args = {
90
+ ...args,
91
+ };
92
+ return (
93
+ <div className="flex flex-row gap-4 w-full">
94
+ <Tabs
95
+ tabs={tabs}
96
+ {...props}
97
+ tabMode="start"
98
+ leftAction={
99
+ <ActionButton onClick={() => alert("left action")} className="mr-4">
100
+ <Icon name="academic-cap" />
101
+ </ActionButton>
102
+ }
103
+ rightAction={
104
+ <ActionButton
105
+ onClick={() => alert("right action")}
106
+ className="ml-4"
107
+ >
108
+ <Icon name="arrow-down-tray" />
109
+ </ActionButton>
110
+ }
111
+ />
112
+ </div>
113
+ );
114
+ },
115
+ } satisfies StoryObj;
116
+
117
+ export const AddTabWithScrolling = {
118
+ args: {
119
+ initialTab: 0,
120
+ tabs,
121
+ enableAddTabButton: true,
122
+ },
123
+ render: (args) => {
124
+ const props: any = {
125
+ ...args,
126
+ };
127
+
128
+ const [, setArgs] = useArgs();
129
+ return (
130
+ <div className="flex flex-row gap-4 w-[500px]">
131
+ <Tabs
132
+ tabs={tabs}
133
+ {...props}
134
+ tabMode="start"
135
+ onAddTab={() => {
136
+ setArgs({
137
+ tabs: [
138
+ ...props.tabs,
139
+ {
140
+ label: "Tab" + (props.tabs.length + 1),
141
+ content: <p>Tab {props.tabs.length + 1} content</p>,
142
+ },
143
+ ],
144
+ });
145
+ }}
146
+ />
147
+ </div>
148
+ );
149
+ },
150
+ } satisfies StoryObj;
151
+
152
+ export const KeepIconSpacing = {
153
+ args: {
154
+ initialTab: 0,
155
+ tabs,
156
+ keepIconSpace: true,
157
+ },
158
+ render: (args) => {
159
+ const props: any = {
160
+ ...args,
161
+ };
162
+ return (
163
+ <div className="flex flex-row gap-4 w-[500px]">
164
+ <Tabs tabs={tabs} {...props} tabMode="start" />
165
+ </div>
166
+ );
167
+ },
168
+ } satisfies StoryObj;
169
+
170
+ export const Loading = {
171
+ args: {
172
+ initialTab: 0,
173
+ tabs: tabs.map((tab, i) => ({
174
+ ...tab,
175
+ isLoading: i !== 0,
176
+ startTabContent: <Icon name="rocket-launch" />,
177
+ })),
178
+ },
179
+ render: (args) => {
180
+ const props: any = {
181
+ ...args,
182
+ };
183
+
184
+ return (
185
+ <div className="flex flex-row gap-4 w-[500px]">
186
+ <Tabs tabs={tabs} {...props} tabMode="start" />
187
+ </div>
188
+ );
189
+ },
190
+ } satisfies StoryObj;
191
+
192
+ export const Disabled = {
193
+ args: {
194
+ initialTab: 0,
195
+ tabs: tabs.map((tab, i) => ({
196
+ ...tab,
197
+ disabled: i !== 0,
198
+ })),
199
+ },
200
+ render: (args) => {
201
+ const props: any = {
202
+ ...args,
203
+ };
204
+ return (
205
+ <div className="flex flex-row gap-4">
206
+ <Tabs tabs={tabs} {...props} />
207
+ <Tabs tabs={tabs} {...props} disabled />
208
+ </div>
209
+ );
210
+ },
211
+ } satisfies StoryObj;
@@ -1,11 +1,17 @@
1
1
  import React, { useState, useRef, useEffect } from "react";
2
2
  import { cn } from "@/utils/cn";
3
+ import "./Tabs.css";
4
+ import ActionButton from "../ActionButton/ActionButton";
5
+ import Icon from "../Icon/Icon";
6
+ import { Loading } from "@/index";
3
7
 
4
8
  type Tab = {
5
9
  label: string;
6
10
  startTabContent?: React.ReactElement;
7
11
  endTabContent?: React.ReactElement;
8
12
  content: React.ReactNode;
13
+ disabled?: boolean;
14
+ isLoading?: boolean;
9
15
  };
10
16
 
11
17
  type TabsProps = {
@@ -14,12 +20,22 @@ type TabsProps = {
14
20
  tabBarSize?: number;
15
21
  tabMode?: "start" | "justify";
16
22
  enableBorderLine?: boolean;
23
+ enableAddTabButton?: boolean;
24
+ keepIconSpace?: boolean;
17
25
  className?: string;
18
26
  tabBarClassName?: string;
27
+ tabBarContainerClassName?: string;
28
+ tabBarWrapperClassName?: string;
19
29
  tabButtonClassName?: string;
20
30
  tabButtonActiveClassName?: string;
21
31
  tabContentClassName?: string;
22
- borderSliderClassname?: string;
32
+ addTabButtonWrapperClassName?: string;
33
+ borderSliderClassName?: string;
34
+ leftAction?: React.ReactNode;
35
+ rightAction?: React.ReactNode;
36
+ disabled?: boolean;
37
+ onAddTab?: () => void;
38
+ onTabChange?: (tabIndex: number) => void;
23
39
  };
24
40
 
25
41
  const Tabs: React.FC<TabsProps> = ({
@@ -27,13 +43,23 @@ const Tabs: React.FC<TabsProps> = ({
27
43
  initialTab = 0,
28
44
  tabBarSize = 38,
29
45
  enableBorderLine = true,
46
+ enableAddTabButton = false,
47
+ keepIconSpace = true,
48
+ disabled = false,
30
49
  tabMode = "start",
31
50
  className,
32
51
  tabBarClassName,
52
+ tabBarContainerClassName,
53
+ tabBarWrapperClassName,
33
54
  tabButtonClassName,
34
55
  tabButtonActiveClassName,
35
56
  tabContentClassName,
36
- borderSliderClassname,
57
+ addTabButtonWrapperClassName,
58
+ borderSliderClassName,
59
+ leftAction,
60
+ rightAction,
61
+ onAddTab,
62
+ onTabChange,
37
63
  }) => {
38
64
  const [activeTab, setActiveTab] = useState(initialTab);
39
65
  const [sliderStyle, setSliderStyle] = useState({
@@ -76,66 +102,124 @@ const Tabs: React.FC<TabsProps> = ({
76
102
  updateSliderStyle();
77
103
  }
78
104
 
79
- // const handleResize = () => {
80
- // updateSliderStyle();
81
- // };
105
+ const handleResize = () => {
106
+ updateSliderStyle();
107
+ };
82
108
 
83
- // window.addEventListener("resize", handleResize);
84
- // return () => window.removeEventListener("resize", handleResize);
85
- }, [activeTab, tabs, tabMode]);
109
+ window.addEventListener("resize", handleResize);
110
+ return () => window.removeEventListener("resize", handleResize);
111
+ }, [activeTab, tabs, tabMode, keepIconSpace]);
86
112
 
87
113
  return (
88
114
  <div className={cn("w-full", className)}>
89
115
  <div
90
- className={cn(
91
- `relative flex gap-6 h-[${tabBarSize}px] box-border`,
92
- {
93
- [`border-b-[1px] border-base-stroke`]: enableBorderLine,
94
- "gap-0": tabMode === "justify",
95
- },
96
- tabBarClassName
97
- )}
98
- style={{
99
- justifyContent: tabMode === "justify" ? "stretch" : tabMode,
100
- }}
101
- role="tablist"
116
+ className={cn(" relative flex flex-row w-full", {
117
+ [`border-b-[1px] border-base-stroke`]: enableBorderLine,
118
+ "border-state-disable-outline": disabled,
119
+ "flex-1": tabMode === "justify",
120
+ tabBarContainerClassName,
121
+ })}
102
122
  >
103
- {tabs.map((tab, index) => (
104
- <button
105
- key={index}
106
- ref={(el) => (tabRefs.current[index] = el)}
107
- role="tab"
108
- aria-selected={index === activeTab}
109
- aria-controls={`tab-content-${index}`}
110
- id={`tab-${index}`}
123
+ {leftAction}
124
+ <div
125
+ className={cn(
126
+ "relative flex flex-row overflow-x-auto",
127
+ {
128
+ "flex-1": tabMode === "justify",
129
+ },
130
+ tabBarWrapperClassName
131
+ )}
132
+ >
133
+ <div
111
134
  className={cn(
112
- "flex justify-center flex-row items-center py-4 px-1 cursor-pointer transition-colors duration-300 box-border gap-3",
135
+ "tabs-scrollbar overflow-x-auto w-full",
136
+ `relative flex gap-3 h-[${tabBarSize}px] box-border`,
113
137
  {
114
- "typography-small3 text-text-dark": index === activeTab,
115
- "typography-small1 text-text-grey-light hover:text-text-grey-dark active:text-text-dark":
116
- index !== activeTab,
117
- [tabButtonClassName ?? ""]: true,
118
- [tabButtonActiveClassName ?? ""]: index === activeTab,
119
- "flex-1": tabMode === "justify",
120
- }
138
+ "gap-0": tabMode === "justify",
139
+ },
140
+ tabBarClassName
121
141
  )}
122
- onClick={() => setActiveTab(index)}
142
+ style={{
143
+ justifyContent: tabMode === "justify" ? "stretch" : tabMode,
144
+ }}
145
+ role="tablist"
123
146
  >
124
- {tab.startTabContent}
125
- {tab.label}
126
- {tab.endTabContent}
127
- </button>
128
- ))}
129
- <div
130
- className={cn(
131
- `absolute -bottom-[1px] h-[1px] bg-primary transition-all duration-300 ease-in-out`,
132
- borderSliderClassname
133
- )}
134
- style={sliderStyle}
135
- />
147
+ {tabs.map((tab, index) => (
148
+ <button
149
+ key={index}
150
+ ref={(el) => (tabRefs.current[index] = el)}
151
+ role="tab"
152
+ aria-selected={index === activeTab}
153
+ aria-controls={`tab-content-${index}`}
154
+ disabled={disabled || tab.disabled}
155
+ id={`tab-${index}`}
156
+ className={cn(
157
+ "flex justify-center flex-row items-center py-3 cursor-pointer transition-colors duration-300 box-border gap-1 flex-shrink-0 typography-subtitile6",
158
+ {
159
+ "text-foreground": index === activeTab,
160
+ "text-text-grey-medium hover:text-text-grey-dark active:text-text-dark":
161
+ index !== activeTab,
162
+ "text-state-disable-solid pointer-events-none":
163
+ disabled || tab.disabled,
164
+ "text-state-disable-outline":
165
+ (index === activeTab && disabled) || tab.disabled,
166
+ [tabButtonClassName ?? ""]: true,
167
+ [tabButtonActiveClassName ?? ""]: index === activeTab,
168
+ "flex-1": tabMode === "justify",
169
+ }
170
+ )}
171
+ onClick={() => {
172
+ setActiveTab(index);
173
+ onTabChange?.(index);
174
+ }}
175
+ >
176
+ {(keepIconSpace || tab.startTabContent) && (
177
+ <div className="h-full w-3 flex items-center justify-center">
178
+ {tab.isLoading ? <Loading /> : tab.startTabContent}
179
+ </div>
180
+ )}
181
+ {tab.label}
182
+ {(keepIconSpace || tab.endTabContent) && (
183
+ <div className="h-full w-3 flex items-center justify-center">
184
+ {tab.endTabContent}
185
+ </div>
186
+ )}
187
+ </button>
188
+ ))}
189
+ <div
190
+ className={cn(
191
+ `absolute left-0 bottom-0 h-[2px] rounded-full bg-foreground transition-all duration-300 ease-in-out`,
192
+ {
193
+ "bg-state-disable-solid": disabled,
194
+ },
195
+ borderSliderClassName
196
+ )}
197
+ style={sliderStyle}
198
+ />
199
+ </div>
200
+ </div>
201
+ {enableAddTabButton && (
202
+ <div
203
+ className={cn(
204
+ "sticky right-0 flex content-center items-center mx-4",
205
+ addTabButtonWrapperClassName
206
+ )}
207
+ >
208
+ <ActionButton
209
+ variant="outline"
210
+ size="sm"
211
+ onClick={() => onAddTab?.()}
212
+ disabled={disabled}
213
+ >
214
+ <Icon name="plus" />
215
+ </ActionButton>
216
+ </div>
217
+ )}
218
+ {rightAction}
136
219
  </div>
220
+
137
221
  <div
138
- className={cn("mt-4", tabContentClassName)}
222
+ className={cn("mt-4 text-foreground", tabContentClassName)}
139
223
  role="tabpanel"
140
224
  id={`tab-content-${activeTab}`}
141
225
  aria-labelledby={`tab-${activeTab}`}