git.iko.soy/rowtype-yoga/ry-blocks
on main help sign in
Mostly buttons
3c1f4dfMark Eibes
src/Yoga/Block/Atom/Button/Story.purs+13−13
@@ -4,11 +4,9 @@ import Prelude hiding (div)
4import Effect (Effect)
4import Effect (Effect)
5import Effect.Unsafe (unsafePerformEffect)
5import Effect.Unsafe (unsafePerformEffect)
6import React.Basic (JSX, element, fragment)
6import React.Basic (JSX, element, fragment)
7−import React.Basic.DOM (css)
8import React.Basic.DOM as R
7import React.Basic.DOM as R
9import React.Basic.Emotion (str)
8import React.Basic.Emotion (str)
10import React.Basic.Emotion as E
9import React.Basic.Emotion as E
11−import React.Basic.Events (handler_)
12import Yoga (div, (/>), (</), (</>))
10import Yoga (div, (/>), (</), (</>))
13import Yoga.Block as Block
11import Yoga.Block as Block
14import Yoga.Block.Atom.Button.Types as ButtonType
12import Yoga.Block.Atom.Button.Types as ButtonType
@@ -40,23 +38,25 @@ button = do
40 [ R.h1_ [ R.text "Button Examples" ]
38 [ R.h1_ [ R.text "Button Examples" ]
41 , R.h2_ [ R.text "Button types" ]
39 , R.h2_ [ R.text "Button types" ]
42 , Block.cluster </ { space: "var(--s-1)" }
40 , Block.cluster </ { space: "var(--s-1)" }
43− /> [ div </ {}
41+ /> [ Button.component </ { buttonType: ButtonType.Generic } /> [ R.text "Generic" ]
44− /> [ Button.component </ { buttonType: ButtonType.Generic } /> [ R.text "Generic" ]
42+ , Button.component </ { buttonType: ButtonType.Primary } /> [ R.text "Primary" ]
45− , Button.component </ { buttonType: ButtonType.Primary } /> [ R.text "Primary" ]
43+ , Button.component </ { buttonType: ButtonType.Dangerous } /> [ R.text "Dangerous" ]
46− ]
47 ]
44 ]
48 , R.h2_ [ R.text "Button shapes" ]
45 , R.h2_ [ R.text "Button shapes" ]
49 , Block.cluster </ { space: "var(--s-1)" }
46 , Block.cluster </ { space: "var(--s-1)" }
50− /> [ div </ {}
51− /> [ Button.component </ { buttonType: ButtonType.Generic, buttonShape: ButtonType.Pill } /> [ R.text "Generic" ]
47+ /> [ Button.component </ { buttonType: ButtonType.Generic, buttonShape: ButtonType.Pill } /> [ R.text "Generic" ]
52− , Button.component </ { buttonType: ButtonType.Primary, buttonShape: ButtonType.Pill } /> [ R.text "Primary" ]
48+ , Button.component </ { buttonType: ButtonType.Primary, buttonShape: ButtonType.Pill } /> [ R.text "Primary" ]
53− ]
54 ]
49 ]
55 , R.h2_ [ R.text "Icon button" ]
50 , R.h2_ [ R.text "Icon button" ]
56 , Block.cluster </ { space: "var(--s-1)" }
51 , Block.cluster </ { space: "var(--s-1)" }
57− /> [ div </ {}
58− /> [ Button.component </ {} /> [ Block.icon </> { icon: Icon.questionMark, size: str "var(--s2)", colour: str colour.highlight } ]
52+ /> [ Button.component </ {} /> [ Block.icon </> { icon: Icon.questionMark, size: str "var(--s2)", colour: str colour.highlight } ]
59− ]
53+ ]
54+ , R.h2_ [ R.text "Disabled" ]
55+ , Block.cluster </ { space: "var(--s-1)" }
56+ /> [ Button.component </ { buttonType: ButtonType.Generic, disabled: true } /> [ R.text "Generic" ]
57+ , Button.component </ { buttonType: ButtonType.Primary, disabled: true } /> [ R.text "Primary" ]
58+ , Button.component </ { buttonType: ButtonType.Generic, buttonShape: ButtonType.Pill, disabled: true } /> [ R.text "Generic" ]
59+ , Button.component </ { buttonType: ButtonType.Primary, buttonShape: ButtonType.Pill, disabled: true } /> [ R.text "Primary" ]
60 ]
60 ]
61 ]
61 ]
62 ]
62 ]
src/Yoga/Block/Atom/Button/Style.purs+68−34
@@ -16,65 +16,99 @@ gradientBackground =
16 colour.highlightDarker
16 colour.highlightDarker
17 ","
17 ","
18 colour.highlightLighter
18 colour.highlightLighter
19+ ")"
20+ ","
19− "),linear-gradient(225deg,"
21+ "linear-gradient(225deg,"
20 colour.highlightRotatedBackwards
22 colour.highlightRotatedBackwards
21 ","
23 ","
22 colour.highlightRotatedForwards
24 colour.highlightRotatedForwards
23 ")"
25 ")"
24
26
25−buttonContainer ∷ Style
27+backgroundAnimation ∷ StyleProperty
26−buttonContainer =
28+backgroundAnimation =
29+ keyframes
30+ $ { "from": css { backgroundPosition: str "0% 50%" }
31+ , "to": css { backgroundPosition: str "100% 50%" }
32+ }
33+
34+button ∷ Style
35+button =
27 css
36 css
28 { background: str colour.interfaceBackground
37 { background: str colour.interfaceBackground
29 , boxShadow: str "0 1px 4px rgba(0,0,0,0.30)"
38 , boxShadow: str "0 1px 4px rgba(0,0,0,0.30)"
39+ , border: str $ i "1px solid transparent"
30 , borderTop: str $ i "1px solid " colour.interfaceBackgroundHighlight
40 , borderTop: str $ i "1px solid " colour.interfaceBackgroundHighlight
31 , borderBottom: str $ i "1px solid " colour.interfaceBackgroundShadow
41 , borderBottom: str $ i "1px solid " colour.interfaceBackgroundShadow
32 , display: inlineFlex
42 , display: inlineFlex
33− , padding: str "2px"
43+ , padding: str "calc(var(--s-1) * 0.85) var(--s0)"
34 , justifyContent: center
44 , justifyContent: center
35 , alignItems: center
45 , alignItems: center
36 , borderRadius: var "--s-1"
46 , borderRadius: var "--s-1"
47+ , color: str colour.text
48+ , boxSizing: borderBox
49+ , fontSize: var "--s0"
50+ , fontFamily: var "--mainFont"
51+ , fontWeight: str "450"
52+ , letterSpacing: str "calc(var(--s-5)* (-0.1))"
53+ , userSelect: none
54+ , transition: str "all 0.2s ease-out" <> str "transform 50ms ease-in"
37 , """&[data-button-shape="pill"]""":
55 , """&[data-button-shape="pill"]""":
38 nest
56 nest
39− { borderRadius: var "--s1"
57+ { borderRadius: str "calc(var(--s1) * 0.85)"
40− , "& > button":
41− nest
42− { padding: str "calc(var(--s-1) * 0.8) var(--s0)"
58+ , padding: str "calc(var(--s-1) * 0.9) var(--s0)"
43− }
44 }
59 }
45 , """&[data-button-type="primary"]""":
60 , """&[data-button-type="primary"]""":
46 nest
61 nest
47 { background: gradientBackground
62 { background: gradientBackground
48 , backgroundSize: str "200% 200%"
63 , backgroundSize: str "200% 200%"
64+ , fontWeight: str "600"
65+ , letterSpacing: str "calc(var(--s-5)* (0.1))"
49 , animation: backgroundAnimation <> str " alternate ease-out 10s infinite"
66 , animation: backgroundAnimation <> str " alternate ease-out 10s infinite"
50 , boxShadow: str "0 1px 4px 0px rgba(0,0,0,0.40)"
67 , boxShadow: str "0 1px 4px 0px rgba(0,0,0,0.40)"
51 , borderColor: str "transparent"
68 , borderColor: str "transparent"
52− , "& > button":
69+ , color: str colour.highlightText
70+ , """&:focus-visible""":
53 nest
71 nest
54− { color: str colour.highlightText
72+ { borderColor: str $ colour.background0
73+ }
74+ , """&:active""":
75+ nest
76+ { boxShadow: str "inset 0 1px 6px rgba(0,0,0,0.40)"
77+ , border: str $ i "1px solid transparent"
78+ }
79+ , "&:disabled":
80+ nest
81+ { background: str colour.highlightDisabled
55 }
82 }
56 }
83 }
57− }
84+ , """&[data-button-type="dangerous"]""":
58−
85+ nest
59−backgroundAnimation ∷ StyleProperty
86+ { color: str $ colour.interfaceDangerousText
60−backgroundAnimation =
87+ , background: str $ colour.interfaceBackgroundDangerous
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"
88+ , fontWeight: str "600"
75− , letterSpacing: str "calc(var(--s-5)*0.2)"
89+ , letterSpacing: str "calc(var(--s-5) * -0.10)"
76− , padding: str "calc(var(--s-1) * 0.85) var(--s0)"
90+ }
77− , border: none
78− , userSelect: none
79− , "&:focus": nest { outline: none }
91+ , """&:focus""": nest { outline: none }
92+ , """&:focus-visible""":
93+ nest
94+ { boxShadow: str $ "0 0 0 var(--s-4) " <> colour.highlight
95+ }
96+ , """&:active""":
97+ nest
98+ { boxShadow:
99+ str
100+ $ "inset 0 1px var(--s-1) rgba(0,0,0,0.20)"
101+ , borderTop: str $ i "1px solid " colour.interfaceBackgroundShadow
102+ , borderBottom: str $ i "1px solid " colour.interfaceBackgroundShadow
103+ , transform: str "scale3d(0.95,0.95,0.95)"
104+ , transition: str "transform 50ms ease"
105+ }
106+ , "&:disabled":
107+ nest
108+ { color: str colour.interfaceTextDisabled
109+ , boxShadow: none
110+ , background: str colour.interfaceBackgroundDisabled
111+ , borderTop: str $ i "1px solid " colour.interfaceBackgroundShadow
112+ , borderBottom: str $ i "1px solid " colour.interfaceBackgroundShadow
113+ }
80 }
114 }
src/Yoga/Block/Atom/Button/Types.purs+2
@@ -4,6 +4,7 @@ import Prelude
4
4
5data ButtonType
5data ButtonType
6 = Primary
6 = Primary
7+ | Dangerous
7 | Generic
8 | Generic
8
9
9derive instance eqButtonType ∷ Eq ButtonType
10derive instance eqButtonType ∷ Eq ButtonType
@@ -12,6 +13,7 @@ renderButtonType ∷ ButtonType -> String
12renderButtonType = case _ of
13renderButtonType = case _ of
13 Primary -> "primary"
14 Primary -> "primary"
14 Generic -> "generic"
15 Generic -> "generic"
16+ Dangerous -> "dangerous"
15
17
16data ButtonShape
18data ButtonShape
17 = Rounded
19 = Rounded
src/Yoga/Block/Atom/Button/View.purs+7−11
@@ -36,14 +36,10 @@ rawComponent =
36 { "button-type": renderButtonType (props.buttonType ?|| Button.Generic)
36 { "button-type": renderButtonType (props.buttonType ?|| Button.Generic)
37 , "button-shape": renderButtonShape (props.buttonShape ?|| Button.Rounded)
37 , "button-shape": renderButtonShape (props.buttonShape ?|| Button.Rounded)
38 }
38 }
39− pure $ div
39+ pure
40− </* { css: Style.buttonContainer
41− , className: "ry-button-container"
42− , _data
43− }
44− /> [ emotionButton propsRef
40+ $ emotionButton propsRef
45− props
41+ props
46− { className: "ry-button"
42+ { className: "ry-button"
47− , css: Style.button
43+ , css: Style.button
44+ , _data
48− }
45+ }
49− ]
src/Yoga/Block/Atom/Icon/Style.purs+13−2
@@ -22,9 +22,20 @@ span props =
22 , display: inlineFlex
22 , display: inlineFlex
23 , justifyContent: center
23 , justifyContent: center
24 , alignItems: center
24 , alignItems: center
25+ , margin: _0
26+ , padding: _0
27+ , width
28+ , height
29+ , overflow: hidden
25 , "& > svg":
30 , "& > svg":
26 nest
31 nest
27− { width: (props.width <|> props.size) ?|| (str "auto")
32+ { width
28− , height: (props.height <|> props.size) ?|| (str "1.2ch")
33+ , height
34+ , margin: _0
35+ , padding: _0
29 }
36 }
30 }
37 }
38+ where
39+ width = (props.width <|> props.size) ?|| (str "auto")
40+
41+ height = (props.height <|> props.size) ?|| (str "1ch")
src/Yoga/Block/Atom/Input/Story.purs+11−13
@@ -10,7 +10,7 @@ import React.Basic (JSX, element, fragment)
10import React.Basic.DOM as R
10import React.Basic.DOM as R
11import React.Basic.Emotion as E
11import React.Basic.Emotion as E
12import React.Basic.Events (handler_)
12import React.Basic.Events (handler_)
13−import Yoga (el)
13+import Yoga (el, (</), (/>), (</>))
14import Yoga.Block as Block
14import Yoga.Block as Block
15import Yoga.Block.Atom.Input as Input
15import Yoga.Block.Atom.Input as Input
16import Yoga.Block.Atom.Input.Types as HTMLInput
16import Yoga.Block.Atom.Input.Types as HTMLInput
@@ -38,7 +38,7 @@ input = do
38 [ R.div_
38 [ R.div_
39 [ R.h1_ [ R.text "Input Examples" ]
39 [ R.h1_ [ R.text "Input Examples" ]
40 , R.h2_ [ R.text "Generic Input" ]
40 , R.h2_ [ R.text "Generic Input" ]
41− , element Input.component { value: "A Generic Input", onChange: handler_ mempty }
41+ , Input.component </> { value: "A Generic Input", onChange: handler_ mempty }
42 , R.h2_ [ R.text "Validation on text Input" ]
42 , R.h2_ [ R.text "Validation on text Input" ]
43 , element Input.component { type: HTMLInput.Text, label: nes (SProxy ∷ _ "Is undefined a function?"), value: "Yes, why not?", onChange: handler_ mempty, _aria: Object.singleton "invalid" "true" }
43 , element Input.component { type: HTMLInput.Text, label: nes (SProxy ∷ _ "Is undefined a function?"), value: "Yes, why not?", onChange: handler_ mempty, _aria: Object.singleton "invalid" "true" }
44 , element Input.component { type: HTMLInput.Text, label: nes (SProxy ∷ _ "What's the type of null?"), value: "object", onChange: handler_ mempty, _aria: Object.singleton "invalid" "false" }
44 , element Input.component { type: HTMLInput.Text, label: nes (SProxy ∷ _ "What's the type of null?"), value: "object", onChange: handler_ mempty, _aria: Object.singleton "invalid" "false" }
@@ -49,17 +49,15 @@ input = do
49 , _aria: Object.singleton "required" "true"
49 , _aria: Object.singleton "required" "true"
50 }
50 }
51 , R.h3_ [ R.text "With a label" ]
51 , R.h3_ [ R.text "With a label" ]
52− , el Block.cluster {}
52+ , Block.cluster </ {}
53− [ el R.form' {}
54− [ element Input.component { label: nes (SProxy ∷ _ "This has a label"), value: "And text", onChange: handler_ mempty }
53+ /> [ element Input.component { label: nes (SProxy ∷ _ "This has a label"), value: "And text", onChange: handler_ mempty }
55− , element Input.component { label: nes (SProxy ∷ _ "This has a label"), value: "", onChange: handler_ mempty }
54+ , element Input.component { label: nes (SProxy ∷ _ "This has a label"), value: "", onChange: handler_ mempty }
56− , element Input.component { label: nes (SProxy ∷ _ "This has a label"), placeholder: "A very long placeholder, too..." }
55+ , element Input.component { label: nes (SProxy ∷ _ "This has a label"), placeholder: "A very long placeholder, too..." }
57− , element Input.component { label: nes (SProxy ∷ _ "Pig nose"), leading: R.text "🐽🤣" }
56+ , element Input.component { label: nes (SProxy ∷ _ "Pig nose"), leading: R.text "🐽🤣" }
58− , element Input.component { label: nes (SProxy ∷ _ "Pig nose"), trailing: R.text "🤫" }
57+ , element Input.component { label: nes (SProxy ∷ _ "Pig nose"), trailing: R.text "🤫" }
59− , element Input.component { label: nes (SProxy ∷ _ "Pig nose"), leading: R.text "🌭" }
58+ , element Input.component { label: nes (SProxy ∷ _ "Pig nose"), leading: R.text "🌭" }
60− , element Input.component { label: nes (SProxy ∷ _ "Pig nose"), leading: R.text "⭐", trailing: R.text "🔮" }
59+ , element Input.component { label: nes (SProxy ∷ _ "Pig nose"), leading: R.text "⭐", trailing: R.text "🔮" }
61− ]
62− ]
60+ ]
63 , R.h2_ [ R.text "[BUG] Overflowing label" ]
61 , R.h2_ [ R.text "[BUG] Overflowing label" ]
64 , element Input.component
62 , element Input.component
65 { type: HTMLInput.Text
63 { type: HTMLInput.Text
src/Yoga/Block/Atom/Input/Style.purs+12−16
@@ -43,6 +43,7 @@ labelContainer ∷ Style
43labelContainer =
43labelContainer =
44 css
44 css
45 { position: absolute
45 { position: absolute
46+ , overflow: visible
46 , top: _0
47 , top: _0
47 , left: _0
48 , left: _0
48 , display: inlineBlock
49 , display: inlineBlock
@@ -147,13 +148,14 @@ leftIconContainer =
147 }
148 }
148 }
149 }
149
150
150−inputWrapper ∷ ∀ r. { | Props OptionalProp r } -> Style
151+inputWrapper ∷ Style
151−inputWrapper props =
152+inputWrapper =
152 css
153 css
153 { position: relative
154 { position: relative
154 , boxSizing: borderBox
155 , boxSizing: borderBox
155 , backgroundColor: str colour.inputBackground
156 , backgroundColor: str colour.inputBackground
156− , display: inlineFlex
157+ , display: flex
158+ , minWidth: str "calc(var(--s4) *2 )"
157 , "--left-icon-size": var "--s0"
159 , "--left-icon-size": var "--s0"
158 , "--right-icon-size": str "calc(var(--s0) * 1.2)"
160 , "--right-icon-size": str "calc(var(--s0) * 1.2)"
159 , "--input-border-radius": var "--s-1"
161 , "--input-border-radius": var "--s-1"
@@ -161,7 +163,7 @@ inputWrapper props =
161 , "--input-top-padding": var "--s-5"
163 , "--input-top-padding": var "--s-5"
162 , "--input-bottom-padding": var "--s-5"
164 , "--input-bottom-padding": var "--s-5"
163 , alignItems: center
165 , alignItems: center
164− , justifyContent: flexStart
166+ , justifyContent: center
165 , paddingLeft: str "calc(var(--input-side-padding) - var(--border-width))"
167 , paddingLeft: str "calc(var(--input-side-padding) - var(--border-width))"
166 , paddingRight: str "calc(var(--input-side-padding) - var(--border-width))"
168 , paddingRight: str "calc(var(--input-side-padding) - var(--border-width))"
167 , paddingTop: str "calc(var(--input-top-padding) - var(--border-width))"
169 , paddingTop: str "calc(var(--input-top-padding) - var(--border-width))"
@@ -173,26 +175,28 @@ inputWrapper props =
173 , """&[data-invalid="false"]""":
175 , """&[data-invalid="false"]""":
174 nest
176 nest
175 { borderColor: str colour.success
177 { borderColor: str colour.success
178+ , "--border-width": str "var(--s-5)"
176 }
179 }
177 , """&[data-invalid="true"]""":
180 , """&[data-invalid="true"]""":
178 nest
181 nest
179 { borderColor: str colour.invalid
182 { borderColor: str colour.invalid
183+ , "--border-width": str "var(--s-5)"
180 }
184 }
181 , "&:focus-within":
185 , "&:focus-within":
182 nest
186 nest
183 { "--border-width": str "var(--s-5)"
187 { "--border-width": str "var(--s-5)"
184 , borderColor: str colour.highlight
188 , borderColor: str colour.highlight
189+ , transition: str "border-color 0s linear 0.1s"
185 }
190 }
186 }
191 }
187
192
188−input ∷ ∀ r. { | Props OptionalProp r } -> Style
193+input ∷ Style
189−input props =
194+input =
190 css
195 css
191 { "&[type=text],&[type=search],&[type=password],&[type=number],&:not([type])":
196 { "&[type=text],&[type=search],&[type=password],&[type=number],&:not([type])":
192 nest
197 nest
193 { color: str colour.text
198 { color: str colour.text
194− , width: _100percent
195− , flex: str "1"
199+ , flex: str "2"
196 , "--padding-top": var "--s-1"
200 , "--padding-top": var "--s-1"
197 , "--padding-bottom": var "--s-1"
201 , "--padding-bottom": var "--s-1"
198 , "&[aria-labelledby]":
202 , "&[aria-labelledby]":
@@ -221,12 +225,4 @@ input props =
221 nest
225 nest
222 { outline: none
226 { outline: none
223 }
227 }
224− , "&[type=button], &[type=submit]":
225− nest
226− { background: str colour.highlight
227− , color: str "white"
228− , boxShadow: str "0 1px 4px rgba(0,0,0,0.5)"
229− , borderColour: str colour.highlight
230− , height: str "auto"
231− }
232 }
228 }
src/Yoga/Block/Atom/Input/View.purs+21−25
@@ -3,11 +3,9 @@ module Yoga.Block.Atom.Input.View where
3import Yoga.Prelude.View
3import Yoga.Prelude.View
4import Data.Array as Array
4import Data.Array as Array
5import Data.Interpolate (i)
5import Data.Interpolate (i)
6−import Data.Semigroup.Foldable (intercalateMap)
7import Data.String.NonEmpty (NonEmptyString)
6import Data.String.NonEmpty (NonEmptyString)
8import Data.String.NonEmpty as NonEmptyString
7import Data.String.NonEmpty as NonEmptyString
9import Data.Symbol (SProxy(..))
8import Data.Symbol (SProxy(..))
10−import Debug.Trace (spy)
11import Foreign.Object (Object)
9import Foreign.Object (Object)
12import Foreign.Object as Object
10import Foreign.Object as Object
13import Framer.Motion as M
11import Framer.Motion as M
@@ -21,7 +19,6 @@ import Yoga.Block.Atom.Input.Style as Style
21import Yoga.Block.Atom.Input.Types (HTMLInput)
19import Yoga.Block.Atom.Input.Types (HTMLInput)
22import Yoga.Block.Atom.Input.Types as HTMLInput
20import Yoga.Block.Atom.Input.Types as HTMLInput
23import Yoga.Block.Icon.SVG as SVGIcon
21import Yoga.Block.Icon.SVG as SVGIcon
24−import Yoga.Block.Internal.OptionalProp (asMaybe)
25
22
26type PropsF f =
23type PropsF f =
27 ( leading ∷ f JSX
24 ( leading ∷ f JSX
@@ -60,16 +57,16 @@ containerVariants =
60 { focussed:
57 { focussed:
61 css
58 css
62 { clipPath
59 { clipPath
63− , transition: { duration: 1.3 }
60+ , transition: { duration: 0.7 }
64 }
61 }
65 , blurred:
62 , blurred:
66 css
63 css
67 { clipPath:
64 { clipPath:
68− drawPathUntil (Array.length path) path
65+ drawPathUntil (Array.length path + 1) path
69 }
66 }
70 }
67 }
71 where
68 where
72− clipPath = 3 Array... (Array.length path / 2 + 1) <#> \ln -> drawPathUntil (ln * 2) path
69+ clipPath = 6 Array... (Array.length path) <#> \ln -> drawPathUntil ln path
73
70
74type Point =
71type Point =
75 { x ∷ Int, y ∷ Int }
72 { x ∷ Int, y ∷ Int }
@@ -83,28 +80,27 @@ drawPathUntil idx thePath = do
83 let firstFew = Array.take idx thePath
80 let firstFew = Array.take idx thePath
84 let lastFew = Array.drop idx thePath $> (Array.last firstFew # fromMaybe' \_ -> unsafeCrashWith "ogod")
81 let lastFew = Array.drop idx thePath $> (Array.last firstFew # fromMaybe' \_ -> unsafeCrashWith "ogod")
85 let rendered = intercalate "," $ fn <$> (firstFew <> lastFew)
82 let rendered = intercalate "," $ fn <$> (firstFew <> lastFew)
86− spy "polybius" $ i "polygon(" rendered ")"
83+ i "polygon(" rendered ")"
87
84
88path ∷ Array Point
85path ∷ Array Point
89−path = mkPath 5
86+path = mkPath 3 7
90
87
91−mkPath ∷ Int -> Array Point
88+mkPath ∷ Int -> Int -> Array Point
92−mkPath d = do
89+mkPath borderX borderY = do
93 let
90 let
94 inside =
91 inside =
95− [ p d d
92+ [ {- ⌜ -} p borderX borderY
96− , p (100 - d) d
93+ , {- ⌞ -} p borderX (100 - borderY)
97− , p (100 - d) (100 - d)
94+ , {- ⌟ -} p (100 - borderX) (100 - borderY)
98− , p d (100 - d)
95+ , {- ⌝ -} p (100 - borderX) borderY
99− , p d d
96+ , {- ⌜ -} p borderX borderY
100 ]
97 ]
101 outside =
98 outside =
102− [ p d 0
99+ [ {- ⌜ -} p 0 0
103− , p 100 0
100+ , {- ⌞ -} p 0 100
104− , p 100 100
101+ , {- ⌟ -} p 100 100
105− , p 0 100
106− , p 0 0
102+ , {- ⌝ -} p 100 0
107− , p d 0 -- one turn, starting way back
103+ , {- ⌜ -} p 0 0
108 ]
104 ]
109 inside <> outside <> (Array.reverse inside)
105 inside <> outside <> (Array.reverse inside)
110
106
@@ -216,7 +212,7 @@ rawComponent =
216 , animate: M.animate if hasFocus then containerVariantLabels.focussed else containerVariantLabels.blurred
212 , animate: M.animate if hasFocus then containerVariantLabels.focussed else containerVariantLabels.blurred
217 }
213 }
218 { className: "ry-input-wrapper"
214 { className: "ry-input-wrapper"
219− , css: Style.inputWrapper props
215+ , css: Style.inputWrapper
220 , _data:
216 , _data:
221 Object.fromHomogeneous
217 Object.fromHomogeneous
222 { "invalid": aria # Object.lookup "invalid" # fromMaybe ""
218 { "invalid": aria # Object.lookup "invalid" # fromMaybe ""
@@ -230,7 +226,7 @@ rawComponent =
230 # setOrDelete (SProxy ∷ _ "value") (maybeValue # maybeToOp)
226 # setOrDelete (SProxy ∷ _ "value") (maybeValue # maybeToOp)
231 )
227 )
232 { className: "ry-input"
228 { className: "ry-input"
233− , css: Style.input props
229+ , css: Style.input
234 , onFocus: composeHandler props.onFocus onFocus
230 , onFocus: composeHandler props.onFocus onFocus
235 , onBlur: composeHandler props.onBlur onBlur
231 , onBlur: composeHandler props.onBlur onBlur
236 , _aria:
232 , _aria:
@@ -303,14 +299,14 @@ password =
303 pure
299 pure
304 $ div
300 $ div
305 </* { className: "ry-input-wrapper"
301 </* { className: "ry-input-wrapper"
306− , css: Style.inputWrapper props
302+ , css: Style.inputWrapper
307 }
303 }
308 /> [ leading
304 /> [ leading
309 , emotionInput
305 , emotionInput
310 ref
306 ref
311 props { type = HTMLInput.toString <$> props.type # unsafeUnOptional }
307 props { type = HTMLInput.toString <$> props.type # unsafeUnOptional }
312 { className: "ry-input"
308 { className: "ry-input"
313− , css: Style.input props
309+ , css: Style.input
314 , type: if hidePassword then "password" else "text"
310 , type: if hidePassword then "password" else "text"
315 }
311 }
316 , trailing
312 , trailing
src/Yoga/Block/Atom/Popover/Story.purs+47−11
@@ -18,6 +18,7 @@ import React.Basic (JSX, ReactComponent, element, elementKeyed, fragment)
18import React.Basic.DOM (CSS, css)
18import React.Basic.DOM (CSS, css)
19import React.Basic.DOM as R
19import React.Basic.DOM as R
20import React.Basic.DOM.Events (targetValue)
20import React.Basic.DOM.Events (targetValue)
21+import React.Basic.Emotion (str)
21import React.Basic.Emotion as E
22import React.Basic.Emotion as E
22import React.Basic.Events (handler, handler_)
23import React.Basic.Events (handler, handler_)
23import React.Basic.Hooks (reactComponent)
24import React.Basic.Hooks (reactComponent)
@@ -27,11 +28,16 @@ import React.Basic.Popper.Placement.Types as Placement
27import React.Basic.Popper.Types (nullRef)
28import React.Basic.Popper.Types (nullRef)
28import Unsafe.Coerce (unsafeCoerce)
29import Unsafe.Coerce (unsafeCoerce)
29import Yoga ((/>), (</), (</>))
30import Yoga ((/>), (</), (</>))
31+import Yoga.Block as Block
32+import Yoga.Block.Atom.Icon as Icon
30import Yoga.Block.Atom.Input as Input
33import Yoga.Block.Atom.Input as Input
31import Yoga.Block.Atom.Input.Types as HTMLInput
34import Yoga.Block.Atom.Input.Types as HTMLInput
32import Yoga.Block.Atom.Popover as Popover
35import Yoga.Block.Atom.Popover as Popover
36+import Yoga.Block.Container.Style (colour)
33import Yoga.Block.Container.Style as Styles
37import Yoga.Block.Container.Style as Styles
38+import Yoga.Block.Icon.SVG as Icons
34import Yoga.Block.Layout.Box as Box
39import Yoga.Block.Layout.Box as Box
40+import Yoga.Block.Layout.Cluster as Cluster
35import Yoga.Block.Layout.Stack as Stack
41import Yoga.Block.Layout.Stack as Stack
36
42
37default ∷
43default ∷
@@ -67,20 +73,47 @@ popover = do
67 reactComponent "PopoverExample" \props -> React.do
73 reactComponent "PopoverExample" \props -> React.do
68 referenceElement /\ setReferenceElement <- React.useState' nullRef
74 referenceElement /\ setReferenceElement <- React.useState' nullRef
69 text /\ setText <- React.useState' ""
75 text /\ setText <- React.useState' ""
70− visible /\ setVisible <- React.useState' false
76+ visible /\ setVisible <- React.useState' true
77+ selectedAuthors /\ modSelectedAuthors <-
78+ React.useState [ "William Shakespeare", "Agatha Christie" ]
71 let
79 let
72 matchingAuthors =
80 matchingAuthors =
73 authors
81 authors
82+ # (_ Array.\\ selectedAuthors)
74 # Array.filter
83 # Array.filter
75 ( \a ->
84 ( \a ->
76 String.contains (String.Pattern (String.toLower text))
85 String.contains (String.Pattern (String.toLower text))
77 (String.toLower a)
86 (String.toLower a)
78 )
87 )
79 let
88 let
80− inputWrapper =
81− R.div'
82− </ { ref: unsafeCoerce (mkEffectFn1 setReferenceElement)
89+ inputWrapper = R.div' </ { ref: unsafeCoerce (mkEffectFn1 setReferenceElement) }
83− }
90+ pill t =
91+ Block.box </ { padding: str "var(--s-3)" }
92+ /> [ Block.cluster
93+ </ { style:
94+ css
95+ { background: colour.highlight
96+ , fontSize: "var(--s-1)"
97+ , space: "var(--s-5)"
98+ , borderRadius: "var(--s-2)"
99+ }
100+ }
101+ /> [ R.text t
102+ , Block.centre
103+ </ { style:
104+ css
105+ { background: "hotpink"
106+ }
107+ , andText: true
108+ }
109+ /> [ Icon.component
110+ </> { icon: Icons.cross, size: str "var(--s-1)"
111+ }
112+ ]
113+ ]
114+ ]
115+ pills = pill <$> selectedAuthors
116+ leading = Block.cluster </ {} /> pills
84 input =
117 input =
85 Input.component
118 Input.component
86 </> { id: "author"
119 </> { id: "author"
@@ -92,19 +125,20 @@ popover = do
92 , onChange: handler targetValue $ traverse_ setText
125 , onChange: handler targetValue $ traverse_ setText
93 , onBlur: handler_ (setVisible false)
126 , onBlur: handler_ (setVisible false)
94 , onFocus: handler_ (setVisible true)
127 , onFocus: handler_ (setVisible true)
95− , trailing: R.text "▼"
128+ , leading
96 , autoComplete: "off"
129 , autoComplete: "off"
97 }
130 }
98 pop children =
131 pop children =
99 elementKeyed motionPopover
132 elementKeyed motionPopover
100 $ Motion.motion
133 $ Motion.motion
101 { initial:
134 { initial:
102− css { clipPath: "polygon(0% 0%, 100% 0%, 100% 0%, 0% 0%)" }
135+ css { maxHeight: 30, opacity: 0.0 }
103 , exit:
136 , exit:
104− css { clipPath: "polygon(0% 0%, 100% 0%, 100% 0%, 0% 0%)" }
137+ css { maxHeight: 30, opacity: 0.0 }
105 , animate:
138 , animate:
106 css
139 css
107− { clipPath: "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)"
140+ { maxHeight: 400
141+ , opacity: 1
108 }
142 }
109 , transition:
143 , transition:
110 Motion.transition
144 Motion.transition
@@ -120,9 +154,10 @@ popover = do
120 , style:
154 , style:
121 css
155 css
122 { boxShadow: "0px 9px 12px rgba(40,40,40,0.5)"
156 { boxShadow: "0px 9px 12px rgba(40,40,40,0.5)"
123− , background: "rgba(50,50,70, 0.7)"
157+ , background: colour.interfaceBackground
124 , borderRadius: "9px"
158 , borderRadius: "9px"
125− , borderTop: "solid 1px rgba(80,80,100,1.0)"
159+ , borderTop: "solid 1px " <> colour.interfaceBackgroundHighlight
160+ , borderBottom: "solid 1px " <> colour.interfaceBackgroundShadow
126 , overflowY: "scroll"
161 , overflowY: "scroll"
127 , maxHeight: "400px"
162 , maxHeight: "400px"
128 , width: "300px"
163 , width: "300px"
@@ -149,6 +184,7 @@ popover = do
149 </ { key: a
184 </ { key: a
150 -- , layout: Motion.layout true
185 -- , layout: Motion.layout true
151 -- , variants: Motion.variants itemVariants
186 -- , variants: Motion.variants itemVariants
187+ , onClick: handler_ (modSelectedAuthors (_ `Array.snoc` a))
152 }
188 }
153 /> [ R.text a ]
189 /> [ R.text a ]
154 pure
190 pure
src/Yoga/Block/Container/Story.purs+16−20
@@ -22,29 +22,25 @@ container =
22 [ R.text "Content"
22 [ R.text "Content"
23 , el Stack.component {}
23 , el Stack.component {}
24 [ el Cluster.component {}
24 [ el Cluster.component {}
25− [ R.div_
26− [ R.input { value: "Text" }
25+ [ R.input { value: "Text" }
27− , R.input { type: "number", value: "0" }
26+ , R.input { type: "number", value: "0" }
28− , styledLeaf R.input'
27+ , styledLeaf R.input'
29− { className: "styledinput"
28+ { className: "styledinput"
30− , css: inputFocus
29+ , css: inputFocus
31− , value: "focus"
30+ , value: "focus"
32− }
31+ }
33− , R.input
32+ , R.input
34− { className: "styledinput"
33+ { className: "styledinput"
35− , value: "focus"
34+ , value: "focus"
36− , disabled: true
35+ , disabled: true
37− }
36+ }
38− ]
39 ]
37 ]
40 , R.input { type: "file" }
38 , R.input { type: "file" }
41 , el Cluster.component {}
39 , el Cluster.component {}
42− [ R.div_
43− [ R.input { type: "checkbox" }
40+ [ R.input { type: "checkbox" }
44− , R.input { type: "checkbox", checked: true }
41+ , R.input { type: "checkbox", checked: true }
45− , R.input { type: "radio" }
42+ , R.input { type: "radio" }
46− , R.input { type: "radio", checked: true }
43+ , R.input { type: "radio", checked: true }
47− ]
48 ]
44 ]
49 , R.input { type: "range" }
45 , R.input { type: "range" }
50 ]
46 ]
src/Yoga/Block/Container/Style.purs+29−5
@@ -131,9 +131,13 @@ defaultColours =
131 , invalid
131 , invalid
132 , invalidText
132 , invalidText
133 , required
133 , required
134− , interfaceBackground: lightBg
134+ , interfaceBackground
135+ , interfaceBackgroundDangerous
136+ , interfaceDangerousText
137+ , interfaceBackgroundDisabled: darken 0.03 lightBg
135− , interfaceTextDisabled: darken 0.33 lightBg
138+ , interfaceTextDisabled: darken 0.30 lightBg
136 , interfaceBackgroundHighlight: lighten 0.05 lightBg
139 , interfaceBackgroundHighlight: lighten 0.05 lightBg
140+ , highlightDisabled: (desaturate 0.80 >>> lighten 0.28) highlight
137 , interfaceBackgroundShadow: darken 0.04 lightBg
141 , interfaceBackgroundShadow: darken 0.04 lightBg
138 , inputBackground: lightBg
142 , inputBackground: lightBg
139 , inputBorder: darken 0.1 lightBg
143 , inputBorder: darken 0.1 lightBg
@@ -167,17 +171,21 @@ defaultColours =
167 , textInverted: darkBg
171 , textInverted: darkBg
168 , backgroundInverted: lightBg
172 , backgroundInverted: lightBg
169 , interfaceBackground: interfaceBackgroundDark
173 , interfaceBackground: interfaceBackgroundDark
174+ , interfaceBackgroundDangerous: interfaceBackgroundDangerousDark
175+ , interfaceDangerousText: interfaceDangerousTextDark
176+ , interfaceBackgroundDisabled: darken 0.3 interfaceBackgroundDark
170− , interfaceTextDisabled: lighten 0.8 darkBg
177+ , interfaceTextDisabled: (desaturate 0.3 >>> lighten 0.25) interfaceBackgroundDark
171 , interfaceBackgroundHighlight: lighten 0.1 interfaceBackgroundDark
178 , interfaceBackgroundHighlight: lighten 0.1 interfaceBackgroundDark
172 , interfaceBackgroundShadow: darken 0.1 interfaceBackgroundDark
179 , interfaceBackgroundShadow: darken 0.1 interfaceBackgroundDark
173 , inputBackground: darkBg
180 , inputBackground: darkBg
174 , inputBorder: lighten 0.17 darkBg
181 , inputBorder: lighten 0.17 darkBg
175− , success
182+ , success: successDark
176 , successText
183 , successText
177 , required
184 , required
178 , invalid
185 , invalid
179 , invalidText
186 , invalidText
180 , highlight: highlightDark
187 , highlight: highlightDark
188+ , highlightDisabled: (desaturate 0.76 >>> darken 0.32) highlightDark
181 , highlightLighter: withAlpha 0.2 (Color.lighten 0.5 highlightDark)
189 , highlightLighter: withAlpha 0.2 (Color.lighten 0.5 highlightDark)
182 , highlightDarker: withAlpha 0.4 (Color.darken 0.5 highlightDark)
190 , highlightDarker: withAlpha 0.4 (Color.darken 0.5 highlightDark)
183 , highlightRotatedForwards: highlightDark # rotateHue 30.0
191 , highlightRotatedForwards: highlightDark # rotateHue 30.0
@@ -194,9 +202,21 @@ defaultColours =
194
202
195 interfaceBackgroundDark = Color.hsl 240.0 0.10 0.33
203 interfaceBackgroundDark = Color.hsl 240.0 0.10 0.33
196
204
205+ interfaceBackground = lightBg
206+
207+ interfaceBackgroundDangerous = interfaceBackground
208+
209+ interfaceDangerousText = invalid
210+
211+ interfaceBackgroundDangerousDark = Color.hsl 340.0 0.55 0.30
212+
213+ interfaceDangerousTextDark = Color.hsl 340.0 1.0 0.90
214+
197 highlightText = Color.rgb 0xFF 0xFF 0xFF
215 highlightText = Color.rgb 0xFF 0xFF 0xFF
198
216
199− success = Color.rgb 20 200 60
217+ success = Color.rgb 10 150 25
218+
219+ successDark = Color.rgb 20 200 60
200
220
201 successText = Color.rgb 250 250 250
221 successText = Color.rgb 250 250 250
202
222
@@ -232,6 +252,9 @@ type FlatTheme a =
232 , background100 ∷ a
252 , background100 ∷ a
233 , backgroundInverted ∷ a
253 , backgroundInverted ∷ a
234 , interfaceBackground ∷ a
254 , interfaceBackground ∷ a
255+ , interfaceBackgroundDangerous ∷ a
256+ , interfaceDangerousText ∷ a
257+ , interfaceBackgroundDisabled ∷ a
235 , interfaceTextDisabled ∷ a
258 , interfaceTextDisabled ∷ a
236 , interfaceBackgroundHighlight ∷ a
259 , interfaceBackgroundHighlight ∷ a
237 , interfaceBackgroundShadow ∷ a
260 , interfaceBackgroundShadow ∷ a
@@ -242,6 +265,7 @@ type FlatTheme a =
242 , highlightRotatedForwards ∷ a
265 , highlightRotatedForwards ∷ a
243 , highlightDarker ∷ a
266 , highlightDarker ∷ a
244 , highlightLighter ∷ a
267 , highlightLighter ∷ a
268+ , highlightDisabled ∷ a
245 , highlightText ∷ a
269 , highlightText ∷ a
246 , success ∷ a
270 , success ∷ a
247 , successText ∷ a
271 , successText ∷ a
src/Yoga/Block/Icon/SVG/Cross.pursnew file+21
@@ -0,0 +1,21 @@
1+module Yoga.Block.Icon.SVG.Cross where
2+
3+import React.Basic (JSX)
4+import React.Basic.DOM.SVG as SVG
5+
6+cross ∷ JSX
7+cross =
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 2.339c26.305 0 47.661 21.356 47.661 47.661S76.305 97.661 50 97.661 2.339 76.305 2.339 50 23.695 2.339 50 2.339zm0 38.773L31.838 22.949l-8.889 8.889L41.112 50 22.949 68.162l8.889 8.889L50 58.888l18.162 18.163 8.889-8.889L58.888 50l18.163-18.162-8.889-8.889L50 41.112z"
18+ , fill: "var(--stroke-colour)"
19+ }
20+ ]
21+ }
src/Yoga/Block/Icon/SVG/Icon.purs+2
@@ -7,6 +7,7 @@ module Yoga.Block.Icon.SVG
7 , module Yoga.Block.Icon.SVG.Key
7 , module Yoga.Block.Icon.SVG.Key
8 , module Yoga.Block.Icon.SVG.SimpleKey
8 , module Yoga.Block.Icon.SVG.SimpleKey
9 , module Yoga.Block.Icon.SVG.QuestionMark
9 , module Yoga.Block.Icon.SVG.QuestionMark
10+ , module Yoga.Block.Icon.SVG.Cross
10 ) where
11 ) where
11
12
12import Yoga.Block.Icon.SVG.On (on)
13import Yoga.Block.Icon.SVG.On (on)
@@ -17,3 +18,4 @@ import Yoga.Block.Icon.SVG.EyeOpen (eyeOpen)
17import Yoga.Block.Icon.SVG.Key (key)
18import Yoga.Block.Icon.SVG.Key (key)
18import Yoga.Block.Icon.SVG.SimpleKey (simpleKey)
19import Yoga.Block.Icon.SVG.SimpleKey (simpleKey)
19import Yoga.Block.Icon.SVG.QuestionMark (questionMark)
20import Yoga.Block.Icon.SVG.QuestionMark (questionMark)
21+import Yoga.Block.Icon.SVG.Cross (cross)
src/Yoga/Block/Icon/SVG/Warn.pursnew file+25
@@ -0,0 +1,25 @@
1+module Yoga.Block.Icon.SVG.Warn where
2+
3+import React.Basic (JSX)
4+import React.Basic.DOM as R
5+import React.Basic.DOM.SVG as SVG
6+
7+warn :: JSX
8+warn = 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: "M41.478 15.313a9.704 9.704 0 0117.044 0L91.27 75.397a9.706 9.706 0 01-8.522 14.351H17.252A9.705 9.705 0 018.73 75.397l32.748-60.084zM50 77.357c2.909 0 5.432-2.432 5.455-5.455-.023-2.977-2.546-5.409-5.455-5.409-3 0-5.477 2.432-5.454 5.409C44.523 74.925 47 77.357 50 77.357zm5.046-44.137H44.932l.909 29.591h8.318l.887-29.591z"
22+ , fill: "#333"
23+ }
24+ ]
25+ }
src/Yoga/Block/Icon/SVG/cross.svgnew file+1
@@ -0,0 +1 @@
1+<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2"><path fill="none" d="M0 0h100v100H0z"/><path d="M50 2.339c26.305 0 47.661 21.356 47.661 47.661S76.305 97.661 50 97.661 2.339 76.305 2.339 50 23.695 2.339 50 2.339zm0 38.773L31.838 22.949l-8.889 8.889L41.112 50 22.949 68.162l8.889 8.889L50 58.888l18.162 18.163 8.889-8.889L58.888 50l18.163-18.162-8.889-8.889L50 41.112z" fill="#333"/></svg>
src/Yoga/Block/Icon/SVG/warn.svgnew file+1
@@ -0,0 +1 @@
1+<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2"><path fill="none" d="M0 0h100v100H0z"/><path d="M41.478 15.313a9.704 9.704 0 0117.044 0L91.27 75.397a9.706 9.706 0 01-8.522 14.351H17.252A9.705 9.705 0 018.73 75.397l32.748-60.084zM50 77.357c2.909 0 5.432-2.432 5.455-5.455-.023-2.977-2.546-5.409-5.455-5.409-3 0-5.477 2.432-5.454 5.409C44.523 74.925 47 77.357 50 77.357zm5.046-44.137H44.932l.909 29.591h8.318l.887-29.591z" fill="#333"/></svg>
src/Yoga/Block/Layout/Cluster/Story.purs+9−13
@@ -36,15 +36,13 @@ cluster =
36 , el Cluster.component
36 , el Cluster.component
37 { style: css { backgroundColor: "hotpink" }
37 { style: css { backgroundColor: "hotpink" }
38 }
38 }
39− [ R.div_
40− $ [ power
39+ [ power
41− ( R.div
40+ ( R.div
42− { children: [ R.text "Content" ]
41+ { children: [ R.text "Content" ]
43− , style: css { backgroundColor: "teal" }
42+ , style: css { backgroundColor: "teal" }
44− }
43+ }
45− )
44+ )
46− 30
45+ 30
47− ]
48 ]
46 ]
49 , R.h2_ [ R.text "Zero Space" ]
47 , R.h2_ [ R.text "Zero Space" ]
50 , el Cluster.component
48 , el Cluster.component
@@ -52,10 +50,8 @@ cluster =
52 , space: "0"
50 , space: "0"
53 , justify: "flex-end"
51 , justify: "flex-end"
54 }
52 }
55− [ R.div_
56− [ R.div { children: [ R.text "Child 1" ], style: css { backgroundColor: "teal" } }
53+ [ R.div { children: [ R.text "Child 1" ], style: css { backgroundColor: "teal" } }
57− , R.div { children: [ R.text "Child 2" ], style: css { backgroundColor: "rebeccapurple" } }
54+ , R.div { children: [ R.text "Child 2" ], style: css { backgroundColor: "rebeccapurple" } }
58− ]
59 ]
55 ]
60 ]
56 ]
61 ]
57 ]
src/Yoga/Block/Layout/Cluster/View.purs+2
@@ -1,6 +1,7 @@
1module Yoga.Block.Layout.Cluster.View (component, Props, PropsF) where
1module Yoga.Block.Layout.Cluster.View (component, Props, PropsF) where
2
2
3import Yoga.Prelude.View
3import Yoga.Prelude.View
4+import React.Basic.DOM as R
4import Yoga.Block.Layout.Cluster.Style as Style
5import Yoga.Block.Layout.Cluster.Style as Style
5
6
6type PropsF f =
7type PropsF f =
@@ -25,4 +26,5 @@ rawComponent =
25 $ emotionDiv ref props
26 $ emotionDiv ref props
26 { className: "ry-cluster " <>? props.className
27 { className: "ry-cluster " <>? props.className
27 , css: Style.cluster props
28 , css: Style.cluster props
29+ , children: [ R.div' </ {} /> props.children ]
28 }
30 }
src/Yoga/Block/Layout/Switcher/Spec.purs+1−1
@@ -7,7 +7,7 @@ import React.Basic.DOM as R
7spec ∷ Spec Unit
7spec ∷ Spec Unit
8spec =
8spec =
9 after_ cleanup do
9 after_ cleanup do
10− describe "The cluster" do
10+ describe "The switcher" do
11 it "renders without errors" do
11 it "renders without errors" do
12 void
12 void
13 $ renderComponent Switcher.component {}
13 $ renderComponent Switcher.component {}