Skip to content

Class names discovery from the context ✨ #322

Description

@viktor-yakubiv

I’ve just come to the idea that we can simplify our components API if we utilise context technique in the library on the top level. For the instance, we have:

<Card>
  <Card.Title>I'm a card!</Card.Title>
</Card>

that turns into

<div class="card">
  <h2 class="card-title">I'm a card!</h2>
</div>

The proposal

Potentially, we can have a bit easier API like

<Card>
  <Heading>I'm a card!</Heading>
</Card>

that produces the same result.

Simple implementation

const SectionContext = React.createContext({ level: 1 })
const ClassNamesContext = React.createContext({})

const Card = ({ children, className, tag: Tag = 'div', ...restProps }) => (
  <SectionContext.Provider value={{ level: 2 }}>
    <ClassNamesContext.Provider value={{ heading: 'card-title' }}>
      <Tag className={joinClasses('card', className)} {...restProps}>
        {children}
      </Tag>
    </ClassNamesContext.Provider>
  </SectionContext.Provider>
)

const Heading = ({ children, className, ...restProps }) => {
  const level = useContext(SectionContext)?.level ?? 1
  const contextClassName = useContext(ClassNamesContext)?.heading

  const Tag = `h${level}`

  return (
    <Tag className={joinClasses(contextClassName, className)} {...restProps}>
      {children}
    </Tag>
  )
}

Use cases

My use case above is pretty simple and seems to be not worth it. I not sure either in this.

Apart from Heading replacing the Card.Title along with Section.Title we may have in the future, it looks more convenient for implicit passing classes to:

  • Icon that is descendent of the TextField, Select or Menu
  • similar to Button that is descendet of the TextField

I am pretty sure, there are other cases. However, since it's implicit, it's not obvious: very easy to use, very hard to debug.

@Joozty what do you think?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions