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

506 lines
18 KiB
Elm
Raw Normal View History

2020-03-31 22:43:32 +03:00
module Examples.Tooltip exposing (example, State, Msg)
2019-08-17 01:26:51 +03:00
{-|
2020-03-31 22:43:32 +03:00
@docs example, State, Msg
2019-08-17 01:26:51 +03:00
-}
2020-09-03 20:26:48 +03:00
import Accessibility.Styled as Html exposing (Html)
import Accessibility.Styled.Key as Key
import Category exposing (Category(..))
2022-03-18 03:30:50 +03:00
import CommonControls
2019-08-17 01:26:51 +03:00
import Css
2020-09-03 20:33:31 +03:00
import Debug.Control as Control exposing (Control)
2021-10-28 18:57:25 +03:00
import Debug.Control.Extra as ControlExtra
2022-03-18 03:25:51 +03:00
import Debug.Control.View as ControlView
import EllieLink
2020-03-31 23:20:03 +03:00
import Example exposing (Example)
2022-04-26 03:59:24 +03:00
import Html.Styled.Attributes exposing (css, href, id)
2022-04-26 02:28:06 +03:00
import KeyboardSupport exposing (Key(..))
2022-05-03 00:51:56 +03:00
import Markdown
2021-05-28 04:59:03 +03:00
import Nri.Ui.ClickableSvg.V2 as ClickableSvg
2022-05-25 23:46:04 +03:00
import Nri.Ui.ClickableText.V3 as ClickableText
2022-04-26 03:13:39 +03:00
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.Svg.V1 as Svg
import Nri.Ui.Table.V5 as Table
2022-04-26 01:42:25 +03:00
import Nri.Ui.Tooltip.V3 as Tooltip
2020-09-03 20:50:42 +03:00
import Nri.Ui.UiIcon.V1 as UiIcon
2019-08-17 01:26:51 +03:00
version : Int
version =
2022-04-26 01:42:25 +03:00
3
moduleName : String
moduleName =
"Tooltip"
2020-09-03 20:26:48 +03:00
example : Example State Msg
example =
{ name = moduleName
, version = version
2021-11-12 01:54:56 +03:00
, categories = [ Messaging ]
2022-04-26 02:28:06 +03:00
, keyboardSupport =
[ { keys = [ Esc ]
2022-04-26 03:07:12 +03:00
, result = "Hitting escape while focusing a tooltip trigger closes all tooltips. Note that hovered-but-not-focused tooltips can't be closed this way."
2022-04-26 02:28:06 +03:00
}
, { keys = [ Space ]
, result = "While focusing a tooltip trigger, opens/closes the tooltip. May trigger the underlying action too."
}
, { keys = [ Enter ]
, result = "While focusing a tooltip trigger, opens/closes the tooltip. May trigger the underlying action too."
}
]
2020-09-03 20:26:48 +03:00
, state = init
, update = update
, subscriptions = \_ -> Sub.none
2021-11-06 00:17:14 +03:00
, preview =
[ Html.div
[ css
[ Css.marginTop (Css.px 60)
, Css.alignSelf Css.center
]
]
[ Tooltip.view
{ id = "preview-tooltip"
, trigger =
\attributes ->
ClickableSvg.button "example-preview-tooltip-icon"
UiIcon.gear
[ ClickableSvg.custom attributes
, ClickableSvg.small
, ClickableSvg.custom [ Key.tabbable False ]
2021-11-06 00:17:14 +03:00
]
}
[ Tooltip.plaintext "This is a tooltip."
, Tooltip.open True
, Tooltip.onTop
, Tooltip.smallPadding
, Tooltip.fitToContent
]
]
]
2020-09-03 20:26:48 +03:00
, view = view
}
2019-08-17 01:26:51 +03:00
type alias State =
{ openTooltip : Maybe TooltipId
, staticExampleSettings : Control (List ( String, Tooltip.Attribute Never ))
2019-08-17 01:26:51 +03:00
}
init : State
init =
2020-09-03 20:26:48 +03:00
{ openTooltip = Nothing
2020-09-03 20:33:31 +03:00
, staticExampleSettings = initStaticExampleSettings
2020-09-03 20:26:48 +03:00
}
type TooltipId
= PrimaryLabel
2020-09-03 20:26:48 +03:00
| AuxillaryDescription
| LearnMore
2022-04-26 03:13:39 +03:00
| Disclosure
2019-08-17 01:26:51 +03:00
type Msg
= ToggleTooltip TooltipId Bool
| SetControl (Control (List ( String, Tooltip.Attribute Never )))
| Log String
2019-08-17 01:26:51 +03:00
2020-03-31 22:43:32 +03:00
update : Msg -> State -> ( State, Cmd Msg )
2019-08-17 01:26:51 +03:00
update msg model =
case msg of
ToggleTooltip type_ isOpen ->
if isOpen then
2020-03-31 22:43:32 +03:00
( { model | openTooltip = Just type_ }, Cmd.none )
2019-08-17 01:26:51 +03:00
else
2020-03-31 22:43:32 +03:00
( { model | openTooltip = Nothing }, Cmd.none )
2019-08-17 01:26:51 +03:00
2022-03-18 03:25:51 +03:00
SetControl settings ->
2020-09-03 20:33:31 +03:00
( { model | staticExampleSettings = settings }, Cmd.none )
Log message ->
2022-05-03 00:31:03 +03:00
( Debug.log "Tooltip Log:" |> always model, Cmd.none )
2019-08-17 01:26:51 +03:00
view : EllieLink.Config -> State -> List (Html Msg)
view ellieLinkConfig model =
[ viewCustomizableExample ellieLinkConfig model.staticExampleSettings
, Table.view
[ Table.string
{ header = "Type"
, value = .name
2022-05-03 00:51:56 +03:00
, width = Css.pct 15
2022-05-26 00:08:16 +03:00
, cellStyles = always [ Css.padding2 Css.zero (Css.px 7) ]
}
, Table.custom
{ header = Html.text "Usage"
, view = .usage >> Markdown.toHtml Nothing >> List.map Html.fromUnstyled >> Html.span []
, width = Css.px 150
2022-05-26 00:08:16 +03:00
, cellStyles = always [ Css.padding2 Css.zero (Css.px 7) ]
2022-05-03 00:51:56 +03:00
}
, Table.custom
{ header = Html.text "About"
, view = .description >> Markdown.toHtml Nothing >> List.map Html.fromUnstyled >> Html.span []
, width = Css.px 200
2022-05-26 00:08:16 +03:00
, cellStyles = always [ Css.padding2 Css.zero (Css.px 7) ]
}
, Table.custom
{ header = Html.text "Example"
2022-05-25 23:41:27 +03:00
, view = .example
, width = Css.px 50
2022-05-03 00:51:56 +03:00
, cellStyles = always [ Css.textAlign Css.center ]
}
]
[ { name = "Tooltip.primaryLabel"
2022-05-25 23:44:52 +03:00
, usage = """
Use when all of the following are true:
- the tooltip trigger does more than just reveal the tooltip content
- the content of the tooltip is the same as the name of the tooltip trigger
2022-05-26 00:08:16 +03:00
Think of this as the "What."
2022-05-25 23:44:52 +03:00
"""
2022-05-03 00:51:56 +03:00
, description =
"""
2022-05-25 23:47:08 +03:00
This is the default tooltip type.
2022-05-03 00:51:56 +03:00
2022-05-25 23:47:08 +03:00
When using the Tooltip component with the ClickableSvg component, the Tooltip acts as a visible text indicator
of ***what*** the tooltip trigger does. The same text is provided to assitive technology via the ClickableSvg's `name`.
2022-05-03 00:51:56 +03:00
"""
2022-05-25 23:41:27 +03:00
, example = viewPrimaryLabelTooltip model.openTooltip
, tooltipId = PrimaryLabel
}
2022-05-02 19:54:14 +03:00
, { name = "Tooltip.auxiliaryDescription"
2022-05-26 00:08:16 +03:00
, usage = """
2022-05-25 23:44:52 +03:00
Use when all of the following are true:
- the tooltip trigger does more than just reveal the tooltip content
- the content of the tooltip provides additional information about the functionality of the tooltip trigger itself.
2022-05-26 00:08:16 +03:00
Think of this as the "How."
2022-05-25 23:44:52 +03:00
"""
2022-05-03 00:51:56 +03:00
, description =
"""
2022-05-25 23:47:08 +03:00
In contrast to Tooltip.primaryLabel, Tooltip.auxiliaryDescription provides information about ***how*** the user should expect the tooltip target to behave when activated.
2022-05-03 00:51:56 +03:00
2022-05-25 23:47:08 +03:00
Examples:
- We might show an icon to indicate that a link opens in a new tab. This icon would have a tooltip to explain ***how*** the link will open.
- On a Quick Write teacher preview, we use Tooltip.auxiliaryDescription on the Save button to let teachers know that the Save button will not actually save in the preview.
2022-05-03 00:51:56 +03:00
"""
2022-05-25 23:41:27 +03:00
, example = viewAuxillaryDescriptionToolip model.openTooltip
, tooltipId = AuxillaryDescription
}
2022-04-26 03:13:39 +03:00
, { name = "Tooltip.disclosure"
2022-05-26 00:08:16 +03:00
, usage = """
2022-05-25 23:44:52 +03:00
Use when all of the following are true:
- the tooltip trigger only opens the tooltip without doing anything else
2022-05-26 00:08:16 +03:00
- the tooltip trigger ***isn't*** a "?" icon
2022-05-25 23:44:52 +03:00
"""
2022-05-03 00:51:56 +03:00
, description =
"""
2022-05-25 23:47:08 +03:00
Sometimes a tooltip trigger doesn't have any functionality itself outside of revealing information.
2022-05-03 00:51:56 +03:00
If clicking the "tooltip trigger" only ever shows you more info (and especially if this info is rich or interactable), use this attribute.
2022-05-25 23:47:08 +03:00
This behavior is analogous to disclosure behavior, except that it's presented different visually. (For more information, please read [Sarah Higley's "Tooltips in the time of WCAG 2.1" post](https://sarahmhigley.com/writing/tooltips-in-wcag-21).)
2022-05-03 00:51:56 +03:00
"""
2022-05-25 23:41:27 +03:00
, example = viewDisclosureToolip model.openTooltip
2022-04-26 03:13:39 +03:00
, tooltipId = Disclosure
}
2022-05-02 20:03:04 +03:00
, { name = "Tooltip.viewToggleTip"
2022-05-26 00:08:16 +03:00
, usage = """
2022-05-25 23:44:52 +03:00
Use when all of the following are true:
- the tooltip trigger only opens the tooltip without doing anything else
2022-05-26 00:08:16 +03:00
- the tooltip trigger ***is*** a "?" icon
2022-05-25 23:44:52 +03:00
"""
2022-05-03 00:51:56 +03:00
, description =
"""
2022-05-25 23:47:08 +03:00
This is a helper for using Tooltip.disclosure with a "?" icon because it is a commonly used UI pattern. We use this helper when we want to show more information about an element but we don't want the element itself to have its own tooltip. The "?" icon typically appears visually adjacent to the element it reveals information about. Please see the documentation for `disclosure` to learn more.
2022-05-03 00:51:56 +03:00
"""
2022-05-25 23:41:27 +03:00
, example = viewToggleTip model.openTooltip
, tooltipId = LearnMore
}
2020-09-03 20:26:48 +03:00
]
]
viewPrimaryLabelTooltip : Maybe TooltipId -> Html Msg
viewPrimaryLabelTooltip openTooltip =
Tooltip.view
{ id = "tooltip__primaryLabel"
, trigger =
\eventHandlers ->
ClickableSvg.button "Download"
UiIcon.download
[ ClickableSvg.custom eventHandlers
, ClickableSvg.onClick (Log "Fake content totally downloaded!")
]
2020-09-03 20:26:48 +03:00
}
[ Tooltip.plaintext "Download"
, Tooltip.primaryLabel
2022-05-03 01:40:11 +03:00
, Tooltip.onToggle (ToggleTooltip PrimaryLabel)
, Tooltip.open (openTooltip == Just PrimaryLabel)
, Tooltip.smallPadding
, Tooltip.fitToContent
2020-09-03 20:26:48 +03:00
]
viewAuxillaryDescriptionToolip : Maybe TooltipId -> Html Msg
viewAuxillaryDescriptionToolip openTooltip =
Tooltip.view
2022-05-02 19:54:14 +03:00
{ id = "tooltip__auxiliaryDescription"
, trigger =
\eventHandlers ->
2022-05-25 23:46:04 +03:00
ClickableText.link "Tooltips & Toggletips"
[ ClickableText.custom eventHandlers
2022-05-26 00:08:16 +03:00
, ClickableText.icon UiIcon.openInNewTab
, ClickableText.linkExternal "https://inclusive-components.design/tooltips-toggletips/"
]
}
2022-05-25 23:46:04 +03:00
[ Tooltip.plaintext "Opens in a new window"
2022-05-02 19:54:14 +03:00
, Tooltip.auxiliaryDescription
2022-05-03 01:40:11 +03:00
, Tooltip.onToggle (ToggleTooltip AuxillaryDescription)
, Tooltip.open (openTooltip == Just AuxillaryDescription)
, Tooltip.smallPadding
, Tooltip.fitToContent
2022-05-03 00:57:39 +03:00
, Tooltip.onLeftForMobile
2020-09-03 20:26:48 +03:00
]
2022-04-26 03:13:39 +03:00
viewDisclosureToolip : Maybe TooltipId -> Html Msg
viewDisclosureToolip openTooltip =
2022-04-26 03:59:24 +03:00
let
triggerId =
"tooltip__disclosure-trigger"
lastId =
"tooltip__disclosure-what-is-mastery"
in
2022-04-26 03:13:39 +03:00
Tooltip.view
{ id = "tooltip__disclosure"
, trigger =
\eventHandlers ->
ClickableSvg.button "Previously mastered"
(Svg.withColor Colors.green UiIcon.starFilled)
[ ClickableSvg.custom eventHandlers
2022-04-26 03:59:24 +03:00
, ClickableSvg.id triggerId
2022-04-26 03:13:39 +03:00
]
}
[ Tooltip.html
[ Html.text "You mastered this skill in a previous year! Way to go! "
, Html.a
2022-04-26 03:59:24 +03:00
[ id lastId
, href "https://noredink.zendesk.com/hc/en-us/articles/203022319-What-is-mastery-"
]
2022-04-26 03:13:39 +03:00
[ Html.text "Learn more about NoRedInk Mastery" ]
]
2022-04-26 03:59:24 +03:00
, Tooltip.disclosure { triggerId = triggerId, lastId = Just lastId }
2022-05-03 01:40:11 +03:00
, Tooltip.onToggle (ToggleTooltip Disclosure)
2022-04-26 03:13:39 +03:00
, Tooltip.open (openTooltip == Just Disclosure)
, Tooltip.smallPadding
2022-05-03 00:57:39 +03:00
, Tooltip.alignEndForMobile (Css.px 148)
2022-04-26 03:13:39 +03:00
]
viewToggleTip : Maybe TooltipId -> Html Msg
viewToggleTip openTooltip =
2022-05-02 20:03:04 +03:00
Tooltip.viewToggleTip { label = "What is mastery?", lastId = Nothing }
[ Tooltip.plaintext "Students master topics by correctly answering a series of questions of varying difficulty and scope."
2022-05-03 01:40:11 +03:00
, Tooltip.onToggle (ToggleTooltip LearnMore)
, Tooltip.open (openTooltip == Just LearnMore)
2022-05-03 00:57:39 +03:00
, Tooltip.alignEndForMobile (Css.px 144)
2020-09-03 20:26:48 +03:00
]
2020-09-03 20:33:31 +03:00
initStaticExampleSettings : Control (List ( String, Tooltip.Attribute Never ))
2020-09-03 20:33:31 +03:00
initStaticExampleSettings =
2021-10-28 18:57:25 +03:00
ControlExtra.list
|> ControlExtra.listItem "content" controlContent
|> ControlExtra.optionalListItem "direction" controlDirection
|> ControlExtra.optionalListItem "direction -- mobile" controlDirectionForMobile
|> ControlExtra.optionalListItem "alignment" controlAlignment
|> ControlExtra.optionalListItem "alignment -- mobile" controlAlignmentForMobile
2022-03-18 03:45:16 +03:00
|> ControlExtra.optionalBoolListItem "withoutTail" ( "Tooltip.withoutTail", Tooltip.withoutTail )
|> ControlExtra.optionalListItem "width" controlWidth
|> ControlExtra.optionalListItem "padding" controlPadding
2022-05-02 20:05:52 +03:00
|> CommonControls.css { moduleName = moduleName, use = Tooltip.css }
|> CommonControls.mobileCss { moduleName = moduleName, use = Tooltip.mobileCss }
|> CommonControls.quizEngineMobileCss { moduleName = moduleName, use = Tooltip.quizEngineMobileCss }
|> CommonControls.notMobileCss { moduleName = moduleName, use = Tooltip.notMobileCss }
2020-09-03 20:50:42 +03:00
2022-03-18 03:45:16 +03:00
controlContent : Control ( String, Tooltip.Attribute Never )
2020-09-03 20:50:42 +03:00
controlContent =
2022-03-18 03:30:50 +03:00
CommonControls.content
{ moduleName = "Tooltip"
, plaintext = Tooltip.plaintext
, markdown = Nothing
, html = Tooltip.html
, httpError = Nothing
}
2020-09-03 20:33:31 +03:00
2022-03-18 03:45:16 +03:00
controlDirection : Control ( String, Tooltip.Attribute Never )
2020-09-03 20:52:46 +03:00
controlDirection =
2022-03-18 03:45:16 +03:00
CommonControls.choice "Tooltip"
[ ( "onTop", Tooltip.onTop )
, ( "onBottom", Tooltip.onBottom )
, ( "onLeft", Tooltip.onLeft )
, ( "onRight", Tooltip.onRight )
2020-09-03 20:52:46 +03:00
]
controlDirectionForMobile : Control ( String, Tooltip.Attribute Never )
controlDirectionForMobile =
CommonControls.choice "Tooltip"
[ ( "onTopForMobile", Tooltip.onTopForMobile )
, ( "onBottomForMobile", Tooltip.onBottomForMobile )
, ( "onLeftForMobile", Tooltip.onLeftForMobile )
, ( "onRightForMobile", Tooltip.onRightForMobile )
]
2022-03-18 03:45:16 +03:00
controlAlignment : Control ( String, Tooltip.Attribute Never )
2020-09-04 01:28:58 +03:00
controlAlignment =
Control.choice
2022-03-18 03:45:16 +03:00
[ ( "alignMiddle (default)", Control.value ( "Tooltip.alignMiddle", Tooltip.alignMiddle ) )
, ( "alignStart"
, Control.map
(\float ->
( "Tooltip.alignStart (Css.px " ++ String.fromFloat float ++ ")"
, Tooltip.alignStart (Css.px float)
)
)
(ControlExtra.float 0)
)
, ( "alignEnd"
, Control.map
(\float ->
( "Tooltip.alignEnd (Css.px " ++ String.fromFloat float ++ ")"
, Tooltip.alignEnd (Css.px float)
)
)
(ControlExtra.float 0)
)
2020-09-04 01:28:58 +03:00
]
controlAlignmentForMobile : Control ( String, Tooltip.Attribute Never )
controlAlignmentForMobile =
Control.choice
[ ( "alignMiddleForMobile (default)", Control.value ( "Tooltip.alignMiddleForMobile", Tooltip.alignMiddleForMobile ) )
, ( "alignStartForMobile"
, Control.map
(\float ->
( "Tooltip.alignStartForMobile (Css.px " ++ String.fromFloat float ++ ")"
, Tooltip.alignStartForMobile (Css.px float)
)
)
(ControlExtra.float 0)
)
, ( "alignEndForMobile"
, Control.map
(\float ->
( "Tooltip.alignEndForMobile (Css.px " ++ String.fromFloat float ++ ")"
, Tooltip.alignEndForMobile (Css.px float)
)
)
(ControlExtra.float 0)
)
]
2022-03-18 03:45:16 +03:00
controlWidth : Control ( String, Tooltip.Attribute Never )
2020-09-03 20:56:07 +03:00
controlWidth =
Control.choice
2022-03-18 03:45:16 +03:00
[ ( "exactWidth (default is 320)"
, Control.map
(\int ->
( "Tooltip.exactWidth " ++ String.fromInt int, Tooltip.exactWidth int )
)
(ControlExtra.int 320)
)
, ( "fitToContent", Control.value ( "Tooltip.fitToContent", Tooltip.fitToContent ) )
2020-09-03 20:56:07 +03:00
]
2022-03-18 03:45:16 +03:00
controlPadding : Control ( String, Tooltip.Attribute Never )
2020-09-03 20:57:55 +03:00
controlPadding =
Control.choice
2022-03-18 03:45:16 +03:00
[ ( "normalPadding (default)", Control.value ( "Tooltip.normalPadding", Tooltip.normalPadding ) )
, ( "smallPadding", Control.value ( "Tooltip.smallPadding", Tooltip.smallPadding ) )
, ( "customPadding"
, Control.map
(\float ->
( "Tooltip.customPadding " ++ String.fromFloat float
, Tooltip.customPadding float
)
)
(ControlExtra.float 0)
)
2020-09-03 20:57:55 +03:00
]
viewCustomizableExample : EllieLink.Config -> Control (List ( String, Tooltip.Attribute Never )) -> Html Msg
viewCustomizableExample ellieLinkConfig controlSettings =
2020-09-03 20:33:31 +03:00
Html.div []
2022-03-18 03:25:51 +03:00
[ ControlView.view
{ ellieLinkConfig = ellieLinkConfig
, name = moduleName
, version = version
, update = SetControl
2022-03-18 03:25:51 +03:00
, settings = controlSettings
, mainType = "RootHtml.Html msg"
2022-04-13 03:32:46 +03:00
, extraImports = []
2022-03-18 03:25:51 +03:00
, toExampleCode =
\controls ->
[ { sectionName = "Example"
, code =
String.join "\n"
[ "Tooltip.view"
, " { trigger ="
, " \\popupTriggerAttributes ->"
, " ClickableSvg.button \"Up\""
, " UiIcon.arrowTop"
, " [ ClickableSvg.custom popupTriggerAttributes"
, " ]"
, " , id = \"an-id-for-the-tooltip\""
, " }"
, " [ "
++ String.join "\n , "
("Tooltip.open True" :: List.map Tuple.first controls)
2022-03-18 03:25:51 +03:00
, " ]"
]
}
]
}
2020-09-04 01:28:58 +03:00
, Html.div
[ css
[ Css.displayFlex
, Css.justifyContent Css.center
, Css.alignItems Css.center
, Css.height (Css.px 300)
]
]
2020-09-03 20:50:42 +03:00
[ Tooltip.view
{ trigger =
\eventHandlers ->
2022-03-18 03:25:51 +03:00
ClickableSvg.button "Up"
UiIcon.arrowTop
[ ClickableSvg.custom eventHandlers
]
2022-03-18 03:25:51 +03:00
, id = "an-id-for-the-tooltip"
2020-09-03 20:50:42 +03:00
}
(Tooltip.open True
:: List.map Tuple.second (Control.currentValue controlSettings)
)
2020-09-03 20:50:42 +03:00
|> Html.map never
]
2020-09-03 20:33:31 +03:00
]