hds-web 1.0.3 → 1.0.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.
- package/dist/index.css +2 -2
- package/dist/index.es.css +2 -2
- package/dist/index.es.js +1 -1
- package/dist/index.js +3 -3
- package/package.json +1 -1
- package/src/HDS/components/Tables/tableB.js +132 -33
- package/src/HDS/components/Tabs/import React, { useState, useRef } from .js +61 -0
- package/src/HDS/components/Tabs/tab.js +59 -45
- package/src/HDS/components/index.js +2 -1
- package/src/HDS/modules/TextCard/textCard.js +0 -1
- package/src/index.css +32 -0
- package/src/styles/tailwind.css +118 -220
package/package.json
CHANGED
@@ -1,21 +1,21 @@
|
|
1
1
|
import React from 'react';
|
2
|
+
import { useState } from 'react';
|
2
3
|
import { v4 as uuidv4 } from 'uuid';
|
3
4
|
import { Typography } from '../../foundation/Typography'
|
4
5
|
import { Icon } from '../common-components/Icon'
|
6
|
+
import { Tab } from '../Tabs'
|
5
7
|
|
6
|
-
const
|
7
|
-
|
8
|
-
|
8
|
+
const tabs = [
|
9
|
+
{ name: 'My Account', href: '', current: false },
|
10
|
+
{ name: 'Company', href: '', current: false },
|
11
|
+
{ name: 'Team Members', href: '', current: true },
|
12
|
+
{ name: 'Billing', href: '', current: false },
|
13
|
+
]
|
9
14
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
>
|
15
|
-
{key}
|
16
|
-
</th>
|
17
|
-
))
|
18
|
-
)
|
15
|
+
function handleTabClick(tab) {
|
16
|
+
console.log(`Tab "${tab.name}" updatedTabs`);
|
17
|
+
// Perform any other actions based on the clicked tab
|
18
|
+
}
|
19
19
|
|
20
20
|
export default function TableB(props) {
|
21
21
|
const {
|
@@ -24,31 +24,130 @@ export default function TableB(props) {
|
|
24
24
|
TABLE_VALUE,
|
25
25
|
TABLE_HEADER,
|
26
26
|
children
|
27
|
-
|
28
27
|
} = props;
|
29
|
-
|
28
|
+
const [activeTab, setActiveTab] = useState(0);
|
30
29
|
return (
|
31
|
-
<div className="
|
32
|
-
<div className="sm:flex sm:items-center ">
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
30
|
+
<div className=" max-w-7xl">
|
31
|
+
<div className="sm:flex sm:items-center flex justify-around ">
|
32
|
+
|
33
|
+
<div className="w-full items-center flex justify-around md:flex md:flex-col md:items-center">
|
34
|
+
<div>
|
35
|
+
|
36
|
+
|
37
|
+
{title && (
|
38
|
+
<Typography
|
39
|
+
textStyle='h3'>
|
40
|
+
{title}
|
41
|
+
</Typography>
|
42
|
+
)
|
43
|
+
}
|
44
|
+
{/* {description && (
|
42
45
|
<Typography
|
43
46
|
textStyle='body1c'>
|
44
47
|
{description}
|
45
48
|
</Typography>
|
46
49
|
)
|
47
|
-
}
|
50
|
+
} */}
|
51
|
+
</div>
|
52
|
+
<div className=''>
|
53
|
+
<Tab onTabClick={handleTabClick} tabs={tabs} />
|
54
|
+
</div>
|
48
55
|
</div>
|
49
56
|
</div>
|
50
57
|
|
51
|
-
<div>
|
58
|
+
{/* <div className=''>
|
59
|
+
<div className="-mx-4 mt-8 sm:-mx-0 bg-neutral-0 rounded-3xl ">
|
60
|
+
<table className="min-w-full shadow rounded-3xl ">
|
61
|
+
<thead>
|
62
|
+
<tr className='divide-x divide-neutral-200 text-center rounded-t-3xl'>
|
63
|
+
<th
|
64
|
+
key={activeTab}
|
65
|
+
scope="col"
|
66
|
+
className="px-8 py-6 sm:table-cell"
|
67
|
+
>
|
68
|
+
<div className=''>
|
69
|
+
<div className='flex flex-col justify-center items-center text-center'>
|
70
|
+
<div className={'flex items-center gap-2'}>
|
71
|
+
{TABLE_HEADER[activeTab]['icon'] &&
|
72
|
+
(
|
73
|
+
<Icon
|
74
|
+
height='h-6 w-6'
|
75
|
+
variant={TABLE_HEADER[activeTab]['icon']}
|
76
|
+
strokeClass={TABLE_HEADER[activeTab]['iconStrokeClass']} />
|
77
|
+
)
|
78
|
+
}
|
79
|
+
{
|
80
|
+
TABLE_HEADER[activeTab]['title'] && activeTab == 0 && (
|
81
|
+
<Typography
|
82
|
+
textStyle='h5'
|
83
|
+
className={TABLE_HEADER[activeTab]['title_text_color']}>
|
84
|
+
{TABLE_HEADER[activeTab]['title']}
|
85
|
+
</Typography>)
|
86
|
+
}
|
87
|
+
{
|
88
|
+
TABLE_HEADER[activeTab]['title'] && activeTab != 0 && (
|
89
|
+
<Typography
|
90
|
+
textStyle='h5'
|
91
|
+
className={TABLE_HEADER[activeTab]['title_text_color']}>
|
92
|
+
{TABLE_HEADER[activeTab]['title']}
|
93
|
+
</Typography>)
|
94
|
+
}
|
95
|
+
|
96
|
+
|
97
|
+
</div>
|
98
|
+
<div className=' max-w-[10rem]'>
|
99
|
+
{TABLE_HEADER[activeTab]['descr'] && (
|
100
|
+
<Typography
|
101
|
+
textStyle='body1'
|
102
|
+
className={TABLE_HEADER[activeTab]['descr_text_color']}>
|
103
|
+
{TABLE_HEADER[activeTab]['descr']}
|
104
|
+
</Typography>)}
|
105
|
+
</div>
|
106
|
+
</div>
|
107
|
+
</div>
|
108
|
+
</th>
|
109
|
+
</tr>
|
110
|
+
</thead>
|
111
|
+
<tbody className="divide-y divide-neutral-200 rounded-b-3xl">
|
112
|
+
{TABLE_VALUE.map((value) => (
|
113
|
+
<tr className='divide-x divide-neutral-200' key={uuidv4()}>
|
114
|
+
{Object.keys(value).map((key) => (
|
115
|
+
<React.Fragment key={uuidv4()}>
|
116
|
+
{key === 'rowTitle' && (<td
|
117
|
+
key={uuidv4()}
|
118
|
+
className="px-8 py-7 w-[22.5rem] whitespace-pre-line "
|
119
|
+
>
|
120
|
+
<Typography className='max-w-[22rem] text-neutral-700' textStyle='body1c'>{value[key]}</Typography>
|
121
|
+
|
122
|
+
</td>)}
|
123
|
+
|
124
|
+
{key !== 'rowTitle' && (
|
125
|
+
<td
|
126
|
+
key={uuidv4()}
|
127
|
+
className="px-8 py-7 text-center"
|
128
|
+
>
|
129
|
+
{value[key]['text'] && (
|
130
|
+
<Typography className='text-neutral-700' textStyle='body1c'>{value[key]['text']}</Typography>
|
131
|
+
|
132
|
+
)}
|
133
|
+
{!value[key]['text'] && (
|
134
|
+
<div className='flex justify-center'>
|
135
|
+
<Icon height='h-5 w-5' variant={value[key]['iconVariant']} strokeClass={value[key]['iconStrokeClass']} />
|
136
|
+
</div>
|
137
|
+
)}
|
138
|
+
|
139
|
+
|
140
|
+
</td>)}
|
141
|
+
</React.Fragment>
|
142
|
+
))}
|
143
|
+
</tr>
|
144
|
+
))}
|
145
|
+
</tbody>
|
146
|
+
</table>
|
147
|
+
</div>
|
148
|
+
</div> */}
|
149
|
+
|
150
|
+
<div className='hidden md:block' >
|
52
151
|
<div className="-mx-4 mt-8 sm:-mx-0 bg-neutral-0 rounded-3xl ">
|
53
152
|
<table className="min-w-full shadow rounded-3xl ">
|
54
153
|
<thead>
|
@@ -71,7 +170,7 @@ export default function TableB(props) {
|
|
71
170
|
)
|
72
171
|
}
|
73
172
|
{
|
74
|
-
TABLE_HEADER[key]['title'] && key==0 && (
|
173
|
+
TABLE_HEADER[key]['title'] && key == 0 && (
|
75
174
|
<Typography
|
76
175
|
textStyle='h5'
|
77
176
|
className={TABLE_HEADER[key]['title_text_color']}>
|
@@ -79,15 +178,15 @@ export default function TableB(props) {
|
|
79
178
|
</Typography>)
|
80
179
|
}
|
81
180
|
{
|
82
|
-
TABLE_HEADER[key]['title'] && key!=0 && (
|
181
|
+
TABLE_HEADER[key]['title'] && key != 0 && (
|
83
182
|
<Typography
|
84
183
|
textStyle='h5'
|
85
184
|
className={TABLE_HEADER[key]['title_text_color']}>
|
86
185
|
{TABLE_HEADER[key]['title']}
|
87
186
|
</Typography>)
|
88
187
|
}
|
89
|
-
|
90
|
-
|
188
|
+
|
189
|
+
|
91
190
|
</div>
|
92
191
|
<div className=' max-w-[10rem]'>
|
93
192
|
{TABLE_HEADER[key]['descr'] && (
|
@@ -107,7 +206,7 @@ export default function TableB(props) {
|
|
107
206
|
{TABLE_VALUE.map((value) => (
|
108
207
|
<tr className='divide-x divide-neutral-200' key={uuidv4()}>
|
109
208
|
{Object.keys(value).map((key) => (
|
110
|
-
|
209
|
+
<React.Fragment key={uuidv4()}>
|
111
210
|
{key === 'rowTitle' && (<td
|
112
211
|
key={uuidv4()}
|
113
212
|
className="px-8 py-7 w-[22.5rem] whitespace-pre-line "
|
@@ -133,7 +232,7 @@ export default function TableB(props) {
|
|
133
232
|
|
134
233
|
|
135
234
|
</td>)}
|
136
|
-
|
235
|
+
</React.Fragment>
|
137
236
|
))}
|
138
237
|
</tr>
|
139
238
|
))}
|
@@ -0,0 +1,61 @@
|
|
1
|
+
import React, { useState, useRef, useEffect } from 'react';
|
2
|
+
|
3
|
+
export default function Tab(props) {
|
4
|
+
const { tabs, onTabClick } = props;
|
5
|
+
const [activeTab, setActiveTab] = useState(tabs.find(tab => tab.current) || tabs[0]);
|
6
|
+
const pillRef = useRef(null);
|
7
|
+
const activeTabRef = useRef(null);
|
8
|
+
|
9
|
+
const handleTabClick = (event, clickedTab) => {
|
10
|
+
event.preventDefault();
|
11
|
+
setActiveTab(clickedTab);
|
12
|
+
if (onTabClick) {
|
13
|
+
onTabClick(clickedTab);
|
14
|
+
}
|
15
|
+
};
|
16
|
+
|
17
|
+
useEffect(() => {
|
18
|
+
// Update the pill position and height when activeTab changes
|
19
|
+
const pill = pillRef.current;
|
20
|
+
const activeTabElement = activeTabRef.current;
|
21
|
+
|
22
|
+
if (pill && activeTabElement) {
|
23
|
+
const pillWidth = activeTabElement.offsetWidth;
|
24
|
+
const pillHeight = activeTabElement.offsetHeight;
|
25
|
+
const pillOffset = activeTabElement.offsetLeft;
|
26
|
+
|
27
|
+
pill.style.transform = `translateX(${pillOffset}px)`;
|
28
|
+
pill.style.width = `${pillWidth}px`;
|
29
|
+
pill.style.height = `${pillHeight}px`;
|
30
|
+
}
|
31
|
+
}, [activeTab]);
|
32
|
+
|
33
|
+
return (
|
34
|
+
<div>
|
35
|
+
<div className="hidden md:block">
|
36
|
+
<nav className="relative inline-flex bg-neutral-0 p-2 rounded-full" aria-label="Tabs">
|
37
|
+
{tabs.map((tab, index) => (
|
38
|
+
<a
|
39
|
+
key={tab.name}
|
40
|
+
href="#"
|
41
|
+
className={`relative px-3 py-1 font-medium text-sm rounded-full ${
|
42
|
+
activeTab === tab
|
43
|
+
? 'bg-blue-600 text-neutral-0 z-10' // Increase z-index for active tab
|
44
|
+
: 'text-neutral-500 bg-neutral-0 hover:bg-neutral-100 flex-nowrap transition-all duration-500'
|
45
|
+
}`}
|
46
|
+
aria-current={activeTab === tab ? 'page' : undefined}
|
47
|
+
onClick={(event) => handleTabClick(event, tab)}
|
48
|
+
ref={activeTab === tab ? activeTabRef : null}
|
49
|
+
>
|
50
|
+
{tab.name}
|
51
|
+
</a>
|
52
|
+
))}
|
53
|
+
<span
|
54
|
+
ref={pillRef}
|
55
|
+
className="absolute bg-blue-600 rounded-full transition-all duration-500 z-0 -mt-px" // Add negative margin to counteract the gap
|
56
|
+
/>
|
57
|
+
</nav>
|
58
|
+
</div>
|
59
|
+
</div>
|
60
|
+
);
|
61
|
+
}
|
@@ -1,47 +1,61 @@
|
|
1
|
-
import React from 'react';
|
1
|
+
import React, { useState, useRef } from 'react';
|
2
|
+
import { Typography } from '../../foundation/Typography'
|
2
3
|
|
3
|
-
function
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
4
|
+
export default function Tab(props) {
|
5
|
+
const { tabs, onTabClick } = props;
|
6
|
+
const [activeTab, setActiveTab] = useState(tabs.find(tab => tab.current) || tabs[0]);
|
7
|
+
const pillRef = useRef(null);
|
8
|
+
|
9
|
+
const handleTabClick = (event, clickedTab) => {
|
10
|
+
event.preventDefault();
|
11
|
+
setActiveTab(clickedTab);
|
12
|
+
if (onTabClick) {
|
13
|
+
onTabClick(clickedTab);
|
14
|
+
}
|
15
|
+
|
16
|
+
// Move the pill indicator to the clicked tab
|
17
|
+
const pill = pillRef.current;
|
18
|
+
if (pill) {
|
19
|
+
const pillWidth = event.currentTarget.offsetWidth;
|
20
|
+
const clickedTabOffset = event.currentTarget.offsetLeft;
|
21
|
+
const pillOffset = pill.parentElement.offsetLeft;
|
22
|
+
const translateX = clickedTabOffset ;
|
23
|
+
|
24
|
+
pill.style.transform = `translateX(${translateX}px)`;
|
25
|
+
pill.style.width = `${pillWidth}px`;
|
26
|
+
}
|
27
|
+
};
|
28
|
+
|
29
|
+
return (
|
30
|
+
<div>
|
31
|
+
<div className="block">
|
32
|
+
<nav className="relative inline-flex gap-2 p-2 rounded-full" aria-label="Tabs">
|
33
|
+
{tabs.map(tab => (
|
34
|
+
<a
|
35
|
+
key={tab.name}
|
36
|
+
href="#"
|
37
|
+
className={`px-3 py-1 font-medium text-sm rounded-full ${
|
38
|
+
activeTab === tab
|
39
|
+
? 'bg-blue-600 text-neutral-0'
|
40
|
+
: 'text-neutral-500 bg-neutral-0 hover:bg-neutral-100 flex-nowrap transition-all duration-500'
|
41
|
+
}`}
|
42
|
+
aria-current={activeTab === tab ? 'page' : undefined}
|
43
|
+
onClick={(event) => handleTabClick(event, tab)}
|
44
|
+
>
|
45
|
+
<Typography className='z-10 whitespace-nowrap' textStyle='body3c-medium'>{tab.name}</Typography>
|
46
|
+
</a>
|
47
|
+
))}
|
48
|
+
<span
|
49
|
+
ref={pillRef}
|
50
|
+
className="absolute left-0 -z-10 bg-blue-600 rounded-full transition-all ease-in-out duration-500"
|
51
|
+
style={{
|
52
|
+
left: `${activeTab.index * 100}%`,
|
53
|
+
width: `${activeTab.width}px`, // Use the width of the clicked tab
|
54
|
+
height: '28px' // Add desired height to make the pill visible
|
55
|
+
}}
|
56
|
+
/>
|
57
|
+
</nav>
|
44
58
|
</div>
|
45
|
-
|
46
|
-
|
47
|
-
|
59
|
+
</div>
|
60
|
+
);
|
61
|
+
}
|
package/src/index.css
CHANGED
@@ -3,6 +3,38 @@
|
|
3
3
|
@tailwind utilities;
|
4
4
|
/* Typography classes */
|
5
5
|
|
6
|
+
|
7
|
+
@keyframes pill-move-left {
|
8
|
+
0% {
|
9
|
+
left: 0;
|
10
|
+
width: 0%;
|
11
|
+
}
|
12
|
+
50% {
|
13
|
+
left: 0;
|
14
|
+
width: 100%;
|
15
|
+
}
|
16
|
+
100% {
|
17
|
+
left: 0;
|
18
|
+
width: 0%;
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
@keyframes pill-move-right {
|
23
|
+
0% {
|
24
|
+
left: 0;
|
25
|
+
width: 0%;
|
26
|
+
}
|
27
|
+
50% {
|
28
|
+
left: 100%;
|
29
|
+
width: 0%;
|
30
|
+
}
|
31
|
+
100% {
|
32
|
+
left: 0;
|
33
|
+
width: 0%;
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
|
6
38
|
.card-animation-wrapper {
|
7
39
|
position: relative;
|
8
40
|
}
|