2020-05-07 22:46:21 +03:00
|
|
|
module Examples.Menu exposing (Msg, State, example)
|
|
|
|
|
|
|
|
{-|
|
|
|
|
|
|
|
|
@docs Msg, State, example
|
|
|
|
|
|
|
|
-}
|
|
|
|
|
2022-03-24 23:43:57 +03:00
|
|
|
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(..))
|
2022-03-24 23:41:31 +03:00
|
|
|
import CommonControls
|
2020-05-07 23:22:49 +03:00
|
|
|
import Debug.Control as Control exposing (Control)
|
2022-03-24 23:14:21 +03:00
|
|
|
import Debug.Control.Extra as ControlExtra
|
2022-03-24 23:05:08 +03:00
|
|
|
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(..))
|
2020-05-07 23:22:49 +03:00
|
|
|
import Nri.Ui.ClickableText.V3 as ClickableText
|
2021-08-28 00:56:17 +03:00
|
|
|
import Nri.Ui.Menu.V3 as Menu
|
2020-05-07 23:22:49 +03:00
|
|
|
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
|
|
|
|
|
|
|
|
2022-03-24 23:05:08 +03:00
|
|
|
moduleName : String
|
|
|
|
moduleName =
|
|
|
|
"Menu"
|
|
|
|
|
|
|
|
|
|
|
|
version : Int
|
|
|
|
version =
|
|
|
|
3
|
|
|
|
|
|
|
|
|
2020-05-07 22:46:21 +03:00
|
|
|
{-| -}
|
|
|
|
example : Example State Msg
|
|
|
|
example =
|
2022-03-24 23:05:08 +03:00
|
|
|
{ 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 ]
|
2021-02-11 02:50:33 +03:00
|
|
|
, 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." }
|
2021-02-11 02:50:33 +03:00
|
|
|
, { keys = [ Arrow KeyboardSupport.Up ]
|
2021-03-05 00:47:18 +03:00
|
|
|
, 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."
|
2021-02-11 02:50:33 +03:00
|
|
|
}
|
|
|
|
, { keys = [ Arrow KeyboardSupport.Down ]
|
2021-03-05 00:47:18 +03:00
|
|
|
, 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."
|
2021-02-11 02:50:33 +03:00
|
|
|
}
|
|
|
|
, { keys = [ Esc ], result = "Closes the menu" }
|
|
|
|
]
|
2021-11-05 21:19:08 +03:00
|
|
|
, preview = []
|
2020-05-07 23:22:49 +03:00
|
|
|
, view = view
|
2020-05-07 22:46:21 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-05-07 23:22:49 +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
|
|
|
|
|
2022-03-24 23:31:34 +03:00
|
|
|
defaultButtonAttributes =
|
|
|
|
(Control.currentValue state.settings).buttonAttributes
|
|
|
|
|> List.map Tuple.second
|
|
|
|
|
2020-05-07 23:22:49 +03:00
|
|
|
isOpen name =
|
|
|
|
case state.openMenu of
|
|
|
|
Just open ->
|
|
|
|
open == name
|
|
|
|
|
|
|
|
Nothing ->
|
|
|
|
False
|
|
|
|
in
|
2022-03-24 23:05:08 +03:00
|
|
|
[ 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:05:08 +03:00
|
|
|
)
|
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" <|
|
2022-03-24 23:05:08 +03:00
|
|
|
\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:05:08 +03:00
|
|
|
]
|
|
|
|
]
|
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
|
|
|
|
]
|
|
|
|
]
|
2022-03-24 23:41:31 +03:00
|
|
|
, 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 ->
|
2022-03-24 23:43:57 +03:00
|
|
|
button buttonAttributes [ text "Custom Menu trigger button" ]
|
2022-03-24 23:06:40 +03:00
|
|
|
}
|
|
|
|
)
|
|
|
|
]
|
2020-05-07 23:22:49 +03:00
|
|
|
]
|
|
|
|
|
|
|
|
|
2020-05-07 22:46:21 +03:00
|
|
|
{-| -}
|
|
|
|
init : State
|
|
|
|
init =
|
2020-05-07 23:22:49 +03:00
|
|
|
{ openMenu = Nothing
|
|
|
|
, checkboxChecked = False
|
|
|
|
, openTooltips = Set.empty
|
2022-03-24 23:05:08 +03:00
|
|
|
, settings = initSettings
|
2020-05-07 23:22:49 +03:00
|
|
|
}
|
2020-05-07 22:46:21 +03:00
|
|
|
|
|
|
|
|
|
|
|
{-| -}
|
|
|
|
type alias State =
|
2020-05-07 23:22:49 +03:00
|
|
|
{ openMenu : Maybe Id
|
|
|
|
, checkboxChecked : Bool
|
|
|
|
, openTooltips : Set String
|
2022-03-24 23:05:08 +03:00
|
|
|
, settings : Control Settings
|
2020-05-07 23:22:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-03-24 23:05:08 +03:00
|
|
|
type alias Settings =
|
2022-03-24 23:14:21 +03:00
|
|
|
{ menuAttributes : List ( String, Menu.Attribute Msg )
|
2022-03-24 23:31:34 +03:00
|
|
|
, buttonAttributes : List ( String, Menu.ButtonAttribute )
|
2022-03-24 23:05:08 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
initSettings : Control Settings
|
|
|
|
initSettings =
|
|
|
|
Control.record Settings
|
2022-03-24 23:31:34 +03:00
|
|
|
|> Control.field "Menu attributes" controlMenuAttributes
|
|
|
|
|> Control.field "Button attributes" controlButtonAttributes
|
2022-03-24 23:05:08 +03:00
|
|
|
|
|
|
|
|
2022-03-24 23:14:21 +03:00
|
|
|
controlMenuAttributes : Control (List ( String, Menu.Attribute msg ))
|
|
|
|
controlMenuAttributes =
|
|
|
|
ControlExtra.list
|
|
|
|
|> ControlExtra.optionalListItem "alignment" controlAlignment
|
2022-03-24 23:17:13 +03:00
|
|
|
|> ControlExtra.optionalBoolListItem "isDisabled" ( "Menu.isDisabled True", Menu.isDisabled True )
|
2022-03-24 23:22:20 +03:00
|
|
|
|> 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 )
|
|
|
|
)
|
|
|
|
]
|
|
|
|
|
|
|
|
|
2022-03-24 23:22:20 +03:00
|
|
|
controlMenuWidth : Control ( String, Menu.Attribute msg )
|
|
|
|
controlMenuWidth =
|
|
|
|
Control.map
|
|
|
|
(\val -> ( "Menu.menuWidth " ++ String.fromInt val, Menu.menuWidth val ))
|
|
|
|
(ControlExtra.int 220)
|
|
|
|
|
|
|
|
|
2022-03-24 23:31:34 +03:00
|
|
|
controlButtonAttributes : Control (List ( String, Menu.ButtonAttribute ))
|
|
|
|
controlButtonAttributes =
|
|
|
|
ControlExtra.list
|
2022-03-24 23:41:31 +03:00
|
|
|
|> CommonControls.icon moduleName Menu.icon
|
2022-03-24 23:31:34 +03:00
|
|
|
|> ControlExtra.optionalBoolListItemDefaultTrue "hasBorder" ( "Menu.hasBorder False", Menu.hasBorder False )
|
2022-03-24 23:34:39 +03:00
|
|
|
|> ControlExtra.optionalListItem "buttonWidth" controlButtonWidth
|
2022-03-24 23:37:16 +03:00
|
|
|
|> ControlExtra.optionalListItem "wrapping" controlWrapping
|
2022-03-24 23:34:39 +03:00
|
|
|
|
|
|
|
|
|
|
|
controlButtonWidth : Control ( String, Menu.ButtonAttribute )
|
|
|
|
controlButtonWidth =
|
|
|
|
Control.map
|
|
|
|
(\val -> ( "Menu.buttonWidth " ++ String.fromInt val, Menu.buttonWidth val ))
|
|
|
|
(ControlExtra.int 220)
|
2022-03-24 23:31:34 +03:00
|
|
|
|
|
|
|
|
2022-03-24 23:37:16 +03:00
|
|
|
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
|
2022-03-24 23:43:57 +03:00
|
|
|
= ConsoleLog String
|
2022-03-24 23:05:08 +03:00
|
|
|
| UpdateControls (Control Settings)
|
2021-02-11 23:26:36 +03:00
|
|
|
| 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
|
2020-05-07 23:22:49 +03:00
|
|
|
ConsoleLog message ->
|
2022-03-15 21:06:13 +03:00
|
|
|
( Debug.log "Menu Example" message |> always state, Cmd.none )
|
2020-05-07 23:22:49 +03:00
|
|
|
|
2022-03-24 23:05:08 +03:00
|
|
|
UpdateControls configuration ->
|
|
|
|
( { state | settings = configuration }, Cmd.none )
|
2020-05-07 23:22:49 +03:00
|
|
|
|
2021-02-11 23:26:36 +03:00
|
|
|
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 )
|
|
|
|
|
2020-05-07 23:22:49 +03:00
|
|
|
|
|
|
|
|
|
|
|
-- INTERNAL
|
|
|
|
|
|
|
|
|
|
|
|
type alias Id =
|
|
|
|
String
|