noredink-ui/styleguide-app/Examples/Tabs.elm
2022-03-15 18:06:13 +00:00

259 lines
7.6 KiB
Elm

module Examples.Tabs exposing
( example
, State, Msg
)
{-|
@docs example
@docs State, Msg
-}
import Browser.Dom as Dom
import Category exposing (Category(..))
import Css
import Debug.Control as Control exposing (Control)
import Example exposing (Example)
import Html.Styled as Html exposing (fromUnstyled)
import Html.Styled.Attributes exposing (css)
import KeyboardSupport exposing (Key(..))
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.Svg.V1 as Svg
import Nri.Ui.Tabs.V7 as Tabs exposing (Alignment(..), Tab)
import Nri.Ui.Text.V6 as Text
import Nri.Ui.Tooltip.V2 as Tooltip
import Nri.Ui.UiIcon.V1 as UiIcon
import Routes
import Task
type alias State =
{ selected : Id
, settings : Control Settings
, openTooltip : Maybe Id
}
init : State
init =
{ selected = First
, settings = initSettings
, openTooltip = Nothing
}
type alias Settings =
{ title : Maybe String
, alignment : Alignment
, customSpacing : Maybe Float
, labelledBy : Maybe String
}
initSettings : Control Settings
initSettings =
Control.record Settings
|> Control.field "title" (Control.maybe False (Control.string "Title"))
|> Control.field "alignment"
(Control.choice
[ ( "Left", Control.value Left )
, ( "Center", Control.value Center )
, ( "Right", Control.value Right )
]
)
|> Control.field "customSpacing"
(Control.maybe False
(Control.choice
[ ( "2", Control.value 2 )
, ( "3", Control.value 3 )
, ( "4", Control.value 4 )
, ( "8", Control.value 8 )
, ( "16", Control.value 16 )
]
)
)
|> Control.field "labelledBy" (Control.maybe False (Control.string "someId"))
type Id
= First
| Second
| Third
| Fourth
type Msg
= FocusAndSelectTab { select : Id, focus : Maybe String }
| Focused (Result Dom.Error ())
| SetSettings (Control Settings)
| ToggleTooltip Id Bool
update : Msg -> State -> ( State, Cmd Msg )
update msg model =
case msg of
FocusAndSelectTab { select, focus } ->
( { model | selected = select }
, focus
|> Maybe.map (Dom.focus >> Task.attempt Focused)
|> Maybe.withDefault Cmd.none
)
Focused error ->
( model, Cmd.none )
SetSettings settings ->
( { model | settings = settings }, Cmd.none )
ToggleTooltip id openTooltip ->
( { model
| openTooltip =
if openTooltip then
Just id
else
Nothing
}
, Cmd.none
)
exampleName : String
exampleName =
"Tabs"
example : Example State Msg
example =
{ name = exampleName
, version = 7
, categories = [ Layout ]
, keyboardSupport =
[ { keys = [ KeyboardSupport.Tab ]
, result = "Move focus to the currently-selected Tab's tab panel"
}
, { keys = [ Arrow KeyboardSupport.Left ]
, result = "Select the tab to the left of the currently-selected Tab"
}
, { keys = [ Arrow KeyboardSupport.Right ]
, result = "Select the tab to the right of the currently-selected Tab"
}
]
, state = init
, update = update
, subscriptions = \_ -> Sub.none
, preview =
[ -- faking a mini version of the Tabs component to give styleguide users a sense of what the
-- component might look like
Html.div [ css [ Css.displayFlex, Css.flexWrap Css.wrap ] ]
[ Html.div
[ css
[ Css.backgroundColor Colors.white
, Css.padding (Css.px 4)
, Css.borderRadius4 (Css.px 4) (Css.px 4) Css.zero Css.zero
, Css.border3 (Css.px 1) Css.solid Colors.navy
, Css.borderBottomWidth Css.zero
]
]
[ Text.smallBody [ Text.plaintext "Tab 1" ] ]
, Html.div
[ css [ Css.width (Css.px 4), Css.borderBottom3 (Css.px 1) Css.solid Colors.navy ]
]
[]
, Html.div
[ css
[ Css.backgroundColor Colors.frost
, Css.padding (Css.px 4)
, Css.borderRadius4 (Css.px 4) (Css.px 4) Css.zero Css.zero
, Css.border3 (Css.px 1) Css.solid Colors.navy
]
]
[ Text.smallBody [ Text.plaintext "Tab 1" ] ]
, Html.div
[ css
[ Css.width (Css.px 30)
, Css.borderBottom3 (Css.px 1) Css.solid Colors.navy
]
]
[]
, Html.div
[ css
[ Css.paddingTop (Css.px 4)
, Css.minWidth (Css.px 100)
]
]
[ Text.caption [ Text.plaintext "Tab 1 content" ] ]
]
]
, view =
\model ->
let
settings =
Control.currentValue model.settings
in
[ Control.view SetSettings model.settings |> fromUnstyled
, Tabs.view
{ title = settings.title
, alignment = settings.alignment
, customSpacing = settings.customSpacing
, focusAndSelect = FocusAndSelectTab
, selected = model.selected
, tabs = allTabs model.openTooltip settings.labelledBy
}
]
}
allTabs : Maybe Id -> Maybe String -> List (Tab Id Msg)
allTabs openTooltipId labelledBy =
let
bulbIcon =
UiIcon.bulb
|> Svg.withWidth (Css.px 40)
|> Svg.withHeight (Css.px 45)
|> Svg.withLabel "Bulb"
|> Svg.withCss [ Css.padding2 Css.zero (Css.px 6) ]
|> Svg.toHtml
in
[ Tabs.build { id = First, idString = "tab-0" }
([ Tabs.spaHref <| Routes.toString (Routes.Doodad exampleName)
, Tabs.tabString "1"
, Tabs.withTooltip
[ Tooltip.plaintext "Link Example"
, Tooltip.onHover (ToggleTooltip First)
, Tooltip.alignStart (Css.px 75)
, Tooltip.primaryLabel
, Tooltip.open (openTooltipId == Just First)
]
, Tabs.panelHtml (Html.text "First Panel")
]
++ (case labelledBy of
Nothing ->
[]
Just labelledById ->
[ Tabs.labelledBy labelledById ]
)
)
, Tabs.build { id = Second, idString = "tab-1" }
[ Tabs.tabString "Second Tab (disabled)"
, Tabs.disabled True
, Tabs.panelHtml (Html.text "Second Panel")
]
, Tabs.build { id = Third, idString = "tab-2" }
[ Tabs.tabHtml bulbIcon
, Tabs.withTooltip
[ Tooltip.plaintext "The Electrifying Third Tab"
, Tooltip.onHover (ToggleTooltip Third)
, Tooltip.primaryLabel
, Tooltip.open (openTooltipId == Just Third)
]
, Tabs.panelHtml (Html.text "Third Panel")
]
, Tabs.build { id = Fourth, idString = "tab-3" }
[ Tabs.tabString "Fourth Tab"
, Tabs.panelHtml (Html.text "Fourth Panel")
]
]