Towards reusable components
See original GitHub issueTowards reusable components
I’ve just been looking at “styled-components” and chatted to @geelen about it a few days ago and he suggested I share my thoughts here.
Thinking about how “styled-components” (and similar things) should be used, I think the there’s an interesting difference between “theming” (passing common styling information down to components through context) and “including” (importing common styling information from shared files in different components and injecting with string interpolation in javascript).
Theming
Theming is something that is explicitly focused on in “styled-components”, where top-down style information can be made available anywhere within a ThemeProvider
component using React’s Context feature. As described here and here, a component that responds to a theme would look something like this:
import styled from 'styled-components';
const Button = styled.button`
background: ${props => props.theme.main || 'palevioletred'};
`;
Including
Here’s an example of what I mean by “including”, where string interpolation is used to inject a colour variable that’s read in from a common constants file:
import styled from 'styled-components';
import constants from './constants';
const Button = styled.button`
background: ${constants.main};
`;
This is also referred to in the “styled-components” README, albeit only in passing. To me, “including” is somewhat similar to how “composes” works in CSS Modules. It is a (common) dependency of a component.
Theming suggests reusability
Both of these are ways of sharing common styles between components within a particular application but there is one big difference between them relating to reusability. Theming assumes that components have default styles and that a theme/context simply overwrites these. Including/importing could in theory work the same: default styles are specified and overwritten by anything found in the common styles that are imported, but, at least to me, that is not what I would expect and it’s not really designed to work like this.
In my mind, _including common styles works against, or is in conflict with, having your components reusable and sharable_. Maybe others see if differently - please let me know if that’s the case. And probably others see that as being a necessary thing to give up - as it has been so far with CSS and creating reusable components. But the thing that I think is the most exciting about “styled-components” is that maybe we are close to finally having components that are reusable from a styling perspective. Maybe I’m just being hopeful but shouldn’t this always be the end-goal?
Do we need a standardised theming convention?
I feel like we do because otherwise different “reusable” components will all expect different theme properties - even for things that should actually be the same thing, such as theme.bgColour
and theme.backgroundColour
and even theme.background
. And there are different levels of specificity a component may be looking for: theme.spacing
vs. theme.lineSpacing
and theme.verticalPadding
; and these may be given as descriptors (e.g. "large"
and "small"
) or as specific values.
Anyway, I think it would be interesting to attempt to create a theme specification that people could write themeable components against. I don’t have a good sense for how hard that would be or how useful but what do people think?
Issue Analytics
- State:
- Created 7 years ago
- Reactions:10
- Comments:5 (5 by maintainers)
Top GitHub Comments
@robrkerr this is something we’ve been debating a lot lately. If your goal (which ours is) is to have a component fully describe itself and be able to be ported over to any code base with minimal, if any dependencies, then the concept of having shared variables does seem to fly in the face of that.
Looking at the other side of the argument, though: I think CSS purists would argue that we are fighting against CSS in our endless pursuit of standalone components. Ditching any shared styling does go against everything we’ve known CSS to do. Is CSS as a concept changing, though, and we are more worried about how a specific component looks in a vacuum and nothing more? I feel like that is where we are heading.
When it comes to theming, the concept that I have been getting more and more behind is an approach that seems to fit with what you are proposing. To have a standalone component that fully describes its styles but can be themed in a standard way. This component has these default styles, but you can provide your app a theme file that, following a certain standard, will naturally override those defaults. Feels like the best of both worlds and doesn’t break the shareable component concept in my mind. If you want to use it as is, here is everything you need, but here is also a standard way to make it your own.
This is something I could get behind, and something we are working through internally. I think the question becomes. “is it too opinionated for the library to decide this for me.”
My two cents at least…
Since nobody else has brought this up or started to work on it I’ll close this issue for now. If you want to work on a standard theming convention please feel free to open a new issue to discuss what that could look like!