Skip to content

Library Agnostic components #191

Description

@einari

Our components are for the most part higher order components, composing other components. Today this is all built on top of PrimeReact, making us locked into one library.

The components we rely on are something that are common to all UI libraries. What we need to provide is our interface for what these are and then have implementations for the different UI libraries.

By leveraging React context we can get there. Our components would rely on the configured context to pass along the necessary information to the actual component being rendered.

Each library would then be responsible to implement the context interface and establish it and implement the necessary wrappers for the components the context has defined.

For our custom components, they are fine on their own. But they will probably be affected by styling. So we should keep styling these separate and agnostic as well.

The Storybook should support dynamic switching for the supported libraries, a drop down somewhere that selects the UI library for us to verify that it all looks good. This might mean that we need the stories to be extracted into its own project that can reference the core components and the specific UI library projects to achieve this.

This means that our PrimeReact11 support should have its own package

@cratis/components.primereact

We don’t add 11 to this, as PrimeReact will support 11 and forward, but for version 10 we should have:

@cratis/components.primereact10

Documentation should state clearly that version 11 of PrimeReact has a license that it needs, and how this technically can be set up with a env variable that gets injected into both a Vite pipeline, but also in publishing. We should have a link to the Primeui page for getting a license (https://primeui.store/primeui).

This means we will get a new folder structure inside Source:

  • Core
  • PrimeReact
  • PrimeReact10
  • Storybook

This means also that we should configure yarn workspace to work with this.

Practically, the way I see it, is that we need to make the developers consuming our stuff configure it, and I'd like something like this:

import { Components } from '@cratis/components`
import { PrimeReact } from '@cratis/components.primereact'

export const App = () => {
    return (
        <Components library={PrimeReact}>
        </Components>
    )
}

The Components would then have a context contract it defines that the PrimeReact in this case has to meet.
It would have something like Button on it. The definition of button with then be our Button and the props it expects.

For Our button implementation, we would rely on the context and use the button (Pseudo code, might be wrong, but in the general direction):

import { ComponentContext } from '../Components`;

export interface ButtonProps {
   /* Whatever we expose */
}

export const Button = (props: ButtonProps) => {
   const ComponentContext = useContext<ComponentContext>(); // Can't remember how this is done - and we could probably get this more elegantly.

   return (
       <ComponentContext ...props />
   )
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions