@equinor/eds-core-react
Version:
The React implementation of the Equinor Design System
95 lines (91 loc) • 2.56 kB
JavaScript
import { forwardRef, useRef, useMemo, useState, useEffect } from 'react';
import { TabsProvider } from './Tabs.context.js';
import { token } from './Tabs.tokens.js';
import { useId, mergeRefs, useToken } from '@equinor/eds-utils';
import { ThemeProvider } from 'styled-components';
import { jsx } from 'react/jsx-runtime';
import { useEds } from '../EdsProvider/eds.context.js';
const Tabs = /*#__PURE__*/forwardRef(function Tabs({
activeTab = 0,
onChange = () => null,
onBlur,
onFocus,
variant = 'minWidth',
scrollable = false,
id,
...props
}, ref) {
const tabsId = useId(id, 'tabs');
const tabsRef = useRef(null);
const combinedTabsRef = useMemo(() => mergeRefs(tabsRef, ref), [tabsRef, ref]);
const [tabsFocused, setTabsFocused] = useState(false);
const [listenerAttached, setListenerAttached] = useState(false);
let blurTimer;
const handleBlur = e => {
setListenerAttached(false);
if (tabsRef.current) {
tabsRef.current.removeEventListener('keyup', checkIfTabWasPressed);
}
blurTimer = setTimeout(() => {
if (tabsFocused) {
setTabsFocused(false);
}
}, 0);
onBlur && onBlur(e);
};
const handleFocus = e => {
if (e.target.getAttribute('role') !== 'tab') {
return;
}
clearTimeout(blurTimer);
if (tabsFocused) return;
if (!listenerAttached) {
if (tabsRef.current) {
setListenerAttached(true);
tabsRef.current.addEventListener('keyup', checkIfTabWasPressed, {
once: true,
capture: true
});
}
}
onFocus && onFocus(e);
};
//Only force focus on active Tab if Tabs was navigated to with keyboard
const checkIfTabWasPressed = event => {
setListenerAttached(false);
if (event.key === 'Tab') setTabsFocused(true);
};
useEffect(() => {
const tabs = tabsRef.current;
return () => {
if (tabs) tabs.removeEventListener('keyup', checkIfTabWasPressed);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const {
density
} = useEds();
const token$1 = useToken({
density
}, token);
return /*#__PURE__*/jsx(ThemeProvider, {
theme: token$1,
children: /*#__PURE__*/jsx(TabsProvider, {
value: {
activeTab,
handleChange: onChange,
tabsId,
variant,
scrollable,
tabsFocused
},
children: /*#__PURE__*/jsx("div", {
ref: combinedTabsRef,
...props,
onBlur: handleBlur,
onFocus: handleFocus
})
})
});
});
export { Tabs };