@spark-web/nav-link
Version:
--- title: Nav Link storybookPath: navigation-navlink--default isExperimentalPackage: true ---
102 lines (99 loc) • 3.24 kB
JavaScript
import { css } from '@emotion/css';
import { useFocusRing } from '@spark-web/a11y';
import { Box } from '@spark-web/box';
import { useLinkComponent } from '@spark-web/link';
import { Text } from '@spark-web/text';
import { useTheme } from '@spark-web/theme';
import { forwardRef, Children, isValidElement, cloneElement } from 'react';
import { jsx } from 'react/jsx-runtime';
var NavLink = /*#__PURE__*/forwardRef(function (_ref, forwardedRef) {
var _ref$borderRadius = _ref.borderRadius,
borderRadius = _ref$borderRadius === void 0 ? 'small' : _ref$borderRadius,
children = _ref.children,
data = _ref.data,
href = _ref.href,
_ref$inline = _ref.inline,
inline = _ref$inline === void 0 ? false : _ref$inline,
_ref$isSelected = _ref.isSelected,
isSelected = _ref$isSelected === void 0 ? false : _ref$isSelected,
_ref$size = _ref.size,
size = _ref$size === void 0 ? 'medium' : _ref$size;
var linkComponent = useLinkComponent(forwardedRef);
var styles = useNavLinkStyles(isSelected);
return /*#__PURE__*/jsx(Box, {
as: linkComponent,
asElement: "a",
href: href,
"aria-current": isSelected ? 'page' : undefined,
data: data
// styles
,
background: isSelected ? 'primaryMuted' : undefined,
display: inline ? 'inline-flex' : 'flex',
alignItems: "center",
gap: "small",
paddingY: "small",
paddingX: "medium",
borderRadius: {
tablet: borderRadius
},
className: css(styles),
children: resolveNavLinkChildren({
children: children,
isSelected: isSelected,
size: size
})
});
});
NavLink.displayName = 'NavLink';
function useNavLinkStyles(isSelected) {
var theme = useTheme();
var focusRingStyles = useFocusRing();
return {
':focus': focusRingStyles,
':hover': {
backgroundColor: isSelected ? theme.backgroundInteractions.primaryLowHover : theme.color.background.surfaceMuted,
'> *': {
color: isSelected ? theme.color.foreground.primaryHover : undefined,
stroke: isSelected ? theme.color.foreground.primaryHover : undefined
}
},
':active': {
backgroundColor: isSelected ? theme.backgroundInteractions.positiveLowActive : theme.color.background.surfacePressed,
'> *': {
color: isSelected ? theme.color.foreground.primaryActive : undefined,
stroke: isSelected ? theme.color.foreground.primaryActive : undefined
}
}
};
}
function resolveNavLinkChildren(_ref2) {
var children = _ref2.children,
isSelected = _ref2.isSelected,
size = _ref2.size;
return Children.map(children, function (child) {
if (typeof child === 'string') {
return /*#__PURE__*/jsx(Text, {
as: "span",
baseline: false,
overflowStrategy: "nowrap",
weight: "semibold",
size: mapTextSize[size],
tone: isSelected ? 'primaryActive' : 'muted',
children: child
});
}
if ( /*#__PURE__*/isValidElement(child)) {
return /*#__PURE__*/cloneElement(child, {
size: 'xxsmall',
tone: isSelected ? 'primaryActive' : 'muted'
});
}
return null;
});
}
var mapTextSize = {
medium: 'small',
large: 'standard'
};
export { NavLink };