hds-web 1.0.2 → 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 +4 -4
- package/dist/index.js +3 -3
- package/package.json +1 -1
- package/src/HDS/components/Avatars/profileAvatar.js +2 -2
- package/src/HDS/components/BadgesCaption/badges.js +10 -10
- package/src/HDS/components/Cards/Misc/talkCard.js +22 -18
- package/src/HDS/components/Hero/h1.js +0 -1
- package/src/HDS/components/Hero/h2.js +3 -3
- package/src/HDS/components/Tables/tableB.js +201 -42
- 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/common-components/Icon/IconMap.js +1 -6
- package/src/HDS/components/index.js +2 -1
- package/src/HDS/foundation/ColorPalette/color.js +1 -1
- package/src/HDS/modules/TextCard/textCard.js +0 -1
- package/src/index.css +32 -0
- package/src/styles/tailwind.css +238 -198
- package/tailwind.config.js +3 -0
package/package.json
CHANGED
@@ -33,7 +33,7 @@ export default function ProfileAvatar({ name, designation, size, imageUrl, avata
|
|
33
33
|
const defaultAvatarIcon = "user03";
|
34
34
|
const hasImageUrl = imageUrl && imageUrl.length > 0;
|
35
35
|
return (
|
36
|
-
<
|
36
|
+
<div className="group block flex-shrink-0">
|
37
37
|
<div className="flex items-center">
|
38
38
|
<div>
|
39
39
|
{hasImageUrl ? (
|
@@ -61,7 +61,7 @@ export default function ProfileAvatar({ name, designation, size, imageUrl, avata
|
|
61
61
|
</p>
|
62
62
|
</div>
|
63
63
|
</div>
|
64
|
-
</
|
64
|
+
</div>
|
65
65
|
)
|
66
66
|
}
|
67
67
|
|
@@ -2,6 +2,7 @@ import React from 'react';
|
|
2
2
|
import { useState } from 'react';
|
3
3
|
import PropTypes from 'prop-types';
|
4
4
|
import { Icon } from '../common-components/Icon';
|
5
|
+
import {Typography} from '../../foundation/Typography'
|
5
6
|
const sizeClasses = {
|
6
7
|
sm: 'py-0.5 px-2 hds-d-body3c',
|
7
8
|
default: 'py-1 px-3',
|
@@ -13,17 +14,16 @@ const iconClasses = {
|
|
13
14
|
};
|
14
15
|
|
15
16
|
const colorVariants = {
|
16
|
-
blue: 'bg-blue-
|
17
|
-
grey: 'bg-neutral-
|
18
|
-
purple: 'bg-purple-
|
19
|
-
pink: 'bg-pink-
|
20
|
-
amber: 'bg-amber-
|
21
|
-
cyan: 'bg-cyan-
|
22
|
-
|
17
|
+
blue: 'bg-blue-200 text-blue-800 group-hover:bg-blue-300 border border-blue-400 ',
|
18
|
+
grey: 'bg-neutral-200 text-neutral-800 group-hover:bg-neutral-300 border border-neutral-400 ',
|
19
|
+
purple: 'bg-purple-200 text-purple-800 group-hover:bg-purple-300 border border-purple-400 ',
|
20
|
+
pink: 'bg-pink-200 text-pink-800 group-hover:bg-pink-300 border border-pink-400 ',
|
21
|
+
amber: 'bg-amber-200 text-amber-800 group-hover:bg-amber-300 border border-amber-400 ',
|
22
|
+
cyan: 'bg-cyan-200 text-cyan-800 group-hover:bg-cyan-300 border border-cyan-400 ',
|
23
|
+
cyan200: 'bg-cyan-200 text-cyan-600 border border-cyan-400 border border-cyan-400 ',
|
24
|
+
green: 'bg-green-200 text-green-800 group-hover:bg-green-300 border border-green-400 ',
|
23
25
|
}
|
24
26
|
|
25
|
-
|
26
|
-
|
27
27
|
export default function Badge({
|
28
28
|
leftIconVariant,
|
29
29
|
leftIconColor,
|
@@ -55,7 +55,7 @@ export default function Badge({
|
|
55
55
|
<Icon height={'h-4 w-4'} variant={leftIconVariant} strokeColor={leftIconColor} />
|
56
56
|
</div>
|
57
57
|
)}
|
58
|
-
{children}
|
58
|
+
<Typography textStyle='h6'>{children}</Typography>
|
59
59
|
|
60
60
|
{rightIconVariant && rightIconVariant !== 'none' && (
|
61
61
|
<div className='ml-1'>
|
@@ -10,8 +10,8 @@ export default function TalkCard(props) {
|
|
10
10
|
|
11
11
|
<div className=" ">
|
12
12
|
|
13
|
-
<div className="grid rounded-3xl shadow bg-neutral-0
|
14
|
-
<div className="px-8 py-6 border-r border-r-neutral-150" >
|
13
|
+
<div className="grid rounded-3xl shadow bg-neutral-0 grid-cols-1 tb:grid-cols-2 border border-neutral-200 w-full max-w-[882px] ">
|
14
|
+
<div className="px-8 py-6 border-b border-b-neutral-150 tb:border-0 tb:border-r tb:border-r-neutral-150" >
|
15
15
|
|
16
16
|
|
17
17
|
<Badges
|
@@ -22,25 +22,29 @@ export default function TalkCard(props) {
|
|
22
22
|
children={props.badges.label}
|
23
23
|
/>
|
24
24
|
|
25
|
-
<Typography className='my-2 text-
|
26
|
-
<Typography className='my-2 text-neutral-
|
25
|
+
<Typography className='my-2 text-blue-800' textStyle='h5'>{props.title}</Typography>
|
26
|
+
<Typography className='my-2 text-neutral-700' textStyle='body1'>{props.para}</Typography>
|
27
27
|
</div>
|
28
28
|
|
29
|
-
<div className="flex flex-col pt-[2.875rem] justify-between">
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
<div className="flex flex-col pt-0 tb:pt-[2.875rem] justify-between">
|
30
|
+
{
|
31
|
+
props.speakerSet && (
|
32
|
+
<div className="pl-6 flex gap-6 mt-9 tb:mt-0 mb-9 flex-col ">
|
33
|
+
{props.speakerSet.map((value, i) => (
|
34
|
+
<div key={i} className="">
|
33
35
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
36
|
+
<ProfileAvatar
|
37
|
+
name={value.name}
|
38
|
+
size='md'
|
39
|
+
designation={value.designation}
|
40
|
+
imageUrl={value.imageUrl}
|
41
|
+
/>
|
42
|
+
</div>
|
41
43
|
|
42
|
-
|
43
|
-
|
44
|
+
))}
|
45
|
+
</div>
|
46
|
+
)
|
47
|
+
}
|
44
48
|
<div className=" w-full border-t border-t-neutral-150 p-6 flex flex-row justify-between items-center">
|
45
49
|
<Typography textStyle='h6' className='text-blue-800'>{props.eventTime}</Typography>
|
46
50
|
<HDSButton
|
@@ -50,7 +54,7 @@ export default function TalkCard(props) {
|
|
50
54
|
state='default'
|
51
55
|
size='sm'
|
52
56
|
type="iconOnly"
|
53
|
-
|
57
|
+
label=''
|
54
58
|
/>
|
55
59
|
</div>
|
56
60
|
</div>
|
@@ -31,7 +31,6 @@ export default function Hero({ heroData, logo, scrollArrow, fontSize }) {
|
|
31
31
|
{
|
32
32
|
heroData.tag_line && (
|
33
33
|
<div
|
34
|
-
|
35
34
|
>
|
36
35
|
<Typography textStyle="h6" as="h6" className={"pb-6 uppercase text-center db:text-left font-normal tb-l:text-left " + ((heroData.tag_line_color) ? heroData.tag_line_color : "") + ((heroData.video_url) ? " tb:text-center" : " tb:text-left")}
|
37
36
|
>
|
@@ -137,8 +137,8 @@ export default function HeroSecondary({ heroData, logo, scrollArrow, fontSize })
|
|
137
137
|
|
138
138
|
const imageCard = (heroData) => (
|
139
139
|
heroData.imageUrl && (
|
140
|
-
<div className="
|
141
|
-
<img src={heroData.imageUrl} alt={heroData.imageAlt} />
|
140
|
+
<div className="">
|
141
|
+
<img src={heroData.imageUrl} alt={heroData.imageAlt} className='w-[560px] h-[580px] rounded-b-3xl' />
|
142
142
|
</div>
|
143
143
|
)
|
144
144
|
)
|
@@ -150,7 +150,7 @@ export default function HeroSecondary({ heroData, logo, scrollArrow, fontSize })
|
|
150
150
|
<div className={"max-w-7xl mx-auto rounded-3xl overflow-hidden " + ((heroData.bg_color) ? heroData.bg_color : "")} >
|
151
151
|
<div className="w-full">
|
152
152
|
<div className={"db:flex db:w-full tb-l:flex block" + ((heroData.video_url) ? " tb:block" : " tb:flex")}>
|
153
|
-
<div className={
|
153
|
+
<div className={("w-full")}
|
154
154
|
>
|
155
155
|
{
|
156
156
|
heroData.tag_line && (
|
@@ -1,20 +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'
|
5
|
+
import { Icon } from '../common-components/Icon'
|
6
|
+
import { Tab } from '../Tabs'
|
4
7
|
|
5
|
-
const
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
))
|
17
|
-
)
|
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
|
+
]
|
14
|
+
|
15
|
+
function handleTabClick(tab) {
|
16
|
+
console.log(`Tab "${tab.name}" updatedTabs`);
|
17
|
+
// Perform any other actions based on the clicked tab
|
18
|
+
}
|
18
19
|
|
19
20
|
export default function TableB(props) {
|
20
21
|
const {
|
@@ -23,57 +24,215 @@ export default function TableB(props) {
|
|
23
24
|
TABLE_VALUE,
|
24
25
|
TABLE_HEADER,
|
25
26
|
children
|
26
|
-
|
27
27
|
} = props;
|
28
|
-
|
28
|
+
const [activeTab, setActiveTab] = useState(0);
|
29
29
|
return (
|
30
|
-
<div className="
|
31
|
-
<div className="sm:flex sm:items-center ">
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
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 && (
|
41
45
|
<Typography
|
42
46
|
textStyle='body1c'>
|
43
47
|
{description}
|
44
48
|
</Typography>
|
45
49
|
)
|
46
|
-
}
|
50
|
+
} */}
|
51
|
+
</div>
|
52
|
+
<div className=''>
|
53
|
+
<Tab onTabClick={handleTabClick} tabs={tabs} />
|
54
|
+
</div>
|
47
55
|
</div>
|
48
56
|
</div>
|
49
57
|
|
50
|
-
<div>
|
51
|
-
|
52
|
-
<table className="min-w-full
|
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' >
|
151
|
+
<div className="-mx-4 mt-8 sm:-mx-0 bg-neutral-0 rounded-3xl ">
|
152
|
+
<table className="min-w-full shadow rounded-3xl ">
|
53
153
|
<thead>
|
54
|
-
<tr>
|
55
|
-
{Object.keys(TABLE_HEADER
|
154
|
+
<tr className='divide-x divide-neutral-200 text-center rounded-t-3xl'>
|
155
|
+
{Object.keys(TABLE_HEADER).map((key, value) => (
|
56
156
|
<th
|
57
157
|
key={key}
|
58
158
|
scope="col"
|
59
|
-
className="px-
|
159
|
+
className="px-8 py-6 sm:table-cell"
|
60
160
|
>
|
61
|
-
|
161
|
+
<div className=''>
|
162
|
+
<div className='flex flex-col justify-center items-center text-center'>
|
163
|
+
<div className={'flex items-center gap-2'}>
|
164
|
+
{TABLE_HEADER[key]['icon'] &&
|
165
|
+
(
|
166
|
+
<Icon
|
167
|
+
height='h-6 w-6'
|
168
|
+
variant={TABLE_HEADER[key]['icon']}
|
169
|
+
strokeClass={TABLE_HEADER[key]['iconStrokeClass']} />
|
170
|
+
)
|
171
|
+
}
|
172
|
+
{
|
173
|
+
TABLE_HEADER[key]['title'] && key == 0 && (
|
174
|
+
<Typography
|
175
|
+
textStyle='h5'
|
176
|
+
className={TABLE_HEADER[key]['title_text_color']}>
|
177
|
+
{TABLE_HEADER[key]['title']}
|
178
|
+
</Typography>)
|
179
|
+
}
|
180
|
+
{
|
181
|
+
TABLE_HEADER[key]['title'] && key != 0 && (
|
182
|
+
<Typography
|
183
|
+
textStyle='h5'
|
184
|
+
className={TABLE_HEADER[key]['title_text_color']}>
|
185
|
+
{TABLE_HEADER[key]['title']}
|
186
|
+
</Typography>)
|
187
|
+
}
|
188
|
+
|
189
|
+
|
190
|
+
</div>
|
191
|
+
<div className=' max-w-[10rem]'>
|
192
|
+
{TABLE_HEADER[key]['descr'] && (
|
193
|
+
<Typography
|
194
|
+
textStyle='body1'
|
195
|
+
className={TABLE_HEADER[key]['descr_text_color']}>
|
196
|
+
{TABLE_HEADER[key]['descr']}
|
197
|
+
</Typography>)}
|
198
|
+
</div>
|
199
|
+
</div>
|
200
|
+
</div>
|
62
201
|
</th>
|
63
202
|
))}
|
64
203
|
</tr>
|
65
204
|
</thead>
|
66
|
-
<tbody className="divide-y divide-
|
205
|
+
<tbody className="divide-y divide-neutral-200 rounded-b-3xl">
|
67
206
|
{TABLE_VALUE.map((value) => (
|
68
|
-
<tr key={uuidv4()}>
|
207
|
+
<tr className='divide-x divide-neutral-200' key={uuidv4()}>
|
69
208
|
{Object.keys(value).map((key) => (
|
70
|
-
<
|
71
|
-
key
|
72
|
-
|
73
|
-
|
74
|
-
|
209
|
+
<React.Fragment key={uuidv4()}>
|
210
|
+
{key === 'rowTitle' && (<td
|
211
|
+
key={uuidv4()}
|
212
|
+
className="px-8 py-7 w-[22.5rem] whitespace-pre-line "
|
213
|
+
>
|
214
|
+
<Typography className='max-w-[22rem] text-neutral-700' textStyle='body1c'>{value[key]}</Typography>
|
215
|
+
|
216
|
+
</td>)}
|
217
|
+
|
218
|
+
{key !== 'rowTitle' && (
|
219
|
+
<td
|
220
|
+
key={uuidv4()}
|
221
|
+
className="px-8 py-7 text-center"
|
222
|
+
>
|
223
|
+
{value[key]['text'] && (
|
224
|
+
<Typography className='text-neutral-700' textStyle='body1c'>{value[key]['text']}</Typography>
|
225
|
+
|
226
|
+
)}
|
227
|
+
{!value[key]['text'] && (
|
228
|
+
<div className='flex justify-center'>
|
229
|
+
<Icon height='h-5 w-5' variant={value[key]['iconVariant']} strokeClass={value[key]['iconStrokeClass']} />
|
230
|
+
</div>
|
231
|
+
)}
|
232
|
+
|
75
233
|
|
76
|
-
|
234
|
+
</td>)}
|
235
|
+
</React.Fragment>
|
77
236
|
))}
|
78
237
|
</tr>
|
79
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
|
+
}
|
@@ -2353,7 +2353,7 @@ const iconReferenceMap = {
|
|
2353
2353
|
HasuraBlueLogo: HasuraBlueLogoIcon,
|
2354
2354
|
};
|
2355
2355
|
export default function Icon ({ variant, height, strokeColor, strokeClass, className }){
|
2356
|
-
const CurrentActiveIcon = iconReferenceMap[variant];
|
2356
|
+
const CurrentActiveIcon = iconReferenceMap[variant] ;
|
2357
2357
|
const IconStrokeCLass = HDSColor(strokeClass);
|
2358
2358
|
return (
|
2359
2359
|
<div style={{ stroke: `${strokeColor}` }}>
|
@@ -2367,8 +2367,3 @@ Icon.propTypes = {
|
|
2367
2367
|
fillColor: PropTypes.string,
|
2368
2368
|
strokeColor: PropTypes.string,
|
2369
2369
|
};
|
2370
|
-
|
2371
|
-
Icon.defaultProps = {
|
2372
|
-
strokeClass: 'stroke-neutral-0',
|
2373
|
-
height: 'h-6 w-6'
|
2374
|
-
};
|