Use Select instead of Menu for icon selector

This commit is contained in:
Tessa Kelly 2022-07-08 18:23:43 -07:00
parent 2ff116155e
commit e17fffad52
4 changed files with 64 additions and 53 deletions

View File

@ -1,6 +1,7 @@
module Nri.Ui.Select.V8 exposing
( view, generateId
, Choice, choices
, ChoicesGroup, groupedChoices
, value
, Attribute, defaultDisplayText
, hiddenLabel, visibleLabel
@ -24,6 +25,7 @@ module Nri.Ui.Select.V8 exposing
### Input types
@docs Choice, choices
@docs ChoicesGroup, groupedChoices
### Input content
@ -160,6 +162,26 @@ noMargin removeMargin =
Attribute <| \config -> { config | noMarginTop = removeMargin }
{-| Groupings of choices (will be added _after_ isolated choices.)
-}
type alias ChoicesGroup value =
{ label : String
, choices : List (Choice value)
}
{-| -}
groupedChoices : (value -> String) -> List (ChoicesGroup value) -> Attribute value
groupedChoices valueToString optgroups =
Attribute
(\config ->
{ config
| valueToString = Just valueToString
, optgroups = optgroups
}
)
{-| A single possible choice.
-}
type alias Choice value =
@ -195,6 +217,7 @@ type alias Config value =
{ id : Maybe String
, value : Maybe value
, choices : List (Choice value)
, optgroups : List (ChoicesGroup value)
, valueToString : Maybe (value -> String)
, defaultDisplayText : Maybe String
, error : ErrorState
@ -211,6 +234,7 @@ defaultConfig =
{ id = Nothing
, value = Nothing
, choices = []
, optgroups = []
, valueToString = Nothing
, defaultDisplayText = Nothing
, error = InputErrorAndGuidanceInternal.noError
@ -255,6 +279,7 @@ view label attributes =
config
, viewSelect
{ choices = config.choices
, optgroups = config.optgroups
, current = config.value
, id = id_
, custom = config.custom
@ -268,6 +293,7 @@ view label attributes =
viewSelect :
{ choices : List (Choice a)
, optgroups : List (ChoicesGroup a)
, current : Maybe a
, id : String
, valueToString : Maybe (a -> String)
@ -278,23 +304,25 @@ viewSelect :
-> Html a
viewSelect config =
let
stringChoices =
toChoice valueToString choice =
{ label = choice.label
, idAndValue = generateId (valueToString choice.value)
, value = choice.value
}
( optionStringChoices, groupStringChoices ) =
case config.valueToString of
Just valueToString ->
List.map
(\choice ->
{ label = choice.label
, idAndValue = generateId (valueToString choice.value)
, value = choice.value
}
)
config.choices
( List.map (toChoice valueToString) config.choices
, List.concatMap (.choices >> List.map (toChoice valueToString)) config.optgroups
)
Nothing ->
[]
( [], [] )
valueLookup =
stringChoices
optionStringChoices
++ groupStringChoices
|> List.map (\x -> ( x.idAndValue, x.value ))
|> Dict.fromList
@ -327,10 +355,23 @@ viewSelect config =
else
config.current
viewGroupedChoices group =
Html.optgroup [ Attributes.attribute "label" group.label ]
(case config.valueToString of
Just valueToString ->
List.map
(toChoice valueToString >> viewChoice currentVal)
group.choices
Nothing ->
[]
)
in
stringChoices
|> List.map (viewChoice currentVal)
|> (++) defaultOption
(defaultOption
++ List.map (viewChoice currentVal) optionStringChoices
++ List.map viewGroupedChoices config.optgroups
)
|> Nri.Ui.styled Html.select
"nri-select-menu"
[ -- border

View File

@ -11,8 +11,6 @@ import Example exposing (Example)
import Examples.IconExamples as IconExamples
import Nri.Ui.Sprite.V1 as Sprite exposing (SpriteId)
import Nri.Ui.Svg.V1 as Svg exposing (Svg)
import Svg.Styled exposing (svg)
import Svg.Styled.Attributes as Attributes
{-| -}

View File

@ -6,24 +6,19 @@ module Examples.Svg exposing (Msg, State, example)
-}
import Browser.Dom as Dom
import Category exposing (Category(..))
import Css
import Example exposing (Example)
import Examples.AssignmentIcon as AssignmentIcons
import Examples.IconExamples as IconExamples exposing (IconExampleGroup)
import Examples.UiIcon as UiIcons
import Html.Styled as Html
import Html.Styled.Attributes as Attributes
import Html.Styled.Events as Events
import Nri.Ui.ClickableText.V3 as ClickableText
import Nri.Ui.Colors.Extra exposing (fromCssColor, toCssColor)
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.Menu.V3 as Menu
import Nri.Ui.Select.V8 as Select
import Nri.Ui.Svg.V1 as Svg exposing (Svg)
import Nri.Ui.UiIcon.V1 as UiIcon
import SolidColor exposing (SolidColor)
import Task
{-| -}
@ -53,15 +48,11 @@ viewSettings state =
, Css.justifyContent Css.spaceBetween
]
]
[ Menu.view
[ Menu.buttonId "svg-example__icon-selector-button"
, Menu.menuId "svg-example__icon-selector-menu"
[ Select.view "Icon"
[ Select.groupedChoices Tuple.first (List.map svgGroupedChoices UiIcons.all)
, Select.value (Just state.icon)
]
{ isOpen = state.iconSelectorExpanded
, focusAndToggle = FocusAndToggleIconSelector
, entries = List.map viewSvgGroup UiIcons.all
, button = Menu.button [] "Icon"
}
|> Html.map SetIcon
, Html.label []
[ Html.text "Color: "
, Html.input
@ -104,19 +95,12 @@ viewSettings state =
]
viewSvgGroup : IconExampleGroup -> Menu.Entry Msg
viewSvgGroup ( groupName, items ) =
svgGroupedChoices ( groupName, items ) =
let
toEntry ( name, icon ) =
Menu.entry ("svg-selector__" ++ name) <|
\attrs ->
ClickableText.button name
[ ClickableText.small
, ClickableText.icon icon
, ClickableText.onClick (SetIcon ( name, icon ))
]
Select.Choice name ( name, icon )
in
Menu.group groupName (List.map toEntry items)
Select.ChoicesGroup groupName (List.map toEntry items)
viewResults : State -> Html.Html Msg
@ -199,25 +183,17 @@ init =
{-| -}
type Msg
= FocusAndToggleIconSelector { isOpen : Bool, focus : Maybe String }
| SetIcon ( String, Svg )
= SetIcon ( String, Svg )
| SetColor (Result String SolidColor)
| SetWidth (Maybe Float)
| SetHeight (Maybe Float)
| SetLabel String
| Focused (Result Dom.Error ())
{-| -}
update : Msg -> State -> ( State, Cmd Msg )
update msg state =
case msg of
FocusAndToggleIconSelector { isOpen, focus } ->
( { state | iconSelectorExpanded = isOpen }
, Maybe.map (\idString -> Task.attempt Focused (Dom.focus idString)) focus
|> Maybe.withDefault Cmd.none
)
SetIcon svg ->
( { state | icon = svg }
, Cmd.none
@ -245,6 +221,3 @@ update msg state =
SetLabel label ->
( { state | label = label }, Cmd.none )
Focused _ ->
( state, Cmd.none )

View File

@ -17,7 +17,6 @@ import Examples.IconExamples as IconExamples
( IconExampleGroup
, viewByGroupWithSettings
)
import Nri.Ui.Svg.V1 exposing (Svg)
import Nri.Ui.UiIcon.V1 as UiIcon