UNPKG

@spark-web/text-link

Version:

--- title: Text Link storybookPath: navigation-textlink--default isExperimentalPackage: true ---

92 lines (85 loc) 3.4 kB
import _objectSpread from '@babel/runtime/helpers/esm/objectSpread2'; import _objectWithoutProperties from '@babel/runtime/helpers/esm/objectWithoutProperties'; import { css } from '@emotion/css'; import { Box } from '@spark-web/box'; import { useLinkComponent } from '@spark-web/link'; import { forwardRefWithAs } from '@spark-web/utils/ts'; import { useTextContext, useForegroundTone } from '@spark-web/text'; import { useTheme } from '@spark-web/theme'; import { resetElementStyles, buildDataAttributes } from '@spark-web/utils/internal'; import { jsx } from 'react/jsx-runtime'; import { useComposedRefs } from '@spark-web/utils'; import { forwardRef, useRef, useCallback } from 'react'; var TEXT_LINK_ERROR_MESSAGE = 'TextLink components must be inside `Text`.'; function useTextLink(tag) { var textContext = useTextContext(); // Limit API surface area; expect style inheritance if (!textContext) { throw new Error(TEXT_LINK_ERROR_MESSAGE); } var theme = useTheme(); var textColor = useForegroundTone(textContext.tone); var resetStyles = resetElementStyles(tag); var linkStyles = { color: textColor, cursor: 'pointer', textDecoration: 'underline', fontWeight: theme.typography.fontWeight.semibold }; var styles = [resetStyles, linkStyles]; return styles; } var _excluded$1 = ["as", "data"]; /** * Text links are used as navigational elements. They may appear on their own, * within a sentence or paragraph, or directly following content. * * @note If you are **only** providing "onClick" use `TextLinkButton` instead. */ var TextLink = forwardRefWithAs( // NOTE: we need `forwardRefWithAs` for TS, but we don't want consumers changing the underlying element // eslint-disable-next-line @typescript-eslint/no-unused-vars function (_ref, ref) { _ref.as; var data = _ref.data, consumerProps = _objectWithoutProperties(_ref, _excluded$1); var LinkComponent = useLinkComponent(ref); var styles = useTextLink('a'); return /*#__PURE__*/jsx(Box, _objectSpread({ as: LinkComponent, asElement: "a", ref: ref, className: css(styles), data: data }, consumerProps)); }); var _excluded = ["data"]; // NOTE: Rather than a native `button` element, we render a `span` with the ARIA // role of "button" to avoid issues with text behaviour. Resolves: // - alignment // - truncating // - wrapping /** The appearance of `TextLink`, with the semantics of a `<button/>`. */ var TextLinkButton = /*#__PURE__*/forwardRef(function (_ref, forwardedRef) { var data = _ref.data, consumerProps = _objectWithoutProperties(_ref, _excluded); var styles = useTextLink('span'); var internalRef = useRef(null); var ref = useComposedRefs(internalRef, forwardedRef); var handleKeyDown = useCallback(function (event) { if (event.key === 'Enter' || event.key === ' ') { var _internalRef$current; event.preventDefault(); (_internalRef$current = internalRef.current) === null || _internalRef$current === void 0 ? void 0 : _internalRef$current.click(); } }, [internalRef]); return /*#__PURE__*/jsx("span", _objectSpread(_objectSpread({ role: "button", ref: ref, className: css(styles), tabIndex: 0, onKeyDown: handleKeyDown }, data ? buildDataAttributes(data) : undefined), consumerProps)); }); TextLinkButton.displayName = 'TextLinkButton'; export { TextLink, TextLinkButton };