carbon-react 144.11.0 → 144.12.1
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/esm/__internal__/focus-trap/focus-trap.component.js +1 -1
- package/esm/components/popover-container/popover-container.component.js +34 -1
- package/esm/components/tabs/__internal__/tab-title/tab-title.component.js +0 -1
- package/esm/components/tabs/__internal__/tab-title/tab-title.style.js +166 -118
- package/esm/components/tabs/__internal__/tabs-header/tabs-header.component.d.ts +2 -1
- package/esm/components/tabs/__internal__/tabs-header/tabs-header.component.js +102 -50
- package/esm/components/tabs/__internal__/tabs-header/tabs-header.style.d.ts +21 -10
- package/esm/components/tabs/__internal__/tabs-header/tabs-header.style.js +72 -85
- package/esm/components/tabs/tabs.component.js +17 -2
- package/lib/__internal__/focus-trap/focus-trap.component.js +1 -1
- package/lib/components/popover-container/popover-container.component.js +34 -1
- package/lib/components/tabs/__internal__/tab-title/tab-title.component.js +0 -1
- package/lib/components/tabs/__internal__/tab-title/tab-title.style.js +166 -118
- package/lib/components/tabs/__internal__/tabs-header/tabs-header.component.d.ts +2 -1
- package/lib/components/tabs/__internal__/tabs-header/tabs-header.component.js +100 -47
- package/lib/components/tabs/__internal__/tabs-header/tabs-header.style.d.ts +21 -10
- package/lib/components/tabs/__internal__/tabs-header/tabs-header.style.js +72 -85
- package/lib/components/tabs/tabs.component.js +17 -2
- package/package.json +1 -1
|
@@ -156,7 +156,7 @@ const FocusTrap = ({
|
|
|
156
156
|
onFocus: updateCurrentFocusedElement
|
|
157
157
|
});
|
|
158
158
|
|
|
159
|
-
// passes focusProps, sets tabIndex and onBlur if no tabIndex has been
|
|
159
|
+
// passes focusProps, sets tabIndex and onBlur if no tabIndex has been explicitly set on child
|
|
160
160
|
const clonedChildren = React.Children.map(children, child => {
|
|
161
161
|
const focusableChild = child;
|
|
162
162
|
return /*#__PURE__*/React.cloneElement(focusableChild, focusProps(focusableChild?.props?.tabIndex === undefined));
|
|
@@ -15,6 +15,7 @@ import FocusTrap from "../../__internal__/focus-trap";
|
|
|
15
15
|
import ModalContext from "../modal/__internal__/modal.context";
|
|
16
16
|
import useFocusPortalContent from "../../hooks/__internal__/useFocusPortalContent";
|
|
17
17
|
import tagComponent from "../../__internal__/utils/helpers/tags/tags";
|
|
18
|
+
import { defaultFocusableSelectors } from "../../__internal__/focus-trap/focus-trap-utils";
|
|
18
19
|
export const renderOpen = ({
|
|
19
20
|
tabIndex,
|
|
20
21
|
onClick,
|
|
@@ -127,6 +128,24 @@ export const PopoverContainer = ({
|
|
|
127
128
|
closePopover(e);
|
|
128
129
|
};
|
|
129
130
|
useFocusPortalContent(shouldCoverButton ? undefined : popoverContentNodeRef, shouldCoverButton ? undefined : openButtonRef, closePopover);
|
|
131
|
+
const onFocusNextElement = useCallback(ev => {
|
|
132
|
+
const allFocusableElements = Array.from(document.querySelectorAll(defaultFocusableSelectors) || /* istanbul ignore next */[]);
|
|
133
|
+
const filteredElements = allFocusableElements.filter(el => el === openButtonRef.current || Number(el.tabIndex) !== -1);
|
|
134
|
+
const openButtonRefIndex = filteredElements.indexOf(openButtonRef.current);
|
|
135
|
+
filteredElements[openButtonRefIndex + 1].focus();
|
|
136
|
+
closePopover(ev);
|
|
137
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
138
|
+
}, []);
|
|
139
|
+
const handleFocusGuard = (direction, ev) => {
|
|
140
|
+
if (direction === "next" && onFocusNextElement) {
|
|
141
|
+
// Focus the next focusable element outside of the popover
|
|
142
|
+
onFocusNextElement(ev);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// istanbul ignore else
|
|
147
|
+
if (direction === "prev") openButtonRef.current?.focus();
|
|
148
|
+
};
|
|
130
149
|
const renderOpenComponentProps = {
|
|
131
150
|
tabIndex: 0,
|
|
132
151
|
"aria-expanded": isOpen,
|
|
@@ -173,7 +192,21 @@ export const PopoverContainer = ({
|
|
|
173
192
|
}, /*#__PURE__*/React.createElement(FocusTrap, {
|
|
174
193
|
wrapperRef: popoverContentNodeRef,
|
|
175
194
|
isOpen: isOpen
|
|
176
|
-
}, popover())) :
|
|
195
|
+
}, popover())) : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
|
196
|
+
"data-element": "tab-guard-top"
|
|
197
|
+
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
|
|
198
|
+
,
|
|
199
|
+
tabIndex: 0,
|
|
200
|
+
"aria-hidden": true,
|
|
201
|
+
onFocus: ev => handleFocusGuard("prev", ev)
|
|
202
|
+
}), popover(), /*#__PURE__*/React.createElement("div", {
|
|
203
|
+
"data-element": "tab-guard-bottom"
|
|
204
|
+
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
|
|
205
|
+
,
|
|
206
|
+
tabIndex: 0,
|
|
207
|
+
"aria-hidden": true,
|
|
208
|
+
onFocus: ev => handleFocusGuard("next", ev)
|
|
209
|
+
}));
|
|
177
210
|
return /*#__PURE__*/React.createElement(PopoverContainerWrapperStyle, {
|
|
178
211
|
"data-component": "popover-container",
|
|
179
212
|
onMouseDown: handleClick
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import styled, { css } from "styled-components";
|
|
2
2
|
import StyledIcon from "../../../icon/icon.style";
|
|
3
3
|
import StyledValidationIcon from "../../../../__internal__/validations/validation-icon.style";
|
|
4
|
-
import addFocusStyling from "../../../../style/utils/add-focus-styling";
|
|
5
|
-
const oldFocusStyling = `
|
|
6
|
-
outline: solid 3px var(--colorsSemanticFocus500);
|
|
7
|
-
`;
|
|
8
4
|
const StyledTitleContent = styled.span`
|
|
9
5
|
outline: none;
|
|
10
|
-
display:
|
|
6
|
+
display: flex;
|
|
7
|
+
align-items: flex-start;
|
|
11
8
|
line-height: 20px;
|
|
12
9
|
margin: 0;
|
|
13
10
|
position: relative;
|
|
@@ -110,7 +107,7 @@ const StyledTitleContent = styled.span`
|
|
|
110
107
|
padding: 10px 16px;
|
|
111
108
|
|
|
112
109
|
${borders && `padding-bottom: 9px;`}
|
|
113
|
-
`}
|
|
110
|
+
`}
|
|
114
111
|
|
|
115
112
|
${(warning || info) && css`
|
|
116
113
|
outline: 1px solid;
|
|
@@ -133,7 +130,7 @@ const StyledTitleContent = styled.span`
|
|
|
133
130
|
border-right-color: transparent;
|
|
134
131
|
padding-right: ${size === "large" ? "26px" : "18px"};
|
|
135
132
|
`}
|
|
136
|
-
|
|
133
|
+
|
|
137
134
|
&:hover {
|
|
138
135
|
outline: 1px solid;
|
|
139
136
|
outline-offset: -1px;
|
|
@@ -174,7 +171,7 @@ const StyledTitleContent = styled.span`
|
|
|
174
171
|
border-right-color: transparent;
|
|
175
172
|
padding-right: ${size === "large" ? "26px" : "18px"};
|
|
176
173
|
`}
|
|
177
|
-
|
|
174
|
+
|
|
178
175
|
&:hover {
|
|
179
176
|
outline: 2px solid var(--colorsSemanticNegative500);
|
|
180
177
|
outline-offset: -2px;
|
|
@@ -274,152 +271,198 @@ const tabTitleStyles = css`
|
|
|
274
271
|
height: ${size === "large" ? "var(--sizing600)" : "var(--sizing500)"};
|
|
275
272
|
|
|
276
273
|
${position === "top" && css`
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
274
|
+
${borders && !(noRightBorder || noLeftBorder) && css`
|
|
275
|
+
&:nth-of-type(n + 1):not(:first-of-type) {
|
|
276
|
+
margin-left: -1px;
|
|
277
|
+
}
|
|
278
|
+
&:first-child {
|
|
279
|
+
margin-left: 0;
|
|
280
|
+
}
|
|
281
|
+
`}
|
|
284
282
|
`}
|
|
285
|
-
`}
|
|
286
283
|
${position === "left" && css`
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
284
|
+
${borders && css`
|
|
285
|
+
&:nth-of-type(n + 1):not(:first-of-type) {
|
|
286
|
+
margin-top: -1px;
|
|
287
|
+
}
|
|
288
|
+
&:first-child {
|
|
289
|
+
margin-top: 0;
|
|
290
|
+
}
|
|
291
|
+
`}
|
|
294
292
|
`}
|
|
295
|
-
`}
|
|
296
293
|
|
|
297
294
|
${!isTabSelected && css`
|
|
298
|
-
|
|
299
|
-
${validationRedesignOptIn && css`
|
|
300
|
-
background: transparent;
|
|
301
|
-
`}
|
|
302
|
-
|
|
303
|
-
&:hover {
|
|
304
|
-
background: var(--colorsActionMinor100);
|
|
295
|
+
color: var(--colorsActionMinorYin090);
|
|
305
296
|
${validationRedesignOptIn && css`
|
|
306
|
-
background:
|
|
297
|
+
background: transparent;
|
|
307
298
|
`}
|
|
308
|
-
color: var(--colorsActionMinorYin090);
|
|
309
|
-
outline: none;
|
|
310
|
-
}
|
|
311
|
-
&:focus {
|
|
312
|
-
color: var(--colorsActionMinorYin090);
|
|
313
|
-
outline: none;
|
|
314
|
-
}
|
|
315
|
-
`}
|
|
316
299
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
300
|
+
&:hover {
|
|
301
|
+
background: var(--colorsActionMinor100);
|
|
302
|
+
${validationRedesignOptIn && css`
|
|
303
|
+
background: var(--colorsUtilityMajor100);
|
|
304
|
+
`}
|
|
305
|
+
color: var(--colorsActionMinorYin090);
|
|
306
|
+
outline: none;
|
|
307
|
+
}
|
|
308
|
+
&:focus {
|
|
309
|
+
color: var(--colorsActionMinorYin090);
|
|
310
|
+
outline: none;
|
|
311
|
+
}
|
|
323
312
|
`}
|
|
324
313
|
|
|
325
|
-
|
|
326
|
-
background-color: var(--colorsActionMajorYang100);
|
|
327
|
-
border-bottom-color: ${alternateStyling ? "var(--colorsActionMinor100)" : "var(--colorsActionMajor500)"};
|
|
314
|
+
${isTabSelected && css`
|
|
328
315
|
color: var(--colorsActionMajorYin090);
|
|
329
|
-
|
|
330
|
-
}
|
|
331
|
-
`}
|
|
316
|
+
background-color: var(--colorsActionMajorYang100);
|
|
332
317
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
}) => `${!theme.focusRedesignOptOut ? addFocusStyling() : /* istanbul ignore next */oldFocusStyling}`}
|
|
337
|
-
z-index: 3;
|
|
318
|
+
${(error || warning || info) && css`
|
|
319
|
+
padding-bottom: 0px;
|
|
320
|
+
`}
|
|
338
321
|
|
|
339
|
-
|
|
340
|
-
|
|
322
|
+
&:hover {
|
|
323
|
+
background-color: var(--colorsActionMajorYang100);
|
|
324
|
+
border-bottom-color: ${alternateStyling ? "var(--colorsActionMinor100)" : "var(--colorsActionMajor500)"};
|
|
325
|
+
color: var(--colorsActionMajorYin090);
|
|
326
|
+
cursor: default;
|
|
327
|
+
}
|
|
341
328
|
`}
|
|
342
|
-
}
|
|
343
329
|
|
|
344
|
-
${
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
${alternateStyling ? "1px" : "var(--border-right-value)"} solid
|
|
352
|
-
var(--colorsActionMinor100);
|
|
353
|
-
`}
|
|
330
|
+
${({
|
|
331
|
+
theme
|
|
332
|
+
}) => `
|
|
333
|
+
&:focus {
|
|
334
|
+
outline: 4px solid ${!theme.focusRedesignOptOut ? "black" : /* istanbul ignore next */"var(--colorsSemanticFocus500)"};
|
|
335
|
+
top: -2px;
|
|
336
|
+
z-index: 6;
|
|
354
337
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
border-bottom: none;
|
|
338
|
+
> span[data-role="tab-title-content"] {
|
|
339
|
+
outline:none;
|
|
358
340
|
}
|
|
359
|
-
`}
|
|
360
341
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
342
|
+
${position === "top" ? css`
|
|
343
|
+
border-top-left-radius: var(--borderRadius100);
|
|
344
|
+
border-top-right-radius: var(--borderRadius100);
|
|
345
|
+
` : css`
|
|
346
|
+
border-top-left-radius: var(--borderRadius100);
|
|
347
|
+
border-bottom-left-radius: var(--borderRadius100);
|
|
348
|
+
`}
|
|
349
|
+
|
|
350
|
+
${!theme.focusRedesignOptOut ? `::before {
|
|
351
|
+
content: "";
|
|
352
|
+
position: absolute;
|
|
353
|
+
top: 0;
|
|
354
|
+
left 0;
|
|
355
|
+
bottom: 0;
|
|
356
|
+
right: ${position === "top" ? "0" : "-1px"};
|
|
357
|
+
outline: 3px solid var(--colorsSemanticFocus500);
|
|
358
|
+
${position === "top" ? css`
|
|
359
|
+
border-top-left-radius: var(--borderRadius100);
|
|
360
|
+
border-top-right-radius: var(--borderRadius100);
|
|
361
|
+
` : css`
|
|
362
|
+
border-top-left-radius: var(--borderRadius100);
|
|
363
|
+
border-bottom-left-radius: var(--borderRadius100);
|
|
364
|
+
`}
|
|
365
|
+
outline-offset: -2px;
|
|
366
|
+
z-index: 5;
|
|
367
|
+
}
|
|
364
368
|
|
|
365
|
-
|
|
366
|
-
|
|
369
|
+
> [data-element="tab-selected-indicator"] {
|
|
370
|
+
z-index: 4;
|
|
371
|
+
${position === "top" ? css`
|
|
372
|
+
bottom: 2px;
|
|
373
|
+
left: 2px;
|
|
374
|
+
right: 1px;
|
|
375
|
+
` : css`
|
|
376
|
+
bottom: 2px;
|
|
377
|
+
right: 1px;
|
|
378
|
+
`}
|
|
379
|
+
}` : /* istanbul ignore next */""}
|
|
367
380
|
}
|
|
381
|
+
`}
|
|
368
382
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
383
|
+
${position === "left" && css`
|
|
384
|
+
background-color: transparent;
|
|
385
|
+
border-bottom: 0px;
|
|
386
|
+
|
|
387
|
+
${!isInSidebar && !error && css`
|
|
388
|
+
--border-right-value: ${validationRedesignOptIn ? "0px" : "2px"}
|
|
389
|
+
border-right:
|
|
390
|
+
${alternateStyling ? "1px" : "var(--border-right-value)"} solid
|
|
391
|
+
var(--colorsActionMinor100);
|
|
392
|
+
`}
|
|
372
393
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
394
|
+
${!borders && css`
|
|
395
|
+
${StyledTitleContent} {
|
|
396
|
+
border-bottom: none;
|
|
397
|
+
}
|
|
398
|
+
`}
|
|
376
399
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
400
|
+
display: flex;
|
|
401
|
+
height: auto;
|
|
402
|
+
margin-left: 0px;
|
|
380
403
|
|
|
381
|
-
|
|
382
|
-
|
|
404
|
+
&:first-child {
|
|
405
|
+
margin-top: 0;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
&:hover {
|
|
409
|
+
${alternateStyling && "border-right-color: var(--colorsActionMinor100)"}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
${(warning || info) && css`
|
|
413
|
+
border-right: none;
|
|
414
|
+
`}
|
|
415
|
+
|
|
416
|
+
${!isTabSelected && css`
|
|
383
417
|
border-right-color: var(--colorsActionMinor100);
|
|
384
418
|
`}
|
|
385
419
|
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
420
|
+
${isTabSelected && css`
|
|
421
|
+
${alternateStyling && css`
|
|
422
|
+
border-right-color: var(--colorsActionMinor100);
|
|
423
|
+
`}
|
|
389
424
|
|
|
390
|
-
${
|
|
391
|
-
${!(error || warning || info) && !validationRedesignOptIn && "margin-right: 2px;"}
|
|
425
|
+
${!alternateStyling && css`
|
|
392
426
|
border-right: none;
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
427
|
+
padding-bottom: 0px;
|
|
428
|
+
|
|
429
|
+
${StyledTitleContent} {
|
|
430
|
+
${!(error || warning || info) && !validationRedesignOptIn && "margin-right: 2px;"}
|
|
431
|
+
border-right: none;
|
|
432
|
+
}
|
|
433
|
+
`}
|
|
434
|
+
|
|
396
435
|
background-color: var(--colorsActionMajorYang100);
|
|
397
436
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
437
|
+
&:hover {
|
|
438
|
+
${alternateStyling && "border-right-color: var(--colorsActionMinor100);"}
|
|
439
|
+
background-color: var(--colorsActionMajorYang100);
|
|
440
|
+
${(error || warning || info) && "border-right-color: var(--colorsSemanticNegative500);"}
|
|
441
|
+
}
|
|
403
442
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
443
|
+
&:focus {
|
|
444
|
+
${(error || warning || info) && "border-right-color: var(--colorsSemanticNegative500);"}
|
|
445
|
+
}
|
|
446
|
+
`}
|
|
407
447
|
`}
|
|
408
|
-
`}
|
|
409
448
|
|
|
410
449
|
${alternateStyling && css`
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
450
|
+
&:focus {
|
|
451
|
+
background-color: var(--colorsActionMinor200);
|
|
452
|
+
}
|
|
414
453
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
454
|
+
&:hover {
|
|
455
|
+
background-color: ${isTabSelected ? "var(--colorsActionMinor200)" : "var(--colorsActionMinor250)"};
|
|
456
|
+
}
|
|
418
457
|
|
|
419
|
-
|
|
420
|
-
|
|
458
|
+
${isTabSelected && css`
|
|
459
|
+
background-color: var(--colorsActionMinor200);
|
|
460
|
+
`}
|
|
421
461
|
`}
|
|
422
|
-
|
|
462
|
+
|
|
463
|
+
& ${StyledIcon} { {
|
|
464
|
+
${validationRedesignOptIn ? "margin-top: 10px;" : "margin-top: 2px;"}
|
|
465
|
+
}
|
|
423
466
|
`}
|
|
424
467
|
`;
|
|
425
468
|
const StyledTabTitleButton = styled.button`
|
|
@@ -433,7 +476,6 @@ const StyledLayoutWrapper = styled.div`
|
|
|
433
476
|
hasCustomLayout,
|
|
434
477
|
titlePosition = "before",
|
|
435
478
|
hasCustomSibling,
|
|
436
|
-
position,
|
|
437
479
|
validationRedesignOptIn
|
|
438
480
|
}) => css`
|
|
439
481
|
${hasCustomLayout && css`
|
|
@@ -501,7 +543,7 @@ const StyledSelectedIndicator = styled.div`
|
|
|
501
543
|
--selected-indicator-color: var(--colorsSemanticNegative500);
|
|
502
544
|
`}
|
|
503
545
|
${position === "top" && css`
|
|
504
|
-
bottom:
|
|
546
|
+
bottom: -1px;
|
|
505
547
|
left: 0px;
|
|
506
548
|
right: 0px;
|
|
507
549
|
box-shadow: inset 0px calc(-1 * var(--sizing050)) 0px
|
|
@@ -518,5 +560,11 @@ const StyledSelectedIndicator = styled.div`
|
|
|
518
560
|
width: var(--sizing050);
|
|
519
561
|
`}
|
|
520
562
|
`}
|
|
563
|
+
|
|
564
|
+
&:focus {
|
|
565
|
+
bottom: 3px;
|
|
566
|
+
left: 3px;
|
|
567
|
+
right: 3px;
|
|
568
|
+
}
|
|
521
569
|
`;
|
|
522
570
|
export { StyledTabTitleButton, StyledTabTitleLink, StyledTitleContent, StyledLayoutWrapper, StyledSelectedIndicator, StyledVerticalIndicator };
|
|
@@ -7,6 +7,7 @@ export interface TabHeaderProps {
|
|
|
7
7
|
isInSidebar?: boolean;
|
|
8
8
|
children: React.ReactNode;
|
|
9
9
|
align?: "left" | "right";
|
|
10
|
+
size?: "default" | "large";
|
|
10
11
|
}
|
|
11
|
-
declare const TabsHeader: ({ align, children, position, role, extendedLine, noRightBorder, isInSidebar, }: TabHeaderProps) => React.JSX.Element;
|
|
12
|
+
declare const TabsHeader: ({ align, children, position, role, extendedLine, noRightBorder, isInSidebar, size, }: TabHeaderProps) => React.JSX.Element;
|
|
12
13
|
export default TabsHeader;
|
|
@@ -1,19 +1,8 @@
|
|
|
1
|
-
import React, { useRef, useState
|
|
1
|
+
import React, { useCallback, useEffect, useRef, useState } from "react";
|
|
2
2
|
import PropTypes from "prop-types";
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
/* In the original prototype the tabs have shadows that fade out as you scroll horizontally.
|
|
8
|
-
* This value is the closest replication to the way that the shadow disappears.
|
|
9
|
-
* It is ultimately tied to the position of the scroll that will then fade the shadow in and out. */
|
|
10
|
-
const fullOpacityThreshold = 128;
|
|
11
|
-
const getOpacityRatio = value => value / fullOpacityThreshold;
|
|
12
|
-
const getScrollRight = ({
|
|
13
|
-
scrollWidth,
|
|
14
|
-
clientWidth,
|
|
15
|
-
scrollLeft
|
|
16
|
-
}) => scrollWidth - clientWidth - scrollLeft;
|
|
3
|
+
import useResizeObserver from "../../../../hooks/__internal__/useResizeObserver";
|
|
4
|
+
import StyledIcon from "../../../icon/icon.style";
|
|
5
|
+
import { StyledTabsHeaderWrapper, StyledTabsHeaderList, StyledVerticalTabsWrapper, StyledWrapper, StyledNavigationButtonWrapper, StyledNavigationButton, StyledContainer, StyledBottomBorder } from "./tabs-header.style";
|
|
17
6
|
const TabsHeader = ({
|
|
18
7
|
align = "left",
|
|
19
8
|
children,
|
|
@@ -21,49 +10,112 @@ const TabsHeader = ({
|
|
|
21
10
|
role,
|
|
22
11
|
extendedLine,
|
|
23
12
|
noRightBorder = false,
|
|
24
|
-
isInSidebar = false
|
|
13
|
+
isInSidebar = false,
|
|
14
|
+
size = "default"
|
|
25
15
|
}) => {
|
|
26
|
-
const [leftScrollOpacity, setLeftScrollOpacity] = useState(0);
|
|
27
|
-
const [rightScrollOpacity, setRightScrollOpacity] = useState(1);
|
|
28
|
-
const {
|
|
29
|
-
validationRedesignOptIn
|
|
30
|
-
} = useContext(NewValidationContext);
|
|
31
16
|
const ref = useRef(null);
|
|
32
|
-
let isScrollable = false;
|
|
33
17
|
const {
|
|
34
18
|
current
|
|
35
19
|
} = ref;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
20
|
+
const [leftVisible, setLeftVisible] = useState(false);
|
|
21
|
+
const [rightVisible, setRightVisible] = useState(false);
|
|
22
|
+
const updateUI = useCallback(() => {
|
|
23
|
+
if (current) {
|
|
24
|
+
const maxScrollValue = current.scrollWidth - current.clientWidth - 20;
|
|
25
|
+
setLeftVisible(current.scrollLeft >= 20);
|
|
26
|
+
setRightVisible(current.scrollLeft <= maxScrollValue);
|
|
27
|
+
}
|
|
28
|
+
}, [current]);
|
|
29
|
+
useResizeObserver(ref, () => {
|
|
30
|
+
updateUI();
|
|
31
|
+
});
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (current) {
|
|
34
|
+
updateUI();
|
|
35
|
+
}
|
|
36
|
+
}, [current, updateUI]);
|
|
37
|
+
function handleKeyDown(ev) {
|
|
38
|
+
/* istanbul ignore if */
|
|
39
|
+
if (!current) return;
|
|
40
40
|
const {
|
|
41
|
-
|
|
42
|
-
} =
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
41
|
+
key
|
|
42
|
+
} = ev;
|
|
43
|
+
if (key === "ArrowLeft") {
|
|
44
|
+
updateUI();
|
|
45
|
+
} else if (key === "ArrowRight") {
|
|
46
|
+
updateUI();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (position === "left") {
|
|
50
|
+
return /*#__PURE__*/React.createElement(StyledTabsHeaderWrapper, {
|
|
51
|
+
isInSidebar: isInSidebar,
|
|
52
|
+
position: "left"
|
|
53
|
+
}, /*#__PURE__*/React.createElement(StyledTabsHeaderList, {
|
|
54
|
+
align: align,
|
|
55
|
+
position: "left",
|
|
56
|
+
role: role,
|
|
57
|
+
extendedLine: extendedLine,
|
|
58
|
+
noRightBorder: noRightBorder,
|
|
59
|
+
isInSidebar: isInSidebar,
|
|
60
|
+
ref: ref
|
|
61
|
+
}, /*#__PURE__*/React.createElement(StyledVerticalTabsWrapper, {
|
|
62
|
+
isInSidebar: isInSidebar
|
|
63
|
+
}, children)));
|
|
64
|
+
}
|
|
65
|
+
return /*#__PURE__*/React.createElement(StyledWrapper, {
|
|
66
|
+
id: "tab-header-wrapper",
|
|
67
|
+
"data-role": "tab-header-wrapper",
|
|
52
68
|
align: align,
|
|
53
|
-
position:
|
|
54
|
-
role: role,
|
|
69
|
+
position: "top",
|
|
55
70
|
extendedLine: extendedLine,
|
|
56
71
|
noRightBorder: noRightBorder,
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
72
|
+
onKeyDown: handleKeyDown
|
|
73
|
+
}, /*#__PURE__*/React.createElement(StyledNavigationButtonWrapper, {
|
|
74
|
+
position: "left",
|
|
75
|
+
visible: leftVisible,
|
|
76
|
+
id: "tab-navigation-button-wrapper-left",
|
|
77
|
+
"data-role": "tab-navigation-button-wrapper-left",
|
|
78
|
+
size: size
|
|
79
|
+
}, /*#__PURE__*/React.createElement(StyledNavigationButton, {
|
|
80
|
+
tabIndex: -1,
|
|
81
|
+
title: "Scroll Tabs Left",
|
|
82
|
+
id: "tab-navigation-button-left",
|
|
83
|
+
"data-role": "tab-navigation-button-left",
|
|
84
|
+
onClick: () => {
|
|
85
|
+
/* istanbul ignore if */
|
|
86
|
+
if (current) {
|
|
87
|
+
current.scrollLeft -= 200;
|
|
88
|
+
updateUI();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}, /*#__PURE__*/React.createElement(StyledIcon, {
|
|
92
|
+
type: "chevron_left"
|
|
93
|
+
}))), /*#__PURE__*/React.createElement(StyledContainer, {
|
|
94
|
+
ref: ref,
|
|
95
|
+
id: "tab-container",
|
|
96
|
+
role: role,
|
|
97
|
+
"data-role": "tab-container",
|
|
98
|
+
size: size
|
|
99
|
+
}, /*#__PURE__*/React.createElement(StyledBottomBorder, null), children), /*#__PURE__*/React.createElement(StyledNavigationButtonWrapper, {
|
|
100
|
+
position: "right",
|
|
101
|
+
visible: rightVisible,
|
|
102
|
+
id: "tab-navigation-button-wrapper-right",
|
|
103
|
+
"data-role": "tab-navigation-button-wrapper-right",
|
|
104
|
+
size: size
|
|
105
|
+
}, /*#__PURE__*/React.createElement(StyledNavigationButton, {
|
|
106
|
+
tabIndex: -1,
|
|
107
|
+
title: "Scroll Tabs Right",
|
|
108
|
+
id: "tab-navigation-button-right",
|
|
109
|
+
"data-role": "tab-navigation-button-right",
|
|
110
|
+
onClick: () => {
|
|
111
|
+
/* istanbul ignore if */
|
|
112
|
+
if (current) {
|
|
113
|
+
current.scrollLeft += 200;
|
|
114
|
+
updateUI();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}, /*#__PURE__*/React.createElement(StyledIcon, {
|
|
118
|
+
type: "chevron_right"
|
|
119
|
+
}))));
|
|
68
120
|
};
|
|
69
121
|
export default TabsHeader;
|
|
@@ -1,17 +1,28 @@
|
|
|
1
1
|
import { TabHeaderProps } from "./tabs-header.component";
|
|
2
2
|
declare type StyledTabsHeaderWrapperProps = Pick<TabHeaderProps, "position" | "isInSidebar">;
|
|
3
3
|
declare const StyledTabsHeaderWrapper: import("styled-components").StyledComponent<"div", any, StyledTabsHeaderWrapperProps, never>;
|
|
4
|
-
export
|
|
5
|
-
leftScrollOpacity?: number;
|
|
6
|
-
rightScrollOpacity?: number;
|
|
7
|
-
isScrollable?: boolean;
|
|
8
|
-
}
|
|
4
|
+
export declare type StyledTabsHeaderListProps = Pick<TabHeaderProps, "align" | "extendedLine" | "noRightBorder" | "isInSidebar" | "position">;
|
|
9
5
|
declare const StyledTabsHeaderList: import("styled-components").StyledComponent<"div", any, StyledTabsHeaderListProps, never>;
|
|
10
|
-
declare const StyledTabsWrapper: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
11
6
|
declare type StyledVerticalTabsWrapperProps = Pick<TabHeaderProps, "isInSidebar">;
|
|
12
7
|
declare const StyledVerticalTabsWrapper: import("styled-components").StyledComponent<"div", any, StyledVerticalTabsWrapperProps, never>;
|
|
13
|
-
declare
|
|
14
|
-
|
|
8
|
+
declare type StyledWrapperProps = {
|
|
9
|
+
align: string;
|
|
10
|
+
position: string;
|
|
11
|
+
role?: string;
|
|
12
|
+
extendedLine?: boolean;
|
|
13
|
+
noRightBorder?: boolean;
|
|
14
|
+
isInSidebar?: boolean;
|
|
15
|
+
};
|
|
16
|
+
declare type StyledNavigationButtonWrapperProps = {
|
|
17
|
+
position: string;
|
|
18
|
+
visible: boolean;
|
|
19
|
+
size: string;
|
|
20
|
+
};
|
|
21
|
+
declare const StyledWrapper: import("styled-components").StyledComponent<"section", any, StyledWrapperProps, never>;
|
|
22
|
+
declare const StyledNavigationButtonWrapper: import("styled-components").StyledComponent<"div", any, StyledNavigationButtonWrapperProps, never>;
|
|
23
|
+
declare const StyledNavigationButton: import("styled-components").StyledComponent<"button", any, {}, never>;
|
|
24
|
+
declare const StyledContainer: import("styled-components").StyledComponent<"div", any, {
|
|
25
|
+
size: string;
|
|
15
26
|
}, never>;
|
|
16
|
-
declare const
|
|
17
|
-
export { StyledTabsHeaderWrapper, StyledTabsHeaderList,
|
|
27
|
+
declare const StyledBottomBorder: import("styled-components").StyledComponent<"div", any, {}, never>;
|
|
28
|
+
export { StyledTabsHeaderWrapper, StyledTabsHeaderList, StyledVerticalTabsWrapper, StyledWrapper, StyledNavigationButtonWrapper, StyledNavigationButton, StyledContainer, StyledBottomBorder, };
|