ui icon indicating copy to clipboard operation
ui copied to clipboard

Adding a reusable typography component

Open nilaq opened this issue 2 years ago • 19 comments
trafficstars

Following the discussion in #315 and with some inspiration from #11. The idea is to not only have the typography in the introduction of the docs as inspiration, but having a reusable typography component that implements these styles, can be used across the project and be installed with npx shadcn-ui typography

After having run in this issue multiple times myself, i created the code for typography component that exactly mimics the styles from https://ui.shadcn.com/docs/components/typography plus added 'text-foreground' or 'text-muted-foreground' to also enable dark mode.

Ps: this is my first ever contribution to an open source project, so be gentle :)

nilaq avatar May 16 '23 01:05 nilaq

@nilaq is attempting to deploy a commit to the shadcn-pro Team on Vercel.

A member of the Team first needs to authorize it.

vercel[bot] avatar May 16 '23 01:05 vercel[bot]

And maybe you should add the documentation about your component

armandsalle avatar May 17 '23 13:05 armandsalle

The latest updates on your projects. Learn more about Vercel for Git ↗︎

1 Ignored Deployment
Name Status Preview Comments Updated (UTC)
next-template ⬜️ Ignored (Inspect) May 18, 2023 0:30am

vercel[bot] avatar May 18 '23 00:05 vercel[bot]

@armandsalle thanks for the feedback, appreciate it a lot! Were you thinking something like this? Just added the changes you proposed. Will start working on the documentation.

Not sure though if this is the most elegant way to do it Typography element='h1' as='h1>Example</Typography> feels a lot more clunky than <H1>Example. Any thoughts on this?

nilaq avatar May 18 '23 00:05 nilaq

Hey! I was reading the CVA documentation and I saw this example of polymorphic components

-- // A familiar `styled` button as a link
-- <Button as="a" href="#" variant="primary">Button as a link</Button>
 
++ // A `cva` button as a link
++ <a href="#" class={button({variant: "primary"})}>Button as a link</a>

in https://cva.style/docs/faqs

So why not just export classnames? No more need for the createElement() function

armandsalle avatar May 26 '23 14:05 armandsalle

Any updates on this?

its-monotype avatar Jun 11 '23 16:06 its-monotype

So far, it works like a charm. Thank you @nilaq !

maurotrigo avatar Jun 15 '23 20:06 maurotrigo

Agree with @armandsalle Exporting typographyVariants({...}) is more than enough

AhmedBaset avatar Jun 17 '23 08:06 AhmedBaset

Component code with the fixes mentioned above

import * as React from "react";
import { VariantProps, cva } from "class-variance-authority";
import cn from "utils/cn";

const typographyVariants = cva("text-foreground", {
  variants: {
    variant: {
      h1: "scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl",
      h2: "scroll-m-20 border-b pb-2 text-3xl font-semibold tracking-tight first:mt-0",
      h3: "scroll-m-20 text-2xl font-semibold tracking-tight",
      h4: "scroll-m-20 text-xl font-semibold tracking-tight",
      h5: "scroll-m-20 text-lg font-semibold tracking-tight",
      h6: "scroll-m-20 text-base font-semibold tracking-tight",
      p: "leading-7 [&:not(:first-child)]:mt-6",
      blockquote: "mt-6 border-l-2 pl-6 italic",
      ul: "my-6 ml-6 list-disc [&>li]:mt-2",
      inlineCode:
        "relative rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold",
      lead: "text-xl text-muted-foreground",
      largeText: "text-lg font-semibold",
      smallText: "text-sm font-medium leading-none",
      mutedText: "text-sm text-muted-foreground",
    },
  },
});

type VariantPropType = VariantProps<typeof typographyVariants>;

const variantElementMap: Record<
  NonNullable<VariantPropType["variant"]>,
  string
> = {
  h1: "h1",
  h2: "h2",
  h3: "h3",
  h4: "h4",
  h5: "h5",
  h6: "h6",
  p: "p",
  blockquote: "blockquote",
  inlineCode: "code",
  largeText: "div",
  smallText: "small",
  lead: "p",
  mutedText: "p",
  ul: "ul",
};

type Element = keyof JSX.IntrinsicElements;

type TypographyProps<T extends Element> = {
  as?: T;
} & VariantPropType &
  React.HTMLAttributes<HTMLElement>;

const Typography = <T extends Element>({
  className,
  as,
  variant,
  ...props
}: TypographyProps<T>) => {
  const Component =
    as ?? (variant ? variantElementMap[variant] : undefined) ?? "div";

  const componentProps = {
    className: cn(typographyVariants({ variant, className })),
    ...props,
  };

  return React.createElement(Component, componentProps);
};

export default React.forwardRef(Typography);

Ilaiwi avatar Jun 20 '23 00:06 Ilaiwi

This one an update with ref

import * as React from "react";
import {VariantProps, cva} from "class-variance-authority";
import {cn} from "@/lib/utils"
import {Slot} from "@radix-ui/react-slot";

const typographyVariants = cva("text-foreground", {
    variants: {
        variant: {
            h1: "text-6xl scroll-m-20 font-bold",
            h2: "text-5xl scroll-m-20 font-bold",
            h3: "text-4xl scroll-m-20 font-bold",
            h4: "text-3xl scroll-m-20 font-bold",
            h5: "text-2xl scroll-m-20 font-bold",
            h6: "text-xl scroll-m-20 font-bold",
            p: "leading-7 [&:not(:first-child)]:mt-6",
            blockquote: "mt-6 border-l-2 pl-6 italic",
            ul: "my-6 ml-6 list-disc [&>li]:mt-2",
            inlineCode:
                "relative rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold",
            lead: "text-xl text-muted-foreground",
            regularText: "text-base",
            largeText: "text-lg font-semibold",
            smallText: "text-sm leading-none",
            mutedText: "text-sm text-muted-foreground",
        },
        weight: {
            bold: '!font-bold',
            semibold: '!font-semibold',
            normal: '!font-normal',
            medium: '!font-medium',
            light: '!font-light'
        }
    },
    defaultVariants: {
        variant: "regularText",
        weight: "normal",
    },
});

type VariantPropType = VariantProps<typeof typographyVariants>;

const variantElementMap: Record<
    NonNullable<VariantPropType["variant"]>,
    string
> = {
    h1: "h1",
    h2: "h2",
    h3: "h3",
    h4: "h4",
    h5: "h5",
    h6: "h6",
    p: "p",
    blockquote: "blockquote",
    inlineCode: "code",
    largeText: "div",
    regularText: "div",
    smallText: "small",
    lead: "p",
    mutedText: "p",
    ul: "ul",
};


export interface TypographyProps
    extends React.HTMLAttributes<HTMLElement>,
        VariantProps<typeof typographyVariants> {
    asChild?: boolean
    as?: string
}


const Typography = React.forwardRef<HTMLElement, TypographyProps>(
    ({className, variant, weight, as, asChild, ...props}, ref) => {
        const Comp = asChild ? Slot : as ?? (variant ? variantElementMap[variant] : undefined) ?? "div"
        return (
            <Comp
                className={cn(typographyVariants({variant, weight, className}))}
                ref={ref}
                {...props}
            />
        )
    }
)


Typography.displayName = "Typography"

export {Typography, typographyVariants}

rizaldywirawan avatar Jul 15 '23 08:07 rizaldywirawan

Thanks for creating this component I was actually using this and sometimes it works and sometimes it doesn't for some reason, I also can see a warning about forwardRef in console:

image

joaopedrodcf avatar Jul 31 '23 19:07 joaopedrodcf

Based on this comment: https://github.com/shadcn-ui/ui/pull/363#issuecomment-1597916990 and this comment: https://github.com/shadcn-ui/ui/pull/363#issuecomment-1636708882 I made this:

'use client';

import * as React from 'react';
import { VariantProps, cva } from 'class-variance-authority';
import { cn } from 'lib/utils';
import { Slot } from '@radix-ui/react-slot';

const typographyVariants = cva('text-foreground', {
    variants: {
        variant: {
            h1: 'scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl',
            h2: 'scroll-m-20 border-b pb-2 text-3xl font-semibold tracking-tight first:mt-0',
            h3: 'scroll-m-20 text-2xl font-semibold tracking-tight',
            h4: 'scroll-m-20 text-xl font-semibold tracking-tight',
            h5: 'scroll-m-20 text-lg font-semibold tracking-tight',
            h6: 'scroll-m-20 text-base font-semibold tracking-tight',
            p: 'leading-7 [&:not(:first-child)]:mt-6',
            blockquote: 'mt-6 border-l-2 pl-6 italic',
            ul: 'my-6 ml-6 list-disc [&>li]:mt-2',
            inlineCode:
                'relative rounded bg-muted px-[0.3rem] py-[0.2rem] font-mono text-sm font-semibold',
            lead: 'text-xl text-muted-foreground',
            largeText: 'text-lg font-semibold',
            smallText: 'text-sm font-medium leading-none',
            mutedText: 'text-sm text-muted-foreground',
        },
    },
    defaultVariants: {
        variant: "p",
    },
});

type VariantPropType = VariantProps<typeof typographyVariants>;

const variantElementMap: Record<
    NonNullable<VariantPropType['variant']>,
    string
> = {
    h1: 'h1',
    h2: 'h2',
    h3: 'h3',
    h4: 'h4',
    h5: 'h5',
    h6: 'h6',
    p: 'p',
    blockquote: 'blockquote',
    inlineCode: 'code',
    largeText: 'div',
    smallText: 'small',
    lead: 'p',
    mutedText: 'p',
    ul: 'ul',
};

export interface TypographyProps
    extends React.HTMLAttributes<HTMLElement>,
        VariantProps<typeof typographyVariants> {
    asChild?: boolean;
    as?: string;
}

const Typography = React.forwardRef<HTMLElement, TypographyProps>(
    ({ className, variant, as, asChild, ...props }, ref) => {
        const Comp = asChild
            ? Slot
            : as ?? (variant ? variantElementMap[variant] : undefined) ?? 'div';
        return (
            <Comp
                className={cn(typographyVariants({ variant, className }))}
                ref={ref}
                {...props}
            />
        );
    }
);

Typography.displayName = 'Typography';

export { Typography, typographyVariants };

The API like this feels really good to me also defaulting to p as would be one of the most used ones.

 <Typography variant="h1" as="h4">
   Test
</Typography>

joaopedrodcf avatar Jul 31 '23 22:07 joaopedrodcf

any progress here? I'm available to finish this if @shadcn is interested in merge this.

matbrgz avatar Dec 09 '23 05:12 matbrgz

I really like where this is going! I just spend the last couple evenings eventually getting to something very similar for my Typography component!


I additionally decided to create some semantic/wrapper components (Heading, Text, etc.) on top of the Typography component. I decided this after looking at what it looks like using the same "base" Typography component for everything (I didn't love it), as well as looking into what other UI component libraries were doing and seeing them be more semantic (e.g. Radix UI, etc.).

Semantic vs Non-Semantic
 <div className="flex flex-row justify-center gap-6">
      {/* Semantic */}
      <div>
        <Heading variant="h1">Heading 1</Heading>
        <Heading variant="h2">Heading 2</Heading>
        <Heading variant="h3">Heading 3</Heading>
        <Heading variant="h4">Heading 4</Heading>
        <Heading variant="h5">Heading 5</Heading>
        <Heading variant="h6">Heading 6</Heading>
        <Text variant="lead">This is a lead paragraph.</Text>
        <Text variant="large">This is large text.</Text>
        <Text variant="muted">This is muted text.</Text>
        <Text variant="p">This is a paragraph.</Text>
        <Text>This is a paragraph (without a variant prop).</Text>
        <Text>
          This is a paragraph <Em>with em</Em>.
        </Text>
        <Text>
          This is a paragraph <Strong>with strong</Strong>.
        </Text>
        <Text>
          This is a paragraph <Small>with small</Small>.
        </Text>
        <Blockquote>This is a blockquote.</Blockquote>
        <Code>This is inline code.</Code>
      </div>

      {/* Non-semantic */}
      <div>
        <Typography variant="h1" gutterBottom>
          Heading 1
        </Typography>
        <Typography variant="h2">Heading 2</Typography>
        <Typography variant="h3">Heading 3</Typography>
        <Typography variant="h4">Heading 4</Typography>
        <Typography variant="h5">Heading 5</Typography>
        <Typography variant="h6">Heading 6</Typography>
        <Typography variant="p">This is a paragraph.</Typography>
        <Typography>This is a paragraph (without a variant prop).</Typography>
        <Typography variant="lead">This is a lead paragraph.</Typography>
        <Typography variant="large">This is large text.</Typography>
        <Typography variant="muted">This is muted text.</Typography>
        <Typography variant="blockquote">This is a blockquote.</Typography>
        <Typography variant="code">This is inline code.</Typography>
      </div>
    </div>

I adapted my semantic components to now use the "base" typography component that you guys have come up with, instead of my own -- specifically the one @joaopedrodcf posted.

To more easily create semantic components, I added a couple additions to the "base" typography component (could use some renaming):

// typography.tsx

...

type TypographyVariantType = NonNullable<
  VariantProps<typeof typographyVariants>["variant"]
>

interface VariantPropsTypographyWithoutVariant
  extends Omit<VariantProps<typeof typographyVariants>, "variant"> {
  asChild?: boolean;
}

...

export type { VariantPropsTypographyWithoutVariant, TypographyVariantType };

I also created FilterUnionType to filter down the TypographyVariantType in individual semantic components based on what I wanted each to have available to them (while also keeping them connected to the "base" typography component):

// Helper type to filter union types
export type FilterUnionType<T, U> = T extends U ? T : never;

Some of my semantic components:

Heading (heading.tsx)
import React from "react";
import type { FilterUnionType } from "@/lib/types";
import {
  Typography,
  type VariantPropsTypographyWithoutVariant,
  type TypographyVariantType,
} from "./typography";

// Specify the variants you want to allow (linting error will be thrown when using exported component with a variant (1) not specified here or (2) not within TypographyVariant)
type AllowedVariants = FilterUnionType<
  TypographyVariantType,
  "h1" | "h2" | "h3" | "h4" | "h5" | "h6"
>;
type HTMLTypographyElement = HTMLHeadingElement;

interface HeadingProps
  extends React.HTMLAttributes<HTMLTypographyElement>,
    VariantPropsTypographyWithoutVariant {
  variant: AllowedVariants;
}

const Heading = React.forwardRef<HTMLTypographyElement, HeadingProps>(
  ({ variant, ...props }, ref) => {
    return <Typography ref={ref} variant={variant} {...props} />;
  },
);

export default Heading;
Text (text.tsx)
import React from "react";
import type { FilterUnionType } from "@/lib/types";
import {
  Typography,
  type VariantPropsTypographyWithoutVariant,
  type TypographyVariantType,
} from "./typography";

// Specify the variants you want to allow (linting error will be thrown when using exported component with a variant (1) not specified here or (2) not within TypographyVariant)
type AllowedVariants = FilterUnionType<
  TypographyVariantType,
  "p" | "lead" | "largeText" | "mutedText" // ...smallText, etc.
>;
type HTMLTypographyElement = HTMLParagraphElement;

interface TextProps
  extends React.HTMLAttributes<HTMLTypographyElement>,
    VariantPropsTypographyWithoutVariant {
  variant?: AllowedVariants;
}

const Text = React.forwardRef<HTMLTypographyElement, TextProps>(
  ({ variant = "p", ...props }, ref) => {
    return (
      <Typography
        ref={ref}
        variant={variant}
        {...props}
      />
    );
  },
);

export default Text;
Blockquote (blockquote.tsx)
import React from "react";
import {
  Typography,
  type VariantPropsTypographyWithoutVariant,
  type TypographyVariantType,
} from "./typography";
import type { FilterUnionType } from "@/lib/types";

// Specify the variants you want to allow (linting error will be thrown when using exported component with a variant (1) not specified here or (2) not within TypographyVariant)
type AllowedVariants = FilterUnionType<TypographyVariantType, "blockquote">;
type HTMLTypographyElement = HTMLQuoteElement;

export interface BlockquoteProps
  extends React.HTMLAttributes<HTMLTypographyElement>,
    VariantPropsTypographyWithoutVariant {
  variant?: AllowedVariants;
}

const Blockquote = React.forwardRef<HTMLTypographyElement, BlockquoteProps>(
  ({ variant = "blockquote", ...props }, ref) => {
    return <Typography ref={ref} variant={variant} {...props} />;
  },
);

export default Blockquote;
Code (code.tsx)
import React from "react";
import {
  Typography,
  type VariantPropsTypographyWithoutVariant,
  type TypographyVariantType,
} from "./typography";
import type { FilterUnionType } from "@/lib/types";

// Specify the variants you want to allow (linting error will be thrown when using exported component with a variant (1) not specified here or (2) not within TypographyVariant)
type AllowedVariants = FilterUnionType<TypographyVariantType, "inlineCode">;
type HTMLTypographyElement = React.ElementRef<"code">; // using React.ElementRef<"code"> instead of HTMLXElement because HTMLCodeElement is not a valid HTML element type

interface CodeProps
  extends React.HTMLAttributes<HTMLTypographyElement>,
    VariantPropsTypographyWithoutVariant {
  variant?: AllowedVariants;
}

const Code = React.forwardRef<HTMLTypographyElement, CodeProps>(
  ({ variant = "inlineCode", ...props }, ref) => {
    return <Typography ref={ref} variant={variant} {...props} />;
  },
);

export default Code;

...I also started creating some "other" typography-related components (typography elements that are supposed to exist within other typography elements, etc.) (again, similarly to Radix UI). Structurally, they are a bit of a mix of shadcn and Radix UI:

Em (em.tsx)
import { cn } from "@/lib/utils";
import { type VariantProps, cva } from "class-variance-authority";
import * as React from "react";

const emVariants = cva("italic", {
  variants: {
    variant: {
      default: "",
    },
  },
  defaultVariants: {
    variant: "default",
  },
});

type EmElement = React.ElementRef<"em">;
export interface EmProps
  extends React.ComponentPropsWithoutRef<"em">,
    VariantProps<typeof emVariants> {
  asChild?: boolean;
}

const Em = React.forwardRef<EmElement, EmProps>(
  ({ children, className, variant, ...props }, ref) => (
    <em className={cn(emVariants({ variant, className }))} {...props} ref={ref}>
      {children}
    </em>
  ),
);
Em.displayName = "Em";

export default Em;
Strong (strong.tsx)
import { cn } from "@/lib/utils";
import { type VariantProps, cva } from "class-variance-authority";
import * as React from "react";

const strongVariants = cva("strong", {
  variants: {
    variant: {
      default: "",
    },
  },
  defaultVariants: {
    variant: "default",
  },
});

type StrongElement = React.ElementRef<"strong">;
export interface StrongProps
  // extends React.HTMLAttributes<HTMLTypographyElement>,
  extends React.ComponentPropsWithoutRef<"strong">,
    VariantProps<typeof strongVariants> {
  asChild?: boolean;
  as?: string;
}

const Strong = React.forwardRef<StrongElement, StrongProps>(
  ({ children, className, variant, ...props }, ref) => (
    <strong
      className={cn(strongVariants({ variant, className }))}
      {...props}
      ref={ref}
    >
      {children}
    </strong>
  ),
);
Strong.displayName = "Strong";

export default Strong;
Small (small.tsx)
import { cn } from "@/lib/utils";
import { type VariantProps, cva } from "class-variance-authority";
import * as React from "react";

const strongVariants = cva("small", {
  variants: {
    variant: {
      default: "",
    },
  },
  defaultVariants: {
    variant: "default",
  },
});

type SmallElement = React.ElementRef<"small">;
export interface SmallProps
  // extends React.HTMLAttributes<HTMLTypographyElement>,
  extends React.ComponentPropsWithoutRef<"small">,
    VariantProps<typeof strongVariants> {
  asChild?: boolean;
}

const Small = React.forwardRef<SmallElement, SmallProps>(
  ({ children, className, variant, ...props }, ref) => (
    <small
      className={cn(strongVariants({ variant, className }))}
      {...props}
      ref={ref}
    >
      {children}
    </small>
  ),
);
Small.displayName = "Small";

export default Small;


I would love to hear your input!

Overall, I'm new to shadcn and I was just starting to go over the documentation and truly use it for the first time, but I got to the Typography section and went down this rabbit hole lol. I'm coming from using MUI for the last couple years, so... I may have gotten a bit excited about the possibility of semantic components (MUI = non-semantic Typography component for everything 😕)

aaron-mota avatar Dec 23 '23 04:12 aaron-mota

import * as React from "react";
import Link, { LinkProps } from "next/link";
import { Slot } from "@radix-ui/react-slot";
import { VariantProps, cva } from "class-variance-authority";
import { cn } from 'lib/utils';

const typographyVariants = cva("text-foreground", {
  variants: {
    variant: {
      a: "",
      abbr: "",
      b: "",
      strong: "",
      cite: "",
      code: "",
      em: "",
      i: "",
      sub: "",
      sup: "",
      u: "",
      var: "",
      p: "",
      h1: "",
      h2: "",
      h3: "",
      h4: "",
      h5: "",
      h6: "",
      div: "",
      span: "",
      blockquote: "",
      ul: "",
      ol: "",
      li: "",
      large: "",
      small: "",
      lead: "",
      muted: "",
    },
  },
});

type VariantPropType = VariantProps<typeof typographyVariants>;

const excludedVariants = ["a", "large", "lead", "muted"] as const;

type TypographyProps =
  | (React.HTMLAttributes<HTMLElement> &
      VariantPropType &
      LinkProps & {
        as: "a";
        asChild?: boolean;
      })
  | (React.HTMLAttributes<HTMLElement> &
      VariantPropType & {
        as?: Exclude<
          VariantPropType["variant"],
          (typeof excludedVariants)[number]
        >;
        href?: never;
        asChild?: boolean;
      });

const Typography = React.forwardRef<HTMLElement, TypographyProps>(
  ({ className, variant, as, href, asChild, ...props }, ref) => {
    const Component = asChild
      ? Slot
      : as === "a"
        ? Link
        : (as as React.ElementType) ||
          (excludedVariants.includes(
            variant as (typeof excludedVariants)[number],
          )
            ? "p"
            : variant) ||
          "p";

    return (
      <Component
        className={cn(typographyVariants({ variant, className }))}
        ref={ref}
        {...props}
        href={as === "a" ? href : undefined}
      />
    );
  },
);

Typography.displayName = "Typography";

export { Typography, typographyVariants };

Add your styles. 👍

immdraselkhan avatar Dec 23 '23 14:12 immdraselkhan

Adding my 2 cents on this which would allow for an api similar to MUI being

<Typography variant="h1">Hello World</Typography>; // renders as H1 by default
<Typography variant="h1" component='h2'>Hello World</Typography>; // renders as H2

While the code might seem like a-lot most if not all has been copied from MUI

import { cva, cx, VariantProps } from '@/cva.config';

type DistributiveOmit<T, K extends keyof any> = T extends any ? Omit<T, K> : never;

type OverrideProps<TProps, TComponent extends React.ElementType> = TProps &
  DistributiveOmit<React.ComponentPropsWithRef<TComponent>, keyof TProps>;

interface OverrideAbleComponentFC<TDefaultComponent extends React.ElementType, TProps> {
  <TComponent extends React.ElementType = TDefaultComponent>(
    props: {
      component?: TComponent;
    } & OverrideProps<TProps, TComponent>
  ): JSX.Element | null;
  displayName?: string;
}

export interface TypographyProps extends React.PropsWithChildren, VariantProps<typeof variants> {
  className?: string;
}

const variants = cva({
  variants: {
    variant: {
      h1: 'scroll-m-20 text-4xl font-bold text-primary-dark lg:text-5xl',
      h2: 'mt-10 scroll-m-20 pb-2 text-3xl font-bold text-primary-dark first:mt-0 lg:text-4xl',
      h3: 'mt-8 scroll-m-20 text-2xl font-bold text-primary-dark',
      h4: 'mt-6 scroll-m-20 text-xl font-bold text-primary-dark',
      p: 'leading-7 [&:not(:first-child)]:mt-4',
      large: 'text-xl',
    },
  },
  defaultVariants: {
    variant: 'p',
  },
});

const variantComponent = cva({
  variants: {
    variant: {
      h1: 'h1',
      h2: 'h2',
      h3: 'h3',
      h4: 'h4',
      p: 'p',
      large: 'div',
    },
  },
  defaultVariants: {
    variant: 'p',
  },
});

export const Typography: OverrideAbleComponentFC<'p', TypographyProps> = ({
  children,
  className,
  component,
  variant = 'p',
}) => {
  const Component = component || variantComponent({ variant });

  return <Component className={cx(variants({ variant, className }))}>{children}</Component>;
};

onursagir avatar Jan 23 '24 16:01 onursagir

@joaopedrodcf actually your component requires "use client" whenever used. Slot is causing this issue I guess.

amocarski avatar Apr 12 '24 13:04 amocarski

Up :)

X-Titouan avatar Apr 13 '24 20:04 X-Titouan

@amocarski updated to include the missing 'use client' thanks for noticing 🙏

joaopedrodcf avatar Apr 25 '24 08:04 joaopedrodcf