Skip to content

Commit 56a5526

Browse files
[#135] Stop using parametric PropModifiers for styles and fix direction of style composition (#145)
* Add StyleModifier * Rename styleModifier combinators * Fix direction of composition of style modifiers * Add combinators for using an array of styles as a prop modifier
1 parent 27ec237 commit 56a5526

19 files changed

+128
-137
lines changed

docs/Examples2/QRCode.example.purs

+4-4
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,13 @@ qrcodeExample =
4848
{ qrcode, url } <- useQRCode ECLLow props.value
4949
pure
5050
$ box
51-
<<< Box._align Center
51+
$ Box._align Center
5252
$ _
5353
{ content =
5454
[ qrcode
55-
<<< Border.border
56-
>>> Border._round
57-
>>> S.styleModifier_
55+
$ Border.border
56+
$ Border._round
57+
$ S.style_
5858
( S.css
5959
{ padding: S.int 16
6060
, width: S.int 140

docs/Examples2/Slat.example.purs

+7-7
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import Data.Array (intercalate, replicate)
66
import Data.Maybe (Maybe(..))
77
import Data.Nullable as Nullable
88
import Effect.Unsafe (unsafePerformEffect)
9-
import Lumi.Components (LumiComponent, PropsModifier, lumiComponent)
9+
import Lumi.Components (LumiComponent, lumiComponent)
1010
import Lumi.Components.Example (example)
1111
import Lumi.Components.Lockup (userLockup)
1212
import Lumi.Components.Spacing (Space(..), vspace)
@@ -15,7 +15,7 @@ import Lumi.Components.Text (h2_, p_)
1515
import Lumi.Components.Text as Text
1616
import Lumi.Components2.Box (box)
1717
import Lumi.Components2.Slat as Slat
18-
import Lumi.Styles (styleModifier_)
18+
import Lumi.Styles (StyleModifier, style_)
1919
import Lumi.Styles.Box (FlexAlign(..))
2020
import Lumi.Styles.Theme (LumiTheme(..), useTheme)
2121
import React.Basic (JSX, fragment)
@@ -111,12 +111,12 @@ docs =
111111
$ _ { content = exampleSlatContent }
112112
]
113113

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

117-
slatColumn :: forall props. Int -> PropsModifier props
117+
slatColumn :: Int -> StyleModifier
118118
slatColumn flexGrow =
119-
styleModifier_
119+
style_
120120
$ E.css
121121
$ { flexGrow: E.int flexGrow
122122
, "&:not(:first-child)":
@@ -134,7 +134,7 @@ labeledInfo =
134134
theme@(LumiTheme { colorNames }) <- useTheme
135135
pure
136136
$ box
137-
$ styleModifier_ (E.css { label: E.str "labeledInfo" })
137+
$ style_ (E.css { label: E.str "labeledInfo" })
138138
$ _
139139
{ css = css
140140
, className = className

src/Lumi/Components2/Box.purs

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ box =
2424
$ E.element R.div'
2525
{ children: props.content
2626
, className: props.className
27-
, css: toCSS theme props Styles.Box.box
27+
, css: theme # toCSS Styles.Box.box <> props.css
2828
}
2929

3030
row :: LumiComponent BoxProps

src/Lumi/Components2/Button.purs

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ button =
6868
, children
6969
, className: props.className
7070
, css:
71-
toCSS theme props (Styles.Button.button props.color props.kind props.state props.size)
71+
theme # toCSS (Styles.Button.button props.color props.kind props.state props.size) <> props.css
7272
, onClick: handler_ props.onPress
7373
, type: props.type
7474
, disabled:

src/Lumi/Components2/ButtonGroup.purs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@ buttonGroup =
2626
$ E.element R.div'
2727
{ className: props.className
2828
, children: props.content
29-
, css: toCSS theme props (Styles.Button.buttonGroup props.joined)
29+
, css: theme # toCSS (Styles.Button.buttonGroup props.joined) <> props.css
3030
}

src/Lumi/Components2/Clip.purs

+6-6
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import Lumi.Components (LumiComponent, lumiComponent)
1717
import Lumi.Components.Spacing (Space(..))
1818
import Lumi.Components2.Box (box)
1919
import Lumi.Components2.Button (_linkStyle, button)
20-
import Lumi.Styles (styleModifier_, toCSS)
20+
import Lumi.Styles (style_, toCSS)
2121
import Lumi.Styles.Box (FlexAlign(..), _justify)
2222
import Lumi.Styles.Box as Styles.Box
2323
import Lumi.Styles.Clip as Styles.Clip
@@ -45,7 +45,7 @@ clip =
4545
copyButton =
4646
button
4747
$ _linkStyle
48-
$ styleModifier_
48+
$ style_
4949
( E.merge
5050
[ E.css
5151
{ marginLeft: E.prop S16
@@ -65,14 +65,14 @@ clip =
6565
pure
6666
$ E.element R.div'
6767
{ className: props.className
68-
, css: toCSS theme props Styles.Clip.clip
68+
, css: theme # toCSS Styles.Clip.clip <> props.css
6969
, children:
7070
[ E.element R.div'
7171
{ className: ""
7272
, css:
73-
toCSS theme props
74-
$ Styles.Box.box
75-
>>> Styles.Box._justify Center
73+
theme
74+
# toCSS (Styles.Box.box <<< Styles.Box._justify Center)
75+
<> props.css
7676
, ref
7777
, children: props.content
7878
}

src/Lumi/Components2/Link.purs

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ link =
5050
theme <- useTheme
5151
pure
5252
$ lumiAnchorElement
53-
{ css: toCSS theme props Styles.Link.link
53+
{ css: theme # toCSS Styles.Link.link <> props.css
5454
, children: props.content
5555
, className
5656
, href: un URL props.href

src/Lumi/Components2/QRCode.purs

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ useQRCode level value =
7272
]
7373
, ref
7474
, className: props.className
75-
, css: toCSS theme props Styles.QRCode.qrcode
75+
, css: theme # toCSS Styles.QRCode.qrcode <> props.css
7676
}
7777
url /\ setUrl <- useState Nothing
7878
useEffect (UnsafeReference qrcode) do

src/Lumi/Components2/Slat.purs

+7-7
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import Data.Newtype (un)
1313
import Effect (Effect)
1414
import Effect.Unsafe (unsafePerformEffect)
1515
import Lumi.Components (LumiComponent, PropsModifier, lumiComponent, propsModifier)
16-
import Lumi.Styles (styleModifier, styleModifier_, toCSS)
16+
import Lumi.Styles (style, style_, toCSS)
1717
import Lumi.Styles.Slat (_interactive, slat) as Styles.Slat.Hidden
1818
import Lumi.Styles.Slat hiding (_interactive,slat) as Styles.Slat
1919
import Lumi.Styles.Theme (LumiTheme(..), useTheme)
@@ -43,21 +43,21 @@ slat =
4343
pure case props.interaction of
4444
Nothing ->
4545
E.element R.div'
46-
{ css: toCSS theme props slatStyle
46+
{ css: theme # toCSS slatStyle <> props.css
4747
, children: props.content
4848
, className
4949
}
5050
Just interaction@{ href: Nothing } ->
5151
E.element R.button'
52-
{ css: toCSS theme props slatStyleInteractive
52+
{ css: theme # toCSS slatStyleInteractive <> props.css
5353
, children: props.content
5454
, onClick: capture_ interaction.onClick
5555
, tabIndex: interaction.tabIndex
5656
, className
5757
}
5858
Just interaction@{ href: Just href } ->
5959
E.element R.a'
60-
{ css: toCSS theme props slatStyleInteractive
60+
{ css: theme # toCSS slatStyleInteractive <> props.css
6161
, children: props.content
6262
, onClick: capture_ interaction.onClick
6363
, tabIndex: interaction.tabIndex
@@ -72,11 +72,11 @@ slat =
7272

7373
slatStyle =
7474
Styles.Slat.Hidden.slat
75-
>>> styleModifier_ (E.css { appearance: E.none })
75+
<<< style_ (E.css { appearance: E.none })
7676

7777
slatStyleInteractive =
7878
slatStyle
79-
>>> Styles.Slat.Hidden._interactive
79+
<<< Styles.Slat.Hidden._interactive
8080

8181
_interactive :: SlatInteraction -> PropsModifier SlatProps
8282
_interactive interaction =
@@ -91,7 +91,7 @@ _interactiveBackground interaction =
9191
_
9292
{ interaction = Just interaction
9393
}
94-
>>> styleModifier \(LumiTheme theme) ->
94+
<<< style \(LumiTheme theme) ->
9595
E.css
9696
{ "&:hover":
9797
E.nested

src/Lumi/Styles.purs

+27-26
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,41 @@
11
module Lumi.Styles
2-
( styleModifier
3-
, styleModifier_
2+
( StyleModifier
3+
, style
4+
, style_
45
, toCSS
56
, module Emotion
67
) where
78

89
import Prelude
9-
import Lumi.Components (PropsModifier, LumiProps, propsModifier)
10+
11+
import Data.Foldable (fold)
12+
import Lumi.Components (PropsModifier, propsModifier)
1013
import Lumi.Styles.Theme (LumiTheme)
11-
import React.Basic.Emotion hiding (element) as Emotion
12-
13-
-- | Lift a themed set of styles into a `PropsModifier` for composition with other modifiers.
14-
-- |
15-
-- | Note: A style modifier should generally leave the `props` type unconstrained and take
16-
-- | configuration as regular arguments instead. Adding constraints to `props` makes it
17-
-- | difficult to compose style and prop modifiers together across different components,
18-
-- | where the same field name could mean different things.
19-
styleModifier :: forall props. (LumiTheme -> Emotion.Style) -> PropsModifier props
20-
styleModifier f = propsModifier \props -> props { css = f <> props.css }
21-
22-
-- | Lift a static set of styles into a `PropsModifier` for composition with other modifiers.
23-
-- |
24-
-- | Note: A style modifier should generally leave the `props` type unconstrained and take
25-
-- | configuration as regular arguments instead. Adding constraints to `props` makes it
26-
-- | difficult to compose style and prop modifiers together across different components,
27-
-- | where the same field name could mean different things.
28-
styleModifier_ :: forall props. Emotion.Style -> PropsModifier props
29-
styleModifier_ = styleModifier <<< const
14+
import React.Basic.Emotion hiding (element,style) as Emotion
15+
16+
type StyleModifier = forall props. PropsModifier props
17+
18+
-- | Lift a themed set of styles into a `StyleModifier` for composition with other modifiers.
19+
style :: (LumiTheme -> Emotion.Style) -> StyleModifier
20+
style f = propsModifier \props -> props { css = props.css <> f }
21+
22+
-- | Lift a static set of styles into a `StyleModifier` for composition with other modifiers.
23+
style_ :: Emotion.Style -> StyleModifier
24+
style_ = style <<< const
25+
26+
-- | Lift an array of themed styles into a `StyleModifier` for composition with other modifiers.
27+
styles :: Array (LumiTheme -> Emotion.Style) -> StyleModifier
28+
styles = style <<< fold
29+
30+
-- | Lift an array of static styles into a `StyleModifier` for composition with other modifiers.
31+
styles_ :: Array Emotion.Style -> StyleModifier
32+
styles_ = style_ <<< fold
3033

3134
-- | Flatten a `PropsModifier` and extract the Emotion styles for use with `React.Basic.Emotion.element`.
3235
-- | This function is mainly used inside component implementations where the `LumiComponent` boundary
3336
-- | gives way to DOM components or other `ReactComponent`s.
3437
toCSS ::
35-
forall props.
38+
PropsModifier () ->
3639
LumiTheme ->
37-
LumiProps props ->
38-
PropsModifier props ->
3940
Emotion.Style
40-
toCSS theme props m = (m identity props).css theme
41+
toCSS m = (m identity { className: "", css: mempty }).css

src/Lumi/Styles/Border.purs

+14-15
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,17 @@ module Lumi.Styles.Border where
22

33
import Prelude
44

5-
import Lumi.Components (PropsModifier)
65
import Lumi.Components.Spacing (Space(..))
7-
import Lumi.Styles (styleModifier, styleModifier_)
6+
import Lumi.Styles (StyleModifier, style, style_)
87
import Lumi.Styles.Box (box)
98
import Lumi.Styles.Box as Box
109
import Lumi.Styles.Theme (LumiTheme(..))
1110
import React.Basic.Emotion (color, css, int, nested, none, prop, str)
1211

13-
border :: forall props. PropsModifier props
12+
border :: StyleModifier
1413
border =
1514
box
16-
>>> styleModifier \(LumiTheme theme) ->
15+
<<< style \(LumiTheme theme) ->
1716
css
1817
{ label: str "border"
1918
, borderWidth: int 1
@@ -22,16 +21,16 @@ border =
2221
, padding: str "8px 16px"
2322
}
2423

25-
_round :: forall props. PropsModifier props
24+
_round :: StyleModifier
2625
_round =
27-
styleModifier_
26+
style_
2827
$ css
2928
{ borderRadius: int 4
3029
}
3130

32-
_topBottom :: forall props. PropsModifier props
31+
_topBottom :: StyleModifier
3332
_topBottom =
34-
styleModifier_
33+
style_
3534
( css
3635
{ borderLeft: none
3736
, borderRight: none
@@ -41,11 +40,11 @@ _topBottom =
4140
}
4241
)
4342

44-
_interactive :: forall props. PropsModifier props
43+
_interactive :: StyleModifier
4544
_interactive =
4645
Box._interactive
47-
>>> Box._focusable
48-
>>> styleModifier \(LumiTheme theme) ->
46+
<<< Box._focusable
47+
<<< style \(LumiTheme theme) ->
4948
css
5049
{ "&:hover":
5150
nested
@@ -54,9 +53,9 @@ _interactive =
5453
}
5554
}
5655

57-
_listSpaced :: forall props. PropsModifier props
56+
_listSpaced :: StyleModifier
5857
_listSpaced =
59-
styleModifier \(LumiTheme theme) ->
58+
style \(LumiTheme theme) ->
6059
css
6160
{ "&:not(:first-child)":
6261
nested
@@ -65,9 +64,9 @@ _listSpaced =
6564
}
6665
}
6766

68-
_listCompact :: forall props. PropsModifier props
67+
_listCompact :: StyleModifier
6968
_listCompact =
70-
styleModifier \(LumiTheme theme) ->
69+
style \(LumiTheme theme) ->
7170
css
7271
{ "&:first-child":
7372
nested

0 commit comments

Comments
 (0)