Skip to content

A better way to select props #3326

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

Open
mindplay-dk opened this issue Apr 4, 2025 · 0 comments
Open

A better way to select props #3326

mindplay-dk opened this issue Apr 4, 2025 · 0 comments

Comments

@mindplay-dk
Copy link

The problem

The following pattern is extremely common in a styled-components codebase I'm trying to migrate:

export const EmployeeNameRow = styled(FlexRow.Section).attrs({
  justifyContent: 'space-between',
})`
  width: 100%;
`

The best I've been able to do with these is something like this:

export const EmployeeNameRow = styled((props: ComponentProps<typeof FlexRow.Section>) =>
  <FlexRow.Section justifyContent='space-between' {...props}/>
)`
  width: 100%;
`

You need a new functional component, you need to explicitly redeclare the props type, and so on - this is definitely a setback and increases complexity vs styled-components.

Proposed solution

Why don't we have an option to select props by using a callback?

export const EmployeeNameRow = styled(FlexRow.Section, {
  selectProps: ({ justifyContent = 'space-between', ...props }) => ({
    justifyContent,
    css: css`
      width: 100%;
    `,
    ...props,
  }),
})

The function is literally just a simple props => props function that will get applied when the component is called.

I think this very simple addition would provide a lot of flexibility to override/modify or set default values for props.

Since this callback has the props in scope, you can even apply the styles directly using the css prop instead of having to use a separate template string call and needing to unpack the relevant props again.

I might even go so far as to suggest the second argument should just accept a function directly:

export const EmployeeNameRow = styled(
  FlexRow.Section,
  ({ justifyContent = 'space-between', ...props }) => ({
    justifyContent,
    css: css`
      width: 100%;
    `,
    ...props,
  }),
)

Alternative solutions

With that said, this is still nowhere near as compact or readable as with .attrs in styled-components.

I know you've said in the past you don't want this feature, but styled-components is now deprecated, TypeScript is largely universal at this point, and it's just extremely difficult to find convenient and readable patterns for porting these components to Emotion.

Instead of a simple regex search and replace for import statements, even with the LLM based workflow I've come up with to port everything, instead I am currently looking at probably weeks of manual labor, a monolithic pull request updating thousands of files, adding substantial complexity, and disrupting pull requests across the organization, and also potentially introducing 100s of minor bugs and new typing issues in the process.

Are you completely opposed to improving alignment with styled-components?

If so, I might instead go ahead and build a styled-components API compatibility wrapper for Emotion.

We want to switch, but the amount of labor and disruption might just make this too unrealistic at this point.

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

No branches or pull requests

1 participant