Skip to content

[#135] Stop using parametric PropModifiers for styles and fix direction of style composition #145

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

Merged
merged 4 commits into from
May 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions docs/Examples2/QRCode.example.purs
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ qrcodeExample =
{ qrcode, url } <- useQRCode ECLLow props.value
pure
$ box
<<< Box._align Center
$ Box._align Center
$ _
{ content =
[ qrcode
<<< Border.border
>>> Border._round
>>> S.styleModifier_
$ Border.border
$ Border._round
$ S.style_
( S.css
{ padding: S.int 16
, width: S.int 140
Expand Down
14 changes: 7 additions & 7 deletions docs/Examples2/Slat.example.purs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Data.Array (intercalate, replicate)
import Data.Maybe (Maybe(..))
import Data.Nullable as Nullable
import Effect.Unsafe (unsafePerformEffect)
import Lumi.Components (LumiComponent, PropsModifier, lumiComponent)
import Lumi.Components (LumiComponent, lumiComponent)
import Lumi.Components.Example (example)
import Lumi.Components.Lockup (userLockup)
import Lumi.Components.Spacing (Space(..), vspace)
Expand All @@ -15,7 +15,7 @@ import Lumi.Components.Text (h2_, p_)
import Lumi.Components.Text as Text
import Lumi.Components2.Box (box)
import Lumi.Components2.Slat as Slat
import Lumi.Styles (styleModifier_)
import Lumi.Styles (StyleModifier, style_)
import Lumi.Styles.Box (FlexAlign(..))
import Lumi.Styles.Theme (LumiTheme(..), useTheme)
import React.Basic (JSX, fragment)
Expand Down Expand Up @@ -111,12 +111,12 @@ docs =
$ _ { content = exampleSlatContent }
]

slatExWidth :: forall props. PropsModifier props
slatExWidth = styleModifier_ $ E.css { maxWidth: E.int 500, width: E.str "100%" }
slatExWidth :: StyleModifier
slatExWidth = style_ $ E.css { maxWidth: E.int 500, width: E.str "100%" }

slatColumn :: forall props. Int -> PropsModifier props
slatColumn :: Int -> StyleModifier
slatColumn flexGrow =
styleModifier_
style_
$ E.css
$ { flexGrow: E.int flexGrow
, "&:not(:first-child)":
Expand All @@ -134,7 +134,7 @@ labeledInfo =
theme@(LumiTheme { colorNames }) <- useTheme
pure
$ box
$ styleModifier_ (E.css { label: E.str "labeledInfo" })
$ style_ (E.css { label: E.str "labeledInfo" })
$ _
{ css = css
, className = className
Expand Down
2 changes: 1 addition & 1 deletion src/Lumi/Components2/Box.purs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ box =
$ E.element R.div'
{ children: props.content
, className: props.className
, css: toCSS theme props Styles.Box.box
, css: theme # toCSS Styles.Box.box <> props.css
}

row :: LumiComponent BoxProps
Expand Down
2 changes: 1 addition & 1 deletion src/Lumi/Components2/Button.purs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ button =
, children
, className: props.className
, css:
toCSS theme props (Styles.Button.button props.color props.kind props.state props.size)
theme # toCSS (Styles.Button.button props.color props.kind props.state props.size) <> props.css
, onClick: handler_ props.onPress
, type: props.type
, disabled:
Expand Down
2 changes: 1 addition & 1 deletion src/Lumi/Components2/ButtonGroup.purs
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ buttonGroup =
$ E.element R.div'
{ className: props.className
, children: props.content
, css: toCSS theme props (Styles.Button.buttonGroup props.joined)
, css: theme # toCSS (Styles.Button.buttonGroup props.joined) <> props.css
}
12 changes: 6 additions & 6 deletions src/Lumi/Components2/Clip.purs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import Lumi.Components (LumiComponent, lumiComponent)
import Lumi.Components.Spacing (Space(..))
import Lumi.Components2.Box (box)
import Lumi.Components2.Button (_linkStyle, button)
import Lumi.Styles (styleModifier_, toCSS)
import Lumi.Styles (style_, toCSS)
import Lumi.Styles.Box (FlexAlign(..), _justify)
import Lumi.Styles.Box as Styles.Box
import Lumi.Styles.Clip as Styles.Clip
Expand Down Expand Up @@ -45,7 +45,7 @@ clip =
copyButton =
button
$ _linkStyle
$ styleModifier_
$ style_
( E.merge
[ E.css
{ marginLeft: E.prop S16
Expand All @@ -65,14 +65,14 @@ clip =
pure
$ E.element R.div'
{ className: props.className
, css: toCSS theme props Styles.Clip.clip
, css: theme # toCSS Styles.Clip.clip <> props.css
, children:
[ E.element R.div'
{ className: ""
, css:
toCSS theme props
$ Styles.Box.box
>>> Styles.Box._justify Center
theme
# toCSS (Styles.Box.box <<< Styles.Box._justify Center)
<> props.css
, ref
, children: props.content
}
Expand Down
2 changes: 1 addition & 1 deletion src/Lumi/Components2/Link.purs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ link =
theme <- useTheme
pure
$ lumiAnchorElement
{ css: toCSS theme props Styles.Link.link
{ css: theme # toCSS Styles.Link.link <> props.css
, children: props.content
, className
, href: un URL props.href
Expand Down
2 changes: 1 addition & 1 deletion src/Lumi/Components2/QRCode.purs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ useQRCode level value =
]
, ref
, className: props.className
, css: toCSS theme props Styles.QRCode.qrcode
, css: theme # toCSS Styles.QRCode.qrcode <> props.css
}
url /\ setUrl <- useState Nothing
useEffect (UnsafeReference qrcode) do
Expand Down
14 changes: 7 additions & 7 deletions src/Lumi/Components2/Slat.purs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import Data.Newtype (un)
import Effect (Effect)
import Effect.Unsafe (unsafePerformEffect)
import Lumi.Components (LumiComponent, PropsModifier, lumiComponent, propsModifier)
import Lumi.Styles (styleModifier, styleModifier_, toCSS)
import Lumi.Styles (style, style_, toCSS)
import Lumi.Styles.Slat (_interactive, slat) as Styles.Slat.Hidden
import Lumi.Styles.Slat hiding (_interactive,slat) as Styles.Slat
import Lumi.Styles.Theme (LumiTheme(..), useTheme)
Expand Down Expand Up @@ -43,21 +43,21 @@ slat =
pure case props.interaction of
Nothing ->
E.element R.div'
{ css: toCSS theme props slatStyle
{ css: theme # toCSS slatStyle <> props.css
, children: props.content
, className
}
Just interaction@{ href: Nothing } ->
E.element R.button'
{ css: toCSS theme props slatStyleInteractive
{ css: theme # toCSS slatStyleInteractive <> props.css
, children: props.content
, onClick: capture_ interaction.onClick
, tabIndex: interaction.tabIndex
, className
}
Just interaction@{ href: Just href } ->
E.element R.a'
{ css: toCSS theme props slatStyleInteractive
{ css: theme # toCSS slatStyleInteractive <> props.css
, children: props.content
, onClick: capture_ interaction.onClick
, tabIndex: interaction.tabIndex
Expand All @@ -72,11 +72,11 @@ slat =

slatStyle =
Styles.Slat.Hidden.slat
>>> styleModifier_ (E.css { appearance: E.none })
<<< style_ (E.css { appearance: E.none })

slatStyleInteractive =
slatStyle
>>> Styles.Slat.Hidden._interactive
<<< Styles.Slat.Hidden._interactive

_interactive :: SlatInteraction -> PropsModifier SlatProps
_interactive interaction =
Expand All @@ -91,7 +91,7 @@ _interactiveBackground interaction =
_
{ interaction = Just interaction
}
>>> styleModifier \(LumiTheme theme) ->
<<< style \(LumiTheme theme) ->
E.css
{ "&:hover":
E.nested
Expand Down
53 changes: 27 additions & 26 deletions src/Lumi/Styles.purs
Original file line number Diff line number Diff line change
@@ -1,40 +1,41 @@
module Lumi.Styles
( styleModifier
, styleModifier_
( StyleModifier
, style
, style_
, toCSS
, module Emotion
) where

import Prelude
import Lumi.Components (PropsModifier, LumiProps, propsModifier)

import Data.Foldable (fold)
import Lumi.Components (PropsModifier, propsModifier)
import Lumi.Styles.Theme (LumiTheme)
import React.Basic.Emotion hiding (element) as Emotion

-- | Lift a themed set of styles into a `PropsModifier` for composition with other modifiers.
-- |
-- | Note: A style modifier should generally leave the `props` type unconstrained and take
-- | configuration as regular arguments instead. Adding constraints to `props` makes it
-- | difficult to compose style and prop modifiers together across different components,
-- | where the same field name could mean different things.
styleModifier :: forall props. (LumiTheme -> Emotion.Style) -> PropsModifier props
styleModifier f = propsModifier \props -> props { css = f <> props.css }

-- | Lift a static set of styles into a `PropsModifier` for composition with other modifiers.
-- |
-- | Note: A style modifier should generally leave the `props` type unconstrained and take
-- | configuration as regular arguments instead. Adding constraints to `props` makes it
-- | difficult to compose style and prop modifiers together across different components,
-- | where the same field name could mean different things.
styleModifier_ :: forall props. Emotion.Style -> PropsModifier props
styleModifier_ = styleModifier <<< const
import React.Basic.Emotion hiding (element,style) as Emotion

type StyleModifier = forall props. PropsModifier props

-- | Lift a themed set of styles into a `StyleModifier` for composition with other modifiers.
style :: (LumiTheme -> Emotion.Style) -> StyleModifier
style f = propsModifier \props -> props { css = props.css <> f }

-- | Lift a static set of styles into a `StyleModifier` for composition with other modifiers.
style_ :: Emotion.Style -> StyleModifier
style_ = style <<< const

-- | Lift an array of themed styles into a `StyleModifier` for composition with other modifiers.
styles :: Array (LumiTheme -> Emotion.Style) -> StyleModifier
styles = style <<< fold

-- | Lift an array of static styles into a `StyleModifier` for composition with other modifiers.
styles_ :: Array Emotion.Style -> StyleModifier
styles_ = style_ <<< fold

-- | Flatten a `PropsModifier` and extract the Emotion styles for use with `React.Basic.Emotion.element`.
-- | This function is mainly used inside component implementations where the `LumiComponent` boundary
-- | gives way to DOM components or other `ReactComponent`s.
toCSS ::
forall props.
PropsModifier () ->
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@spicydonuts Since we're forcing the monomorphization of StyleModifier here we don't get any escaped skolem errors anymore :)

LumiTheme ->
LumiProps props ->
PropsModifier props ->
Emotion.Style
toCSS theme props m = (m identity props).css theme
toCSS m = (m identity { className: "", css: mempty }).css
29 changes: 14 additions & 15 deletions src/Lumi/Styles/Border.purs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,17 @@ module Lumi.Styles.Border where

import Prelude

import Lumi.Components (PropsModifier)
import Lumi.Components.Spacing (Space(..))
import Lumi.Styles (styleModifier, styleModifier_)
import Lumi.Styles (StyleModifier, style, style_)
import Lumi.Styles.Box (box)
import Lumi.Styles.Box as Box
import Lumi.Styles.Theme (LumiTheme(..))
import React.Basic.Emotion (color, css, int, nested, none, prop, str)

border :: forall props. PropsModifier props
border :: StyleModifier
border =
box
>>> styleModifier \(LumiTheme theme) ->
<<< style \(LumiTheme theme) ->
css
{ label: str "border"
, borderWidth: int 1
Expand All @@ -22,16 +21,16 @@ border =
, padding: str "8px 16px"
}

_round :: forall props. PropsModifier props
_round :: StyleModifier
_round =
styleModifier_
style_
$ css
{ borderRadius: int 4
}

_topBottom :: forall props. PropsModifier props
_topBottom :: StyleModifier
_topBottom =
styleModifier_
style_
( css
{ borderLeft: none
, borderRight: none
Expand All @@ -41,11 +40,11 @@ _topBottom =
}
)

_interactive :: forall props. PropsModifier props
_interactive :: StyleModifier
_interactive =
Box._interactive
>>> Box._focusable
>>> styleModifier \(LumiTheme theme) ->
<<< Box._focusable
<<< style \(LumiTheme theme) ->
css
{ "&:hover":
nested
Expand All @@ -54,9 +53,9 @@ _interactive =
}
}

_listSpaced :: forall props. PropsModifier props
_listSpaced :: StyleModifier
_listSpaced =
styleModifier \(LumiTheme theme) ->
style \(LumiTheme theme) ->
css
{ "&:not(:first-child)":
nested
Expand All @@ -65,9 +64,9 @@ _listSpaced =
}
}

_listCompact :: forall props. PropsModifier props
_listCompact :: StyleModifier
_listCompact =
styleModifier \(LumiTheme theme) ->
style \(LumiTheme theme) ->
css
{ "&:first-child":
nested
Expand Down
Loading