ui icon indicating copy to clipboard operation
ui copied to clipboard

Typography could be components

Open geraldodev opened this issue 1 year ago • 13 comments

Hi,

Typography could be in components folder as components.

Regards,

Geraldo

geraldodev avatar May 07 '23 22:05 geraldodev

This is not a component library, therefore Typography component is not suited here. Is there any specific feature that you would like the Typography component to perform?

abhinav-anshul avatar May 08 '23 06:05 abhinav-anshul

I'm not a designer, and I've been learning CSS for what feels like forever (it never seems to stick), but I know that this approach is the right one. I've been trying to use Stitches before, and if a designer is part of the project, they can make changes to the components that are bootstrapped by this marvelous library and handed to us. Therefore, I think it would be helpful to have the example code presented as components.

geraldodev avatar May 08 '23 19:05 geraldodev

@shadcn need your inputs here

abhinav-anshul avatar May 08 '23 19:05 abhinav-anshul

Agreed. We can add the typography with the same command as other components: npx shadcn-ui add typography.

nauvalazhar avatar May 11 '23 02:05 nauvalazhar

Potential Approaches?

I am posting this here as a follow up from the work by @nilaq and discussion on-going in #363! I recently had to implement something like this in a different codebase, and opted for custom components for each HTML tag.

  1. Only including and exporting a typographyVariants(...) cva function for use anywhere in your project, as suggested by @armandsalle
  2. Using a polymorphic Typography component as implemented by @nilaq in same PR.
  3. Having a custom component to match each HTML tag / variant - an approach I implemented recently
  4. External Github Gist/library or something

I am leaning toward a middle-ground between approaches 1 and 3...but possibly also including 2?

2 (Polymorphic)

This is already being implemented in #363

<Typography variant="h1">...</Typography>

// OR

<Typography variant="h1" as="h2">...</Typography>

Pros

  • Easy to use, established pattern

Cons

  • Can be cumbersome to type/ensure type-safety + accessibility in general (e.g rendering h1 as link but forgetting to add href)
  • This is component library territory? as noted by @abhinav-anshul

1, 3 (cva + component per tag)

// ui/typography.tsx

export const typographyVariants = cva(...)

export const H1 = React.forwardRef({ className, ...props }, ref){
   return <h1 ref={ref} className={cn(typographyVariants({ variant: "h1" }), className)} {...props}/>
}

H1.displayName = "H1"

//...

Pros

  • It is straightforward to add new Typography components (e.g <Mark />, <A /> etc.)
  • Easy find and replace: Find all h1 and replace with H1.
  • The approach is not as opinionated in the rendering logic, and somewhat matches the existing examples in current docs already. This may be what @shadcn was going for by adopting the className-only approach?
  • Plug and play into things like MDX

Cons

  • It is more code which could mean way more maintenance overhead especially if you want to make sweeping functionality changes across Typography components - then you'd need more copy-pasta.

1, 2, 3 (cva + "polymorphic" + custom component per tag)

To mitigate the Con's from above, a polymorphic typography component could be an implementation detail of the custom HTML components.

Further, instead of being "polymorphic", the base Typography component could use the asChild functionality similar to what ui/button.tsx uses to ensure base Typography behavior across all custom HTML components, which is recommended by Radix docs (over the deprecated Polymorphic utilities).

CLI

The cli for this could also be interactive opt-in for which typography components you want in your codebase...depending on the approach taken.

Not taking any action on this yet, just something for @shadcn and community to consider!

rexfordessilfie avatar Jun 17 '23 07:06 rexfordessilfie

That would be great!

Creating a rich typography system is a pain. And just plain boring

artjom-mashanin avatar Aug 19 '23 18:08 artjom-mashanin

I was wondering. Given that much of this project is based on reusing radix-ui and providing additional styles on top of it, is it worth re-using the typography system as defined in the radix-ui docs?

AdiRishi avatar Aug 31 '23 04:08 AdiRishi

Plus one on this ➕

nsantos16 avatar Oct 01 '23 21:10 nsantos16

It would be great help for developers to have such Typography components :+1:

DaikiTanak avatar Oct 25 '23 03:10 DaikiTanak

Would be awesome!

ataschz avatar Dec 03 '23 16:12 ataschz

@rexfordessilfie I created some semantic typography components on top of the "polymorphic Typography component" idea from the PR @nilaq started (https://github.com/shadcn/ui/pull/363) that you mentioned. (I added the code as a large comment to that PR).

I think the "polymorphic Typography component" idea could be a powerful one, as you could:

  • use it directly (Typography variant="x" for your entire app), or
  • use semantic components that wrap it (Heading, Text, Blockquote, etc.), or
  • use "custom component to match each HTML tag / variant" that wrap it (H1, H2, P, etc.).

The "base" polymorphic Typography component could house all the main logic/etc. in one place, with the wrapper components being pretty "dumb", and as a dev you're able to choose which implementation you want to use 😎

(this is what I've started doing already with my semantic components, see https://github.com/shadcn/ui/pull/363)

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

As mentioned by @rexfordessilfie to use the Polymorphic approach for this "feature". I've implemented this approach for real world use.

EDIT: In certain use cases, the added margin top on the paragraphs is undesirable. Therefore I've added an affect to remove it when desired. ("removePMargin").

import { cn } from "@/lib/utils"
import { cva, type VariantProps } from "class-variance-authority"
import React from "react"

export const typographyVariants = cva("text-xl", {
  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",
      p: "leading-7 [&:not(:first-child)]:mt-6",
      // blockquote: "mt-6 border-l-2 pl-6 italic",
      // list: "my-6 ml-6 list-disc [&>li]:mt-2",
    },
    affects: {
      default: "",
      lead: "text-xl text-muted-foreground",
      large: "text-lg font-semibold",
      small: "text-sm font-medium leading-none",
      muted: "text-sm text-muted-foreground",
      removePMargin: "[&:not(:first-child)]:mt-0",
    },
  },
  defaultVariants: {
    variant: "h1",
    affects: "default",
  },
})

export interface TypographyProps
  extends React.HTMLAttributes<HTMLHeadingElement>,
    VariantProps<typeof typographyVariants> {}

const Typography = React.forwardRef<HTMLHeadingElement, TypographyProps>(
  ({ className, variant, affects, ...props }, ref) => {
    const Comp = variant || "p"
    return (
      <Comp
        className={cn(typographyVariants({ variant, affects, className }))}
        ref={ref}
        {...props}
      />
    )
  },
)
Typography.displayName = "H1"

export default Typography

Blockquotes, Table items, and list have been omitted.

MeatBoyed avatar Jan 09 '24 09:01 MeatBoyed

affects

Thank you, @MeatBoyed! It would be good to include multiple affects support!

sakhmedbayev avatar Feb 08 '24 16:02 sakhmedbayev

In the meantime ive made reusable components out of it. They can be copy pasted or used as a package via npm :)

https://github.com/kian1991/shadcn-typography?tab=readme-ov-file#installation

kian1991 avatar Mar 29 '24 20:03 kian1991

Thank you so much @kian1991! That's exactly what I needed!

Gustqve avatar May 20 '24 12:05 Gustqve

Thank you so much @kian1991! That's exactly what I needed!

Glad you liked it! :)

kian1991 avatar May 20 '24 17:05 kian1991

Hi, It's a bit late to contribute, but I thought this could still be useful.

I created my own versions of the Typography Addon for shadcn. The folder contains 3 versions:

  • A 1:1 copy with shadcn under Typography.tsx.
  • One that can be rendered as a given tag, named TypographyAs.tsx.
  • One inspired by this discussion, that includes Affects, still drawing inspiration from the original Typography rule set. This one is under the name TypographyCommunity.tsx.

Here's the README for the original 1:1 version https://github.com/ARCADEGC/shadcnAddons/blob/main/README.md I recommend using the As version. It simplifies things by letting you change the tag directly inline with as attribute, without needing asChild. https://github.com/ARCADEGC/shadcnAddons/blob/main/components/ui/TypographyAs.tsx

ARCADEGC avatar Jun 16 '24 17:06 ARCADEGC

This issue has been automatically closed because it received no activity for a while. If you think it was closed by accident, please leave a comment. Thank you.

shadcn avatar Jul 09 '24 23:07 shadcn