From 24a3f7d32a2b3ec6da624bc02cebdcb4bb6abe5e Mon Sep 17 00:00:00 2001 From: Radek Podrazky Date: Tue, 26 Nov 2024 12:33:35 +0100 Subject: [PATCH] fix(ElementLabel): allow element polymorphism Closes UXD-1671 --- src/components/ElementLabel/ElementLabel.tsx | 42 +++++++++++--------- src/types/utils.types.ts | 12 ++++-- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/src/components/ElementLabel/ElementLabel.tsx b/src/components/ElementLabel/ElementLabel.tsx index e223b2d0d..a11f67087 100644 --- a/src/components/ElementLabel/ElementLabel.tsx +++ b/src/components/ElementLabel/ElementLabel.tsx @@ -1,9 +1,9 @@ -import { ComponentPropsWithoutRef, ReactNode } from 'react'; +import { ElementType, ReactNode, useMemo } from 'react'; import styled from 'styled-components'; -import { WithAsProp } from '../../types/utils.types'; +import { PolymorphicProps } from '../../types/utils.types'; -export type ElementLabelProps = WithAsProp<{ +type ElementLabelOwnProps = { children: ReactNode; /* Font size */ size?: 'sm' | 'md'; @@ -18,8 +18,11 @@ export type ElementLabelProps = WithAsProp<{ | 'link'; /* Font weight. When true ElementLabel will be rendered as bold */ isStrong?: boolean; -}> & - ComponentPropsWithoutRef<'span'>; +}; +export type ElementLabelProps = PolymorphicProps< + ElementLabelOwnProps, + Element +>; const ElementLabelRoot = styled.span` font-family: var(--sscds-font-family-body); @@ -30,24 +33,27 @@ const ElementLabelRoot = styled.span` `; ElementLabelRoot.displayName = 'ElementLabel.Root'; -function ElementLabel({ +function ElementLabel({ children, size = 'sm', color = 'default', isStrong = false, ...props -}: ElementLabelProps) { - const vars = { - '--sscds-elementlabel-font-size': `var(--sscds-font-size-elementlabel-${size})`, - '--sscds-elementlabel-font-weight': isStrong - ? 'var(--sscds-font-weight-elementlabel-strong)' - : 'var(--sscds-font-weight-elementlabel-default)', - '--sscds-elementlabel-color': - color === 'link' - ? 'var(--sscds-color-link-default)' - : `var(--sscds-color-text-${color})`, - ...props.style, - }; +}: ElementLabelProps) { + const vars = useMemo( + () => ({ + '--sscds-elementlabel-font-size': `var(--sscds-font-size-elementlabel-${size})`, + '--sscds-elementlabel-font-weight': isStrong + ? 'var(--sscds-font-weight-elementlabel-strong)' + : 'var(--sscds-font-weight-elementlabel-default)', + '--sscds-elementlabel-color': + color === 'link' + ? 'var(--sscds-color-link-default)' + : `var(--sscds-color-text-${color})`, + ...props.style, + }), + [color, isStrong, props.style, size], + ); return ( diff --git a/src/types/utils.types.ts b/src/types/utils.types.ts index a92b2c009..a6a1dd47c 100644 --- a/src/types/utils.types.ts +++ b/src/types/utils.types.ts @@ -1,4 +1,4 @@ -import { ElementType } from 'react'; +import { ComponentProps, ElementType } from 'react'; export type Subset = { [attr in keyof K]?: K[attr] extends object @@ -18,8 +18,8 @@ export type RequireAtLeastOne = Pick< [K in Keys]-?: Required> & Partial>>; }[Keys]; -export type WithAsProp = Props & { - as?: ElementType; +export type WithAsProp = Props & { + as?: Element; }; export type ReactComponentLike = @@ -28,3 +28,9 @@ export type ReactComponentLike = | ((props: any, context?: any) => any) // eslint-disable-next-line @typescript-eslint/no-explicit-any | (new (props: any, context?: any) => any); + +export type PolymorphicProps< + OwnProps, + Element extends ElementType, +> = WithAsProp & + Omit, keyof WithAsProp>;