GithubHelp home page GithubHelp logo

Add a `Styled` component about jsxstyle HOT 2 CLOSED

petehunt avatar petehunt commented on May 29, 2024
Add a `Styled` component

from jsxstyle.

Comments (2)

petehunt avatar petehunt commented on May 29, 2024 1

Ship it. I think it’s the right call.

from jsxstyle.

meyer avatar meyer commented on May 29, 2024

Sorry for the delay! I’ve been thinking about this one for a while. I’m into the concept but I have some thoughts/concerns:

😓

  • I’m not wild about the cloneElement usage.
  • This makes static analysis quite difficult if the Styled component contains dynamic children. Could warn about it in jsxtyle-webpack-plugin though, so not super concerning.
  • If a component doesn’t do anything with a className prop it will remain unstyled. This is a problem with the current component prop as well, so also not super concerning.

😍

  • Being able to style multiple children with the same styles is pretty cool.
  • Component props and style props get to both be top-level (at long last!).

Styling inputs does suck, and it’s something I’ve been exploring a bit for jsxstyle 3. Up until now, jsxstyle has basically just swapped style props and component props.

Instead of writing code like this:

<input
  type="text"
  value="Hello"
  style={{
    display: 'block',
    color: 'purple',
  }}
/>

you write code like this:

<Block
  component="input"
  props={{
    type: 'text',
    value: 'Hello',
  }}
  color="purple"
/>

If you think of the styles as an object and component props as an object, the style object is usually going to contain more stuff, so moving it to the top level feels like the right thing to do. Swapping styles and component props isn’t necessarily better than what it’s replacing though—it’s just an API with a different set of priorities. Components that require a lot of props all of a sudden become a real chore to configure.

Separating component props from style props

Here’s an assumption I’m making: we want component props and style props at the same level.

<Block
  component="input"
  type="text"
  value="Hello"
  color="purple"
/>

If we had an allowlist of all component props, we’d be able to keep both component props and style props at the top level. With some runtime hacks we can actually get a list of all possible style props and then use that to separate component props from style props. The problem is that it’s not consistent, which means the types would potentially be lying to you and runtime implementations would differ slightly across each browser.

We could ask users for that list of props but this just seems like a different version of the same suckage:

<Block
  component="input"
  componentProps={['type', 'value']}
  type="text"
  value="Hello"
  color="purple"
/>

The solution (?)

What if we kept an array of common component props? Here’s a rough example:

import React from 'react';

const commonProps = [
  'id',
  'name',
  'placeholder',
  'type',
  'value',
] as const; // `as const` is necessary to make `CommonProp` nice and specific

// our common props as a union of strings
type CommonProp = (typeof commonProps)[number];

// a union of all HTML element names
type IntrinsicElement = keyof JSX.IntrinsicElements;

interface JsxstyleProps<T> extends React.CSSProperties {
  component?: T;
}

// this is where the magic happens
type ComponentProps<T extends IntrinsicElement> = Pick<
  JSX.IntrinsicElements[T],
  Extract<keyof JSX.IntrinsicElements[T], CommonProp>
>;

const Example = <C extends IntrinsicElement = 'div'>(
  props: JsxstyleProps<C> & ComponentProps<C>
): JSX.Element | null => {
  // TODO: implementation :D
  return null;
};

If you want to mess around with this a bit, here’s a TypeScript playground with a functioning example.

This array of common props wouldn’t be perfect, so we could allow users to provide a componentProps array to add to the internal array of common props. The hope would be that we’d be able to remove the need for a componentProps prop for the majority of users.

We could also auto-allow all aria/a11y-related props. I think we might do something like this already? 🤔

I like the simplicity, and we already do something like this for pseudoelement and pseudoclass prefixes.

Let me know what you think!

from jsxstyle.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.