git.iko.soy/rowtype-yoga/psfp
on master help sign in
Some animations
982389dMark Eibes
components/src/React/Basic/Helpers.purs+6
@@ -1,13 +1,16 @@
1module React.Basic.Helpers where
1module React.Basic.Helpers where
2
2
3+import Data.Maybe (Maybe, fromMaybe, fromMaybe')
3import Data.Symbol (SProxy(..))
4import Data.Symbol (SProxy(..))
4import Justifill.Fillable (class Fillable, class FillableFields, fill)
5import Justifill.Fillable (class Fillable, class FillableFields, fill)
5import Justifill.Justifiable (class Justifiable, justify)
6import Justifill.Justifiable (class Justifiable, justify)
7+import Literals.Undefined (undefined)
6import Prim.Row (class Lacks, class Nub)
8import Prim.Row (class Lacks, class Nub)
7import Prim.RowList (class RowToList)
9import Prim.RowList (class RowToList)
8import React.Basic (JSX)
10import React.Basic (JSX)
9import React.Basic.Hooks (ReactComponent, element)
11import React.Basic.Hooks (ReactComponent, element)
10import Record (disjointUnion, insert)
12import Record (disjointUnion, insert)
13+import Unsafe.Coerce (unsafeCoerce)
11
14
12element_ ∷
15element_ ∷
13 ∀ to missing missingRL thru thruRL from fromRL.
16 ∀ to missing missingRL thru thruRL from fromRL.
@@ -62,3 +65,6 @@ jsx x partialProps kids = element x propsWithKids
62 partialProps
65 partialProps
63 )
66 )
64 )
67 )
68+
69+orUndefined ∷ ∀ a. Maybe a -> a
70+orUndefined = fromMaybe' \_ -> unsafeCoerce undefined
components/src/React/Basic/Hooks/Spring.purs+31−7
@@ -8,7 +8,8 @@ import Effect (Effect)
8import Effect.Uncurried (EffectFn1, EffectFn3, runEffectFn1, runEffectFn3)
8import Effect.Uncurried (EffectFn1, EffectFn3, runEffectFn1, runEffectFn3)
9import Prim.Row (class Union)
9import Prim.Row (class Union)
10import React.Basic (JSX, ReactComponent, element)
10import React.Basic (JSX, ReactComponent, element)
11−import React.Basic.DOM (CSS, Props_div)
11+import React.Basic.DOM (CSS, Props_div, Props_span)
12+import React.Basic.DOM.SVG (Props_svg, Props_path)
12import React.Basic.Hooks (Hook, unsafeHook)
13import React.Basic.Hooks (Hook, unsafeHook)
13import React.Basic.Hooks as React
14import React.Basic.Hooks as React
14
15
@@ -23,9 +24,9 @@ type SetSpringImpl r
23type SetSpring r
24type SetSpring r
24 = { | r } -> Effect Unit
25 = { | r } -> Effect Unit
25
26
26−foreign import useSpringImpl ∷ ∀ r props. (props -> { | r }) -> Effect { style ∷ { | r }, set ∷ SetSpringImpl r, stop ∷ StopSpring }
27+foreign import useSpringImpl ∷ ∀ r s props. (props -> { | r }) -> Effect { style ∷ { | r }, set ∷ SetSpringImpl s, stop ∷ StopSpring }
27
28
28−useSpring ∷ ∀ r props. (props -> { | r }) -> Hook (UseSpring { | r }) { style ∷ { | r }, set ∷ SetSpring r, stop ∷ StopSpring }
29+useSpring ∷ ∀ r s props. (props -> { | r }) -> Hook (UseSpring { | r }) { style ∷ { | r }, set ∷ SetSpring s, stop ∷ StopSpring }
29useSpring f = React.do
30useSpring f = React.do
30 res <- unsafeHook (useSpringImpl f)
31 res <- unsafeHook (useSpringImpl f)
31 pure $ res { set = runEffectFn1 res.set }
32 pure $ res { set = runEffectFn1 res.set }
@@ -41,10 +42,12 @@ useTransition ∷
41 CSS ->
42 CSS ->
42 Hook (UseTransition item) (Array { item ∷ Maybe item, key ∷ Maybe String, props ∷ CSS })
43 Hook (UseTransition item) (Array { item ∷ Maybe item, key ∷ Maybe String, props ∷ CSS })
43useTransition items toKey transition =
44useTransition items toKey transition =
44− unsafeHook
45− ( runEffectFn3 useTransitionImpl items (toNullable toKey) transition
45+ unsafeHook $ runEffectFn3 useTransitionImpl items (toNullable toKey) transition
46+ <#> map \x@{ item, key } ->
47+ x
46− <#> map \x -> x { item = x.item # Nullable.toMaybe, key = x.key # Nullable.toMaybe }
48+ { item = item # Nullable.toMaybe
47− )
49+ , key = key # Nullable.toMaybe
50+ }
48
51
49foreign import animatedImpl ∷ ∀ attrs. String -> ReactComponent { | attrs }
52foreign import animatedImpl ∷ ∀ attrs. String -> ReactComponent { | attrs }
50
53
@@ -65,3 +68,24 @@ animatedDiv ∷
65 { style ∷ CSS | attrs } ->
68 { style ∷ CSS | attrs } ->
66 JSX
69 JSX
67animatedDiv = element (animatedImpl "div")
70animatedDiv = element (animatedImpl "div")
71+
72+animatedSpan ∷
73+ ∀ attrs attrs_.
74+ Union attrs attrs_ Props_span =>
75+ { style ∷ CSS | attrs } ->
76+ JSX
77+animatedSpan = element (animatedImpl "span")
78+
79+animatedSvg ∷
80+ ∀ attrs attrs_.
81+ Union attrs attrs_ Props_svg =>
82+ { style ∷ CSS | attrs } ->
83+ JSX
84+animatedSvg = element (animatedImpl "svg")
85+
86+animatedPath ∷
87+ ∀ attrs attrs_.
88+ Union attrs attrs_ Props_path =>
89+ { style ∷ CSS | attrs } ->
90+ JSX
91+animatedPath = element (animatedImpl "path")
components/src/React/Basic/Hooks/Spring/Stories.purs+13−4
@@ -16,7 +16,9 @@ import React.Basic.Hooks.Spring (animatedDiv, useSpring, useTransition)
16import React.Basic.Hooks.UseGesture (useDrag, withDragProps)
16import React.Basic.Hooks.UseGesture (useDrag, withDragProps)
17import Storybook.React (Storybook, add, storiesOf)
17import Storybook.React (Storybook, add, storiesOf)
18import Yoga.Box.Component as Box
18import Yoga.Box.Component as Box
19+import Yoga.Box.Component as Center
19import Yoga.Button.Component (mkButton)
20import Yoga.Button.Component (mkButton)
21+import Yoga.Card.Component (mkCard)
20import Yoga.Spec.Helpers (withDarkTheme)
22import Yoga.Spec.Helpers (withDarkTheme)
21import Yoga.Theme.Styles (makeStylesJSS)
23import Yoga.Theme.Styles (makeStylesJSS)
22import Yoga.Theme.Types (CSSTheme)
24import Yoga.Theme.Types (CSSTheme)
@@ -92,10 +94,15 @@ mkTransition = do
92
94
93mkDragAnimated ∷ Effect (ReactComponent {})
95mkDragAnimated ∷ Effect (ReactComponent {})
94mkDragAnimated = do
96mkDragAnimated = do
95− box <- Box.makeComponent
97+ card <- mkCard
98+ useStyles <-
99+ makeStylesJSS
100+ $ jssClasses \t ->
96− useStyles <- makeStylesJSS $ jssClasses \t -> { div: { width: "200px", height: "200px", background: "hotpink" } }
101+ { card: { width: "200px", height: "200px" }
102+ , div: { overflow: "visible" }
103+ }
97 component "Draggable Example" \{} -> React.do
104 component "Draggable Example" \{} -> React.do
98− { style, set } <- useSpring $ const { x: 0.0, y: 0.0 }
105+ { style, set } <- useSpring $ const { x: 0.0, y: 0.0, config: { mass: 1, tension: 210, friction: 20 } }
99 classes <- useStyles {}
106 classes <- useStyles {}
100 mkDragProps <-
107 mkDragProps <-
101 useDrag \{ down, movement: mx /\ my } ->
108 useDrag \{ down, movement: mx /\ my } ->
@@ -105,7 +112,9 @@ mkDragAnimated = do
105 [ animatedDiv
112 [ animatedDiv
106 ( { style: css style
113 ( { style: css style
107 , className: classes.div
114 , className: classes.div
115+ , children:
108− , children: [ jsx box {} [ R.text "Drag me somewhere" ] ]
116+ [ jsx card { className: classes.card } [ R.text "Drag me somewhere" ]
117+ ]
109 }
118 }
110 `withDragProps`
119 `withDragProps`
111 mkDragProps
120 mkDragProps
components/src/Yoga/Button/Component.purs+15−8
@@ -1,13 +1,16 @@
1module Yoga.Button.Component where
1module Yoga.Button.Component where
2
2
3import Prelude
3import Prelude
4−import CSS (Color, cssStringRGBA, desaturate)
4+import CSS (Color, angular, black, cssStringRGBA, deg, desaturate, pct, saturate)
5+import CSS as C
5import CSS as Color
6import CSS as Color
7+import Color.Scheme.Clrs (blue)
6import Data.Array.NonEmpty as NEA
8import Data.Array.NonEmpty as NEA
7import Data.Foldable (intercalate)
9import Data.Foldable (intercalate)
8import Data.Interpolate (i)
10import Data.Interpolate (i)
9import Data.Maybe (Maybe)
11import Data.Maybe (Maybe)
10import Data.Monoid (guard)
12import Data.Monoid (guard)
13+import Data.Tuple.Nested ((/\))
11import Effect (Effect)
14import Effect (Effect)
12import JSS (JSSClasses, JSSElem, jssClasses)
15import JSS (JSSClasses, JSSElem, jssClasses)
13import React.Basic (JSX)
16import React.Basic (JSX)
@@ -43,10 +46,6 @@ highlightStyles =
43 [ withAlpha (if theme.isLight then 0.15 else 0.07) theme.backgroundColourDarker
46 [ withAlpha (if theme.isLight then 0.15 else 0.07) theme.backgroundColourDarker
44 , withAlpha (if theme.isLight then 0.15 else 0.07) theme.backgroundColourLighter
47 , withAlpha (if theme.isLight then 0.15 else 0.07) theme.backgroundColourLighter
45 ]
48 ]
46− , "&:active":
47− { background:
48− linearGradient "145deg" [ theme.highlightColourDark, theme.highlightColour ]
49− }
50 , color: theme.backgroundColour
49 , color: theme.backgroundColour
51 }
50 }
52 }
51 }
@@ -136,10 +135,18 @@ styles =
136 String
135 String
137 , background:
136 , background:
138 linearGradient
137 linearGradient
139− "145deg"
138+ "135deg"
140− [ theme.backgroundColourDarker
139+ [ withAlpha (if theme.isLight then 0.15 else 0.07) theme.backgroundColourLighter
141− , theme.backgroundColourDarkest
140+ , withAlpha (if theme.isLight then 0.15 else 0.07) theme.backgroundColourDarker
142 ]
141 ]
142+ <> ","
143+ <> linearGradient
144+ "180deg"
145+ [ Color.rgba 0 0 10 0.17
146+ , Color.rgba 0 0 10 0.03
147+ , Color.rgba 0 0 10 0.067
148+ ]
149+ , color: theme.backgroundColour
143 }
150 }
144 , "&:disabled":
151 , "&:disabled":
145 { boxShadow: "0 0 0 black"
152 { boxShadow: "0 0 0 black"
components/src/Yoga/Card/Component.purs+42−18
@@ -1,17 +1,19 @@
1module Yoga.Card.Component where
1module Yoga.Card.Component where
2
2
3import Prelude
3import Prelude
4+import CSS (CSS, angular, deg, desaturate, linearGradient, pct)
4−import Color (cssStringRGBA, toHexString)
5+import Color (cssStringRGBA)
5import Color as Color
6import Color as Color
6import Data.Interpolate (i)
7import Data.Interpolate (i)
7import Data.Maybe (Maybe)
8import Data.Maybe (Maybe)
9+import Data.Tuple.Nested ((/\))
8import Effect (Effect)
10import Effect (Effect)
9import JSS (JSSClasses, JSSElem, jssClasses)
11import JSS (JSSClasses, JSSElem, jssClasses)
10import React.Basic (JSX)
12import React.Basic (JSX)
11−import React.Basic.DOM as R
12import React.Basic.Helpers (jsx)
13import React.Basic.Helpers (jsx)
13import React.Basic.Hooks (ReactComponent, component)
14import React.Basic.Hooks (ReactComponent, component)
14import React.Basic.Hooks as React
15import React.Basic.Hooks as React
16+import Unsafe.Coerce (unsafeCoerce)
15import Yoga.Box.Component as Box
17import Yoga.Box.Component as Box
16import Yoga.Helpers ((?||))
18import Yoga.Helpers ((?||))
17import Yoga.Theme.Styles (makeStylesJSS)
19import Yoga.Theme.Styles (makeStylesJSS)
@@ -27,25 +29,46 @@ styles =
27 lighten x = Color.lighten if theme.isLight then (0.5 * x) else 1.7 * x
29 lighten x = Color.lighten if theme.isLight then (0.5 * x) else 1.7 * x
28
30
29 darken x = Color.darken if theme.isLight then 1.0 * x else (1.2 * x)
31 darken x = Color.darken if theme.isLight then 1.0 * x else (1.2 * x)
32+
33+ normal =
34+ if theme.isLight then
35+ darken 0.03 $ theme.backgroundColour
36+ else
37+ lighten 0.015 theme.backgroundColour
38+
39+ dark =
40+ if theme.isLight then
41+ darken 0.03 normal
42+ else
43+ darken 0.05 normal
44+
45+ light =
46+ if theme.isLight then
47+ lighten 0.10 normal
48+ else
49+ lighten 0.05 normal
30 in
50 in
31 { card:
51 { card:
32 { borderRadius: "var(--s1)"
52 { borderRadius: "var(--s1)"
33 , boxShadow:
53 , boxShadow:
34− ( i -- bottom right
54+ i -- bottom right
35− "var(--s1) var(--s1) var(--s2) "
55+ "var(--s-2) var(--s-2) var(--s-1) "
36− (cssStringRGBA $ darken 0.04 theme.backgroundColour)
56+ (cssStringRGBA dark)
37− --bottom left
57+ --bottom left
38− ", calc(-1 * var(--s1)) var(--s1) var(--s2) "
58+ ", calc(-1 * var(--s-2)) var(--s-2) var(--s-1) "
39− (cssStringRGBA $ darken 0.01 theme.backgroundColour)
59+ (cssStringRGBA normal)
40− --top left
60+ --top left
41− ", calc(-1 * var(--s1)) calc(-1 * var(--s1)) var(--s2) "
61+ ", calc(-1 * var(--s-2)) calc(-1 * var(--s-2)) var(--s-1) "
42− (cssStringRGBA $ lighten 0.05 theme.backgroundColour)
62+ (cssStringRGBA light)
43− --top right
63+ --top right
44− ", var(--s1) calc(-1 * var(--s1)) var(--s2) "
64+ ", var(--s-2) calc(-1 * var(--s-2)) var(--s-1) "
45− (cssStringRGBA $ darken 0.02 theme.backgroundColour)
65+ (cssStringRGBA normal) ∷
46− ) ∷
47 String
66 String
48− -- background: (i "linear-gradient(145deg," (toHexString theme.backgroundColourDarker) ", " (toHexString theme.backgroundColourLighter) ")") ∷ String
67+ , background:
68+ linearGradient (angular (-45.0 # deg))
69+ [ dark /\ (0.0 # pct)
70+ , light /\ (100.0 # pct)
71+ ]
49 }
72 }
50 }
73 }
51
74
@@ -59,9 +82,10 @@ mkCard ∷
59mkCard = do
82mkCard = do
60 useStyles <- makeStylesJSS styles
83 useStyles <- makeStylesJSS styles
61 box <- Box.makeComponent
84 box <- Box.makeComponent
62− component "Card" \{ kids, className } -> React.do
85+ component "Card" \props@{ kids, className } -> React.do
63 classes <- useStyles {}
86 classes <- useStyles {}
64 pure
87 pure
65 $ jsx box
88 $ jsx box
66− { className: classes.card <> " " <> (className ?|| "") }
89+ { className: classes.card <> " " <> (className ?|| "")
90+ }
67 kids
91 kids
components/src/Yoga/Imposter/Component.purs+6−2
@@ -5,10 +5,12 @@ import Data.Array (foldMap)
5import Data.Maybe (Maybe)
5import Data.Maybe (Maybe)
6import Effect (Effect)
6import Effect (Effect)
7import React.Basic (JSX)
7import React.Basic (JSX)
8−import React.Basic.DOM as R
8+import React.Basic.DOM (CSS)
9import React.Basic.Events (EventHandler, handler_)
9import React.Basic.Events (EventHandler, handler_)
10+import React.Basic.Helpers (orUndefined)
10import React.Basic.Hooks (ReactComponent, component)
11import React.Basic.Hooks (ReactComponent, component)
11import React.Basic.Hooks as React
12import React.Basic.Hooks as React
13+import React.Basic.Hooks.Spring (animatedDiv)
12import Record.Extra (pick)
14import Record.Extra (pick)
13import Yoga.Helpers (ifJustFalse, (?||))
15import Yoga.Helpers (ifJustFalse, (?||))
14import Yoga.Imposter.Styles as Style
16import Yoga.Imposter.Styles as Style
@@ -24,6 +26,7 @@ type OptionalProps r
24 = ( kids ∷ Array JSX
26 = ( kids ∷ Array JSX
25 , className ∷ Maybe String
27 , className ∷ Maybe String
26 , onClick ∷ Maybe EventHandler
28 , onClick ∷ Maybe EventHandler
29+ , style ∷ Maybe CSS
27 | r
30 | r
28 )
31 )
29
32
@@ -33,8 +36,9 @@ makeComponent = do
33 component "Imposter" \props@{ kids, className } -> React.do
36 component "Imposter" \props@{ kids, className } -> React.do
34 classes <- useStyles (pick props)
37 classes <- useStyles (pick props)
35 pure
38 pure
36− $ R.div
39+ $ animatedDiv
37 { className: classes.imposter <> ifJustFalse props.breakout (" " <> classes.contain) <> foldMap (" " <> _) className
40 { className: classes.imposter <> ifJustFalse props.breakout (" " <> classes.contain) <> foldMap (" " <> _) className
38 , onClick: props.onClick ?|| (handler_ (pure unit))
41 , onClick: props.onClick ?|| (handler_ (pure unit))
39 , children: kids
42 , children: kids
43+ , style: props.style # orUndefined
40 }
44 }
components/src/Yoga/JSS.purs+7−1
@@ -1,9 +1,10 @@
1module JSS where
1module JSS where
2
2
3import Prelude
3import Prelude
4−import CSS (App(..), Color, Key(..), Keyframes(..), Path(..), Predicate(..), Refinement(..), Rule(..), Selector(..), StyleM, Value(..), cssStringRGBA, plain, predicate, runS)
4+import CSS (class Val, App(..), BackgroundImage, Color, Key(..), Keyframes(..), Path(..), Predicate(..), Refinement(..), Rule(..), Selector(..), StyleM, Value(..), cssStringRGBA, plain, predicate, runS, value)
5import Data.Foldable (foldMap)
5import Data.Foldable (foldMap)
6import Data.Int (round)
6import Data.Int (round)
7+import Data.Newtype (un, unwrap)
7import Data.Symbol (class IsSymbol, SProxy(..), reflectSymbol)
8import Data.Symbol (class IsSymbol, SProxy(..), reflectSymbol)
8import Data.Tuple (Tuple(..))
9import Data.Tuple (Tuple(..))
9import Debug.Trace (spy)
10import Debug.Trace (spy)
@@ -98,6 +99,11 @@ instance jssAbleJssElem ∷ JSSAble p (JSSElem p) where
98instance jssAbleColor ∷ JSSAble p Color where
99instance jssAbleColor ∷ JSSAble p Color where
99 jss c = PrimitiveJss (coerce (cssStringRGBA c))
100 jss c = PrimitiveJss (coerce (cssStringRGBA c))
100
101
102+instance jssAbleBackgroundImage ∷ JSSAble p BackgroundImage where
103+ jss v = PrimitiveJss (coerce (render (value v)))
104+ where
105+ render (Value val) = plain val
106+
101instance jssAbleString ∷ JSSAble p String where
107instance jssAbleString ∷ JSSAble p String where
102 jss = coerce >>> PrimitiveJss
108 jss = coerce >>> PrimitiveJss
103
109
components/src/Yoga/Modal/Component.purs+98−32
@@ -3,18 +3,24 @@ module Yoga.Modal.Component where
3import Prelude
3import Prelude
4import CSS (JustifyContentValue(..), spaceBetween)
4import CSS (JustifyContentValue(..), spaceBetween)
5import Data.Foldable (foldMap)
5import Data.Foldable (foldMap)
6+import Data.Int (round, toNumber)
7+import Data.Interpolate (i)
6import Data.Maybe (Maybe)
8import Data.Maybe (Maybe)
9+import Data.Tuple.Nested ((/\))
7import Effect (Effect)
10import Effect (Effect)
8import Foreign.Object as Obj
11import Foreign.Object as Obj
12+import Math (pi, pow, sqrt)
9−import React.Basic (JSX)
13+import React.Basic (JSX, fragment)
14+import React.Basic.DOM (css)
10import React.Basic.DOM as R
15import React.Basic.DOM as R
11import React.Basic.DOM.Events (stopPropagation)
16import React.Basic.DOM.Events (stopPropagation)
12import React.Basic.DOM.SVG as SVG
17import React.Basic.DOM.SVG as SVG
13−import React.Basic.Events (EventHandler, handler, handler_)
18+import React.Basic.Events (handler, handler_)
14import React.Basic.Extra.Hooks.UseKeyUp (useKeyUp)
19import React.Basic.Extra.Hooks.UseKeyUp (useKeyUp)
15import React.Basic.Helpers (jsx)
20import React.Basic.Helpers (jsx)
16−import React.Basic.Hooks (ReactComponent, component, useEffect, useMemo, useState)
21+import React.Basic.Hooks (ReactComponent, component, element, useEffect, useState)
17import React.Basic.Hooks as React
22import React.Basic.Hooks as React
23+import React.Basic.Hooks.Spring (animatedPath, useSpring)
18import Record.Extra (pick)
24import Record.Extra (pick)
19import Yoga.Box.Component as Box
25import Yoga.Box.Component as Box
20import Yoga.Cluster.Component as Cluster
26import Yoga.Cluster.Component as Cluster
@@ -40,29 +46,48 @@ makeComponent = do
40 box <- Box.makeComponent
46 box <- Box.makeComponent
41 stack <- Stack.makeComponent
47 stack <- Stack.makeComponent
42 cluster <- Cluster.makeComponent
48 cluster <- Cluster.makeComponent
49+ closeIcon <- mkCloseIcon
43 useStyles <- makeStylesJSS Style.styles
50 useStyles <- makeStylesJSS Style.styles
44 component "Modal" \props -> React.do
51 component "Modal" \props -> React.do
45 cs <- useStyles (pick props)
52 cs <- useStyles (pick props)
46 useKeyUp 27 $ props.onClose ?|| pure unit
53 useKeyUp 27 $ props.onClose ?|| pure unit
54+ animationDone /\ modifyAnimationDone <- useState false
55+ overlayStyle <- useSpring $ const { opacity: 0.0 }
56+ dialogStyle <-
57+ useSpring
58+ $ const
59+ { transform: "translate3d(-50%, -50%, 0) scale3d(0.2, 0.2, 0.0)"
60+ , config: { mass: 0.8, tension: 120, friction: 14 }
61+ }
62+ useEffect unit do
63+ overlayStyle.set { opacity: 1.0 }
64+ dialogStyle.set
65+ { transform: "translate3d(-50%, -50%, 0) scale3d(1.0, 1.0, 1.0)"
66+ , onRest: modifyAnimationDone (const true)
67+ }
68+ pure mempty
47 let
69 let
48 darkOverlay =
70 darkOverlay =
49 jsx imposter
71 jsx imposter
50− { className: cs.darkOverlay <> " " <> cs.fadeIn
72+ { className: cs.darkOverlay
51 , fixed: true
73 , fixed: true
52 , breakout: false
74 , breakout: false
53 , onClick: props.onClose ?|| mempty # handler_
75 , onClick: props.onClose ?|| mempty # handler_
76+ , style: css overlayStyle.style
54 }
77 }
78+ []
55
79
56 dialogImposter =
80 dialogImposter =
57 jsx imposter
81 jsx imposter
58 { className: cs.dialog
82 { className: cs.dialog
59 , onClick: handler stopPropagation mempty
83 , onClick: handler stopPropagation mempty
60 , fixed: true
84 , fixed: true
85+ , style: css dialogStyle.style
61 }
86 }
62
87
63 dialogBox =
88 dialogBox =
64 jsx box
89 jsx box
65− { className: cs.box <> " " <> cs.zoomIn
90+ { className: cs.box
66 }
91 }
67
92
68 dialogBoxStack =
93 dialogBoxStack =
@@ -83,13 +108,20 @@ makeComponent = do
83 , R.div
108 , R.div
84 { className: cs.closeIcon
109 { className: cs.closeIcon
85 , children:
110 , children:
86− [ props.onClose # foldMap (closeIcon cs <<< handler_)
111+ [ props.onClose
112+ # foldMap
113+ ( \onClick ->
114+ ( element closeIcon
115+ { className: cs.closeIcon, onClick, startAnimation: animationDone }
116+ )
117+ )
87 ]
118 ]
88 }
119 }
89 ]
120 ]
90 pure
121 pure
122+ $ fragment
91− $ darkOverlay
123+ [ darkOverlay
92− [ dialogImposter
124+ , dialogImposter
93 [ dialogBox
125 [ dialogBox
94 [ dialogBoxStack
126 [ dialogBoxStack
95 [ titleCluster [ title ]
127 [ titleCluster [ title ]
@@ -99,27 +131,61 @@ makeComponent = do
99 ]
131 ]
100 ]
132 ]
101
133
102−closeIcon ∷ ∀ a. { closeIcon ∷ String | a } -> EventHandler -> JSX
134+mkCloseIcon ∷
103−closeIcon classes onClick =
135+ Effect
104− SVG.svg
136+ ( ReactComponent
105− { xmlns: "http://www.w3.org/2000/svg"
137+ { className ∷ String
138+ , onClick ∷ Effect Unit
139+ , startAnimation ∷ Boolean
140+ }
141+ )
142+mkCloseIcon = do
143+ box <- Box.makeComponent
144+ component "CloseIcon" \{ className, onClick, startAnimation } -> React.do
145+ { style, set, stop } <-
146+ useSpring
147+ $ const
148+ { strokeDasharray: "0, " <> show lineLen
149+ }
150+ circleStyle <-
151+ useSpring
152+ $ const
153+ { strokeDasharray: "0," <> show circleCircumf
154+ , onRest: set { "strokeDasharray": i lineLen "," lineLen ∷ String }
155+ }
156+ useEffect startAnimation do
157+ when startAnimation $ circleStyle.set { "strokeDasharray": (i circleCircumf "," circleCircumf) ∷ String }
158+ pure mempty
159+ pure
160+ $ SVG.svg
106− , viewBox: "5 0 100 105"
161+ { viewBox: i "0 0 " width " " width
107− , fillRule: "evenodd"
108− , clipRule: "evenodd"
109− , strokeLinejoin: "round"
110− , strokeMiterlimit: "2"
111− , _data: Obj.singleton "testid" "close-icon-svg"
162+ , _data: Obj.singleton "testid" "close-icon-svg"
112− , onClick
163+ , onClick: handler_ onClick
113− , className: classes.closeIcon
164+ , fill: "none"
165+ , className
114− , children:
166+ , children:
115− [ SVG.g_
167+ [ animatedPath
116− [ SVG.path
168+ { d: i "M" padding "," padding "L" (width - padding) "," (width - padding)
117− { d: "M101.703,36.06c2.054,-2.054 2.054,-5.388 0,-7.442l-7.441,-7.441c-2.054,-2.054 -5.388,-2.054 -7.442,0l-65.643,65.643c-2.054,2.054 -2.054,5.388 0,7.442l7.441,7.441c2.054,2.054 5.388,2.054 7.442,0l65.643,-65.643Z"
169+ , style: css style
170+ }
171+ , animatedPath
172+ { d: i "M" padding "," (width - padding) ",L" (width - padding) "," padding
173+ , style: css style
118− }
174+ }
119− , SVG.path
175+ , animatedPath
120− { d:
176+ { d: move <> line1 <> line2
121− "M86.82,101.703c2.054,2.054 5.388,2.054 7.442,0l7.441,-7.441c2.054,-2.054 2.054,-5.388 0,-7.442l-65.643,-65.643c-2.054,-2.054 -5.388,-2.054 -7.442,0l-7.441,7.441c-2.054,2.054 -2.054,5.388 0,7.442l65.643,65.643Z"
177+ , style: css circleStyle.style
122− }
178+ }
123− ]
179+ ]
124− ]
180+ }
125− }
181+ where
182+ move = i "M " (cx - r) "," cx
183+ line1 = i " a " r "," r " 0 1,0 " (r * 2) ",0 "
184+ line2 = i " a " r "," r " 0 1,0 " (-(r * 2)) ",0 "
185+ padding = 70
186+ width = 200
187+ cx = width / 2
188+ r = round ((toNumber width * 0.8) / 2.0)
189+ circleCircumf = round $ 2.0 * pi * toNumber r
190+ aSquare = toNumber (width - (2 * padding)) `pow` 2.0
191+ lineLen = sqrt (aSquare * 2.0)
components/src/Yoga/Modal/Styles.purs+4−39
@@ -22,10 +22,6 @@ type Classes a
22 , dialogBoxStack ∷ a
22 , dialogBoxStack ∷ a
23 , title ∷ a
23 , title ∷ a
24 , titleCluster ∷ a
24 , titleCluster ∷ a
25− , "@keyframes zoomIn" ∷ a
26− , "@keyframes fadeIn" ∷ a
27− , zoomIn ∷ a
28− , fadeIn ∷ a
29 )
25 )
30
26
31styles ∷ JSSClasses YogaTheme Props (Classes (JSSElem Props))
27styles ∷ JSSClasses YogaTheme Props (Classes (JSSElem Props))
@@ -45,9 +41,10 @@ styles =
45 boxShadow nil nil (3.5 # rem) (Color.rgba 0 0 0 0.5)
41 boxShadow nil nil (3.5 # rem) (Color.rgba 0 0 0 0.5)
46 borderRadius boxBorderRadius boxBorderRadius boxBorderRadius boxBorderRadius
42 borderRadius boxBorderRadius boxBorderRadius boxBorderRadius boxBorderRadius
47 , closeIcon:
43 , closeIcon:
48− { fill: theme.red
44+ { stroke: theme.textColour
45+ , strokeWidth: "var(--s0)"
49− , width: "calc(0.8em * var(--ratio))"
46+ , width: "var(--s1)"
50− , height: "calc(0.8em * var(--ratio))"
47+ , height: "var(--s1)"
51 , margin: 0
48 , margin: 0
52 , padding: 0
49 , padding: 0
53 }
50 }
@@ -59,10 +56,6 @@ styles =
59 }
56 }
60 , title:
57 , title:
61 { textOverflow: "ellipsis"
58 { textOverflow: "ellipsis"
62− -- , overflow: "hidden"
63− -- , lineHeight: "1.5rem"
64− -- , whiteSpace: "nowrap"
65− -- , height: "3rem"
66 }
59 }
67 , dialog:
60 , dialog:
68 { width: "var(--measure) !important"
61 { width: "var(--measure) !important"
@@ -73,32 +66,4 @@ styles =
73 , maxHeight:
66 , maxHeight:
74 "10.0 vh !important"
67 "10.0 vh !important"
75 }
68 }
76− , "@keyframes zoomIn":
77− { "from":
78− { opacity: 0
79− , transform: "scale3d(0.1, 0.1, 0.1) translate3d(0, 100vh, 0)"
80− , "animation-timing-function": "cubic-bezier(0.55, 0.055, 0.675, 0.19)"
81− }
82− , "60%":
83− { opacity: 1
84− , transform: "scale3d(0.475, 0.475, 0.475) translate3d(0, -20vh, 0)"
85− , "animation-timing-function": "cubic-bezier(0.175, 0.885, 0.32, 1)"
86− }
87− }
88− , zoomIn:
89− { animation: "$zoomIn 0.90s ease-in"
90− , animationFillMode: "both"
91− }
92− , "@keyframes fadeIn":
93− { from:
94− { opacity: 0
95− }
96− , to:
97− { opacity: 1
98− }
99− }
100− , fadeIn:
101− { animation: "$fadeIn 0.70s"
102− , animationFillMode: "both"
103− }
104 }
69 }
components/src/Yoga/Monaco/Editor.purs+2−1
@@ -5,6 +5,7 @@ import CSS (backgroundColor, borderBox, boxSizing, margin, pct, toHexString, uni
5import CSS.Overflow (hidden, overflowY)
5import CSS.Overflow (hidden, overflowY)
6import Control.Promise (Promise)
6import Control.Promise (Promise)
7import Control.Promise as Promise
7import Control.Promise as Promise
8+import Data.Array.NonEmpty as NEA
8import Data.Foldable (for_)
9import Data.Foldable (for_)
9import Data.Maybe (Maybe(..), maybe)
10import Data.Maybe (Maybe(..), maybe)
10import Data.Nullable (Nullable)
11import Data.Nullable (Nullable)
@@ -131,7 +132,7 @@ mkEditor = do
131 , height
132 , height
132 , options:
133 , options:
133 unsafeToForeign
134 unsafeToForeign
134− { fontFamily: theme.codeFontFamily
135+ { fontFamily: NEA.head theme.codeFontFamily
135 , fontLigatures: true
136 , fontLigatures: true
136 , fontSize: "12pt"
137 , fontSize: "12pt"
137 , lineNumbers: "off"
138 , lineNumbers: "off"
components/src/Yoga/Theme.purs+2−2
@@ -1,7 +1,7 @@
1module Yoga.Theme where
1module Yoga.Theme where
2
2
3import Prelude
3import Prelude
4−import CSS (CSSVariable, Size, contrast, darken, isLight, lighten, reference, rotateHue, unitless, variable, (!*))
4+import CSS (CSSVariable, Size, contrast, darken, desaturate, isLight, lighten, reference, rotateHue, unitless, variable, (!*))
5import CSS.Size (Calc, (!/))
5import CSS.Size (Calc, (!/))
6import Color (Color)
6import Color (Color)
7import Color as Color
7import Color as Color
@@ -74,7 +74,7 @@ fromTheme theme =
74 -- highlight
74 -- highlight
75
75
76 >>> RB.insert (f ∷ _ "highlightColourDark")
76 >>> RB.insert (f ∷ _ "highlightColourDark")
77− (theme.highlightColour # darken 0.2 # rotateHue (-10.0))
77+ (theme.highlightColour # darken 0.2 # desaturate 0.35)
78 >>> RB.insert (f ∷ _ "highlightColourRotatedForwards")
78 >>> RB.insert (f ∷ _ "highlightColourRotatedForwards")
79 (theme.highlightColour # rotateHue (20.0))
79 (theme.highlightColour # rotateHue (20.0))
80 >>> RB.insert (f ∷ _ "highlightColourRotatedBackwards")
80 >>> RB.insert (f ∷ _ "highlightColourRotatedBackwards")
components/src/Yoga/Theme/Default.purs+1−1
@@ -19,7 +19,7 @@ darkTheme =
19 { backgroundColour: Color.hsl 228.0 0.12 0.20
19 { backgroundColour: Color.hsl 228.0 0.12 0.20
20 , textColour: Color.hsl 225.0 0.28 0.90
20 , textColour: Color.hsl 225.0 0.28 0.90
21 , interfaceColour: Color.hsl 225.0 0.48 0.12
21 , interfaceColour: Color.hsl 225.0 0.48 0.12
22− , highlightColour: Color.hsl 350.0 0.50 0.67
22+ , highlightColour: Color.hsl 300.0 0.58 0.77
23 -- , highlightColour: Color.hsl 33.0 0.37 0.8
23 -- , highlightColour: Color.hsl 33.0 0.37 0.8
24 , altHighlightColour: Color.hsl 84.0 0.617 0.631
24 , altHighlightColour: Color.hsl 84.0 0.617 0.631
25 , textFontFamily: cons' "Rubik" systemFontStack
25 , textFontFamily: cons' "Rubik" systemFontStack