noredink-ui/styleguide-app/Examples/Menu.elm

303 lines
9.9 KiB
Elm
Raw Normal View History

2020-05-07 22:46:21 +03:00
module Examples.Menu exposing (Msg, State, example)
{-|
@docs Msg, State, example
-}
import Accessibility.Styled exposing (..)
2021-02-11 03:01:27 +03:00
import Browser.Dom as Dom
2020-05-07 22:46:21 +03:00
import Category exposing (Category(..))
import CommonControls
import Debug.Control as Control exposing (Control)
2022-03-24 23:14:21 +03:00
import Debug.Control.Extra as ControlExtra
import Debug.Control.View as ControlView
2020-05-07 22:46:21 +03:00
import Example exposing (Example)
2022-03-15 21:06:13 +03:00
import KeyboardSupport exposing (Key(..))
import Nri.Ui.ClickableText.V3 as ClickableText
2021-08-28 00:56:17 +03:00
import Nri.Ui.Menu.V3 as Menu
import Nri.Ui.UiIcon.V1 as UiIcon
import Set exposing (Set)
2021-02-11 03:01:27 +03:00
import Task
2022-03-24 23:06:40 +03:00
import ViewHelpers exposing (viewExamples)
2020-05-07 22:46:21 +03:00
moduleName : String
moduleName =
"Menu"
version : Int
version =
3
2020-05-07 22:46:21 +03:00
{-| -}
example : Example State Msg
example =
{ name = moduleName
, version = version
2020-05-07 22:46:21 +03:00
, state = init
, update = update
, subscriptions = \_ -> Sub.none
2021-11-12 01:54:56 +03:00
, categories = [ Layout ]
, keyboardSupport =
[ { keys = [ Space ], result = "Opens the menu" }
, { keys = [ Enter ], result = "Opens the menu" }
2021-03-18 20:35:46 +03:00
, { keys = [ Tab ], result = "Takes focus out of the menu to the next focusable element & closes the menu." }
, { keys = [ Tab, Shift ], result = "Takes focus out of the menu to the previous focusable element & closes the menu." }
, { keys = [ Arrow KeyboardSupport.Up ]
, result = "If menu is closed, opens the menu & selects the last menu item.\nIf menu is open, moves the focus to the previous menu item."
}
, { keys = [ Arrow KeyboardSupport.Down ]
, result = "If menu is closed, opens the menu & selects the first menu item.\nIf menu is open, moves the focus to the next menu item."
}
, { keys = [ Esc ], result = "Closes the menu" }
]
2021-11-05 21:19:08 +03:00
, preview = []
, view = view
2020-05-07 22:46:21 +03:00
}
view : State -> List (Html Msg)
view state =
let
2022-03-24 23:14:21 +03:00
menuAttributes =
(Control.currentValue state.settings).menuAttributes
|> List.map Tuple.second
defaultButtonAttributes =
(Control.currentValue state.settings).buttonAttributes
|> List.map Tuple.second
isOpen name =
case state.openMenu of
Just open ->
open == name
Nothing ->
False
in
[ ControlView.view
{ update = UpdateControls
, settings = state.settings
, toExampleCode =
\settings ->
-- TODO: generate code
[]
}
2022-03-24 23:06:40 +03:00
, viewExamples
2022-03-24 23:44:36 +03:00
[ ( "Menu.button"
2022-03-24 23:06:40 +03:00
, Menu.view
2022-03-24 23:14:21 +03:00
(menuAttributes
++ List.filterMap identity
[ Just <| Menu.buttonId "1stPeriodEnglish__button"
, Just <| Menu.menuId "1stPeriodEnglish__menu"
]
)
2022-03-24 23:06:40 +03:00
{ isOpen = isOpen "1stPeriodEnglish"
, focusAndToggle = FocusAndToggle "1stPeriodEnglish"
, entries =
[ Menu.entry "hello-button" <|
\attrs ->
ClickableText.button "Hello"
[ ClickableText.onClick (ConsoleLog "Hello")
, ClickableText.small
, ClickableText.custom attrs
]
, Menu.group "Menu group"
[ Menu.entry "gift-button" <|
\attrs ->
2022-03-24 23:06:40 +03:00
ClickableText.button "Gift"
[ ClickableText.onClick (ConsoleLog "Gift")
, ClickableText.small
, ClickableText.custom attrs
, ClickableText.icon UiIcon.gift
]
, Menu.entry "null-button" <|
\attrs ->
ClickableText.button "Nope!"
[ ClickableText.onClick (ConsoleLog "Nope!")
, ClickableText.small
, ClickableText.custom attrs
, ClickableText.icon UiIcon.null
]
, Menu.entry "no-icon-button" <|
\attrs ->
ClickableText.button "Skip"
[ ClickableText.onClick (ConsoleLog "Skip")
, ClickableText.small
, ClickableText.custom attrs
]
]
2022-03-24 23:06:40 +03:00
, Menu.entry "performance-button" <|
\attrs ->
ClickableText.button "Performance"
[ ClickableText.onClick (ConsoleLog "Performance")
, ClickableText.small
, ClickableText.custom attrs
]
]
, button = Menu.button defaultButtonAttributes "1st Period English with Mx. Trainer"
2022-03-24 23:06:40 +03:00
}
)
2022-03-24 23:44:36 +03:00
, ( "Menu.custom"
2022-03-24 23:06:40 +03:00
, Menu.view
2022-03-24 23:14:21 +03:00
(menuAttributes
++ List.filterMap identity
[ Just <| Menu.buttonId "icon-button-with-menu__button"
, Just <| Menu.menuId "icon-button-with-menu__menu"
]
2022-03-24 23:06:40 +03:00
)
{ entries =
[ Menu.entry "see-more-button" <|
\attrs ->
ClickableText.button "See more"
[ ClickableText.onClick (ConsoleLog "See more")
, ClickableText.small
, ClickableText.custom attrs
, ClickableText.icon UiIcon.seeMore
]
]
, isOpen = isOpen "icon-button-with-menu"
, focusAndToggle = FocusAndToggle "icon-button-with-menu"
, button =
Menu.custom <|
\buttonAttributes ->
button buttonAttributes [ text "Custom Menu trigger button" ]
2022-03-24 23:06:40 +03:00
}
)
]
]
2020-05-07 22:46:21 +03:00
{-| -}
init : State
init =
{ openMenu = Nothing
, checkboxChecked = False
, openTooltips = Set.empty
, settings = initSettings
}
2020-05-07 22:46:21 +03:00
{-| -}
type alias State =
{ openMenu : Maybe Id
, checkboxChecked : Bool
, openTooltips : Set String
, settings : Control Settings
}
type alias Settings =
2022-03-24 23:14:21 +03:00
{ menuAttributes : List ( String, Menu.Attribute Msg )
, buttonAttributes : List ( String, Menu.ButtonAttribute )
}
initSettings : Control Settings
initSettings =
Control.record Settings
|> Control.field "Menu attributes" controlMenuAttributes
|> Control.field "Button attributes" controlButtonAttributes
2022-03-24 23:14:21 +03:00
controlMenuAttributes : Control (List ( String, Menu.Attribute msg ))
controlMenuAttributes =
ControlExtra.list
|> ControlExtra.optionalListItem "alignment" controlAlignment
|> ControlExtra.optionalBoolListItem "isDisabled" ( "Menu.isDisabled True", Menu.isDisabled True )
|> ControlExtra.optionalListItem "menuWidth" controlMenuWidth
2022-03-24 23:14:21 +03:00
controlAlignment : Control ( String, Menu.Attribute msg )
controlAlignment =
Control.choice
[ ( "Left"
, Control.value ( "Menu.alignment Menu.Left", Menu.alignment Menu.Left )
)
, ( "Right"
, Control.value ( "Menu.alignment Menu.Right", Menu.alignment Menu.Right )
)
]
controlMenuWidth : Control ( String, Menu.Attribute msg )
controlMenuWidth =
Control.map
(\val -> ( "Menu.menuWidth " ++ String.fromInt val, Menu.menuWidth val ))
(ControlExtra.int 220)
controlButtonAttributes : Control (List ( String, Menu.ButtonAttribute ))
controlButtonAttributes =
ControlExtra.list
|> CommonControls.icon moduleName Menu.icon
|> ControlExtra.optionalBoolListItemDefaultTrue "hasBorder" ( "Menu.hasBorder False", Menu.hasBorder False )
|> ControlExtra.optionalListItem "buttonWidth" controlButtonWidth
|> ControlExtra.optionalListItem "wrapping" controlWrapping
controlButtonWidth : Control ( String, Menu.ButtonAttribute )
controlButtonWidth =
Control.map
(\val -> ( "Menu.buttonWidth " ++ String.fromInt val, Menu.buttonWidth val ))
(ControlExtra.int 220)
controlWrapping : Control ( String, Menu.ButtonAttribute )
controlWrapping =
Control.choice
[ ( "WrapAndExpandTitle"
, Control.value ( "Menu.wrapping Menu.WrapAndExpandTitle", Menu.wrapping Menu.WrapAndExpandTitle )
)
, ( "TruncateTitle"
, Control.value ( "Menu.wrapping Menu.TruncateTitle", Menu.wrapping Menu.TruncateTitle )
)
]
2020-05-07 22:46:21 +03:00
{-| -}
type Msg
= ConsoleLog String
| UpdateControls (Control Settings)
| FocusAndToggle String { isOpen : Bool, focus : Maybe String }
2021-02-11 03:01:27 +03:00
| Focused (Result Dom.Error ())
2020-05-07 22:46:21 +03:00
{-| -}
update : Msg -> State -> ( State, Cmd Msg )
update msg state =
case msg of
ConsoleLog message ->
2022-03-15 21:06:13 +03:00
( Debug.log "Menu Example" message |> always state, Cmd.none )
UpdateControls configuration ->
( { state | settings = configuration }, Cmd.none )
FocusAndToggle id { isOpen, focus } ->
( { state
| openMenu =
if isOpen then
Just id
else
Nothing
}
, Maybe.map (\idString -> Task.attempt Focused (Dom.focus idString)) focus
|> Maybe.withDefault Cmd.none
)
2021-02-11 03:01:27 +03:00
Focused _ ->
( state, Cmd.none )
-- INTERNAL
type alias Id =
String