import React from 'react'; import { css, cx } from '@leafygreen-ui/emotion'; import { getNodeTextContent } from '@leafygreen-ui/lib'; import { Polymorph, PolymorphicAs, PolymorphicPropsWithRef, } from '@leafygreen-ui/polymorphic'; import { CommonTypographyProps } from '../types'; interface LocalProps extends CommonTypographyProps { /** * The maximum future weight of the text. Determines the width of the component. * @default 700 */ maxFontWeight?: React.CSSProperties['fontWeight']; /** * Defines the pseudo element used to force the element width */ pseudoElement?: 'before' | 'after'; } type StaticWidthTextProps = PolymorphicPropsWithRef< T, LocalProps >; const staticWidthTextStyle = ({ pseudoElement, maxFontWeight, }: Pick, 'pseudoElement' | 'maxFontWeight'>) => { const pseudoSelector = `&:${pseudoElement}`; return css` /* Inherit relevant properties from the parent */ font-weight: inherit; font-size: inherit; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; position: relative; display: inline-flex; flex-direction: column; align-items: flex-start; justify-content: center; text-decoration: none; min-width: 0; max-width: 100%; ${pseudoSelector} { content: attr(data-text); height: 0; font-weight: ${maxFontWeight}; visibility: hidden; overflow: hidden; user-select: none; pointer-events: none; } `; }; const childWrapper = css` flex: 1; min-width: 0; max-width: 100%; white-space: inherit; overflow: inherit; text-overflow: inherit; `; /** * * A wrapper component to ensure that updating the font weight does not affect the width of the element, * and prevents layout shift should the font weight change. * * Useful for showing a bold effect on hover, focus, or active (See `Tabs`, `MenuItem`). * * Will add an ellipsis if the text would extend beyond the parent, * or if the bold text is significantly larger than the regular text * (This is rare, and will only occur with _very_ long text) * * Note: does not support wrapped text (i.e. text within a paragraph) * * @internal * */ export function StaticWidthText({ as, children, maxFontWeight = 700, pseudoElement = 'after', className, ...rest }: StaticWidthTextProps) { // calling getNodeTextContent in case a node gets passed in without TS const textContent = getNodeTextContent(children); return ( {children} ); }