RFC: Responsive Props API #1686
joshuaellis
started this conversation in
Official RFCs
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Summary
The following document outlines a proposal to introduce a consistent responsive API across the design-system using an object notation. Underneath the “How it works” section is a small, quick POC. Following this RFC, we can introduce this API as part of the V2 release of the design-system with the ambition to move Strapi projects to be fully responsive.
Example
Padding has been used as the example prop because padding should break down it’s four pieces (top / right / bottom / left), which works well with an array.
Detailed proposal
Move to object syntax
The design-system has one base component –
Box
, most components are derived from it becauseBox
has runtime style props e.g.padding
:These index values (
2
) correlate to our custom theme array forspaces
but right now we don’t support a way to change these run time values responsively. To support this we’ll introduce an object notation to all the style shorthands so the above code changes to:To ensure the responsive system is opt in we’ll still accept a single value and alias that to the
initial
value, because the prop will not be anobject
we won’t iterate over it to build the rest of the styled syntax. We also will not reset styles if a breakpoint is missing e.g. in the above example there is nomedium
breakpoint defined, therefore we won’t construct amedia query
for that breakpoint to change from the initial value, you could think of the above code as reading “an initial padding ofspace[2]
and when we get to the large breakpoint, we then change tospace[4]
".How it works
👉🏼 if you just want to look at the code, here’s a super speedy prototype - https://codesandbox.io/s/broken-browser-kzm89yThe first part is we have many props, we could create a media-query per prop but that would create a confusing and complex style sheet especially when you try to edit existing styles on a component, instead we’ll run through all our CSS-like props and group them together under our breakpoint aliases. The first issue we face is that our props are written in [Camel Case](https://en.wikipedia.org/wiki/Camel_case), which means they don’t translate to css properties 1:1 e.g.
paddingTop
is actually written aspadding-top
in css, so we’ll need to create a map of camelCase to CSS properties that we access to resolve our issue.Once the grouping and css prop name changes have been done, we need then need to compose the style string including changing the BP tokens into actual media queries, once this is done we’ll have a very concise style sheet that should only have the amount of breakpoints specified across all props e.g. if no prop for the component contains a breakpoint for
xLarge
we won’t have that written in the style sheet.Because we’re running all this in the styled-component we can access the theme to change any numbers to theme tokens as well as alias them to be
px
value if no theme token is found. We can additionally accept strings. The props that accept an array format e.g.padding
we will also map the array solving the values & joining them into one string so they too, become valid CSS values.Using
styled
Some circumstances might require us to use the
styled
function syntax, we will export our breakpoints under the theme object so they can still be used:This, similarly to now, is considered an escape hatch as we don’t often use this pattern in the codebase.
Tradeoffs
The biggest trade off with this approach is that we’re doubling down on using the runtime to define our CSS which could be problematic if we want to move to streaming in react (see styled-components/styled-components#3658).
In terms of the syntax chosen, the major contenders from researching appear to be either an
object
or anarray
. Thearray
syntax while less verbose (that is you don’t have to type the breakpoint yourself) you have less visibility on the breakpoints in use and available (you could have a named tuple in TS to help but skim reading the code is still problematic), you have to fill innull
if you want to omit a breakpoint & finally, adding a new breakpoint in the middle of your current ones would require all your components to change regardless of whether they want to use this new breakpoint or not.It is a breaking change for some components that already respect an array as a responsive value. However, one or two components already accept an object notation, so in reality we’re unifying approaches.
Alternatives
Array notation
Similar to some libraries, we could opt for array notation, but as stated above adding a breakpoint would mean every instance has to change so imo it’s not very flexible.
MQ functions
The biggest issue with this way is that the
theme
prop can’t contain functions so this option isn’t viable due to the restraints ofstyled-components
, we could opt to export amq
function if we want but this is more complicated than it needs to be. In addition it would create conflicts with our runtime style props which is a high impact breaking change were we to make it (due to the workload involved to refactor).Research
Beta Was this translation helpful? Give feedback.
All reactions