Mostly buttons

This commit is contained in:
Mark Eibes 2020-12-27 22:12:14 +01:00
parent 20e0552b77
commit 3c1f4dfab3
19 changed files with 308 additions and 171 deletions

View File

@ -4,11 +4,9 @@ import Prelude hiding (div)
import Effect (Effect)
import Effect.Unsafe (unsafePerformEffect)
import React.Basic (JSX, element, fragment)
import React.Basic.DOM (css)
import React.Basic.DOM as R
import React.Basic.Emotion (str)
import React.Basic.Emotion as E
import React.Basic.Events (handler_)
import Yoga (div, (/>), (</), (</>))
import Yoga.Block as Block
import Yoga.Block.Atom.Button.Types as ButtonType
@ -40,23 +38,25 @@ button = do
[ R.h1_ [ R.text "Button Examples" ]
, R.h2_ [ R.text "Button types" ]
, Block.cluster </ { space: "var(--s-1)" }
/> [ div </ {}
/> [ Button.component </ { buttonType: ButtonType.Generic } /> [ R.text "Generic" ]
, Button.component </ { buttonType: ButtonType.Primary } /> [ R.text "Primary" ]
]
/> [ Button.component </ { buttonType: ButtonType.Generic } /> [ R.text "Generic" ]
, Button.component </ { buttonType: ButtonType.Primary } /> [ R.text "Primary" ]
, Button.component </ { buttonType: ButtonType.Dangerous } /> [ R.text "Dangerous" ]
]
, R.h2_ [ R.text "Button shapes" ]
, Block.cluster </ { space: "var(--s-1)" }
/> [ div </ {}
/> [ Button.component </ { buttonType: ButtonType.Generic, buttonShape: ButtonType.Pill } /> [ R.text "Generic" ]
, Button.component </ { buttonType: ButtonType.Primary, buttonShape: ButtonType.Pill } /> [ R.text "Primary" ]
]
/> [ Button.component </ { buttonType: ButtonType.Generic, buttonShape: ButtonType.Pill } /> [ R.text "Generic" ]
, Button.component </ { buttonType: ButtonType.Primary, buttonShape: ButtonType.Pill } /> [ R.text "Primary" ]
]
, R.h2_ [ R.text "Icon button" ]
, Block.cluster </ { space: "var(--s-1)" }
/> [ div </ {}
/> [ Button.component </ {} /> [ Block.icon </> { icon: Icon.questionMark, size: str "var(--s2)", colour: str colour.highlight } ]
]
/> [ Button.component </ {} /> [ Block.icon </> { icon: Icon.questionMark, size: str "var(--s2)", colour: str colour.highlight } ]
]
, R.h2_ [ R.text "Disabled" ]
, Block.cluster </ { space: "var(--s-1)" }
/> [ Button.component </ { buttonType: ButtonType.Generic, disabled: true } /> [ R.text "Generic" ]
, Button.component </ { buttonType: ButtonType.Primary, disabled: true } /> [ R.text "Primary" ]
, Button.component </ { buttonType: ButtonType.Generic, buttonShape: ButtonType.Pill, disabled: true } /> [ R.text "Generic" ]
, Button.component </ { buttonType: ButtonType.Primary, buttonShape: ButtonType.Pill, disabled: true } /> [ R.text "Primary" ]
]
]
]

View File

@ -16,46 +16,14 @@ gradientBackground =
colour.highlightDarker
","
colour.highlightLighter
"),linear-gradient(225deg,"
")"
","
"linear-gradient(225deg,"
colour.highlightRotatedBackwards
","
colour.highlightRotatedForwards
")"
buttonContainer ∷ Style
buttonContainer =
css
{ background: str colour.interfaceBackground
, boxShadow: str "0 1px 4px rgba(0,0,0,0.30)"
, borderTop: str $ i "1px solid " colour.interfaceBackgroundHighlight
, borderBottom: str $ i "1px solid " colour.interfaceBackgroundShadow
, display: inlineFlex
, padding: str "2px"
, justifyContent: center
, alignItems: center
, borderRadius: var "--s-1"
, """&[data-button-shape="pill"]""":
nest
{ borderRadius: var "--s1"
, "& > button":
nest
{ padding: str "calc(var(--s-1) * 0.8) var(--s0)"
}
}
, """&[data-button-type="primary"]""":
nest
{ background: gradientBackground
, backgroundSize: str "200% 200%"
, animation: backgroundAnimation <> str " alternate ease-out 10s infinite"
, boxShadow: str "0 1px 4px 0px rgba(0,0,0,0.40)"
, borderColor: str "transparent"
, "& > button":
nest
{ color: str colour.highlightText
}
}
}
backgroundAnimation ∷ StyleProperty
backgroundAnimation =
keyframes
@ -66,15 +34,81 @@ backgroundAnimation =
button ∷ Style
button =
css
{ background: str "transparent"
{ background: str colour.interfaceBackground
, boxShadow: str "0 1px 4px rgba(0,0,0,0.30)"
, border: str $ i "1px solid transparent"
, borderTop: str $ i "1px solid " colour.interfaceBackgroundHighlight
, borderBottom: str $ i "1px solid " colour.interfaceBackgroundShadow
, display: inlineFlex
, padding: str "calc(var(--s-1) * 0.85) var(--s0)"
, justifyContent: center
, alignItems: center
, borderRadius: var "--s-1"
, color: str colour.text
, boxSizing: borderBox
, fontSize: var "--s0"
, fontFamily: var "--mainFont"
, fontWeight: str "500"
, letterSpacing: str "calc(var(--s-5)*0.2)"
, padding: str "calc(var(--s-1) * 0.85) var(--s0)"
, border: none
, fontWeight: str "450"
, letterSpacing: str "calc(var(--s-5)* (-0.1))"
, userSelect: none
, "&:focus": nest { outline: none }
, transition: str "all 0.2s ease-out" <> str "transform 50ms ease-in"
, """&[data-button-shape="pill"]""":
nest
{ borderRadius: str "calc(var(--s1) * 0.85)"
, padding: str "calc(var(--s-1) * 0.9) var(--s0)"
}
, """&[data-button-type="primary"]""":
nest
{ background: gradientBackground
, backgroundSize: str "200% 200%"
, fontWeight: str "600"
, letterSpacing: str "calc(var(--s-5)* (0.1))"
, animation: backgroundAnimation <> str " alternate ease-out 10s infinite"
, boxShadow: str "0 1px 4px 0px rgba(0,0,0,0.40)"
, borderColor: str "transparent"
, color: str colour.highlightText
, """&:focus-visible""":
nest
{ borderColor: str $ colour.background0
}
, """&:active""":
nest
{ boxShadow: str "inset 0 1px 6px rgba(0,0,0,0.40)"
, border: str $ i "1px solid transparent"
}
, "&:disabled":
nest
{ background: str colour.highlightDisabled
}
}
, """&[data-button-type="dangerous"]""":
nest
{ color: str $ colour.interfaceDangerousText
, background: str $ colour.interfaceBackgroundDangerous
, fontWeight: str "600"
, letterSpacing: str "calc(var(--s-5) * -0.10)"
}
, """&:focus""": nest { outline: none }
, """&:focus-visible""":
nest
{ boxShadow: str $ "0 0 0 var(--s-4) " <> colour.highlight
}
, """&:active""":
nest
{ boxShadow:
str
$ "inset 0 1px var(--s-1) rgba(0,0,0,0.20)"
, borderTop: str $ i "1px solid " colour.interfaceBackgroundShadow
, borderBottom: str $ i "1px solid " colour.interfaceBackgroundShadow
, transform: str "scale3d(0.95,0.95,0.95)"
, transition: str "transform 50ms ease"
}
, "&:disabled":
nest
{ color: str colour.interfaceTextDisabled
, boxShadow: none
, background: str colour.interfaceBackgroundDisabled
, borderTop: str $ i "1px solid " colour.interfaceBackgroundShadow
, borderBottom: str $ i "1px solid " colour.interfaceBackgroundShadow
}
}

View File

@ -4,6 +4,7 @@ import Prelude
data ButtonType
= Primary
| Dangerous
| Generic
derive instance eqButtonType ∷ Eq ButtonType
@ -12,6 +13,7 @@ renderButtonType ∷ ButtonType -> String
renderButtonType = case _ of
Primary -> "primary"
Generic -> "generic"
Dangerous -> "dangerous"
data ButtonShape
= Rounded

View File

@ -36,14 +36,10 @@ rawComponent =
{ "button-type": renderButtonType (props.buttonType ?|| Button.Generic)
, "button-shape": renderButtonShape (props.buttonShape ?|| Button.Rounded)
}
pure $ div
</* { css: Style.buttonContainer
, className: "ry-button-container"
, _data
}
/> [ emotionButton propsRef
props
{ className: "ry-button"
, css: Style.button
}
]
pure
$ emotionButton propsRef
props
{ className: "ry-button"
, css: Style.button
, _data
}

View File

@ -22,9 +22,20 @@ span props =
, display: inlineFlex
, justifyContent: center
, alignItems: center
, margin: _0
, padding: _0
, width
, height
, overflow: hidden
, "& > svg":
nest
{ width: (props.width <|> props.size) ?|| (str "auto")
, height: (props.height <|> props.size) ?|| (str "1.2ch")
{ width
, height
, margin: _0
, padding: _0
}
}
where
width = (props.width <|> props.size) ?|| (str "auto")
height = (props.height <|> props.size) ?|| (str "1ch")

View File

@ -10,7 +10,7 @@ import React.Basic (JSX, element, fragment)
import React.Basic.DOM as R
import React.Basic.Emotion as E
import React.Basic.Events (handler_)
import Yoga (el)
import Yoga (el, (</), (/>), (</>))
import Yoga.Block as Block
import Yoga.Block.Atom.Input as Input
import Yoga.Block.Atom.Input.Types as HTMLInput
@ -38,7 +38,7 @@ input = do
[ R.div_
[ R.h1_ [ R.text "Input Examples" ]
, R.h2_ [ R.text "Generic Input" ]
, element Input.component { value: "A Generic Input", onChange: handler_ mempty }
, Input.component </> { value: "A Generic Input", onChange: handler_ mempty }
, R.h2_ [ R.text "Validation on text Input" ]
, 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" }
, 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
, _aria: Object.singleton "required" "true"
}
, R.h3_ [ R.text "With a label" ]
, el Block.cluster {}
[ el R.form' {}
[ element Input.component { label: nes (SProxy ∷ _ "This has a label"), value: "And text", onChange: handler_ mempty }
, element Input.component { label: nes (SProxy ∷ _ "This has a label"), value: "", onChange: handler_ mempty }
, element Input.component { label: nes (SProxy ∷ _ "This has a label"), placeholder: "A very long placeholder, too..." }
, element Input.component { label: nes (SProxy ∷ _ "Pig nose"), leading: R.text "🐽🤣" }
, element Input.component { label: nes (SProxy ∷ _ "Pig nose"), trailing: R.text "🤫" }
, element Input.component { label: nes (SProxy ∷ _ "Pig nose"), leading: R.text "🌭" }
, element Input.component { label: nes (SProxy ∷ _ "Pig nose"), leading: R.text "⭐", trailing: R.text "🔮" }
]
]
, Block.cluster </ {}
/> [ element Input.component { label: nes (SProxy ∷ _ "This has a label"), value: "And text", onChange: handler_ mempty }
, element Input.component { label: nes (SProxy ∷ _ "This has a label"), value: "", onChange: handler_ mempty }
, element Input.component { label: nes (SProxy ∷ _ "This has a label"), placeholder: "A very long placeholder, too..." }
, element Input.component { label: nes (SProxy ∷ _ "Pig nose"), leading: R.text "🐽🤣" }
, element Input.component { label: nes (SProxy ∷ _ "Pig nose"), trailing: R.text "🤫" }
, element Input.component { label: nes (SProxy ∷ _ "Pig nose"), leading: R.text "🌭" }
, element Input.component { label: nes (SProxy ∷ _ "Pig nose"), leading: R.text "⭐", trailing: R.text "🔮" }
]
, R.h2_ [ R.text "[BUG] Overflowing label" ]
, element Input.component
{ type: HTMLInput.Text

View File

@ -43,6 +43,7 @@ labelContainer ∷ Style
labelContainer =
css
{ position: absolute
, overflow: visible
, top: _0
, left: _0
, display: inlineBlock
@ -147,13 +148,14 @@ leftIconContainer =
}
}
inputWrapper ∷ ∀ r. { | Props OptionalProp r } -> Style
inputWrapper props =
inputWrapper ∷ Style
inputWrapper =
css
{ position: relative
, boxSizing: borderBox
, backgroundColor: str colour.inputBackground
, display: inlineFlex
, display: flex
, minWidth: str "calc(var(--s4) *2 )"
, "--left-icon-size": var "--s0"
, "--right-icon-size": str "calc(var(--s0) * 1.2)"
, "--input-border-radius": var "--s-1"
@ -161,7 +163,7 @@ inputWrapper props =
, "--input-top-padding": var "--s-5"
, "--input-bottom-padding": var "--s-5"
, alignItems: center
, justifyContent: flexStart
, justifyContent: center
, paddingLeft: str "calc(var(--input-side-padding) - var(--border-width))"
, paddingRight: str "calc(var(--input-side-padding) - var(--border-width))"
, paddingTop: str "calc(var(--input-top-padding) - var(--border-width))"
@ -173,26 +175,28 @@ inputWrapper props =
, """&[data-invalid="false"]""":
nest
{ borderColor: str colour.success
, "--border-width": str "var(--s-5)"
}
, """&[data-invalid="true"]""":
nest
{ borderColor: str colour.invalid
, "--border-width": str "var(--s-5)"
}
, "&:focus-within":
nest
{ "--border-width": str "var(--s-5)"
, borderColor: str colour.highlight
, transition: str "border-color 0s linear 0.1s"
}
}
input ∷ ∀ r. { | Props OptionalProp r } -> Style
input props =
input ∷ Style
input =
css
{ "&[type=text],&[type=search],&[type=password],&[type=number],&:not([type])":
nest
{ color: str colour.text
, width: _100percent
, flex: str "1"
, flex: str "2"
, "--padding-top": var "--s-1"
, "--padding-bottom": var "--s-1"
, "&[aria-labelledby]":
@ -221,12 +225,4 @@ input props =
nest
{ outline: none
}
, "&[type=button], &[type=submit]":
nest
{ background: str colour.highlight
, color: str "white"
, boxShadow: str "0 1px 4px rgba(0,0,0,0.5)"
, borderColour: str colour.highlight
, height: str "auto"
}
}

View File

@ -3,11 +3,9 @@ module Yoga.Block.Atom.Input.View where
import Yoga.Prelude.View
import Data.Array as Array
import Data.Interpolate (i)
import Data.Semigroup.Foldable (intercalateMap)
import Data.String.NonEmpty (NonEmptyString)
import Data.String.NonEmpty as NonEmptyString
import Data.Symbol (SProxy(..))
import Debug.Trace (spy)
import Foreign.Object (Object)
import Foreign.Object as Object
import Framer.Motion as M
@ -21,7 +19,6 @@ import Yoga.Block.Atom.Input.Style as Style
import Yoga.Block.Atom.Input.Types (HTMLInput)
import Yoga.Block.Atom.Input.Types as HTMLInput
import Yoga.Block.Icon.SVG as SVGIcon
import Yoga.Block.Internal.OptionalProp (asMaybe)
type PropsF f =
( leading ∷ f JSX
@ -60,16 +57,16 @@ containerVariants =
{ focussed:
css
{ clipPath
, transition: { duration: 1.3 }
, transition: { duration: 0.7 }
}
, blurred:
css
{ clipPath:
drawPathUntil (Array.length path) path
drawPathUntil (Array.length path + 1) path
}
}
where
clipPath = 3 Array... (Array.length path / 2 + 1) <#> \ln -> drawPathUntil (ln * 2) path
clipPath = 6 Array... (Array.length path) <#> \ln -> drawPathUntil ln path
type Point =
{ x ∷ Int, y ∷ Int }
@ -83,28 +80,27 @@ drawPathUntil idx thePath = do
let firstFew = Array.take idx thePath
let lastFew = Array.drop idx thePath $> (Array.last firstFew # fromMaybe' \_ -> unsafeCrashWith "ogod")
let rendered = intercalate "," $ fn <$> (firstFew <> lastFew)
spy "polybius" $ i "polygon(" rendered ")"
i "polygon(" rendered ")"
path ∷ Array Point
path = mkPath 5
path = mkPath 3 7
mkPath ∷ Int -> Array Point
mkPath d = do
mkPath ∷ Int -> Int -> Array Point
mkPath borderX borderY = do
let
inside =
[ p d d
, p (100 - d) d
, p (100 - d) (100 - d)
, p d (100 - d)
, p d d
[ {- ⌜ -} p borderX borderY
, {- ⌞ -} p borderX (100 - borderY)
, {- ⌟ -} p (100 - borderX) (100 - borderY)
, {- ⌝ -} p (100 - borderX) borderY
, {- ⌜ -} p borderX borderY
]
outside =
[ p d 0
, p 100 0
, p 100 100
, p 0 100
, p 0 0
, p d 0 -- one turn, starting way back
[ {- ⌜ -} p 0 0
, {- ⌞ -} p 0 100
, {- ⌟ -} p 100 100
, {- ⌝ -} p 100 0
, {- ⌜ -} p 0 0
]
inside <> outside <> (Array.reverse inside)
@ -216,7 +212,7 @@ rawComponent =
, animate: M.animate if hasFocus then containerVariantLabels.focussed else containerVariantLabels.blurred
}
{ className: "ry-input-wrapper"
, css: Style.inputWrapper props
, css: Style.inputWrapper
, _data:
Object.fromHomogeneous
{ "invalid": aria # Object.lookup "invalid" # fromMaybe ""
@ -230,7 +226,7 @@ rawComponent =
# setOrDelete (SProxy ∷ _ "value") (maybeValue # maybeToOp)
)
{ className: "ry-input"
, css: Style.input props
, css: Style.input
, onFocus: composeHandler props.onFocus onFocus
, onBlur: composeHandler props.onBlur onBlur
, _aria:
@ -303,14 +299,14 @@ password =
pure
$ div
</* { className: "ry-input-wrapper"
, css: Style.inputWrapper props
, css: Style.inputWrapper
}
/> [ leading
, emotionInput
ref
props { type = HTMLInput.toString <$> props.type # unsafeUnOptional }
{ className: "ry-input"
, css: Style.input props
, css: Style.input
, type: if hidePassword then "password" else "text"
}
, trailing

View File

@ -18,6 +18,7 @@ import React.Basic (JSX, ReactComponent, element, elementKeyed, fragment)
import React.Basic.DOM (CSS, css)
import React.Basic.DOM as R
import React.Basic.DOM.Events (targetValue)
import React.Basic.Emotion (str)
import React.Basic.Emotion as E
import React.Basic.Events (handler, handler_)
import React.Basic.Hooks (reactComponent)
@ -27,11 +28,16 @@ import React.Basic.Popper.Placement.Types as Placement
import React.Basic.Popper.Types (nullRef)
import Unsafe.Coerce (unsafeCoerce)
import Yoga ((/>), (</), (</>))
import Yoga.Block as Block
import Yoga.Block.Atom.Icon as Icon
import Yoga.Block.Atom.Input as Input
import Yoga.Block.Atom.Input.Types as HTMLInput
import Yoga.Block.Atom.Popover as Popover
import Yoga.Block.Container.Style (colour)
import Yoga.Block.Container.Style as Styles
import Yoga.Block.Icon.SVG as Icons
import Yoga.Block.Layout.Box as Box
import Yoga.Block.Layout.Cluster as Cluster
import Yoga.Block.Layout.Stack as Stack
default ∷
@ -67,20 +73,47 @@ popover = do
reactComponent "PopoverExample" \props -> React.do
referenceElement /\ setReferenceElement <- React.useState' nullRef
text /\ setText <- React.useState' ""
visible /\ setVisible <- React.useState' false
visible /\ setVisible <- React.useState' true
selectedAuthors /\ modSelectedAuthors <-
React.useState [ "William Shakespeare", "Agatha Christie" ]
let
matchingAuthors =
authors
# (_ Array.\\ selectedAuthors)
# Array.filter
( \a ->
String.contains (String.Pattern (String.toLower text))
(String.toLower a)
)
let
inputWrapper =
R.div'
</ { ref: unsafeCoerce (mkEffectFn1 setReferenceElement)
}
inputWrapper = R.div' </ { ref: unsafeCoerce (mkEffectFn1 setReferenceElement) }
pill t =
Block.box </ { padding: str "var(--s-3)" }
/> [ Block.cluster
</ { style:
css
{ background: colour.highlight
, fontSize: "var(--s-1)"
, space: "var(--s-5)"
, borderRadius: "var(--s-2)"
}
}
/> [ R.text t
, Block.centre
</ { style:
css
{ background: "hotpink"
}
, andText: true
}
/> [ Icon.component
</> { icon: Icons.cross, size: str "var(--s-1)"
}
]
]
]
pills = pill <$> selectedAuthors
leading = Block.cluster </ {} /> pills
input =
Input.component
</> { id: "author"
@ -92,19 +125,20 @@ popover = do
, onChange: handler targetValue $ traverse_ setText
, onBlur: handler_ (setVisible false)
, onFocus: handler_ (setVisible true)
, trailing: R.text "▼"
, leading
, autoComplete: "off"
}
pop children =
elementKeyed motionPopover
$ Motion.motion
{ initial:
css { clipPath: "polygon(0% 0%, 100% 0%, 100% 0%, 0% 0%)" }
css { maxHeight: 30, opacity: 0.0 }
, exit:
css { clipPath: "polygon(0% 0%, 100% 0%, 100% 0%, 0% 0%)" }
css { maxHeight: 30, opacity: 0.0 }
, animate:
css
{ clipPath: "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)"
{ maxHeight: 400
, opacity: 1
}
, transition:
Motion.transition
@ -120,9 +154,10 @@ popover = do
, style:
css
{ boxShadow: "0px 9px 12px rgba(40,40,40,0.5)"
, background: "rgba(50,50,70, 0.7)"
, background: colour.interfaceBackground
, borderRadius: "9px"
, borderTop: "solid 1px rgba(80,80,100,1.0)"
, borderTop: "solid 1px " <> colour.interfaceBackgroundHighlight
, borderBottom: "solid 1px " <> colour.interfaceBackgroundShadow
, overflowY: "scroll"
, maxHeight: "400px"
, width: "300px"
@ -149,6 +184,7 @@ popover = do
</ { key: a
-- , layout: Motion.layout true
-- , variants: Motion.variants itemVariants
, onClick: handler_ (modSelectedAuthors (_ `Array.snoc` a))
}
/> [ R.text a ]
pure

View File

@ -22,29 +22,25 @@ container =
[ R.text "Content"
, el Stack.component {}
[ el Cluster.component {}
[ R.div_
[ R.input { value: "Text" }
, R.input { type: "number", value: "0" }
, styledLeaf R.input'
{ className: "styledinput"
, css: inputFocus
, value: "focus"
}
, R.input
{ className: "styledinput"
, value: "focus"
, disabled: true
}
]
[ R.input { value: "Text" }
, R.input { type: "number", value: "0" }
, styledLeaf R.input'
{ className: "styledinput"
, css: inputFocus
, value: "focus"
}
, R.input
{ className: "styledinput"
, value: "focus"
, disabled: true
}
]
, R.input { type: "file" }
, el Cluster.component {}
[ R.div_
[ R.input { type: "checkbox" }
, R.input { type: "checkbox", checked: true }
, R.input { type: "radio" }
, R.input { type: "radio", checked: true }
]
[ R.input { type: "checkbox" }
, R.input { type: "checkbox", checked: true }
, R.input { type: "radio" }
, R.input { type: "radio", checked: true }
]
, R.input { type: "range" }
]

View File

@ -131,9 +131,13 @@ defaultColours =
, invalid
, invalidText
, required
, interfaceBackground: lightBg
, interfaceTextDisabled: darken 0.33 lightBg
, interfaceBackground
, interfaceBackgroundDangerous
, interfaceDangerousText
, interfaceBackgroundDisabled: darken 0.03 lightBg
, interfaceTextDisabled: darken 0.30 lightBg
, interfaceBackgroundHighlight: lighten 0.05 lightBg
, highlightDisabled: (desaturate 0.80 >>> lighten 0.28) highlight
, interfaceBackgroundShadow: darken 0.04 lightBg
, inputBackground: lightBg
, inputBorder: darken 0.1 lightBg
@ -167,17 +171,21 @@ defaultColours =
, textInverted: darkBg
, backgroundInverted: lightBg
, interfaceBackground: interfaceBackgroundDark
, interfaceTextDisabled: lighten 0.8 darkBg
, interfaceBackgroundDangerous: interfaceBackgroundDangerousDark
, interfaceDangerousText: interfaceDangerousTextDark
, interfaceBackgroundDisabled: darken 0.3 interfaceBackgroundDark
, interfaceTextDisabled: (desaturate 0.3 >>> lighten 0.25) interfaceBackgroundDark
, interfaceBackgroundHighlight: lighten 0.1 interfaceBackgroundDark
, interfaceBackgroundShadow: darken 0.1 interfaceBackgroundDark
, inputBackground: darkBg
, inputBorder: lighten 0.17 darkBg
, success
, success: successDark
, successText
, required
, invalid
, invalidText
, highlight: highlightDark
, highlightDisabled: (desaturate 0.76 >>> darken 0.32) highlightDark
, highlightLighter: withAlpha 0.2 (Color.lighten 0.5 highlightDark)
, highlightDarker: withAlpha 0.4 (Color.darken 0.5 highlightDark)
, highlightRotatedForwards: highlightDark # rotateHue 30.0
@ -194,9 +202,21 @@ defaultColours =
interfaceBackgroundDark = Color.hsl 240.0 0.10 0.33
interfaceBackground = lightBg
interfaceBackgroundDangerous = interfaceBackground
interfaceDangerousText = invalid
interfaceBackgroundDangerousDark = Color.hsl 340.0 0.55 0.30
interfaceDangerousTextDark = Color.hsl 340.0 1.0 0.90
highlightText = Color.rgb 0xFF 0xFF 0xFF
success = Color.rgb 20 200 60
success = Color.rgb 10 150 25
successDark = Color.rgb 20 200 60
successText = Color.rgb 250 250 250
@ -232,6 +252,9 @@ type FlatTheme a =
, background100 ∷ a
, backgroundInverted ∷ a
, interfaceBackground ∷ a
, interfaceBackgroundDangerous ∷ a
, interfaceDangerousText ∷ a
, interfaceBackgroundDisabled ∷ a
, interfaceTextDisabled ∷ a
, interfaceBackgroundHighlight ∷ a
, interfaceBackgroundShadow ∷ a
@ -242,6 +265,7 @@ type FlatTheme a =
, highlightRotatedForwards ∷ a
, highlightDarker ∷ a
, highlightLighter ∷ a
, highlightDisabled ∷ a
, highlightText ∷ a
, success ∷ a
, successText ∷ a

View File

@ -0,0 +1,21 @@
module Yoga.Block.Icon.SVG.Cross where
import React.Basic (JSX)
import React.Basic.DOM.SVG as SVG
cross ∷ JSX
cross =
SVG.svg
{ viewBox: "0 0 100 100"
, xmlns: "http://www.w3.org/2000/svg"
, fillRule: "evenodd"
, clipRule: "evenodd"
, strokeLinejoin: "round"
, strokeMiterlimit: "2"
, children:
[ SVG.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: "var(--stroke-colour)"
}
]
}

View File

@ -7,6 +7,7 @@ module Yoga.Block.Icon.SVG
, module Yoga.Block.Icon.SVG.Key
, module Yoga.Block.Icon.SVG.SimpleKey
, module Yoga.Block.Icon.SVG.QuestionMark
, module Yoga.Block.Icon.SVG.Cross
) where
import Yoga.Block.Icon.SVG.On (on)
@ -17,3 +18,4 @@ import Yoga.Block.Icon.SVG.EyeOpen (eyeOpen)
import Yoga.Block.Icon.SVG.Key (key)
import Yoga.Block.Icon.SVG.SimpleKey (simpleKey)
import Yoga.Block.Icon.SVG.QuestionMark (questionMark)
import Yoga.Block.Icon.SVG.Cross (cross)

View File

@ -0,0 +1,25 @@
module Yoga.Block.Icon.SVG.Warn where
import React.Basic (JSX)
import React.Basic.DOM as R
import React.Basic.DOM.SVG as SVG
warn :: JSX
warn = SVG.svg
{ viewBox: "0 0 100 100"
, xmlns: "http://www.w3.org/2000/svg"
, fillRule: "evenodd"
, clipRule: "evenodd"
, strokeLinejoin: "round"
, strokeMiterlimit: "2"
, children:
[ SVG.path
{ fill: "none"
, d: "M0 0h100v100H0z"
}
, SVG.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"
}
]
}

View File

@ -0,0 +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>

After

Width:  |  Height:  |  Size: 487 B

View File

@ -0,0 +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>

After

Width:  |  Height:  |  Size: 540 B

View File

@ -36,15 +36,13 @@ cluster =
, el Cluster.component
{ style: css { backgroundColor: "hotpink" }
}
[ R.div_
$ [ power
( R.div
{ children: [ R.text "Content" ]
, style: css { backgroundColor: "teal" }
}
)
30
]
[ power
( R.div
{ children: [ R.text "Content" ]
, style: css { backgroundColor: "teal" }
}
)
30
]
, R.h2_ [ R.text "Zero Space" ]
, el Cluster.component
@ -52,10 +50,8 @@ cluster =
, space: "0"
, justify: "flex-end"
}
[ R.div_
[ R.div { children: [ R.text "Child 1" ], style: css { backgroundColor: "teal" } }
, R.div { children: [ R.text "Child 2" ], style: css { backgroundColor: "rebeccapurple" } }
]
[ R.div { children: [ R.text "Child 1" ], style: css { backgroundColor: "teal" } }
, R.div { children: [ R.text "Child 2" ], style: css { backgroundColor: "rebeccapurple" } }
]
]
]

View File

@ -1,6 +1,7 @@
module Yoga.Block.Layout.Cluster.View (component, Props, PropsF) where
import Yoga.Prelude.View
import React.Basic.DOM as R
import Yoga.Block.Layout.Cluster.Style as Style
type PropsF f =
@ -25,4 +26,5 @@ rawComponent =
$ emotionDiv ref props
{ className: "ry-cluster " <>? props.className
, css: Style.cluster props
, children: [ R.div' </ {} /> props.children ]
}

View File

@ -7,7 +7,7 @@ import React.Basic.DOM as R
spec ∷ Spec Unit
spec =
after_ cleanup do
describe "The cluster" do
describe "The switcher" do
it "renders without errors" do
void
$ renderComponent Switcher.component {}