@equinor/eds-core-react
Version:
The React implementation of the Equinor Design System
138 lines (135 loc) • 4.74 kB
JavaScript
import styled from 'styled-components';
import { tokens } from '@equinor/eds-tokens';
import { FocusScope, useFocusManager } from 'react-aria';
import { useRef, useEffect } from 'react';
import { jsx } from 'react/jsx-runtime';
// Disable no-autofocus - it's not the native autofocus attribute, but react-aria's autoFocus prop
/* eslint-disable jsx-a11y/no-autofocus */
const Grid = styled.div.withConfig({
displayName: "YearGrid__Grid",
componentId: "sc-1l9jho8-0"
})(["display:grid;grid-template-columns:repeat(6,1fr);grid-gap:8px;margin:8px;"]);
const GridColumn = styled.button.withConfig({
displayName: "YearGrid__GridColumn",
componentId: "sc-1l9jho8-1"
})(["background-color:transparent;outline:none;border:none;display:flex;justify-content:center;cursor:pointer;padding:8px;font-size:", ";font-family:", ";font-weight:", ";line-height:", ";color:", ";border-radius:999px;", ";&:hover{background-color:#f0f0f0;}&:focus{outline:2px dashed ", ";}"], tokens.typography.navigation.button.fontSize, tokens.typography.navigation.button.fontFamily, tokens.typography.navigation.button.fontWeight, tokens.typography.navigation.button.lineHeight, tokens.colors.text.static_icons__default.rgba, ({
$active
}) => $active ? `background-color: ${tokens.colors.interactive.primary__selected_highlight.rgba}` : '', tokens.colors.interactive.primary__resting.rgba);
const TOTAL_VISIBLE_YEARS = 36;
const RANGE_OFFSET = 30 / 2;
const GridFocusManager = ({
year: selectedYear,
setFocusedYear,
yearPickerPage,
setYearPickerPage
}) => {
const focusManager = useFocusManager();
const prevYear = useRef();
const navByKeyboard = useRef(false);
const page = yearPickerPage * TOTAL_VISIBLE_YEARS;
const years = Array.from({
length: TOTAL_VISIBLE_YEARS
}, (_, i) => i + (selectedYear + page - RANGE_OFFSET));
useEffect(() => {
if (prevYear.current === undefined) {
prevYear.current = yearPickerPage;
return;
}
if (!navByKeyboard.current) {
focusManager.focusFirst();
return;
}
navByKeyboard.current = false;
yearPickerPage > prevYear.current ? focusManager.focusFirst() : focusManager.focusLast();
prevYear.current = yearPickerPage;
}, [yearPickerPage, focusManager]);
const onKeyDown = year => e => {
const target = e.currentTarget;
const parent = target.parentElement;
const isFirstYear = years.at(0) === year;
const isLastYear = years.at(-1) === year;
switch (e.key) {
case 'ArrowRight':
e.preventDefault();
if (isLastYear) {
navByKeyboard.current = true;
setYearPickerPage(page => page + 1);
break;
}
focusManager.focusNext({
wrap: true
});
break;
case 'ArrowLeft':
e.preventDefault();
if (isFirstYear) {
navByKeyboard.current = true;
setYearPickerPage(page => page - 1);
break;
}
focusManager.focusPrevious({
wrap: true
});
break;
case 'ArrowDown':
{
e.preventDefault();
if (isLastYear) {
navByKeyboard.current = true;
setYearPickerPage(page => page + 1);
break;
}
const selfIndex = Array.from(parent.children).indexOf(target);
const focusElement = Array.from(parent.children).at(selfIndex + 5);
focusManager.focusNext({
from: focusElement
});
break;
}
case 'ArrowUp':
{
e.preventDefault();
if (isFirstYear) {
navByKeyboard.current = true;
setYearPickerPage(page => page - 1);
break;
}
const selfIndex = Array.from(parent.children).indexOf(target);
const focusElement = Array.from(parent.children).at(selfIndex - 5);
focusManager.focusPrevious({
from: focusElement
});
break;
}
}
};
return years.map(year => /*#__PURE__*/jsx(GridColumn, {
$active: selectedYear === year,
onKeyDown: onKeyDown(year),
onClick: () => setFocusedYear(year),
"aria-label": `Set year to ${year}`,
tabIndex: 0,
children: year
}, year));
};
const YearGrid = ({
setFocusedYear,
year: selectedYear,
yearPickerPage,
setYearPickerPage
}) => {
return /*#__PURE__*/jsx(Grid, {
children: /*#__PURE__*/jsx(FocusScope, {
contain: true,
restoreFocus: true,
autoFocus: true,
children: /*#__PURE__*/jsx(GridFocusManager, {
year: selectedYear,
setFocusedYear: setFocusedYear,
yearPickerPage: yearPickerPage,
setYearPickerPage: setYearPickerPage
})
})
});
};
export { YearGrid };