Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: styles customization and component composability #145

Open
dalechyn opened this issue Feb 16, 2024 · 1 comment
Open

feat: styles customization and component composability #145

dalechyn opened this issue Feb 16, 2024 · 1 comment
Labels

Comments

@dalechyn
Copy link
Collaborator

dalechyn commented Feb 16, 2024

What is the feature you would like to implement?

  • auth-kit package should rely on css variables for such style attributes as colors, sizes, border radiuses, fonts etc, instead of passing such as separate props via jsx;
  • auth-kit package should expose composable low-level elements that allow a user to redefine the order/appearance of components;
  • auth-kit package should allow passing className (or all of the rendered ComponentProps) of an element, along with using forwardRef.

Why is this feature important?

  • The customization of auth-kit components is hard. I myself experienced it, when I tried to change the colors of the QRCode element, as my app uses dark palette and having a light bright QRCode would lead to bad UI. My workaround was using specific css-selectors to change the styles of the rendered SVG.
  • The composition pattern that has faced a high adoption in such libraries as https://ui.shadcn.com/ gives a user full control of how the DOM tree for a specific component is built, and would allow users to build their own components that might not just require a different styling but a different composition.
  • Having className and other DOM elements ComponentProps to be available greatly improves DX as one could pass className if uses TailwindCSS, or ref if a developer needs low-level control of the DOM element, etc.

How should this feature be built? (optional)

  • All the colors, border radiuses, font settings have to be moved to their specific CSS variables.
    The suggestion is to prefix all of them with --fc-auth-kit- to avoid collisions with other CSS variables.
    Such a css could look like the following:
       // bg
       --fc-auth-kit-primary: #hex
       // text
       --fc-auth-kit-primary-foreground: #hex
       // etc.
    Developers would have to import the specific CSS in their codebase to have those variables defined, yet at the same time can define their own CSS variables if needed. Similar approach has been applied by RainbowKit (https://www.rainbowkit.com/docs/installation#import).
  • Take a look at this QRCode implementation:
     <div className={qrCodeContainer}>
       <div className={qrCodeWrapper}>
         <div
           className={qrCode}
           style={{
             top: logoPosition,
             width: size,
           }}
         >
           <FarcasterLogo fill="purple" height={logoSize} />
         </div>
         <svg height={size} style={{ all: "revert" }} width={size}>
           <title>QR Code</title>
           <defs>
             <clipPath id="clip-wrapper">
               <rect height={logoWrapperSize} width={logoWrapperSize} />
             </clipPath>
             <clipPath id="clip-logo">
               <rect height={logoSize} width={logoSize} />
             </clipPath>
           </defs>
           <rect fill="transparent" height={size} width={size} />
           {dots}
         </svg>
       </div>
     </div>
    With those in place, a developer cannot re-define the composition of the components and is stuck to have those elements in DOM, even if it's not desired.
    Instead, all of those DOM Elements shall be moved to components and be exported, so that a user can use them any way he wants to:
    function QRCode(...) {
      return <Container>
        <Wrapper>
          <LogoWrapper position={logoPosition} size={size}>
            <FarcasterLogo fill="purple" height={logoSize} />
          </LogoWrapper>
          <SVG />
        </Wrapper>
      </Container>
    }
      
      QRCode.Container = Container
      QRCode.Wrapper = Wrapper
      QRCode.LogoWrapper = LogoWrapper
      QRCode.SVG = SVG
    
      export { QRCode }
    This allows a user to redefine the composition of components, i.e:
     <QRCode.Container>
       <MyCustomElementThatINeedHere />
       <QRCode.Wrapper>
         <QRCode.LogoWrapper position={logoPosition} size={size}>
           <WarpcastLogo />
         </QRCode.LogoWrapper>
         <QRCode.SVG />
       </QRCode.Wrapper>
     </QRCode.Container>
    Another approach that is worth mentioning is defining a Custom property on each component that relies on some state.
    As an example, such could be used to render a custom SVG:
    <QRCode.SVG.Custom>
     ({ dots, matrix }) => <MyFancyQRRenderer dots={dots} matrix={matrix} />
    </QRCode.SVG.Custom>
    Similar approach is implemented in RainbowKit (https://www.rainbowkit.com/docs/custom-connect-button)
  • All the components must extend from the DOM Element props that is being rendered at the end, and pass refs whenever possible:
    Before:
    export type Props = ButtonHTMLAttributes<HTMLButtonElement> & {
      kind?: "primary" | "secondary" | "tertiary" | "reset";
    };
    
    export function Button({ kind = "primary", children, className, ...rest }: Props) {
      return (
        <button type="button" className={kindClass[kind] || className} {...rest}>
          {children}
        </button>
      );
    }
    After:
    export type Props = ComponentProps<'button'> & {
      kind?: "primary" | "secondary" | "tertiary" | "reset";
    };
    
    export const Button = React.forwardRef<Props>(({ kind = "primary", children, className, ...rest }, ref) {
      return (
        <button type="button" className={kindClass[kind] || className} ref={ref} {...rest}>
          {children}
        </button>
      );
    })

Additional context
Those examples are touching only QRCode but the concerns are applicable to all the components.

@dalechyn dalechyn changed the title feat: styles customization and component compasibility feat: styles customization and component composability Feb 16, 2024
@PirosB3
Copy link

PirosB3 commented Mar 21, 2024

I use auth-kit and would absolutely love to style the component. Thanks for opening this up @dalechyn

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants