mdgriffith / design-discussion-elm-ui-2

A repo for discussing changes to Elm UI 2

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Support for declarative responsive design

gampleman opened this issue · comments

So far the recommendation for achieving responsive design has been to subscribe to resizes and use an initial size in Elm. While this works, it has some downsides:

  • It is unsuitable for static site generators
  • It requires flags and JS to set up properly
  • It requires the width to be passed into every view, necessitating some plumbing
  • It requires re-evaluating the view when resizes happen, which may make it perform poorly

The upside is of course some conceptual simplicity. However I wonder if we could achieve something quite nice with some symbolic operators. We already specify things in Length values, so some things could be specified as special Length values:

viewportWidth |> minus (px 30)

which could be compiled to:

calc(100vw - 30px)

However, I'm not sure this would be useful. However, I think we could also provide some responsive layout primitives:

rowIf (viewportWidth |> greaterThan (px 600)) attrs children

which could be compiled to:

.el23 { flex-direction: column; } 
@media (width > 600px) { .el23 { flex-direction: row; } }  

similarly one could have hiddenIf. These kinds of techniques could also work for responsive text size.

Finally worth noting that this wouldn't remove the previous technique, but for many usecases it could make it unnecessary.

Also see #16 for some further ideas on this.

I quite like the https://chakra-ui.com/docs/features/responsive-styles approach:

<>
  <Box
    height={{
      base: "100%", // 0-48em
      md: "50%", // 48em-80em,
      xl: "25%", // 80em+
    }}
    bg="teal.400"
    width={[
      "100%", // 0-30em
      "50%", // 30em-48em
      "25%", // 48em-62em
      "15%", // 62em+
    ]}
  />
  {/* responsive font size */}
  <Box fontSize={["sm", "md", "lg", "xl"]}>Font Size</Box>
  {/* responsive margin */}
  <Box mt={[2, 4, 6, 8]} width="full" height="24px" bg="tomato" />
  {/* responsive padding */}
  <Box bg="papayawhip" p={[2, 4, 6, 8]}>
    Padding
  </Box>
</>

Every style can be given an object or array and the style that matches the breakpoint size will be used.