Skip to content

Instantly share code, notes, and snippets.

@mdgriffith
Created October 20, 2021 13:59
Show Gist options
  • Save mdgriffith/c2abad030640dd20e0aa3bc3519211e4 to your computer and use it in GitHub Desktop.
Save mdgriffith/c2abad030640dd20e0aa3bc3519211e4 to your computer and use it in GitHub Desktop.
{- A sketch for a potential responsive API for elm-ui
First, the API. Following will be some example code!
-}
-- defining a set of global window-width breakpoints
breakpoints : label -> List (Breakpoint label) -> Breakpoints label
breakAt : Int -> label -> Breakpoint label
{-| Define a layout that is a row when the page in in the specified breakpoints.
Otherwise, it'll render as a `column`.
-}
rowWhen : Breakpoints label -> List label -> List (Attribute msg) -> List (Element msg)
-- an exact value
value : Int -> Value
-- a value that will scale from one value to another depending
-- on it's position in the current window-width range
-- See fluid typography example below
fluid : Int -> Int -> Value
-- Properties that can vary based on the given window size
fontSize : Breakpoints label -> (label -> Value) -> Attribute msg
padding : Breakpoints label -> (label -> Value) -> Attribute msg
height : Breakpoints label -> (label -> Value) -> Attribute msg
heightMin : Breakpoints label -> (label -> Value) -> Attribute msg
heightMax : Breakpoints label -> (label -> Value) -> Attribute msg
width : Breakpoints label -> (label -> Value) -> Attribute msg
widthMin : Breakpoints label -> (label -> Value) -> Attribute msg
widthMax : Breakpoints label -> (label -> Value) -> Attribute msg
{- EXAMPLES -}
{-|
Defined statically. Needs to be provided to Ui.layout so it can render media queries.
Also needs to be provided to all elements that need responsiveness. But since it's top-level, no need to thread it through every view fn.
-}
breakpoints : Ui.Responsive.Breakpoints Breakpoints
breakpoints =
Ui.Responsive.breakpoints ExtraLarge
[ Ui.Responsive.breakAt 2400 Large
, Ui.Responsive.breakAt 1400 Medium
, Ui.Responsive.breakAt 800 Small
]
el
[ Ui.Responsive.visible breakpoints
[ Medium ]
]
(text "only visible at medium")
el
[ Ui.Responsive.fontSize breakpoints
(\breakpoint ->
case breakpoint of
ExtraLarge ->
Ui.Responsive.value 35
Large ->
Ui.Responsive.value 35
Medium ->
-- scales from 16 to 35 when the window is in the `Medium` range
Ui.Responsive.fluid 16 35
Small ->
Ui.Responsive.value 16
)
]
(text "Fluid typography")
-- padding
el
[ Ui.Responsive.padding breakpoints
(\breakpoint ->
case breakpoint of
ExtraLarge ->
Ui.Responsive.value 35
Large ->
Ui.Responsive.value 35
Medium ->
-- scales from 16 to 35 when the window is in the `Medium` range
Ui.Responsive.fluid 16 35
Small ->
Ui.Responsive.value 16
)
]
(text "Responsive padding!")
@mdgriffith
Copy link
Author

Wouldn't that be preferable to having it passed into every responsive value?

I personally don't think so - the additional cognitive complexity for type signatures would be pretty big because this type is everywhere and would need to be explained to anyone starting to use the library. Easy for people who are very familiar with Elm, but I want elm-ui to be a gateway project, so I'm maybe more wary of cognitive overhead than usual.

I don't think mapping breakpoints would actually be useful because you're never reading them beyond essentially doing a ==

Also not many elements actually need to be explicitly responsive like this. It's usually a handful compared to the vast majority of times when width fill is plenty of responsiveness.

Also, ideally you'd have only a few prepackaged responsive properties like this. e.g. Theme.padding.responsive.medium.

At work we have a custom UI system that's kind of inspired by elm-ui and it does this

Cool! Yeah, measuring text is the main blocker. I have a few ideas on how to do that-happy to share once I'm focusing on that directly.

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