From d6acb2b025350a1e2ee556c565465aab3b4a2620 Mon Sep 17 00:00:00 2001 From: Dharit Tantiviramanond Date: Thu, 25 Sep 2025 17:55:04 -0400 Subject: [PATCH 1/2] Text body variant subscripts --- packages/harmony/src/components/text/Text.tsx | 61 ++++++++++++++++++- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/packages/harmony/src/components/text/Text.tsx b/packages/harmony/src/components/text/Text.tsx index a1b78fb706d..14de68ed764 100644 --- a/packages/harmony/src/components/text/Text.tsx +++ b/packages/harmony/src/components/text/Text.tsx @@ -1,4 +1,11 @@ -import { ElementType, ForwardedRef, forwardRef, useContext } from 'react' +import { + cloneElement, + ElementType, + ForwardedRef, + forwardRef, + isValidElement, + useContext +} from 'react' import { Theme, useTheme } from '@emotion/react' import { Slot } from '@radix-ui/react-slot' @@ -23,6 +30,42 @@ const getColorCss = (color: TextProps['color'], theme: Theme) => { return { color: theme.color.text[color] } } +// Check if text contains Unicode subscript characters +const containsSubscripts = (children: any): boolean => { + if (!children) return false + const text = typeof children === 'string' ? children : String(children) + // Unicode subscript range: \u2080-\u2089 (₀-₉) and other subscript chars + return /[\u2080-\u209F]/.test(text) +} + +// Process children to replace Unicode subscripts with tags +const processSubscripts = (children: any): any => { + if (!children) return children + if (typeof children === 'string') { + // Replace Unicode subscript characters with tags + const parts = children.split(/([\u2080-\u209F]+)/) + if (parts.length === 1) return children // No subscripts found + + return parts.map((part, index) => { + if (/[\u2080-\u209F]/.test(part)) { + return {part} + } + return part + }) + } + if (Array.isArray(children)) { + return children.map(processSubscripts) + } + if (isValidElement(children)) { + return cloneElement( + children, + {}, + processSubscripts((children.props as any).children) + ) + } + return children +} + export const Text = forwardRef( ( props: TextProps, @@ -54,6 +97,7 @@ export const Text = forwardRef( const size = sizeProp ?? (parentVariant ? undefined : 'm') const variantConfig = variant && variantStylesMap[variant] + const hasSubscripts = containsSubscripts(children) const css = { fontFamily: theme.typography.font, @@ -105,11 +149,22 @@ export const Text = forwardRef( // @ts-ignore const variantTag = variant && variantTagMap[variant]?.[size] - const Tag: ElementType = asChild ? Slot : (tag ?? variantTag ?? 'span') + const Tag: ElementType = asChild ? Slot : tag ?? variantTag ?? 'span' + + // Only convert Unicode subscripts to tags for body variants with default strength. + // Other variants/strengths render Unicode subscripts correctly without this conversion. + const shouldProcessSubscripts = + hasSubscripts && + variant === 'body' && + (!strength || strength === 'default') + + const processedChildren = shouldProcessSubscripts + ? processSubscripts(children) + : children const textElement = ( - {children} + {processedChildren} ) From 1700673ca5a910afa041c38cd0d47b077b492796 Mon Sep 17 00:00:00 2001 From: Dharit Tantiviramanond Date: Thu, 25 Sep 2025 18:03:42 -0400 Subject: [PATCH 2/2] lint --- packages/harmony/src/components/text/Text.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/harmony/src/components/text/Text.tsx b/packages/harmony/src/components/text/Text.tsx index 14de68ed764..61245d71200 100644 --- a/packages/harmony/src/components/text/Text.tsx +++ b/packages/harmony/src/components/text/Text.tsx @@ -149,7 +149,7 @@ export const Text = forwardRef( // @ts-ignore const variantTag = variant && variantTagMap[variant]?.[size] - const Tag: ElementType = asChild ? Slot : tag ?? variantTag ?? 'span' + const Tag: ElementType = asChild ? Slot : (tag ?? variantTag ?? 'span') // Only convert Unicode subscripts to tags for body variants with default strength. // Other variants/strengths render Unicode subscripts correctly without this conversion.