@dhis2-ui/tab 9.9.0 → 9.10.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.
@@ -7,17 +7,23 @@ exports.Tab = void 0;
7
7
 
8
8
  var _style = _interopRequireDefault(require("styled-jsx/style"));
9
9
 
10
+ var _tooltip = require("@dhis2-ui/tooltip");
11
+
10
12
  var _uiConstants = require("@dhis2/ui-constants");
11
13
 
12
14
  var _classnames = _interopRequireDefault(require("classnames"));
13
15
 
14
16
  var _propTypes = _interopRequireDefault(require("prop-types"));
15
17
 
16
- var _react = _interopRequireDefault(require("react"));
18
+ var _react = _interopRequireWildcard(require("react"));
19
+
20
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
21
+
22
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
17
23
 
18
24
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
25
 
20
- const Tab = _ref => {
26
+ const Tab = /*#__PURE__*/_react.default.forwardRef((_ref, ref) => {
21
27
  let {
22
28
  icon,
23
29
  onClick,
@@ -27,20 +33,48 @@ const Tab = _ref => {
27
33
  className,
28
34
  dataTest
29
35
  } = _ref;
36
+ let tabRef = (0, _react.useRef)(null);
37
+
38
+ if (ref) {
39
+ tabRef = ref;
40
+ }
41
+
42
+ const [isOverflowing, setIsOverflowing] = (0, _react.useState)(false);
43
+ (0, _react.useEffect)(() => {
44
+ const checkOverflow = () => {
45
+ const isOverflow = tabRef.current.scrollWidth > tabRef.current.clientWidth;
46
+ setIsOverflowing(isOverflow);
47
+ };
48
+
49
+ checkOverflow();
50
+ }, []);
30
51
  return /*#__PURE__*/_react.default.createElement("button", {
31
52
  onClick: disabled ? undefined : event => onClick({}, event),
32
53
  "data-test": dataTest,
33
- className: _style.default.dynamic([["3476406340", [_uiConstants.colors.grey400, _uiConstants.colors.grey600, _uiConstants.theme.focus, _uiConstants.colors.grey600, _uiConstants.colors.grey900, _uiConstants.colors.grey600, _uiConstants.colors.grey800, _uiConstants.theme.primary800, _uiConstants.theme.primary700, _uiConstants.theme.primary700, _uiConstants.theme.primary700, _uiConstants.colors.grey500, _uiConstants.colors.grey500]]]) + " " + "".concat((0, _classnames.default)('tab', className, {
54
+ ref: tabRef,
55
+ role: "tab",
56
+ "aria-selected": selected ? 'true' : 'false',
57
+ "aria-disabled": disabled ? 'true' : 'false',
58
+ onFocus: disabled ? undefined : event => onClick({}, event),
59
+ tabIndex: -1,
60
+ className: _style.default.dynamic([["2433456263", [_uiConstants.colors.grey400, _uiConstants.colors.grey600, _uiConstants.theme.focus, _uiConstants.colors.grey600, _uiConstants.colors.grey900, _uiConstants.colors.grey600, _uiConstants.colors.grey800, _uiConstants.theme.primary800, _uiConstants.theme.primary700, _uiConstants.theme.primary700, _uiConstants.theme.primary700, _uiConstants.colors.grey500, _uiConstants.colors.grey500]]]) + " " + "".concat((0, _classnames.default)('tab', className, {
34
61
  selected,
35
62
  disabled
36
63
  }))
37
- }, icon, /*#__PURE__*/_react.default.createElement("span", {
38
- className: _style.default.dynamic([["3476406340", [_uiConstants.colors.grey400, _uiConstants.colors.grey600, _uiConstants.theme.focus, _uiConstants.colors.grey600, _uiConstants.colors.grey900, _uiConstants.colors.grey600, _uiConstants.colors.grey800, _uiConstants.theme.primary800, _uiConstants.theme.primary700, _uiConstants.theme.primary700, _uiConstants.theme.primary700, _uiConstants.colors.grey500, _uiConstants.colors.grey500]]])
64
+ }, icon, isOverflowing ? /*#__PURE__*/_react.default.createElement(_tooltip.Tooltip, {
65
+ content: children,
66
+ maxWidth: '100%'
67
+ }, /*#__PURE__*/_react.default.createElement("span", {
68
+ ref: tabRef,
69
+ className: _style.default.dynamic([["2433456263", [_uiConstants.colors.grey400, _uiConstants.colors.grey600, _uiConstants.theme.focus, _uiConstants.colors.grey600, _uiConstants.colors.grey900, _uiConstants.colors.grey600, _uiConstants.colors.grey800, _uiConstants.theme.primary800, _uiConstants.theme.primary700, _uiConstants.theme.primary700, _uiConstants.theme.primary700, _uiConstants.colors.grey500, _uiConstants.colors.grey500]]])
70
+ }, children)) : /*#__PURE__*/_react.default.createElement("span", {
71
+ ref: tabRef,
72
+ className: _style.default.dynamic([["2433456263", [_uiConstants.colors.grey400, _uiConstants.colors.grey600, _uiConstants.theme.focus, _uiConstants.colors.grey600, _uiConstants.colors.grey900, _uiConstants.colors.grey600, _uiConstants.colors.grey800, _uiConstants.theme.primary800, _uiConstants.theme.primary700, _uiConstants.theme.primary700, _uiConstants.theme.primary700, _uiConstants.colors.grey500, _uiConstants.colors.grey500]]])
39
73
  }, children), /*#__PURE__*/_react.default.createElement(_style.default, {
40
- id: "3476406340",
74
+ id: "2433456263",
41
75
  dynamic: [_uiConstants.colors.grey400, _uiConstants.colors.grey600, _uiConstants.theme.focus, _uiConstants.colors.grey600, _uiConstants.colors.grey900, _uiConstants.colors.grey600, _uiConstants.colors.grey800, _uiConstants.theme.primary800, _uiConstants.theme.primary700, _uiConstants.theme.primary700, _uiConstants.theme.primary700, _uiConstants.colors.grey500, _uiConstants.colors.grey500]
42
- }, ["button.__jsx-style-dynamic-selector{-webkit-box-flex:0;-webkit-flex-grow:0;-ms-flex-positive:0;flex-grow:0;position:relative;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;vertical-align:bottom;height:100%;padding:16px 16px 11px;background-color:transparent;outline:none;border:none;border-bottom:1px solid ".concat(_uiConstants.colors.grey400, ";color:").concat(_uiConstants.colors.grey600, ";font-size:14px;line-height:20px;cursor:pointer;}"), ".fixed>button.__jsx-style-dynamic-selector{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;}", "button.__jsx-style-dynamic-selector::after{content:' ';display:block;position:absolute;bottom:-1px;inset-inline-start:0;height:4px;width:100%;background-color:transparent;}", "span.__jsx-style-dynamic-selector{max-width:320px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-transition:fill 150ms ease-in-out;transition:fill 150ms ease-in-out;}", "button.__jsx-style-dynamic-selector:focus{outline:3px solid ".concat(_uiConstants.theme.focus, ";outline-offset:-3px;}"), "button.__jsx-style-dynamic-selector:focus.__jsx-style-dynamic-selector:not(:focus-visible){outline:none;}", "button.__jsx-style-dynamic-selector>svg{fill:".concat(_uiConstants.colors.grey600, ";width:14px;height:14px;margin:0 4px 0 0;}"), "button.__jsx-style-dynamic-selector:hover{color:".concat(_uiConstants.colors.grey900, ";}"), "button.__jsx-style-dynamic-selector:hover.__jsx-style-dynamic-selector::after{background-color:".concat(_uiConstants.colors.grey600, ";height:2px;}"), "button.__jsx-style-dynamic-selector:active.__jsx-style-dynamic-selector::after{background-color:".concat(_uiConstants.colors.grey800, ";}"), "button.selected.__jsx-style-dynamic-selector{color:".concat(_uiConstants.theme.primary800, ";}"), "button.selected.__jsx-style-dynamic-selector::after{background-color:".concat(_uiConstants.theme.primary700, ";-webkit-transition:background-color 150ms ease-in-out;transition:background-color 150ms ease-in-out;}"), "button.selected.__jsx-style-dynamic-selector:hover.__jsx-style-dynamic-selector::after{background-color:".concat(_uiConstants.theme.primary700, ";height:4px;}"), "button.selected.__jsx-style-dynamic-selector>svg{fill:".concat(_uiConstants.theme.primary700, ";}"), "button.disabled.__jsx-style-dynamic-selector{color:".concat(_uiConstants.colors.grey500, ";cursor:not-allowed;}"), "button.disabled.__jsx-style-dynamic-selector:hover,button.selected.__jsx-style-dynamic-selector:hover{background-color:transparent;}", "button.disabled.__jsx-style-dynamic-selector>svg{fill:".concat(_uiConstants.colors.grey500, ";}")]));
43
- };
76
+ }, ["button.__jsx-style-dynamic-selector{-webkit-box-flex:0;-webkit-flex-grow:0;-ms-flex-positive:0;flex-grow:0;position:relative;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;vertical-align:bottom;height:100%;padding:16px 16px 11px;background-color:transparent;outline:none;border:none;border-bottom:1px solid ".concat(_uiConstants.colors.grey400, ";color:").concat(_uiConstants.colors.grey600, ";font-size:14px;line-height:20px;cursor:pointer;}"), ".fixed>button.__jsx-style-dynamic-selector{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;}", "button.__jsx-style-dynamic-selector::after{content:' ';display:block;position:absolute;bottom:-1px;inset-inline-start:0;height:4px;width:100%;background-color:transparent;}", "span.__jsx-style-dynamic-selector{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;max-width:320px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-transition:fill 150ms ease-in-out;transition:fill 150ms ease-in-out;}", "button.__jsx-style-dynamic-selector:focus{outline:3px solid ".concat(_uiConstants.theme.focus, ";outline-offset:-3px;}"), "button.__jsx-style-dynamic-selector:focus.__jsx-style-dynamic-selector:not(:focus-visible){outline:none;}", "button.__jsx-style-dynamic-selector>svg{fill:".concat(_uiConstants.colors.grey600, ";width:14px;height:14px;margin:0 4px 0 0;}"), "button.__jsx-style-dynamic-selector:hover{color:".concat(_uiConstants.colors.grey900, ";}"), "button.__jsx-style-dynamic-selector:hover.__jsx-style-dynamic-selector::after{background-color:".concat(_uiConstants.colors.grey600, ";height:2px;}"), "button.__jsx-style-dynamic-selector:active.__jsx-style-dynamic-selector::after{background-color:".concat(_uiConstants.colors.grey800, ";}"), "button.selected.__jsx-style-dynamic-selector{color:".concat(_uiConstants.theme.primary800, ";}"), "button.selected.__jsx-style-dynamic-selector::after{background-color:".concat(_uiConstants.theme.primary700, ";-webkit-transition:background-color 150ms ease-in-out;transition:background-color 150ms ease-in-out;}"), "button.selected.__jsx-style-dynamic-selector:hover.__jsx-style-dynamic-selector::after{background-color:".concat(_uiConstants.theme.primary700, ";height:4px;}"), "button.selected.__jsx-style-dynamic-selector>svg{fill:".concat(_uiConstants.theme.primary700, ";}"), "button.disabled.__jsx-style-dynamic-selector{color:".concat(_uiConstants.colors.grey500, ";cursor:not-allowed;}"), "button.disabled.__jsx-style-dynamic-selector:hover,button.selected.__jsx-style-dynamic-selector:hover{background-color:transparent;}", "button.disabled.__jsx-style-dynamic-selector>svg{fill:".concat(_uiConstants.colors.grey500, ";}")]));
77
+ });
44
78
 
45
79
  exports.Tab = Tab;
46
80
  Tab.defaultProps = {
@@ -58,4 +92,5 @@ Tab.propTypes = {
58
92
 
59
93
  /** Called with the signature `({}, event)` */
60
94
  onClick: _propTypes.default.func
61
- };
95
+ };
96
+ Tab.displayName = 'Tab';
@@ -13,7 +13,11 @@ var _classnames = _interopRequireDefault(require("classnames"));
13
13
 
14
14
  var _propTypes = _interopRequireDefault(require("prop-types"));
15
15
 
16
- var _react = _interopRequireDefault(require("react"));
16
+ var _react = _interopRequireWildcard(require("react"));
17
+
18
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
19
+
20
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
17
21
 
18
22
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
23
 
@@ -23,13 +27,63 @@ const Tabs = _ref => {
23
27
  fixed,
24
28
  dataTest
25
29
  } = _ref;
30
+ const tabContainer = (0, _react.useRef)(null);
31
+ const childrenRefs = (0, _react.useMemo)(() => _react.default.Children.map(children, () => /*#__PURE__*/_react.default.createRef()), [children]);
32
+
33
+ const handleKeyDown = event => {
34
+ const currentFocus = document.activeElement;
35
+
36
+ if (tabContainer.current && tabContainer.current === currentFocus) {
37
+ if (childrenRefs.length > 0 && childrenRefs[0].current) {
38
+ childrenRefs[0].current.focus();
39
+ }
40
+
41
+ return;
42
+ }
43
+
44
+ const currentIndex = childrenRefs.findIndex(ref => ref.current === currentFocus);
45
+
46
+ if (currentIndex === -1) {
47
+ return;
48
+ }
49
+
50
+ if (event.key === 'ArrowRight') {
51
+ event.preventDefault();
52
+ const nextIndex = (currentIndex + 1) % childrenRefs.length;
53
+ childrenRefs[nextIndex].current.focus();
54
+ }
55
+
56
+ if (event.key === 'ArrowLeft') {
57
+ event.preventDefault();
58
+ const prevIndex = (currentIndex - 1 + childrenRefs.length) % childrenRefs.length;
59
+ childrenRefs[prevIndex].current.focus();
60
+ }
61
+ };
62
+
26
63
  return /*#__PURE__*/_react.default.createElement("div", {
64
+ ref: tabContainer,
27
65
  "data-test": dataTest,
28
- className: _style.default.dynamic([["2678989862", [_uiConstants.colors.grey400, _uiConstants.colors.white]]]) + " " + ((0, _classnames.default)({
66
+ role: "tablist",
67
+ tabIndex: 0,
68
+ onKeyDown: handleKeyDown,
69
+ className: _style.default.dynamic([["771129571", [_uiConstants.colors.grey400, _uiConstants.colors.white]]]) + " " + ((0, _classnames.default)({
29
70
  fixed
30
71
  }) || "")
31
- }, children, /*#__PURE__*/_react.default.createElement(_style.default, {
32
- id: "2678989862",
72
+ }, _react.default.Children.map(children, (child, index) => {
73
+ if ( /*#__PURE__*/_react.default.isValidElement(child)) {
74
+ return /*#__PURE__*/_react.default.cloneElement(child, {
75
+ ref: childrenRefs[index]
76
+ });
77
+ } // Wrap non-element children e.g string in a <span>
78
+
79
+
80
+ return /*#__PURE__*/_react.default.createElement("span", {
81
+ ref: childrenRefs[index],
82
+ tabIndex: -1,
83
+ className: _style.default.dynamic([["771129571", [_uiConstants.colors.grey400, _uiConstants.colors.white]]])
84
+ }, child);
85
+ }), /*#__PURE__*/_react.default.createElement(_style.default, {
86
+ id: "771129571",
33
87
  dynamic: [_uiConstants.colors.grey400, _uiConstants.colors.white]
34
88
  }, ["div.__jsx-style-dynamic-selector{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;position:relative;overflow:hidden;box-shadow:inset 0 -1px 0 0 ".concat(_uiConstants.colors.grey400, ";-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;background:").concat(_uiConstants.colors.white, ";}")]));
35
89
  };
@@ -1,10 +1,10 @@
1
1
  import _JSXStyle from "styled-jsx/style";
2
+ import { Tooltip } from '@dhis2-ui/tooltip';
2
3
  import { colors, theme } from '@dhis2/ui-constants';
3
4
  import cx from 'classnames';
4
5
  import PropTypes from 'prop-types';
5
- import React from 'react';
6
-
7
- const Tab = _ref => {
6
+ import React, { useState, useEffect, useRef } from 'react';
7
+ export const Tab = /*#__PURE__*/React.forwardRef((_ref, ref) => {
8
8
  let {
9
9
  icon,
10
10
  onClick,
@@ -14,21 +14,48 @@ const Tab = _ref => {
14
14
  className,
15
15
  dataTest
16
16
  } = _ref;
17
+ let tabRef = useRef(null);
18
+
19
+ if (ref) {
20
+ tabRef = ref;
21
+ }
22
+
23
+ const [isOverflowing, setIsOverflowing] = useState(false);
24
+ useEffect(() => {
25
+ const checkOverflow = () => {
26
+ const isOverflow = tabRef.current.scrollWidth > tabRef.current.clientWidth;
27
+ setIsOverflowing(isOverflow);
28
+ };
29
+
30
+ checkOverflow();
31
+ }, []);
17
32
  return /*#__PURE__*/React.createElement("button", {
18
33
  onClick: disabled ? undefined : event => onClick({}, event),
19
34
  "data-test": dataTest,
20
- className: _JSXStyle.dynamic([["3476406340", [colors.grey400, colors.grey600, theme.focus, colors.grey600, colors.grey900, colors.grey600, colors.grey800, theme.primary800, theme.primary700, theme.primary700, theme.primary700, colors.grey500, colors.grey500]]]) + " " + "".concat(cx('tab', className, {
35
+ ref: tabRef,
36
+ role: "tab",
37
+ "aria-selected": selected ? 'true' : 'false',
38
+ "aria-disabled": disabled ? 'true' : 'false',
39
+ onFocus: disabled ? undefined : event => onClick({}, event),
40
+ tabIndex: -1,
41
+ className: _JSXStyle.dynamic([["2433456263", [colors.grey400, colors.grey600, theme.focus, colors.grey600, colors.grey900, colors.grey600, colors.grey800, theme.primary800, theme.primary700, theme.primary700, theme.primary700, colors.grey500, colors.grey500]]]) + " " + "".concat(cx('tab', className, {
21
42
  selected,
22
43
  disabled
23
44
  }))
24
- }, icon, /*#__PURE__*/React.createElement("span", {
25
- className: _JSXStyle.dynamic([["3476406340", [colors.grey400, colors.grey600, theme.focus, colors.grey600, colors.grey900, colors.grey600, colors.grey800, theme.primary800, theme.primary700, theme.primary700, theme.primary700, colors.grey500, colors.grey500]]])
45
+ }, icon, isOverflowing ? /*#__PURE__*/React.createElement(Tooltip, {
46
+ content: children,
47
+ maxWidth: '100%'
48
+ }, /*#__PURE__*/React.createElement("span", {
49
+ ref: tabRef,
50
+ className: _JSXStyle.dynamic([["2433456263", [colors.grey400, colors.grey600, theme.focus, colors.grey600, colors.grey900, colors.grey600, colors.grey800, theme.primary800, theme.primary700, theme.primary700, theme.primary700, colors.grey500, colors.grey500]]])
51
+ }, children)) : /*#__PURE__*/React.createElement("span", {
52
+ ref: tabRef,
53
+ className: _JSXStyle.dynamic([["2433456263", [colors.grey400, colors.grey600, theme.focus, colors.grey600, colors.grey900, colors.grey600, colors.grey800, theme.primary800, theme.primary700, theme.primary700, theme.primary700, colors.grey500, colors.grey500]]])
26
54
  }, children), /*#__PURE__*/React.createElement(_JSXStyle, {
27
- id: "3476406340",
55
+ id: "2433456263",
28
56
  dynamic: [colors.grey400, colors.grey600, theme.focus, colors.grey600, colors.grey900, colors.grey600, colors.grey800, theme.primary800, theme.primary700, theme.primary700, theme.primary700, colors.grey500, colors.grey500]
29
- }, ["button.__jsx-style-dynamic-selector{-webkit-box-flex:0;-webkit-flex-grow:0;-ms-flex-positive:0;flex-grow:0;position:relative;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;vertical-align:bottom;height:100%;padding:16px 16px 11px;background-color:transparent;outline:none;border:none;border-bottom:1px solid ".concat(colors.grey400, ";color:").concat(colors.grey600, ";font-size:14px;line-height:20px;cursor:pointer;}"), ".fixed>button.__jsx-style-dynamic-selector{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;}", "button.__jsx-style-dynamic-selector::after{content:' ';display:block;position:absolute;bottom:-1px;inset-inline-start:0;height:4px;width:100%;background-color:transparent;}", "span.__jsx-style-dynamic-selector{max-width:320px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-transition:fill 150ms ease-in-out;transition:fill 150ms ease-in-out;}", "button.__jsx-style-dynamic-selector:focus{outline:3px solid ".concat(theme.focus, ";outline-offset:-3px;}"), "button.__jsx-style-dynamic-selector:focus.__jsx-style-dynamic-selector:not(:focus-visible){outline:none;}", "button.__jsx-style-dynamic-selector>svg{fill:".concat(colors.grey600, ";width:14px;height:14px;margin:0 4px 0 0;}"), "button.__jsx-style-dynamic-selector:hover{color:".concat(colors.grey900, ";}"), "button.__jsx-style-dynamic-selector:hover.__jsx-style-dynamic-selector::after{background-color:".concat(colors.grey600, ";height:2px;}"), "button.__jsx-style-dynamic-selector:active.__jsx-style-dynamic-selector::after{background-color:".concat(colors.grey800, ";}"), "button.selected.__jsx-style-dynamic-selector{color:".concat(theme.primary800, ";}"), "button.selected.__jsx-style-dynamic-selector::after{background-color:".concat(theme.primary700, ";-webkit-transition:background-color 150ms ease-in-out;transition:background-color 150ms ease-in-out;}"), "button.selected.__jsx-style-dynamic-selector:hover.__jsx-style-dynamic-selector::after{background-color:".concat(theme.primary700, ";height:4px;}"), "button.selected.__jsx-style-dynamic-selector>svg{fill:".concat(theme.primary700, ";}"), "button.disabled.__jsx-style-dynamic-selector{color:".concat(colors.grey500, ";cursor:not-allowed;}"), "button.disabled.__jsx-style-dynamic-selector:hover,button.selected.__jsx-style-dynamic-selector:hover{background-color:transparent;}", "button.disabled.__jsx-style-dynamic-selector>svg{fill:".concat(colors.grey500, ";}")]));
30
- };
31
-
57
+ }, ["button.__jsx-style-dynamic-selector{-webkit-box-flex:0;-webkit-flex-grow:0;-ms-flex-positive:0;flex-grow:0;position:relative;display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;vertical-align:bottom;height:100%;padding:16px 16px 11px;background-color:transparent;outline:none;border:none;border-bottom:1px solid ".concat(colors.grey400, ";color:").concat(colors.grey600, ";font-size:14px;line-height:20px;cursor:pointer;}"), ".fixed>button.__jsx-style-dynamic-selector{-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;}", "button.__jsx-style-dynamic-selector::after{content:' ';display:block;position:absolute;bottom:-1px;inset-inline-start:0;height:4px;width:100%;background-color:transparent;}", "span.__jsx-style-dynamic-selector{display:-webkit-inline-box;display:-webkit-inline-flex;display:-ms-inline-flexbox;display:inline-flex;max-width:320px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-transition:fill 150ms ease-in-out;transition:fill 150ms ease-in-out;}", "button.__jsx-style-dynamic-selector:focus{outline:3px solid ".concat(theme.focus, ";outline-offset:-3px;}"), "button.__jsx-style-dynamic-selector:focus.__jsx-style-dynamic-selector:not(:focus-visible){outline:none;}", "button.__jsx-style-dynamic-selector>svg{fill:".concat(colors.grey600, ";width:14px;height:14px;margin:0 4px 0 0;}"), "button.__jsx-style-dynamic-selector:hover{color:".concat(colors.grey900, ";}"), "button.__jsx-style-dynamic-selector:hover.__jsx-style-dynamic-selector::after{background-color:".concat(colors.grey600, ";height:2px;}"), "button.__jsx-style-dynamic-selector:active.__jsx-style-dynamic-selector::after{background-color:".concat(colors.grey800, ";}"), "button.selected.__jsx-style-dynamic-selector{color:".concat(theme.primary800, ";}"), "button.selected.__jsx-style-dynamic-selector::after{background-color:".concat(theme.primary700, ";-webkit-transition:background-color 150ms ease-in-out;transition:background-color 150ms ease-in-out;}"), "button.selected.__jsx-style-dynamic-selector:hover.__jsx-style-dynamic-selector::after{background-color:".concat(theme.primary700, ";height:4px;}"), "button.selected.__jsx-style-dynamic-selector>svg{fill:".concat(theme.primary700, ";}"), "button.disabled.__jsx-style-dynamic-selector{color:".concat(colors.grey500, ";cursor:not-allowed;}"), "button.disabled.__jsx-style-dynamic-selector:hover,button.selected.__jsx-style-dynamic-selector:hover{background-color:transparent;}", "button.disabled.__jsx-style-dynamic-selector>svg{fill:".concat(colors.grey500, ";}")]));
58
+ });
32
59
  Tab.defaultProps = {
33
60
  dataTest: 'dhis2-uicore-tab'
34
61
  };
@@ -45,4 +72,4 @@ Tab.propTypes = {
45
72
  /** Called with the signature `({}, event)` */
46
73
  onClick: PropTypes.func
47
74
  };
48
- export { Tab };
75
+ Tab.displayName = 'Tab';
@@ -2,7 +2,7 @@ import _JSXStyle from "styled-jsx/style";
2
2
  import { colors } from '@dhis2/ui-constants';
3
3
  import cx from 'classnames';
4
4
  import PropTypes from 'prop-types';
5
- import React from 'react';
5
+ import React, { useRef, useMemo } from 'react';
6
6
 
7
7
  const Tabs = _ref => {
8
8
  let {
@@ -10,13 +10,63 @@ const Tabs = _ref => {
10
10
  fixed,
11
11
  dataTest
12
12
  } = _ref;
13
+ const tabContainer = useRef(null);
14
+ const childrenRefs = useMemo(() => React.Children.map(children, () => /*#__PURE__*/React.createRef()), [children]);
15
+
16
+ const handleKeyDown = event => {
17
+ const currentFocus = document.activeElement;
18
+
19
+ if (tabContainer.current && tabContainer.current === currentFocus) {
20
+ if (childrenRefs.length > 0 && childrenRefs[0].current) {
21
+ childrenRefs[0].current.focus();
22
+ }
23
+
24
+ return;
25
+ }
26
+
27
+ const currentIndex = childrenRefs.findIndex(ref => ref.current === currentFocus);
28
+
29
+ if (currentIndex === -1) {
30
+ return;
31
+ }
32
+
33
+ if (event.key === 'ArrowRight') {
34
+ event.preventDefault();
35
+ const nextIndex = (currentIndex + 1) % childrenRefs.length;
36
+ childrenRefs[nextIndex].current.focus();
37
+ }
38
+
39
+ if (event.key === 'ArrowLeft') {
40
+ event.preventDefault();
41
+ const prevIndex = (currentIndex - 1 + childrenRefs.length) % childrenRefs.length;
42
+ childrenRefs[prevIndex].current.focus();
43
+ }
44
+ };
45
+
13
46
  return /*#__PURE__*/React.createElement("div", {
47
+ ref: tabContainer,
14
48
  "data-test": dataTest,
15
- className: _JSXStyle.dynamic([["2678989862", [colors.grey400, colors.white]]]) + " " + (cx({
49
+ role: "tablist",
50
+ tabIndex: 0,
51
+ onKeyDown: handleKeyDown,
52
+ className: _JSXStyle.dynamic([["771129571", [colors.grey400, colors.white]]]) + " " + (cx({
16
53
  fixed
17
54
  }) || "")
18
- }, children, /*#__PURE__*/React.createElement(_JSXStyle, {
19
- id: "2678989862",
55
+ }, React.Children.map(children, (child, index) => {
56
+ if ( /*#__PURE__*/React.isValidElement(child)) {
57
+ return /*#__PURE__*/React.cloneElement(child, {
58
+ ref: childrenRefs[index]
59
+ });
60
+ } // Wrap non-element children e.g string in a <span>
61
+
62
+
63
+ return /*#__PURE__*/React.createElement("span", {
64
+ ref: childrenRefs[index],
65
+ tabIndex: -1,
66
+ className: _JSXStyle.dynamic([["771129571", [colors.grey400, colors.white]]])
67
+ }, child);
68
+ }), /*#__PURE__*/React.createElement(_JSXStyle, {
69
+ id: "771129571",
20
70
  dynamic: [colors.grey400, colors.white]
21
71
  }, ["div.__jsx-style-dynamic-selector{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-align-items:flex-start;-webkit-box-align:flex-start;-ms-flex-align:flex-start;align-items:flex-start;position:relative;overflow:hidden;box-shadow:inset 0 -1px 0 0 ".concat(colors.grey400, ";-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;-webkit-box-flex:1;-webkit-flex-grow:1;-ms-flex-positive:1;flex-grow:1;background:").concat(colors.white, ";}")]));
22
72
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhis2-ui/tab",
3
- "version": "9.9.0",
3
+ "version": "9.10.0",
4
4
  "description": "UI Tabs",
5
5
  "repository": {
6
6
  "type": "git",
@@ -32,9 +32,10 @@
32
32
  "styled-jsx": "^4"
33
33
  },
34
34
  "dependencies": {
35
+ "@dhis2-ui/tooltip": "9.10.0",
35
36
  "@dhis2/prop-types": "^3.1.2",
36
- "@dhis2/ui-constants": "9.9.0",
37
- "@dhis2/ui-icons": "9.9.0",
37
+ "@dhis2/ui-constants": "9.10.0",
38
+ "@dhis2/ui-icons": "9.10.0",
38
39
  "classnames": "^2.3.1",
39
40
  "prop-types": "^15.7.2"
40
41
  },