mirror of
https://github.com/rowtype-yoga/ry-blocks.git
synced 2024-08-18 01:30:31 +03:00
Visible at the beginning
This commit is contained in:
parent
006d5b0c4e
commit
5c239426fc
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -11,7 +11,7 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Test, Bundle, and Dockerise
|
||||
name: Test, and Build Storybook
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user