git.iko.soy/rowtype-yoga/ry-blocks
on main help sign in
Draw border and buttons
commit20e0552b770ebeafbbe35fec1bae170a6a2229b5 authorMark Eibes <mark.eibes@gmail.com> dateSun 27 Dec 2020, 00:21 (6 years ago) parentec683df
13 files changed+291−128
src/Yoga/Block.purs+10−6 src/Yoga/Block/Atom/Button/Story.purs+28−4 src/Yoga/Block/Atom/Button/Style.purs+61−28 src/Yoga/Block/Atom/Button/Types.purs+18−2 src/Yoga/Block/Atom/Button/View.purs+20−11 src/Yoga/Block/Atom/Icon.purs+1−1 src/Yoga/Block/Atom/Icon/View.purs+10−10 src/Yoga/Block/Atom/Input/Style.purs+15−5 src/Yoga/Block/Atom/Input/View.purs+96−30 src/Yoga/Block/Container/Style.purs+10−9 src/Yoga/Block/Icon/SVG/Icon.purs+2 src/Yoga/Block/Icon/SVG/QuestionMark.purs+16−20 src/Yoga/Block/Layout/Cluster/Style.purs+4−2
src/Yoga/Block.purs+10−6
@@ -1,17 +1,18 @@
11module Yoga.Block where
22
3+import Prim.Row (class Union)
4+import React.Basic (ReactComponent)
5+import Yoga.Block.Atom.Icon as Icon
6+import Yoga.Block.Atom.Range as Range
7+import Yoga.Block.Atom.Segmented as Segmented
8+import Yoga.Block.Container as Container
39import Yoga.Block.Layout.Box as Box
410import Yoga.Block.Layout.Centre as Centre
511import Yoga.Block.Layout.Cluster as Cluster
6−import Yoga.Block.Container as Container
712import Yoga.Block.Layout.Imposter as Imposter
8−import Yoga.Block.Modal as Modal
9−import Yoga.Block.Atom.Range as Range
10−import Yoga.Block.Atom.Segmented as Segmented
1113import Yoga.Block.Layout.Sidebar as Sidebar
1214import Yoga.Block.Layout.Stack as Stack
13−import Prim.Row (class Union)
14−import React.Basic (ReactComponent)
15+import Yoga.Block.Modal as Modal
1516
1617box ∷ ∀ p q. Union p q Box.Props => ReactComponent { | p }
1718box = Box.component
@@ -25,6 +26,9 @@ cluster = Cluster.component
2526container ∷ ∀ p q. Union p q Container.Props => ReactComponent { | p }
2627container = Container.component
2728
29+icon ∷ ∀ p q. Union p q Icon.Props => ReactComponent { | Icon.MandatoryProps p }
30+icon = Icon.component
31+
2832imposter ∷ ∀ p q. Union p q Imposter.Props => ReactComponent { | p }
2933imposter = Imposter.component
3034
src/Yoga/Block/Atom/Button/Story.purs+28−4
@@ -1,15 +1,21 @@
11module Yoga.Block.Atom.Button.Story where
22
3−import Prelude
3+import Prelude hiding (div)
44import Effect (Effect)
55import Effect.Unsafe (unsafePerformEffect)
66import React.Basic (JSX, element, fragment)
7+import React.Basic.DOM (css)
78import React.Basic.DOM as R
9+import React.Basic.Emotion (str)
810import React.Basic.Emotion as E
911import React.Basic.Events (handler_)
12+import Yoga (div, (/>), (</), (</>))
13+import Yoga.Block as Block
14+import Yoga.Block.Atom.Button.Types as ButtonType
1015import Yoga.Block.Atom.Button.View as Button
16+import Yoga.Block.Container.Style (colour)
1117import Yoga.Block.Container.Style as Styles
12−import Yoga ((</), (/>))
18+import Yoga.Block.Icon.SVG as Icon
1319
1420default ∷
1521 { decorators ∷ Array (Effect JSX -> JSX)
@@ -32,7 +38,25 @@ button = do
3238 $ fragment
3339 [ R.div_
3440 [ R.h1_ [ R.text "Button Examples" ]
35− , R.h2_ [ R.text "Generic Button" ]
36− , Button.component </ { onClick: handler_ mempty } /> [ R.text "Click" ]
41+ , R.h2_ [ R.text "Button types" ]
42+ , Block.cluster </ { space: "var(--s-1)" }
43+ /> [ div </ {}
44+ /> [ Button.component </ { buttonType: ButtonType.Generic } /> [ R.text "Generic" ]
45+ , Button.component </ { buttonType: ButtonType.Primary } /> [ R.text "Primary" ]
46+ ]
47+ ]
48+ , R.h2_ [ R.text "Button shapes" ]
49+ , Block.cluster </ { space: "var(--s-1)" }
50+ /> [ div </ {}
51+ /> [ Button.component </ { buttonType: ButtonType.Generic, buttonShape: ButtonType.Pill } /> [ R.text "Generic" ]
52+ , Button.component </ { buttonType: ButtonType.Primary, buttonShape: ButtonType.Pill } /> [ R.text "Primary" ]
53+ ]
54+ ]
55+ , R.h2_ [ R.text "Icon button" ]
56+ , Block.cluster </ { space: "var(--s-1)" }
57+ /> [ div </ {}
58+ /> [ Button.component </ {} /> [ Block.icon </> { icon: Icon.questionMark, size: str "var(--s2)", colour: str colour.highlight } ]
59+ ]
60+ ]
3761 ]
3862 ]
src/Yoga/Block/Atom/Button/Style.purs+61−28
@@ -9,39 +9,72 @@ type Props f r =
99 | r
1010 )
1111
12−button ∷ Style
13−button =
12+gradientBackground ∷ StyleProperty
13+gradientBackground =
14+ str
15+ $ i "linear-gradient(0deg,"
16+ colour.highlightDarker
17+ ","
18+ colour.highlightLighter
19+ "),linear-gradient(225deg,"
20+ colour.highlightRotatedBackwards
21+ ","
22+ colour.highlightRotatedForwards
23+ ")"
24+
25+buttonContainer ∷ Style
26+buttonContainer =
1427 css
15− { background:
16− str
17− $ i "linear-gradient(180deg,"
18− colour.highlightLighter
19− ","
20− colour.highlightDarker
21− "), linear-gradient(225deg,"
22− colour.highlightRotatedBackwards
23− ","
24− colour.highlightRotatedForwards
25− ")"
26− , color: str colour.highlightText
27− , fontSize: var "--s0"
28− , fontFamily: var "--mainFont"
29− , fontWeight: str "550"
30− , padding: str "var(--s-1) var(--s0)"
31− , borderRadius: var "--s0"
32− , border: str $ "var(--s-5) solid " <> colour.interfaceBackgroundShadow
33− , borderWidth: _0
28+ { background: str colour.interfaceBackground
29+ , boxShadow: str "0 1px 4px rgba(0,0,0,0.30)"
30+ , borderTop: str $ i "1px solid " colour.interfaceBackgroundHighlight
31+ , borderBottom: str $ i "1px solid " colour.interfaceBackgroundShadow
32+ , display: inlineFlex
33+ , padding: str "2px"
34+ , justifyContent: center
35+ , alignItems: center
36+ , borderRadius: var "--s-1"
3437 , """&[data-button-shape="pill"]""":
3538 nest
3639 { borderRadius: var "--s1"
37− , padding: str "var(--s-1) var(--s1)"
38− }
39− , """&[data-button-shape="square"]""":
40− nest
41− { borderRadius: _0
42− , padding: str "var(--s-1) var(--s1)"
40+ , "& > button":
41+ nest
42+ { padding: str "calc(var(--s-1) * 0.8) var(--s0)"
43+ }
4344 }
4445 , """&[data-button-type="primary"]""":
4546 nest
46− {}
47+ { background: gradientBackground
48+ , backgroundSize: str "200% 200%"
49+ , animation: backgroundAnimation <> str " alternate ease-out 10s infinite"
50+ , boxShadow: str "0 1px 4px 0px rgba(0,0,0,0.40)"
51+ , borderColor: str "transparent"
52+ , "& > button":
53+ nest
54+ { color: str colour.highlightText
55+ }
56+ }
57+ }
58+
59+backgroundAnimation ∷ StyleProperty
60+backgroundAnimation =
61+ keyframes
62+ $ { "from": css { backgroundPosition: str "0% 50%" }
63+ , "to": css { backgroundPosition: str "100% 50%" }
64+ }
65+
66+button ∷ Style
67+button =
68+ css
69+ { background: str "transparent"
70+ , color: str colour.text
71+ , boxSizing: borderBox
72+ , fontSize: var "--s0"
73+ , fontFamily: var "--mainFont"
74+ , fontWeight: str "500"
75+ , letterSpacing: str "calc(var(--s-5)*0.2)"
76+ , padding: str "calc(var(--s-1) * 0.85) var(--s0)"
77+ , border: none
78+ , userSelect: none
79+ , "&:focus": nest { outline: none }
4780 }
src/Yoga/Block/Atom/Button/Types.purs+18−2
@@ -4,6 +4,22 @@ import Prelude
44
55data ButtonType
66 = Primary
7− | Secondary
87 | Generic
9−derive instance eqHTMLButton ∷ Eq ButtonType
8+
9+derive instance eqButtonType ∷ Eq ButtonType
10+
11+renderButtonType ∷ ButtonType -> String
12+renderButtonType = case _ of
13+ Primary -> "primary"
14+ Generic -> "generic"
15+
16+data ButtonShape
17+ = Rounded
18+ | Pill
19+
20+derive instance eqButtonShape ∷ Eq ButtonShape
21+
22+renderButtonShape ∷ ButtonShape -> String
23+renderButtonShape = case _ of
24+ Rounded -> "rounded"
25+ Pill -> "pill"
src/Yoga/Block/Atom/Button/View.purs+20−11
@@ -2,13 +2,15 @@ module Yoga.Block.Atom.Button.View where
22
33import Yoga.Prelude.View
44import Data.Symbol (SProxy(..))
5−import Record.Builder as RB
5+import Foreign.Object as Object
66import Yoga.Block.Atom.Button.Style as Style
7−import Yoga.Block.Atom.Button.Types (ButtonType)
7+import Yoga.Block.Atom.Button.Types (ButtonShape, ButtonType, renderButtonShape, renderButtonType)
8+import Yoga.Block.Atom.Button.Types as Button
89import Yoga.Block.Internal (ButtonProps, emotionButton)
910
1011type PropsF f =
1112 ( buttonType ∷ f ButtonType
13+ , buttonShape ∷ f ButtonShape
1214 | Style.Props f ButtonProps
1315 )
1416
@@ -28,13 +30,20 @@ rawComponent ∷ ∀ p. ReactComponent { | p }
2830rawComponent =
2931 mkForwardRefComponent "Button" do
3032 \(props ∷ { | PropsOptional }) propsRef -> React.do
31− pure
32− $ emotionButton propsRef
33− ( props
34− # RB.build
35− ( RB.delete (key ∷ _ "css") >>> RB.delete (key ∷ _ "buttonType")
36− )
37− )
38− { className: "ry-button"
39− , css: Style.button
33+ let
34+ _data =
35+ Object.fromHomogeneous
36+ { "button-type": renderButtonType (props.buttonType ?|| Button.Generic)
37+ , "button-shape": renderButtonShape (props.buttonShape ?|| Button.Rounded)
4038 }
39+ pure $ div
40+ </* { css: Style.buttonContainer
41+ , className: "ry-button-container"
42+ , _data
43+ }
44+ /> [ emotionButton propsRef
45+ props
46+ { className: "ry-button"
47+ , css: Style.button
48+ }
49+ ]
src/Yoga/Block/Atom/Icon.purs+1−1
@@ -2,4 +2,4 @@ module Yoga.Block.Atom.Icon
22 ( module Yoga.Block.Atom.Icon.View
33 ) where
44
5−import Yoga.Block.Atom.Icon.View (component, Props)
5+import Yoga.Block.Atom.Icon.View (component, Props, MandatoryProps)
src/Yoga/Block/Atom/Icon/View.purs+10−10
@@ -3,18 +3,18 @@ module Yoga.Block.Atom.Icon.View where
33import Yoga.Prelude.View
44import Yoga.Block.Atom.Icon.Style as Style
55
6−type Props
7− = PropsF Id
6+type Props =
7+ PropsF Id
88
9−type MandatoryProps r
10− = ( icon ∷ JSX
11− | r
12− )
9+type MandatoryProps r =
10+ ( icon ∷ JSX
11+ | r
12+ )
1313
14−type PropsF f
15− = ( className ∷ f String
16− | Style.Props f (MandatoryProps ())
17− )
14+type PropsF f =
15+ ( className ∷ f String
16+ | Style.Props f (MandatoryProps ())
17+ )
1818
1919component ∷ ∀ p p_. Union p p_ Props => ReactComponent { | MandatoryProps p }
2020component = rawComponent
src/Yoga/Block/Atom/Input/Style.purs+15−5
@@ -4,10 +4,10 @@ import Yoga.Prelude.Style
44import Data.Interpolate (i)
55import Yoga.Block.Container.Style (colour)
66
7−type Props f r
8− = ( css ∷ f Style
9− | r
10− )
7+type Props f r =
8+ ( css ∷ f Style
9+ | r
10+ )
1111
1212leftIconSize ∷ StyleProperty
1313leftIconSize = var "--left-icon-size"
@@ -78,7 +78,17 @@ labelSmall =
7878 }
7979 , """&[data-has-focus="true"] > span""":
8080 nest
81− { background: str colour.highlight
81+ { background:
82+ str
83+ $ i "linear-gradient(225deg,"
84+ colour.highlightLighter
85+ ","
86+ colour.highlightDarker
87+ "), linear-gradient(225deg,"
88+ colour.highlightRotatedBackwards
89+ ","
90+ colour.highlightRotatedForwards
91+ ")"
8292 , color: str colour.highlightText
8393 }
8494 }
src/Yoga/Block/Atom/Input/View.purs+96−30
@@ -1,13 +1,18 @@
11module Yoga.Block.Atom.Input.View where
22
33import Yoga.Prelude.View
4+import Data.Array as Array
5+import Data.Interpolate (i)
6+import Data.Semigroup.Foldable (intercalateMap)
47import Data.String.NonEmpty (NonEmptyString)
58import Data.String.NonEmpty as NonEmptyString
69import Data.Symbol (SProxy(..))
10+import Debug.Trace (spy)
711import Foreign.Object (Object)
812import Foreign.Object as Object
913import Framer.Motion as M
10−import React.Basic.DOM (css)
14+import Partial.Unsafe (unsafeCrashWith)
15+import React.Basic.DOM (CSS, css)
1116import React.Basic.DOM as R
1217import React.Basic.Hooks as React
1318import Web.HTML.HTMLInputElement as InputElement
@@ -18,19 +23,19 @@ import Yoga.Block.Atom.Input.Types as HTMLInput
1823import Yoga.Block.Icon.SVG as SVGIcon
1924import Yoga.Block.Internal.OptionalProp (asMaybe)
2025
21−type PropsF f
22− = ( leading ∷ f JSX
23− , trailing ∷ f JSX
24− , label ∷ f NonEmptyString
25− , type ∷ f HTMLInput
26− | Style.Props f InputProps
27− )
26+type PropsF f =
27+ ( leading ∷ f JSX
28+ , trailing ∷ f JSX
29+ , label ∷ f NonEmptyString
30+ , type ∷ f HTMLInput
31+ | Style.Props f InputProps
32+ )
2833
29−type Props
30− = PropsF Id
34+type Props =
35+ PropsF Id
3136
32−type PropsOptional
33− = PropsF OptionalProp
37+type PropsOptional =
38+ PropsF OptionalProp
3439
3540component ∷ ∀ p p_. Union p p_ Props => ReactComponent { | p }
3641component = rawComponent
@@ -47,6 +52,68 @@ mkLeftIcon icon =
4752 }
4853 ]
4954
55+containerVariants ∷
56+ { blurred ∷ CSS
57+ , focussed ∷ CSS
58+ }
59+containerVariants =
60+ { focussed:
61+ css
62+ { clipPath
63+ , transition: { duration: 1.3 }
64+ }
65+ , blurred:
66+ css
67+ { clipPath:
68+ drawPathUntil (Array.length path) path
69+ }
70+ }
71+ where
72+ clipPath = 3 Array... (Array.length path / 2 + 1) <#> \ln -> drawPathUntil (ln * 2) path
73+
74+type Point =
75+ { x ∷ Int, y ∷ Int }
76+
77+p ∷ Int -> Int -> Point
78+p x y = { x, y }
79+
80+drawPathUntil ∷ Int -> Array Point -> String
81+drawPathUntil idx thePath = do
82+ let fn { x, y } = i x "%" " " y "%"
83+ let firstFew = Array.take idx thePath
84+ let lastFew = Array.drop idx thePath $> (Array.last firstFew # fromMaybe' \_ -> unsafeCrashWith "ogod")
85+ let rendered = intercalate "," $ fn <$> (firstFew <> lastFew)
86+ spy "polybius" $ i "polygon(" rendered ")"
87+
88+path ∷ Array Point
89+path = mkPath 5
90+
91+mkPath ∷ Int -> Array Point
92+mkPath d = do
93+ let
94+ inside =
95+ [ p d d
96+ , p (100 - d) d
97+ , p (100 - d) (100 - d)
98+ , p d (100 - d)
99+ , p d d
100+ ]
101+ outside =
102+ [ p d 0
103+ , p 100 0
104+ , p 100 100
105+ , p 0 100
106+ , p 0 0
107+ , p d 0 -- one turn, starting way back
108+ ]
109+ inside <> outside <> (Array.reverse inside)
110+
111+containerVariantLabels ∷
112+ { blurred ∷ M.VariantLabel
113+ , focussed ∷ M.VariantLabel
114+ }
115+containerVariantLabels = M.makeVariantLabels containerVariants
116+
50117rawComponent ∷ ∀ p. ReactComponent { | p }
51118rawComponent =
52119 mkForwardRefComponent "Input" do
@@ -54,8 +121,7 @@ rawComponent =
54121 inputBbox /\ setInputBbox <- useState' (zero ∷ DOMRect)
55122 hasFocus /\ setHasFocus <- useState' false
56123 backupRef ∷ NodeRef <- useRef null -- [TODO] test this
57− let
58− ref = forwardedRefAsMaybe propsRef # fromMaybe backupRef
124+ let ref = forwardedRefAsMaybe propsRef # fromMaybe backupRef
59125 useEffectOnce do
60126 maybeBBox <- getBoundingBoxFromRef ref
61127 for_ maybeBBox setInputBbox
@@ -73,8 +139,7 @@ rawComponent =
73139 maybeBBox <- getBoundingBoxFromRef leftIconRef
74140 for_ maybeBBox (setLeftIconBbox <<< Just)
75141 mempty
76− let
77− (maybeValue ∷ Maybe String) = cast props.value # opToMaybe
142+ let (maybeValue ∷ Maybe String) = cast props.value # opToMaybe
78143 hasValue /\ setHasValue <- useState' ((maybeValue # isJust) && (maybeValue /= Just ""))
79144 let
80145 aria ∷ Object String
@@ -138,22 +203,25 @@ rawComponent =
138203 ( const do
139204 when hasFocus $ setHasFocus false
140205 el <- getHTMLElementFromRef ref
141− let
142− inputEl = InputElement.fromHTMLElement =<< el
206+ let inputEl = InputElement.fromHTMLElement =<< el
143207 for_ inputEl \ie -> do
144208 v <- InputElement.value ie
145209 setHasValue (v /= "")
146210 )
147211 onFocus = handler preventDefault (const $ unless hasFocus $ setHasFocus true)
148212 inputWrapper =
149− div
150− </* { className: "ry-input-wrapper"
151− , css: Style.inputWrapper props
152− , _data:
153− Object.fromHomogeneous
154− { "invalid": aria # Object.lookup "invalid" # fromMaybe ""
155− }
156− }
213+ M.div
214+ </* M.motion
215+ { variants: M.variants containerVariants
216+ , animate: M.animate if hasFocus then containerVariantLabels.focussed else containerVariantLabels.blurred
217+ }
218+ { className: "ry-input-wrapper"
219+ , css: Style.inputWrapper props
220+ , _data:
221+ Object.fromHomogeneous
222+ { "invalid": aria # Object.lookup "invalid" # fromMaybe ""
223+ }
224+ }
157225 /> [ leading # foldMap \l -> div </ { ref: leftIconRef } /> [ l ]
158226 , emotionInput
159227 ref
@@ -230,10 +298,8 @@ password =
230298 ]
231299 ]
232300 ]
233− let
234− trailing = props.trailing ?|| eyeCon
235− let
236− leading = props.leading ?|| mempty
301+ let trailing = props.trailing ?|| eyeCon
302+ let leading = props.leading ?|| mempty
237303 pure
238304 $ div
239305 </* { className: "ry-input-wrapper"
src/Yoga/Block/Container/Style.purs+10−9
@@ -89,8 +89,8 @@ mkGlobal maybeMode =
8989 }
9090 , "::selection":
9191 nest
92− { background: str colour.highlight
93− , colour: str colour.highlightText
92+ { color: str colour.highlightText
93+ , background: str colour.highlight
9494 }
9595 , "*, *:before, *:after":
9696 nested
@@ -133,8 +133,8 @@ defaultColours =
133133 , required
134134 , interfaceBackground: lightBg
135135 , interfaceTextDisabled: darken 0.33 lightBg
136− , interfaceBackgroundHighlight: darken 0.07 lightBg
137− , interfaceBackgroundShadow: darken 0.1 lightBg
136+ , interfaceBackgroundHighlight: lighten 0.05 lightBg
137+ , interfaceBackgroundShadow: darken 0.04 lightBg
138138 , inputBackground: lightBg
139139 , inputBorder: darken 0.1 lightBg
140140 , highlight
@@ -166,10 +166,10 @@ defaultColours =
166166 , background100: lighten 1.0 darkBg
167167 , textInverted: darkBg
168168 , backgroundInverted: lightBg
169− , interfaceBackground: lighten 0.4 darkBg
169+ , interfaceBackground: interfaceBackgroundDark
170170 , interfaceTextDisabled: lighten 0.8 darkBg
171− , interfaceBackgroundHighlight: lighten 0.5 darkBg
172− , interfaceBackgroundShadow: lighten 0.4 darkBg
171+ , interfaceBackgroundHighlight: lighten 0.1 interfaceBackgroundDark
172+ , interfaceBackgroundShadow: darken 0.1 interfaceBackgroundDark
173173 , inputBackground: darkBg
174174 , inputBorder: lighten 0.17 darkBg
175175 , success
@@ -188,11 +188,12 @@ defaultColours =
188188 }
189189 }
190190 where
191− -- highlight = Color.rgb 0x00 0x99 0xFF
192− highlight = Color.hsl 350.0 0.93 0.67
191+ highlight = Color.hsl 270.0 0.90 0.62
193192
194193 highlightDark = Color.rgb 0x88 0x33 0xFF
195194
195+ interfaceBackgroundDark = Color.hsl 240.0 0.10 0.33
196+
196197 highlightText = Color.rgb 0xFF 0xFF 0xFF
197198
198199 success = Color.rgb 20 200 60
src/Yoga/Block/Icon/SVG/Icon.purs+2
@@ -6,6 +6,7 @@ module Yoga.Block.Icon.SVG
66 , module Yoga.Block.Icon.SVG.EyeOpen
77 , module Yoga.Block.Icon.SVG.Key
88 , module Yoga.Block.Icon.SVG.SimpleKey
9+ , module Yoga.Block.Icon.SVG.QuestionMark
910 ) where
1011
1112import Yoga.Block.Icon.SVG.On (on)
@@ -15,3 +16,4 @@ import Yoga.Block.Icon.SVG.EyeClosed (eyeClosed)
1516import Yoga.Block.Icon.SVG.EyeOpen (eyeOpen)
1617import Yoga.Block.Icon.SVG.Key (key)
1718import Yoga.Block.Icon.SVG.SimpleKey (simpleKey)
19+import Yoga.Block.Icon.SVG.QuestionMark (questionMark)
src/Yoga/Block/Icon/SVG/QuestionMark.purs+16−20
@@ -1,25 +1,21 @@
11module Yoga.Block.Icon.SVG.QuestionMark where
22
33import React.Basic (JSX)
4−import React.Basic.DOM as R
54import React.Basic.DOM.SVG as SVG
65
7−questionMark :: JSX
8−questionMark = SVG.svg
9− { viewBox: "0 0 100 100"
10− , xmlns: "http://www.w3.org/2000/svg"
11− , fillRule: "evenodd"
12− , clipRule: "evenodd"
13− , strokeLinejoin: "round"
14− , strokeMiterlimit: "2"
15− , children:
16− [ SVG.path
17− { fill: "none"
18− , d: "M0 0h100v100H0z"
19− }
20− , SVG.path
21− { d: "M50 10.037c22.056 0 39.963 17.907 39.963 39.963S72.056 89.963 50 89.963 10.037 72.056 10.037 50 27.944 10.037 50 10.037zM48.871 77.03c2.87 0 5.326-2.384 5.351-5.351-.025-2.918-2.481-5.301-5.351-5.301-2.967 0-5.374 2.383-5.35 5.301-.024 2.967 2.383 5.351 5.35 5.351zm-4.255-15.176h8.098v-.632c.049-5.156 1.727-7.515 5.691-9.947 4.474-2.675 7.271-6.323 7.271-11.892 0-8.22-6.396-13.375-15.686-13.375-8.512 0-15.418 4.718-15.661 13.959h8.657c.219-4.572 3.526-6.761 6.955-6.761 3.721 0 6.713 2.481 6.713 6.299 0 3.405-2.262 5.739-5.205 7.587-4.304 2.676-6.785 5.375-6.833 14.13v.632z"
22− , fill: "#333"
23− }
24− ]
25− }
6+questionMark ∷ JSX
7+questionMark =
8+ SVG.svg
9+ { viewBox: "0 0 100 100"
10+ , xmlns: "http://www.w3.org/2000/svg"
11+ , fillRule: "evenodd"
12+ , clipRule: "evenodd"
13+ , strokeLinejoin: "round"
14+ , strokeMiterlimit: "2"
15+ , children:
16+ [ SVG.path
17+ { d: "M50 10.037c22.056 0 39.963 17.907 39.963 39.963S72.056 89.963 50 89.963 10.037 72.056 10.037 50 27.944 10.037 50 10.037zM48.871 77.03c2.87 0 5.326-2.384 5.351-5.351-.025-2.918-2.481-5.301-5.351-5.301-2.967 0-5.374 2.383-5.35 5.301-.024 2.967 2.383 5.351 5.35 5.351zm-4.255-15.176h8.098v-.632c.049-5.156 1.727-7.515 5.691-9.947 4.474-2.675 7.271-6.323 7.271-11.892 0-8.22-6.396-13.375-15.686-13.375-8.512 0-15.418 4.718-15.661 13.959h8.657c.219-4.572 3.526-6.761 6.955-6.761 3.721 0 6.713 2.481 6.713 6.299 0 3.405-2.262 5.739-5.205 7.587-4.304 2.676-6.785 5.375-6.833 14.13v.632z"
18+ , fill: "var(--stroke-colour)"
19+ }
20+ ]
21+ }
src/Yoga/Block/Layout/Cluster/Style.purs+4−2
@@ -13,6 +13,8 @@ type Props f r =
1313cluster ∷ ∀ p. { | Props OptionalProp p } -> Style
1414cluster props = styles <>? props.css
1515 where
16+ space = props.space ?|| "var(--s1)"
17+
1618 styles =
1719 css
1820 { "& > *":
@@ -21,10 +23,10 @@ cluster props = styles <>? props.css
2123 , flexWrap: wrap
2224 , alignItems: (str <$> props.align) ?|| center
2325 , justifyContent: (str <$> props.justify) ?|| flexStart
24− , margin: "calc(" <> props.space ?|| "var(--s1)" <> "/2 * -1)" # str
26+ , margin: "calc(" <> space <> "/2 * -1)" # str
2527 }
2628 , "& > * > *":
2729 nest
28− { margin: "calc(" <> props.space ?|| "var(--s1)" <> "/2)" # str
30+ { margin: "calc(" <> space <> "/2)" # str
2931 }
3032 }