Change approach -- add new animated icon module

This commit is contained in:
Tessa Kelly 2022-09-01 15:05:35 -06:00
parent 7b9c97b5c5
commit 38ec34dc0a
7 changed files with 233 additions and 104 deletions

View File

@ -7,6 +7,7 @@
"exposed-modules": [
"Nri.Ui",
"Nri.Ui.Accordion.V3",
"Nri.Ui.AnimatedIcon.V1",
"Nri.Ui.AssetPath",
"Nri.Ui.AssignmentIcon.V2",
"Nri.Ui.Balloon.V1",

View File

@ -0,0 +1,81 @@
module Nri.Ui.AnimatedIcon.V1 exposing (mobileOpenClose)
import Css
import Css.Animations
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.MediaQuery.V1 as MediaQuery
import Nri.Ui.Svg.V1
import Svg.Styled as Svg
import Svg.Styled.Attributes as Attributes
animatedXHamburger : List ( List Css.Animations.Property, List Css.Animations.Property ) -> Nri.Ui.Svg.V1.Svg
animatedXHamburger lineAnimations =
let
animate : ( List Css.Animations.Property, List Css.Animations.Property ) -> Svg.Attribute Never
animate ( start, end ) =
Attributes.css
[ Css.animationDuration (Css.ms 300)
, Css.property "animation-timing-function" "linear"
, Css.property "animation-fill-mode" "forwards"
, Css.animationName
(Css.Animations.keyframes
[ ( 0, start )
, ( 20, [ Css.Animations.custom "width" "25px" ] )
, ( 80, [ Css.Animations.custom "width" "25px" ] )
, ( 100, end )
]
)
]
line ( x_, y ) animation =
Svg.rect
[ Attributes.x (String.fromFloat x_)
, Attributes.y (String.fromFloat y)
, Attributes.width "25"
, Attributes.height "5"
, Attributes.rx "2.5"
, animate animation
]
[]
in
Nri.Ui.Svg.V1.init "0 0 25 27"
(List.map2 identity
[ line ( 0, 0 ), line ( 0, 10 ), line ( 0, 20 ) ]
lineAnimations
)
topLineAsX : List Css.Animations.Property
topLineAsX =
[ Css.Animations.transform
[ Css.rotate (Css.deg 45)
, Css.translate3d (Css.px 3) (Css.px -1) Css.zero
]
, Css.Animations.custom "width" "32px"
]
middleLineAsX : List Css.Animations.Property
middleLineAsX =
[ Css.Animations.opacity (Css.num 0) ]
bottomLineAsX : List Css.Animations.Property
bottomLineAsX =
[ Css.Animations.transform
[ Css.translate3d (Css.px -15) (Css.px 7.5) Css.zero
, Css.rotate (Css.deg -45)
]
, Css.Animations.custom "width" "32px"
]
{-| -}
mobileOpenClose : Bool -> Nri.Ui.Svg.V1.Svg
mobileOpenClose isOpen =
animatedXHamburger
[ ( topLineAsX, [] )
, ( middleLineAsX, [] )
, ( bottomLineAsX, [] )
]

View File

@ -57,6 +57,7 @@ import Html.Styled
import Html.Styled.Attributes as Attributes
import Html.Styled.Events as Events
import Nri.Ui
import Nri.Ui.AnimatedIcon.V1 as AnimatedIcon
import Nri.Ui.ClickableSvg.V2 as ClickableSvg
import Nri.Ui.ClickableText.V3 as ClickableText
import Nri.Ui.Colors.V1 as Colors
@ -251,36 +252,30 @@ viewOpenCloseButton sidenavId navLabel_ { isOpen, toggle, isTooltipOpen, toggleT
name =
Maybe.withDefault "sidebar" navLabel_
( action, icon_, attributes ) =
( action, icon_ ) =
if isOpen then
( "Close " ++ name
, UiIcon.openClose
, [ ClickableSvg.iconForMobile UiIcon.hamburgerToX
]
)
else
( "Open " ++ name
, UiIcon.openClose
|> Svg.withCss [ Css.transform (rotate (deg 180)) ]
, [ ClickableSvg.withBorder
, ClickableSvg.iconForMobile UiIcon.xToHamburger
]
)
trigger tooltipAttributes =
ClickableSvg.button action
icon_
([ ClickableSvg.custom
[ ClickableSvg.custom
[ Aria.controls [ sidenavId ]
, Aria.expanded isOpen
]
, ClickableSvg.custom tooltipAttributes
, ClickableSvg.onClick (toggle (not isOpen))
, ClickableSvg.tertiary
]
++ attributes
)
, ClickableSvg.custom tooltipAttributes
, ClickableSvg.onClick (toggle (not isOpen))
, ClickableSvg.tertiary
, ClickableSvg.iconForMobile (AnimatedIcon.mobileOpenClose isOpen)
]
in
Tooltip.view
{ trigger = trigger

View File

@ -1,6 +1,5 @@
module Nri.Ui.UiIcon.V1 exposing
( xToHamburger, hamburgerToX
, seeMore, openClose, download, sort, gear, flipper, hamburger, kebab
( seeMore, openClose, download, sort, gear, flipper, hamburger, kebab
, archive, unarchive
, playInCircle, pauseInCircle, stopInCircle
, play, skip
@ -37,7 +36,6 @@ module Nri.Ui.UiIcon.V1 exposing
{-| How to add new icons: <https://paper.dropbox.com/doc/How-to-create-a-new-SVG-icon-for-use-in-Elm--Ay9uhSLfGUAix0ERIiJ0Dm8dAg-8WNqtARdr4EgjmYEHPeYD>
@docs xToHamburger, hamburgerToX
@docs seeMore, openClose, download, sort, gear, flipper, hamburger, kebab
@docs archive, unarchive
@docs playInCircle, pauseInCircle, stopInCircle
@ -985,88 +983,6 @@ hamburger =
]
animatedXHamburger : List ( List Css.Animations.Property, List Css.Animations.Property ) -> Nri.Ui.Svg.V1.Svg
animatedXHamburger lineAnimations =
let
animate : ( List Css.Animations.Property, List Css.Animations.Property ) -> Svg.Attribute Never
animate ( start, end ) =
Attributes.css
[ Css.animationDuration (Css.ms 300)
, Css.property "animation-timing-function" "linear"
, Css.property "animation-fill-mode" "forwards"
, Css.animationName
(Css.Animations.keyframes
[ ( 0, start )
, ( 20, [ Css.Animations.custom "width" "25px" ] )
, ( 80, [ Css.Animations.custom "width" "25px" ] )
, ( 100, end )
]
)
]
line ( x_, y ) animation =
Svg.rect
[ Attributes.x (String.fromFloat x_)
, Attributes.y (String.fromFloat y)
, Attributes.width "25"
, Attributes.height "5"
, Attributes.rx "2.5"
, animate animation
]
[]
in
Nri.Ui.Svg.V1.init "0 0 25 27"
(List.map2 identity
[ line ( 0, 0 ), line ( 0, 10 ), line ( 0, 20 ) ]
lineAnimations
)
topLineAsX : List Css.Animations.Property
topLineAsX =
[ Css.Animations.transform
[ Css.translate3d (Css.px 3) (Css.px -1) Css.zero
, Css.rotate (Css.deg 45)
]
, Css.Animations.custom "width" "32px"
]
middleLineAsX : List Css.Animations.Property
middleLineAsX =
[ Css.Animations.opacity (Css.num 0) ]
bottomLineAsX : List Css.Animations.Property
bottomLineAsX =
[ Css.Animations.transform
[ Css.translate3d (Css.px -15) (Css.px 7.5) Css.zero
, Css.rotate (Css.deg -45)
]
, Css.Animations.custom "width" "32px"
]
{-| -}
xToHamburger : Nri.Ui.Svg.V1.Svg
xToHamburger =
animatedXHamburger
[ ( topLineAsX, [] )
, ( middleLineAsX, [] )
, ( bottomLineAsX, [] )
]
{-| -}
hamburgerToX : Nri.Ui.Svg.V1.Svg
hamburgerToX =
animatedXHamburger
[ ( [], topLineAsX )
, ( [], middleLineAsX )
, ( [], bottomLineAsX )
]
{-| -}
kebab : Nri.Ui.Svg.V1.Svg
kebab =

View File

@ -2,6 +2,7 @@ module Examples exposing (Msg, State, all)
import Example exposing (Example)
import Examples.Accordion as Accordion
import Examples.AnimatedIcon as AnimatedIcon
import Examples.AssignmentIcon as AssignmentIcon
import Examples.Balloon as Balloon
import Examples.BreadCrumbs as BreadCrumbs
@ -60,6 +61,25 @@ all =
AccordionState childState ->
Just childState
_ ->
Nothing
)
, AnimatedIcon.example
|> Example.wrapMsg AnimatedIconMsg
(\msg ->
case msg of
AnimatedIconMsg childMsg ->
Just childMsg
_ ->
Nothing
)
|> Example.wrapState AnimatedIconState
(\msg ->
case msg of
AnimatedIconState childState ->
Just childState
_ ->
Nothing
)
@ -790,6 +810,7 @@ all =
type State
= AccordionState Accordion.State
| AnimatedIconState AnimatedIcon.State
| AssignmentIconState AssignmentIcon.State
| BalloonState Balloon.State
| BreadCrumbsState BreadCrumbs.State
@ -832,6 +853,7 @@ type State
type Msg
= AccordionMsg Accordion.Msg
| AnimatedIconMsg AnimatedIcon.Msg
| AssignmentIconMsg AssignmentIcon.Msg
| BalloonMsg Balloon.Msg
| BreadCrumbsMsg BreadCrumbs.Msg

View File

@ -0,0 +1,119 @@
module Examples.AnimatedIcon exposing (example, State, Msg)
{-|
@docs example, State, Msg
-}
import Category exposing (Category(..))
import Css
import Debug.Control as Control exposing (Control)
import Debug.Control.Extra as ControlExtra
import Debug.Control.View as ControlView
import Example exposing (Example)
import Examples.IconExamples as IconExamples
import Nri.Ui.AnimatedIcon.V1 as AnimatedIcon
import Nri.Ui.Heading.V3 as Heading
import Nri.Ui.Svg.V1 as Svg
moduleName : String
moduleName =
"AnimatedIcon"
version : Int
version =
1
{-| -}
example : Example State Msg
example =
{ name = moduleName
, version = version
, categories = [ Icons ]
, keyboardSupport = []
, state = init
, update = update
, subscriptions = \_ -> Sub.none
, preview =
IconExamples.preview
[ AnimatedIcon.mobileOpenClose False
, AnimatedIcon.mobileOpenClose True
]
, view =
\ellieLinkConfig state ->
let
attributes =
Control.currentValue state.settings
in
[ ControlView.view
{ ellieLinkConfig = ellieLinkConfig
, name = moduleName
, version = version
, update = UpdateSettings
, settings = state.settings
, mainType = Just "RootHtml.Html msg"
, extraCode = [ "import Nri.Ui.Svg.V1 as Svg" ]
, toExampleCode =
\settings ->
let
toCode viewName =
moduleName
++ "."
++ viewName
++ " "
++ Tuple.first settings.isOpen
++ "\n |> Svg.withCss [ Css.maxWidth (Css.px 45) ]"
++ "\n |> Svg.toHtml"
in
[ { sectionName = "Code"
, code = toCode "mobileOpenClose"
}
]
}
, Heading.h2 [ Heading.plaintext "Example" ]
, AnimatedIcon.mobileOpenClose (Tuple.second attributes.isOpen)
|> Svg.withCss [ Css.maxWidth (Css.px 45) ]
|> Svg.toHtml
]
}
{-| -}
type alias State =
{ settings : Control Settings
}
{-| -}
init : State
init =
{ settings = initSettings
}
type alias Settings =
{ isOpen : ( String, Bool )
}
initSettings : Control Settings
initSettings =
Control.record Settings
|> Control.field "isOpen" (ControlExtra.bool False)
{-| -}
type Msg
= UpdateSettings (Control Settings)
{-| -}
update : Msg -> State -> ( State, Cmd Msg )
update msg state =
case msg of
UpdateSettings settings ->
( { state | settings = settings }, Cmd.none )

View File

@ -52,12 +52,7 @@ example =
all : List Group
all =
[ ( "Interface with transitions"
, [ ( "xToHamburger", UiIcon.xToHamburger, [] )
, ( "hamburgerToX", UiIcon.hamburgerToX, [] )
]
)
, ( "Interface"
[ ( "Interface"
, [ ( "seeMore", UiIcon.seeMore, [] )
, ( "openClose", UiIcon.openClose, [] )
, ( "download", UiIcon.download, [] )