Visible at the beginning

This commit is contained in:
Mark Eibes 2020-12-13 13:02:48 +01:00
parent 006d5b0c4e
commit 5c239426fc
4 changed files with 61 additions and 46 deletions

View File

@ -11,7 +11,7 @@ on:
jobs:
build:
name: Test, Bundle, and Dockerise
name: Test, and Build Storybook
runs-on: ubuntu-20.04
steps:

View File

@ -18,12 +18,13 @@ segmented = styles
, margin: _0
, padding: _0
, width: auto
, overflow: visible
}
activeElement ∷ Style
activeElement =
css
{ position: fixed
{ position: absolute
, borderRadius: str "8px"
, background: str colour.interfaceBackground
, border: str $ i "1px solid " colour.interfaceBackgroundShadow
@ -32,7 +33,8 @@ activeElement =
, boxShadow: str "0 0 1px rgba(0,0,0,0.55)"
, margin: _0
, padding: _0
, zIndex: str "0"
, zIndex: str "3"
, overflow: visible
}
container ∷ Style
@ -45,6 +47,7 @@ container =
, border: str $ i "1px solid " colour.background15
, borderBottom: str $ i "1px solid " colour.background20
, padding: _0
, overflow: visible
}
button ∷ { isFirst ∷ Boolean, isLast ∷ Boolean } -> Style
@ -55,15 +58,18 @@ button { isFirst, isLast } =
, color: str colour.text
, border: none
, margin: _0
, padding: _0
, padding: str "var(--s-4)"
, paddingLeft: _0
, paddingRight: _0
, fontSize: str "var(--s0)"
, overflow: visible
, boxSizing: borderBox
, zIndex: str "3"
, "&:active": nest { outline: str "0" } -- ensures no outline on click in Chrome
, "&:focus": nest { outline: none }
, "&:focus > .ry-segmented-button__content":
nest
{ boxShadow: str $ i "0px 0px 0px var(--s-4) " colour.highlight
{ border: str $ i "var(--s-4) solid " colour.highlight
}
}
@ -72,12 +78,16 @@ buttonContent { isFirst, isLast } =
css
{ "&:active": nest { outline: str "0" } -- ensures no outline on click in Chrome
, "&:focus": nest { outline: none }
, display: inlineBlock
, top: str "-3px"
, padding: str "var(--s-4)"
, paddingLeft: str if isFirst then "var(--s0)" else "calc(var(--s0)*0.9)"
, paddingRight: str if isLast then "var(--s0)" else "calc(var(--s0)*0.9)"
, borderRadius: str "8px"
, boxSizing: borderBox
, border: str $ i "var(--s-4) solid transparent"
, height: _100percent
, margin: _0
, overflow: visible
}
wrapper ∷ Style
@ -86,4 +96,5 @@ wrapper =
{ display: flex
, alignItems: center
, justifyContent: center
, overflow: visible
}

View File

@ -1,8 +1,7 @@
module Yoga.Block.Atom.Segmented.View (component, Props, MandatoryProps, PropsF, ComponentProps) where
import Prelude
import Yoga.Prelude.View
import Control.Monad.Maybe.Trans (MaybeT(..), lift, runMaybeT)
import Control.Monad.Maybe.Trans (MaybeT(..), runMaybeT)
import Control.Monad.Trans.Class (lift)
import Data.Array as A
import Data.FoldableWithIndex (foldMapWithIndex)
@ -11,7 +10,7 @@ import Data.Traversable (traverse)
import Effect.Aff (Milliseconds(..), delay)
import Effect.Unsafe (unsafePerformEffect)
import Foreign.Object as Object
import Framer.Motion (VariantLabel)
import Framer.Motion (Animate, VariantLabel, Variants)
import Framer.Motion as Motion
import Hooks.Key as Key
import Hooks.UseResize (useResize)
@ -36,7 +35,6 @@ type PropsF f =
type MandatoryProps r =
( activeItemRefs ∷ Array (Ref (Nullable Node))
, previousActiveItemIndex ∷ Int
, activeItemIndex ∷ Int
| r
)
@ -47,36 +45,45 @@ type Props =
activeComponent ∷ ∀ p p_. Union (MandatoryProps p) p_ Props => ReactComponent { | MandatoryProps p }
activeComponent = rawActiveComponent
indexToVariant ∷ Int -> VariantLabel
indexToVariant = show >>> unsafeCoerce
rawActiveComponent ∷ ∀ p. ReactComponent { | p }
rawActiveComponent =
mkForwardRefComponent "SegmentedActive" do
\(props ∷ { | Props }) ref -> React.do
maybeVariants /\ setVariants <- useState' Nothing
animationVariants /\ setVariants <- useState' []
let
computeStyles = do
maybeSt <- runMaybeT $ traverse getStyle props.activeItemRefs
unless (maybeVariants == maybeSt) do
for_ maybeSt (setVariants <<< Just)
computeVariants = do
styles <- traverse getStyle props.activeItemRefs
unless (animationVariants == styles) do
setVariants styles # lift
useLayoutEffectAlways do
computeStyles
mempty
runMaybeT computeVariants *> mempty
let
variants ∷ Variants
variants =
Motion.variants $ animationVariants
# foldMapWithIndex (\i s -> Object.singleton (show i) (css s))
# unsafeCoerce
animate ∷ Animate
animate = Motion.animate (indexToVariant props.activeItemIndex)
clusterProps ∷ { | Cluster.Props }
clusterProps = pick props
activeElement =
styledLeaf Motion.div
{ css: Style.activeElement
, className: "ry-active-segmented-element"
, initial: (unsafeCoerce <<< show) props.previousActiveItemIndex
, transition: Motion.transition { type: "tween", duration: 0.2, ease: "easeOut" }
, variants:
Motion.variants $ maybeVariants
# fromMaybe []
# foldMapWithIndex (\i s -> Object.singleton (show i) (css s))
# unsafeCoerce
, animate: Motion.animate ((unsafeCoerce <<< show $ props.activeItemIndex) ∷ VariantLabel)
, _aria: Object.fromHomogeneous { hidden: "true" }
}
guard (animationVariants /= [])
$ styledLeaf Motion.div
{ css: Style.activeElement
, className: "ry-active-segmented-element"
, initial: Motion.initial (indexToVariant props.activeItemIndex)
, transition:
Motion.transition
{ type: "tween", duration: 0.2, ease: "easeOut" }
, variants
, animate
, _aria: Object.fromHomogeneous { hidden: "true" }
, ref
}
children =
[ E.element R.div'
{ className: "ry-segmented"
@ -86,14 +93,12 @@ rawActiveComponent =
}
]
pure
$ E.element
Cluster.component
( clusterProps
{ children = children
, justify = "center"
, space = "var(--s5)"
}
)
$ E.element Cluster.component
$ clusterProps
{ children = children
, justify = "center"
, space = "var(--s5)"
}
getStyle ∷
Ref (Nullable Node) ->
@ -139,7 +144,6 @@ component ∷ ReactComponent ComponentProps
component =
unsafePerformEffect
$ reactComponent "Segmented" \({ buttonContents, activeIndex, updateActiveIndex } ∷ ComponentProps) -> React.do
previousActiveIndex /\ setPreviousActiveIndex <- useState' 0
-------------------------------------------
-- Store button refs for animation purposes
itemRefs /\ setItemRefs <- useState' []
@ -151,9 +155,11 @@ component =
-- Support keyboard input
let
maxIndex = A.length buttonContents - 1
updateIndex idx = do
updateActiveIndex idx
updateTo toIndex = do
itemRefs # blurAtIndex activeIndex
updateActiveIndex toIndex
updateIndex toIndex
itemRefs # focusAtIndex toIndex
useKeyDown case _ of
Key.Right ->
@ -174,9 +180,6 @@ component =
refs <- traverse (const createRef) buttonContents
setItemRefs refs
let
updateIndex idx = do
setPreviousActiveIndex activeIndex
updateActiveIndex idx
children ∷ Array JSX
children = A.mapWithIndex contentToChild refsAndContents
refsAndContents ∷ Array ({ id ∷ String, value ∷ String } /\ Ref (Nullable Node))
@ -215,7 +218,6 @@ component =
[ styled activeComponent
{ activeItemRefs: itemRefs
, activeItemIndex: activeIndex
, previousActiveItemIndex: previousActiveIndex
, css: Style.container
, className: "ry-segmented-container"
}

View File

@ -16,6 +16,8 @@ global =
$ css
{ minHeight: 100.0 # vh
, minWidth: 100.0 # vw
, lineHeight: str "1.15"
, "-webkit-text-size-adjust": _100percent
}
, ":root":
nested $ variables
@ -212,8 +214,8 @@ variables =
fontVariables ∷ { main ∷ String, mono ∷ String } -> Style
fontVariables { main, mono } =
css
{ "--mainFont": str $ main <> ", monospace"
, "--monoFont": str $ mono <> ", monospace"
{ "--mainFont": str $ main <> """, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol""""
, "--monoFont": str $ mono <> ", monospace, monospace"
}
input ∷ StyleProperty