Merge pull request #701 from NoRedInk/tessa/dependency-updates

New Version, to fix installation issues
This commit is contained in:
Brian Hicks 2021-06-02 10:18:55 -05:00 committed by GitHub
commit e2b903ba6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
74 changed files with 63 additions and 7578 deletions

View File

@ -1,20 +1,9 @@
Nri.Ui.Accordion.V1,upgrade to V2
Nri.Ui.Accordion.V1,upgrade to V3
Nri.Ui.Button.V8,upgrade to V10
Nri.Ui.ClickableSvg.V1,upgrade to V2
Nri.Ui.Icon.V3,upgrade to V5
Nri.Ui.Icon.V4,upgrade to V5
Nri.Ui.InputStyles.V2,upgrade to V3
Nri.Ui.Message.V1,upgrade to V3
Nri.Ui.Message.V2,upgrade to V3
Nri.Ui.Modal.V3,upgrade to V11
Nri.Ui.Menu.V1,upgrade to V2
Nri.Ui.Modal.V10,upgrade to V11
Nri.Ui.RadioButton.V1,upgrade to V2
Nri.Ui.SegmentedControl.V11,upgrade to V14
Nri.Ui.SegmentedControl.V12,upgrade to V14
Nri.Ui.SegmentedControl.V13,upgrade to V14
Nri.Ui.Select.V5,upgrade to V7
Nri.Ui.Table.V4,upgrade to V5
Nri.Ui.Tabs.V6,upgrade to V7
Nri.Ui.Text.V2,upgrade to V5
Nri.Ui.Text.V4,upgrade to V5
Nri.Ui.Tooltip.V1,upgrade to V2

1 Nri.Ui.Accordion.V1 upgrade to V2 upgrade to V3
2 Nri.Ui.Button.V8 upgrade to V10 upgrade to V10
3 Nri.Ui.ClickableSvg.V1 Nri.Ui.Menu.V1 upgrade to V2 upgrade to V2
Nri.Ui.Icon.V3 upgrade to V5
Nri.Ui.Icon.V4 upgrade to V5
Nri.Ui.InputStyles.V2 upgrade to V3
Nri.Ui.Message.V1 upgrade to V3
Nri.Ui.Message.V2 upgrade to V3
Nri.Ui.Modal.V3 upgrade to V11
4 Nri.Ui.Modal.V10 upgrade to V11 upgrade to V11
5 Nri.Ui.RadioButton.V1 upgrade to V2 upgrade to V2
Nri.Ui.SegmentedControl.V11 upgrade to V14
Nri.Ui.SegmentedControl.V12 upgrade to V14
Nri.Ui.SegmentedControl.V13 upgrade to V14
6 Nri.Ui.Select.V5 upgrade to V7 upgrade to V7
7 Nri.Ui.Table.V4 upgrade to V5 upgrade to V5
8 Nri.Ui.Tabs.V6 upgrade to V7 upgrade to V7
Nri.Ui.Text.V2 upgrade to V5
Nri.Ui.Text.V4 upgrade to V5
9 Nri.Ui.Tooltip.V1 upgrade to V2 upgrade to V2

View File

@ -7,7 +7,6 @@
"exposed-modules": [
"Nri.Ui",
"Nri.Ui.Accordion.V1",
"Nri.Ui.Accordion.V2",
"Nri.Ui.Accordion.V3",
"Nri.Ui.AssetPath",
"Nri.Ui.AssignmentIcon.V2",
@ -15,7 +14,6 @@
"Nri.Ui.Button.V8",
"Nri.Ui.Callout.V1",
"Nri.Ui.Checkbox.V5",
"Nri.Ui.ClickableSvg.V1",
"Nri.Ui.ClickableSvg.V2",
"Nri.Ui.ClickableText.V3",
"Nri.Ui.Colors.Extra",
@ -31,20 +29,13 @@
"Nri.Ui.Heading.V2",
"Nri.Ui.Html.Attributes.V2",
"Nri.Ui.Html.V3",
"Nri.Ui.Icon.V3",
"Nri.Ui.Icon.V4",
"Nri.Ui.Icon.V5",
"Nri.Ui.InputStyles.V2",
"Nri.Ui.InputStyles.V3",
"Nri.Ui.Loading.V1",
"Nri.Ui.Logo.V1",
"Nri.Ui.MasteryIcon.V1",
"Nri.Ui.Menu.V1",
"Nri.Ui.Menu.V2",
"Nri.Ui.Message.V1",
"Nri.Ui.Message.V2",
"Nri.Ui.Message.V3",
"Nri.Ui.Modal.V3",
"Nri.Ui.Modal.V10",
"Nri.Ui.Modal.V11",
"Nri.Ui.Page.V3",
@ -53,9 +44,6 @@
"Nri.Ui.PremiumCheckbox.V6",
"Nri.Ui.RadioButton.V1",
"Nri.Ui.RadioButton.V2",
"Nri.Ui.SegmentedControl.V11",
"Nri.Ui.SegmentedControl.V12",
"Nri.Ui.SegmentedControl.V13",
"Nri.Ui.SegmentedControl.V14",
"Nri.Ui.Select.V5",
"Nri.Ui.Select.V7",
@ -68,8 +56,6 @@
"Nri.Ui.Table.V5",
"Nri.Ui.Tabs.V6",
"Nri.Ui.Tabs.V7",
"Nri.Ui.Text.V2",
"Nri.Ui.Text.V4",
"Nri.Ui.Text.V5",
"Nri.Ui.Text.Writing.V1",
"Nri.Ui.TextArea.V4",
@ -80,8 +66,8 @@
],
"elm-version": "0.19.0 <= v < 0.20.0",
"dependencies": {
"BrianHicks/elm-particle": "1.3.1 <= v < 2.0.0",
"elm/browser": "1.0.1 <= v < 2.0.0",
"BrianHicks/elm-particle": "1.5.0 <= v < 2.0.0",
"elm/browser": "1.0.2 <= v < 2.0.0",
"elm/core": "1.0.1 <= v < 2.0.0",
"elm/html": "1.0.0 <= v < 2.0.0",
"elm/http": "2.0.0 <= v < 3.0.0",
@ -89,18 +75,16 @@
"elm/random": "1.0.0 <= v < 2.0.0",
"elm/regex": "1.0.0 <= v < 2.0.0",
"elm/svg": "1.0.1 <= v < 2.0.0",
"elm-community/random-extra": "3.1.0 <= v < 4.0.0",
"elm-community/random-extra": "3.2.0 <= v < 4.0.0",
"elm-community/string-extra": "4.0.1 <= v < 5.0.0",
"pablohirafuji/elm-markdown": "2.0.5 <= v < 3.0.0",
"rtfeldman/elm-css": "16.1.0 <= v < 17.0.0",
"tesk9/accessible-html": "4.0.0 <= v < 5.0.0",
"tesk9/accessible-html-with-css": "2.1.1 <= v < 3.0.0",
"tesk9/modal": "5.0.1 <= v < 6.0.0",
"tesk9/palette": "2.0.0 <= v < 3.0.0",
"wernerdegroot/listzipper": "3.1.1 <= v < 5.0.0"
"rtfeldman/elm-css": "16.1.1 <= v < 17.0.0",
"tesk9/accessible-html-with-css": "2.2.0 <= v < 3.0.0",
"tesk9/palette": "3.0.1 <= v < 4.0.0"
},
"test-dependencies": {
"avh4/elm-program-test": "3.3.0 <= v < 4.0.0",
"elm-explorations/test": "1.2.2 <= v < 2.0.0"
"elm-explorations/test": "1.2.2 <= v < 2.0.0",
"tesk9/accessible-html": "4.1.0 <= v < 5.0.0"
}
}

View File

@ -35,15 +35,12 @@ hint = 'Use Accessibility.Widgetd.Widget'
hint = 'Use Html.Styled'
usages = [
'styleguide-app/../src/Nri/Ui/Button/V8.elm',
'styleguide-app/../src/Nri/Ui/Icon/V3.elm',
'styleguide-app/../src/Nri/Ui/Icon/V4.elm',
'styleguide-app/../src/Nri/Ui/Icon/V5.elm',
'styleguide-app/Examples/Modal.elm',
'styleguide-app/Main.elm',
]
[forbidden."Nri.Ui.Accordion.V1"]
hint = 'upgrade to V2'
hint = 'upgrade to V3'
[forbidden."Nri.Ui.Button.V8"]
hint = 'upgrade to V10'
@ -63,6 +60,9 @@ hint = 'upgrade to V5'
[forbidden."Nri.Ui.InputStyles.V2"]
hint = 'upgrade to V3'
[forbidden."Nri.Ui.Menu.V1"]
hint = 'upgrade to V2'
[forbidden."Nri.Ui.Message.V1"]
hint = 'upgrade to V3'
@ -118,7 +118,4 @@ usages = [
[forbidden."Nri.Ui.Tooltip.V1"]
hint = 'upgrade to V2'
usages = [
'styleguide-app/../src/Nri/Ui/ClickableSvg/V1.elm',
'styleguide-app/../src/Nri/Ui/Menu/V1.elm',
]
usages = ['styleguide-app/../src/Nri/Ui/Menu/V1.elm']

View File

@ -1,383 +0,0 @@
module Accessibility.Modal.Copy exposing
( Model, init, subscriptions
, update, Msg, close, open
, view
, Attribute
, multipleFocusableElementView, onlyFocusableElementView
, autofocusOnLastElement
, overlayColor, custom, titleStyles
)
{-| COPIED from <https://package.elm-lang.org/packages/tesk9/modal/latest/> for
clean monolith upgrades. Remove this and go back to using tesk9/modal when possible!
import Accessibility.Modal as Modal
import Html.Styled exposing (..)
import Html.Styled.Events exposing (onClick)
view : Html Modal.Msg
view =
Modal.view identity
"Example modal"
[ Modal.onlyFocusableElementView
(\onlyFocusableElementAttributes ->
div []
[ text "Welcome to this modal! I'm so happy to have you here with me."
, button
(onClick Modal.close :: onlyFocusableElementAttributes)
[ text "Close Modal" ]
]
)
]
modal
@docs Model, init, subscriptions
@docs update, Msg, close, open
@docs view
@docs Attribute
@docs multipleFocusableElementView, onlyFocusableElementView
@docs autofocusOnLastElement
@docs overlayColor, custom, titleStyles
-}
import Accessibility.Styled exposing (..)
import Accessibility.Styled.Aria as Aria
import Accessibility.Styled.Key as Key
import Accessibility.Styled.Role as Role
import Browser
import Browser.Dom as Dom
import Browser.Events
import Css exposing (..)
import Html.Styled as Root
import Html.Styled.Attributes as Attributes exposing (css, id)
import Html.Styled.Events exposing (onClick)
import Task
{-| -}
type Model
= Opened String
| Closed
{-| -}
init : Model
init =
Closed
type By
= EscapeKey
| OverlayClick
| Other
{-| -}
type Msg
= OpenModal String
| CloseModal By
| Focus String
| Focused (Result Dom.Error ())
{-| -}
update : { dismissOnEscAndOverlayClick : Bool } -> Msg -> Model -> ( Model, Cmd Msg )
update { dismissOnEscAndOverlayClick } msg model =
case msg of
OpenModal returnFocusTo ->
( Opened returnFocusTo
, Dom.focus autofocusId
|> Task.onError (\_ -> Dom.focus firstId)
|> Task.attempt Focused
)
CloseModal by ->
let
closeModal returnFocusTo =
( Closed, Task.attempt Focused (Dom.focus returnFocusTo) )
in
case ( model, by, dismissOnEscAndOverlayClick ) of
( Opened returnFocusTo, _, True ) ->
closeModal returnFocusTo
( Opened returnFocusTo, Other, False ) ->
closeModal returnFocusTo
_ ->
( model, Cmd.none )
Focus id ->
( model, Task.attempt Focused (Dom.focus id) )
Focused _ ->
( model, Cmd.none )
type Autofocus
= Default
| Last
type alias Config msg =
{ overlayColor : Color
, wrapMsg : Msg -> msg
, modalStyle : Style
, titleString : String
, titleStyles : List Style
, autofocusOn : Autofocus
, content :
{ onlyFocusableElement : List (Accessibility.Styled.Attribute msg)
, firstFocusableElement : List (Accessibility.Styled.Attribute msg)
, lastFocusableElement : List (Accessibility.Styled.Attribute msg)
, autofocusOn : Accessibility.Styled.Attribute msg
}
-> Html msg
}
defaults : (Msg -> msg) -> String -> Config msg
defaults wrapMsg t =
{ overlayColor = rgba 128 0 70 0.7
, wrapMsg = wrapMsg
, modalStyle =
batch
[ backgroundColor (rgb 255 255 255)
, borderRadius (px 8)
, border3 (px 2) solid (rgb 127 0 127)
, margin2 (px 80) auto
, padding (px 20)
, maxWidth (px 600)
, minHeight (vh 40)
]
, titleString = t
, titleStyles = []
, autofocusOn = Default
, content = \_ -> text ""
}
{-| -}
type Attribute msg
= Attribute (Config msg -> Config msg)
{-| -}
overlayColor : Color -> Attribute msg
overlayColor color =
Attribute (\config -> { config | overlayColor = color })
{-| -}
title : String -> Attribute msg
title t =
Attribute (\config -> { config | titleString = t })
{-| -}
titleStyles : List Style -> Attribute msg
titleStyles styles =
Attribute (\config -> { config | titleStyles = styles })
{-| -}
custom : List Style -> Attribute msg
custom styles =
Attribute (\config -> { config | modalStyle = batch styles })
{-| -}
autofocusOnLastElement : Attribute msg
autofocusOnLastElement =
Attribute (\config -> { config | autofocusOn = Last })
{-| -}
onlyFocusableElementView : (List (Accessibility.Styled.Attribute msg) -> Html msg) -> Attribute msg
onlyFocusableElementView v =
Attribute (\config -> { config | content = \{ onlyFocusableElement } -> v onlyFocusableElement })
{-| -}
multipleFocusableElementView :
({ firstFocusableElement : List (Accessibility.Styled.Attribute msg)
, lastFocusableElement : List (Accessibility.Styled.Attribute msg)
, autofocusElement : Accessibility.Styled.Attribute msg
}
-> Html msg
)
-> Attribute msg
multipleFocusableElementView v =
Attribute
(\config ->
{ config
| content =
\{ firstFocusableElement, lastFocusableElement, autofocusOn } ->
v
{ firstFocusableElement = firstFocusableElement
, lastFocusableElement = lastFocusableElement
, autofocusElement = autofocusOn
}
}
)
{-| -}
view :
(Msg -> msg)
-> String
-> List (Attribute msg)
-> Model
-> Html msg
view wrapMsg ti attributes model =
let
config =
List.foldl (\(Attribute f) acc -> f acc) (defaults wrapMsg ti) attributes
in
case model of
Opened _ ->
div
[ css
[ position fixed
, top zero
, left zero
, width (pct 100)
, height (pct 100)
, displayFlex
, alignItems center
]
]
[ viewBackdrop config
, div
[ css [ position relative, config.modalStyle ] ]
[ viewModal config ]
, Root.node "style" [] [ Root.text "body {overflow: hidden;} " ]
]
Closed ->
text ""
viewBackdrop :
{ a | wrapMsg : Msg -> msg, overlayColor : Color }
-> Html msg
viewBackdrop config =
Root.div
-- We use Root html here in order to allow clicking to exit out of
-- the overlay. This behavior is available to non-mouse users as
-- well via the ESC key, so imo it's fine to have this div
-- be clickable but not focusable.
[ css
[ position absolute
, width (pct 100)
, height (pct 100)
, backgroundColor config.overlayColor
]
, onClick (config.wrapMsg (CloseModal OverlayClick))
]
[]
viewModal : Config msg -> Html msg
viewModal config =
section
[ Role.dialog
, Aria.labeledBy modalTitleId
]
[ h1 [ id modalTitleId, css config.titleStyles ] [ text config.titleString ]
, config.content
(case config.autofocusOn of
Last ->
{ onlyFocusableElement =
[ Key.onKeyDown
[ Key.tabBack (Focus firstId)
, Key.tab (Focus firstId)
]
, id firstId
]
|> List.map (Attributes.map config.wrapMsg)
, firstFocusableElement =
[ Key.onKeyDown [ Key.tabBack (Focus autofocusId) ]
, id firstId
]
|> List.map (Attributes.map config.wrapMsg)
, lastFocusableElement =
[ Key.onKeyDown [ Key.tab (Focus firstId) ]
, id autofocusId
]
|> List.map (Attributes.map config.wrapMsg)
, autofocusOn =
id autofocusId
|> Attributes.map config.wrapMsg
}
_ ->
{ onlyFocusableElement =
[ Key.onKeyDown
[ Key.tabBack (Focus firstId)
, Key.tab (Focus firstId)
]
, id firstId
]
|> List.map (Attributes.map config.wrapMsg)
, firstFocusableElement =
[ Key.onKeyDown [ Key.tabBack (Focus lastId) ]
, id firstId
]
|> List.map (Attributes.map config.wrapMsg)
, lastFocusableElement =
[ Key.onKeyDown [ Key.tab (Focus firstId) ]
, id lastId
]
|> List.map (Attributes.map config.wrapMsg)
, autofocusOn =
id autofocusId
|> Attributes.map config.wrapMsg
}
)
]
modalTitleId : String
modalTitleId =
"modal__title"
firstId : String
firstId =
"modal__first-focusable-element"
lastId : String
lastId =
"modal__last-focusable-element"
autofocusId : String
autofocusId =
"modal__autofocus-element"
{-| Pass the id of the element that should receive focus when the modal closes.
-}
open : String -> Msg
open =
OpenModal
{-| -}
close : Msg
close =
CloseModal Other
{-| -}
subscriptions : Model -> Sub Msg
subscriptions model =
case model of
Opened _ ->
Browser.Events.onKeyDown (Key.escape (CloseModal EscapeKey))
Closed ->
Sub.none

View File

@ -1,13 +0,0 @@
module List.Zipper.Extra exposing (from)
{-| migration module from List.Zipper 3.2 -> 4. We can drop this when we drop < 3.2 support
-}
import List.Zipper
from : List a -> a -> List a -> List.Zipper.Zipper a
from before current after =
List.Zipper.singleton current
|> List.Zipper.mapBefore (always before)
|> List.Zipper.mapAfter (always after)

View File

@ -1,305 +0,0 @@
module Nri.Ui.Accordion.V2 exposing (view, Caret(..), StyleOptions, HeaderLevel(..))
{-| Changes from V1:
- Combine view and viewKeyed so that nodes are always keyed
- Removes viewCaret from the API -- it's possible to use the DisclosureIndicator directly
- Changed implementation to follow recommendations from <https://www.w3.org/TR/wai-aria-practices-1.1/examples/accordion/accordion.html>
- Adds Up and Down keyboard handling for navigating between the accordions
- Adds aria-expanded and aria-controls
- Changes accordion container to a section
- removes tablist/tab/tabpanel roles
- Adds heading levels for the accordion header (including style resets)
@docs view, Caret, StyleOptions, HeaderLevel
-}
import Accessibility.Styled exposing (Attribute, Html, button, div, section, text)
import Accessibility.Styled.Aria as Aria
import Accessibility.Styled.Key as Key
import Accessibility.Styled.Role as Role
import Accessibility.Styled.Widget as Widget
import Css exposing (..)
import Css.Global
import Html.Styled.Attributes as Attributes
import Html.Styled.Events exposing (onClick)
import Html.Styled.Keyed
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.DisclosureIndicator.V2 as DisclosureIndicator
import Nri.Ui.Fonts.V1 as Fonts
{-| -}
type alias StyleOptions =
{ entryStyles : List Style
, entryExpandedStyles : List Style
, entryClosedStyles : List Style
, headerStyles : List Style
, headerExpandedStyles : List Style
, headerClosedStyles : List Style
, contentStyles : List Style
}
defaultStyleOptions : StyleOptions
defaultStyleOptions =
{ entryStyles =
[ position relative
, marginBottom (px 10)
]
, entryExpandedStyles = []
, entryClosedStyles = []
, headerStyles =
[ displayFlex
, alignItems center
, boxSizing borderBox
, minWidth (pct 100)
, overflow hidden
, padding2 (px 8) (px 15)
, backgroundColor Colors.gray96
-- button resets
, cursor pointer
, borderWidth Css.zero
, margin zero
-- fonts & text
, textAlign left
, Fonts.baseFont
, fontSize (px 16)
, fontWeight (int 600)
, lineHeight (num 1.2)
]
, headerExpandedStyles =
[ color Colors.navy
, borderRadius4 (px 8) (px 8) (px 0) (px 0)
]
, headerClosedStyles =
[ color Colors.azure
, borderRadius (px 8)
]
, contentStyles = [ overflow hidden ]
}
{-| DefaultCaret is the blue caret
-}
type Caret
= DefaultCaret
| WhiteCaret
| NoneCaret
{-| Corresponds to h1, h2, h3 etc.
Choose the correct header level given your page context.
-}
type HeaderLevel
= H1
| H2
| H3
| H4
| H5
| H6
header : HeaderLevel -> Html msg -> Html msg
header headerLevel content =
let
resets =
[ margin zero
, padding zero
]
in
case headerLevel of
H1 ->
Accessibility.Styled.h1 [ Attributes.css resets ] [ content ]
H2 ->
Accessibility.Styled.h2 [ Attributes.css resets ] [ content ]
H3 ->
Accessibility.Styled.h3 [ Attributes.css resets ] [ content ]
H4 ->
Accessibility.Styled.h4 [ Attributes.css resets ] [ content ]
H5 ->
Accessibility.Styled.h5 [ Attributes.css resets ] [ content ]
H6 ->
Accessibility.Styled.h6 [ Attributes.css resets ] [ content ]
{-| -}
view :
{ entries : List { headerId : String, entry : entry, isExpanded : Bool }
, headerLevel : HeaderLevel
, viewHeader : entry -> Html msg
, viewContent : entry -> Html msg
, customStyles : Maybe (entry -> StyleOptions)
, caret : Caret
, toggle : entry -> Bool -> msg
, focus : String -> msg
}
-> Html msg
view { entries, headerLevel, viewHeader, viewContent, customStyles, caret, toggle, focus } =
let
arrowUpIds : List (Maybe String)
arrowUpIds =
lastHeaderId :: List.map (.headerId >> Just) entries
lastHeaderId : Maybe String
lastHeaderId =
Maybe.map .headerId (List.head (List.reverse entries))
in
div
[ Attributes.class "accordion"
, Attributes.attribute "aria-live" "polite"
]
[ Html.Styled.Keyed.node "div"
[]
(entries
|> List.map2 (\id nextEntry -> ( id, nextEntry )) arrowUpIds
|> List.foldr
(\( previousId, { headerId, entry, isExpanded } ) ( nextId, acc ) ->
let
node =
( "keyed-section__" ++ headerId
, viewEntry
{ headerId = headerId
, headerLevel = headerLevel
, viewHeader = viewHeader
, viewContent = viewContent
, styleOptions = customStyles
, caret = caret
, toggle = toggle
, arrowUp = Maybe.map focus previousId
, arrowDown = Maybe.map focus nextId
, entry = entry
, isExpanded = isExpanded
}
)
in
( Just headerId
, node :: acc
)
)
( Maybe.map .headerId (List.head entries), [] )
|> Tuple.second
)
]
viewEntry :
{ headerId : String
, headerLevel : HeaderLevel
, viewHeader : entry -> Html msg
, viewContent : entry -> Html msg
, styleOptions : Maybe (entry -> StyleOptions)
, caret : Caret
, toggle : entry -> Bool -> msg
, arrowUp : Maybe msg
, arrowDown : Maybe msg
, entry : entry
, isExpanded : Bool
}
-> Html msg
viewEntry { headerId, headerLevel, viewHeader, viewContent, styleOptions, caret, toggle, entry, isExpanded, arrowDown, arrowUp } =
let
newStyleOptions =
case Maybe.map (\toStyles -> toStyles entry) styleOptions of
Just { entryStyles, entryExpandedStyles, entryClosedStyles, headerStyles, headerExpandedStyles, headerClosedStyles, contentStyles } ->
{ entryStyles = defaultStyleOptions.entryStyles ++ entryStyles
, entryExpandedStyles = defaultStyleOptions.entryExpandedStyles ++ entryExpandedStyles
, entryClosedStyles = defaultStyleOptions.entryClosedStyles ++ entryClosedStyles
, headerStyles = defaultStyleOptions.headerStyles ++ headerStyles
, headerExpandedStyles = defaultStyleOptions.headerExpandedStyles ++ headerExpandedStyles
, headerClosedStyles = defaultStyleOptions.headerClosedStyles ++ headerClosedStyles
, contentStyles = defaultStyleOptions.contentStyles ++ contentStyles
}
Nothing ->
defaultStyleOptions
styles =
if isExpanded then
{ entry = newStyleOptions.entryStyles ++ newStyleOptions.entryExpandedStyles
, header = newStyleOptions.headerStyles ++ newStyleOptions.headerExpandedStyles
, content = newStyleOptions.contentStyles
}
else
{ entry = newStyleOptions.entryStyles ++ newStyleOptions.entryClosedStyles
, header = newStyleOptions.headerStyles ++ newStyleOptions.headerClosedStyles
, content = [ maxHeight (px 0) ]
}
panelId =
"accordion-panel__" ++ headerId
in
div
[ entryClass isExpanded
, Attributes.css styles.entry
]
[ header headerLevel <|
button
[ Attributes.id headerId
, Attributes.class "accordion-entry-header"
, Attributes.css styles.header
, Widget.expanded isExpanded
, Aria.controls panelId
, onClick (toggle entry (not isExpanded))
, Key.onKeyDown
(List.filterMap identity
[ Maybe.map Key.up arrowUp
, Maybe.map Key.down arrowDown
]
)
]
[ viewCaret isExpanded caret
, viewHeader entry
]
, section
[ Attributes.id panelId
, Aria.labelledBy headerId
, Attributes.class "accordion-entry-panel"
, Attributes.hidden (not isExpanded)
, Attributes.css styles.content
]
[ viewContent entry ]
]
{-| Used for tests that rely on classnames, and couple edge cases where we need to override styles using sass
-}
entryClass : Bool -> Attribute msg
entryClass expanded =
Attributes.classList
[ ( "accordion-entry", True )
, ( "accordion-entry-state-expanded", expanded )
, ( "accordion-entry-state-collapsed", not expanded )
]
{-| Just the caret!
-}
viewCaret : Bool -> Caret -> Html msg
viewCaret expanded caret =
case caret of
DefaultCaret ->
DisclosureIndicator.large
[ marginRight (px 8)
]
expanded
WhiteCaret ->
DisclosureIndicator.large
[ marginRight (px 8)
, Css.Global.descendants
[ Css.Global.everything [ color Colors.white ] ]
]
expanded
NoneCaret ->
text ""

View File

@ -1,598 +0,0 @@
module Nri.Ui.ClickableSvg.V1 exposing
( button, link
, Attribute
, onClick
, href, linkSpa, linkExternal, linkWithMethod, linkWithTracking, linkExternalWithTracking
, width, height
, disabled
, withBorder
, primary, secondary, danger, dangerSecondary
, custom, css
, withTooltipAbove, withTooltipBelow
)
{-|
# Post-release patches
- uses ClickableAttributes
- adds tooltip helpers
# Create a button or link
@docs button, link
@docs Attribute
## Behavior
@docs onClick
@docs href, linkSpa, linkExternal, linkWithMethod, linkWithTracking, linkExternalWithTracking
## Sizing
@docs width, height
## State
@docs disabled
## Customization
@docs withBorder
@docs primary, secondary, danger, dangerSecondary
@docs custom, css
## Tooltips
@docs withTooltipAbove, withTooltipBelow
-}
import Accessibility.Styled.Widget as Widget
import ClickableAttributes exposing (ClickableAttributes)
import Css exposing (Color, Style)
import Html.Styled as Html exposing (Html)
import Html.Styled.Attributes as Attributes
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.Svg.V1 as Svg exposing (Svg)
import Nri.Ui.Tooltip.V1 as Tooltip exposing (Tooltip)
{-| -}
type Attribute msg
= Attribute (ButtonOrLink msg -> ButtonOrLink msg)
{-| -}
button : String -> Svg -> List (Attribute msg) -> Html msg
button name icon attributes =
attributes
|> List.foldl (\(Attribute attribute) b -> attribute b) (build name icon)
|> renderButton
{-| -}
link : String -> Svg -> List (Attribute msg) -> Html msg
link name icon attributes =
attributes
|> List.foldl (\(Attribute attribute) b -> attribute b) (build name icon)
|> renderLink
-- LINKING, CLICKING, and TRACKING BEHAVIOR
setClickableAttributes :
(ClickableAttributes msg -> ClickableAttributes msg)
-> Attribute msg
setClickableAttributes apply =
set
(\attributes ->
{ attributes | clickableAttributes = apply attributes.clickableAttributes }
)
{-| -}
onClick : msg -> Attribute msg
onClick msg =
setClickableAttributes (ClickableAttributes.onClick msg)
{-| -}
href : String -> Attribute msg
href url =
setClickableAttributes (ClickableAttributes.href url)
{-| Use this link for routing within a single page app.
This will make a normal <a> tag, but change the Events.onClick behavior to avoid reloading the page.
See <https://github.com/elm-lang/html/issues/110> for details on this implementation.
-}
linkSpa : String -> Attribute msg
linkSpa url =
setClickableAttributes (ClickableAttributes.linkSpa url)
{-| -}
linkWithMethod : { method : String, url : String } -> Attribute msg
linkWithMethod config =
setClickableAttributes (ClickableAttributes.linkWithMethod config)
{-| -}
linkWithTracking : { track : msg, url : String } -> Attribute msg
linkWithTracking config =
setClickableAttributes (ClickableAttributes.linkWithTracking config)
{-| -}
linkExternal : String -> Attribute msg
linkExternal url =
setClickableAttributes (ClickableAttributes.linkExternal url)
{-| -}
linkExternalWithTracking : { track : msg, url : String } -> Attribute msg
linkExternalWithTracking config =
setClickableAttributes (ClickableAttributes.linkExternalWithTracking config)
-- SIZING
{-| Default width is 17px.
Note: changing this width will change the width of the icon. The button or link
may be wider if you add a border or margin to it.
-}
width : Css.Px -> Attribute msg
width px =
set (\attributes -> { attributes | width = px })
{-| Default height is 17px.
Note: changing this height will change the height of the icon. The button or link
may be taller if you add a border or margin to it.
-}
height : Css.Px -> Attribute msg
height px =
set (\attributes -> { attributes | height = px })
-- STATE
{-| -}
disabled : Bool -> Attribute msg
disabled disabled_ =
set (\attributes -> { attributes | disabled = disabled_ })
-- CUSTOMIZATION
{-| Display a border around the icon.
-}
withBorder : Attribute msg
withBorder =
set (\config -> { config | hasBorder = True })
type Theme
= Primary
| Secondary
| Danger
| DangerSecondary
type alias AppliedTheme =
{ main_ : Color
, mainHovered : Color
, background : Color
, backgroundHovered : Color
}
disabledTheme : AppliedTheme
disabledTheme =
{ main_ = Colors.gray75
, mainHovered = Colors.gray75
, background = Colors.white
, backgroundHovered = Colors.white
}
applyTheme : Theme -> AppliedTheme
applyTheme theme =
case theme of
Primary ->
{ main_ = Colors.white
, mainHovered = Colors.white
, background = Colors.azure
, backgroundHovered = Colors.azureDark
}
Secondary ->
{ main_ = Colors.azure
, mainHovered = Colors.azureDark
, background = Colors.white
, backgroundHovered = Colors.glacier
}
Danger ->
{ main_ = Colors.white
, mainHovered = Colors.white
, background = Colors.red
, backgroundHovered = Colors.redDark
}
DangerSecondary ->
{ main_ = Colors.red
, mainHovered = Colors.redDark
, background = Colors.white
, backgroundHovered = Colors.redLight
}
{-| white/transparent icon on an azure background.
-}
primary : Attribute msg
primary =
set (\attributes -> { attributes | theme = Primary })
{-| This is the default: a blue icon on a transparent background, or a blue icon
on a white/glacier icon with a blue border.
-}
secondary : Attribute msg
secondary =
set (\attributes -> { attributes | theme = Secondary })
{-| White/transparent icon on a red background.
-}
danger : Attribute msg
danger =
set (\attributes -> { attributes | theme = Danger })
{-| Red icon on a white/transparent background.
-}
dangerSecondary : Attribute msg
dangerSecondary =
set (\attributes -> { attributes | theme = DangerSecondary })
{-| Use this helper to add custom attributes.
Do NOT use this helper to add css styles, as they may not be applied the way
you want/expect if underlying Button styles change.
Instead, please use the `css` helper.
-}
custom : List (Html.Attribute msg) -> Attribute msg
custom attributes =
set
(\config ->
{ config
| customAttributes = List.append config.customAttributes attributes
}
)
{-| -}
css : List Style -> Attribute msg
css styles =
set
(\config ->
{ config
| customStyles = List.append config.customStyles styles
}
)
-- TOOLTIPS
type alias TooltipSettings msg =
{ position : Tooltip.Position
, isOpen : Bool
, onShow : Bool -> msg
, id : String
}
showTooltip : String -> Maybe (TooltipSettings msg) -> Html msg -> Html msg
showTooltip label maybeSettings buttonOrLink =
case maybeSettings of
Just { position, onShow, isOpen, id } ->
let
tooltipSettings =
{ trigger = Tooltip.OnHover
, onTrigger = onShow
, isOpen = isOpen
, triggerHtml = buttonOrLink
, extraButtonAttrs = []
, id = id ++ "__clickable-svg-tooltip"
}
in
Tooltip.tooltip [ Html.text label ]
|> Tooltip.withPosition position
|> Tooltip.withWidth Tooltip.FitToContent
|> Tooltip.withPadding Tooltip.SmallPadding
|> Tooltip.primaryLabel tooltipSettings
Nothing ->
buttonOrLink
withTooltip : Tooltip.Position -> { id : String, isOpen : Bool, onShow : Bool -> msg } -> Attribute msg
withTooltip position { id, isOpen, onShow } =
set
(\config ->
{ config
| tooltip =
Just { position = position, id = id, isOpen = isOpen, onShow = onShow }
}
)
{-| DEPRECATED: prefer to use the Tooltip module directly.
-}
withTooltipAbove : { id : String, isOpen : Bool, onShow : Bool -> msg } -> Attribute msg
withTooltipAbove =
withTooltip Tooltip.OnTop
{-| DEPRECATED: prefer to use the Tooltip module directly.
-}
withTooltipBelow : { id : String, isOpen : Bool, onShow : Bool -> msg } -> Attribute msg
withTooltipBelow =
withTooltip Tooltip.OnBottom
-- INTERNALS
set :
(ButtonOrLinkAttributes msg -> ButtonOrLinkAttributes msg)
-> Attribute msg
set with =
Attribute (\(ButtonOrLink config) -> ButtonOrLink (with config))
build : String -> Svg -> ButtonOrLink msg
build label icon =
ButtonOrLink
{ clickableAttributes = ClickableAttributes.init
, label = label
, icon = icon
, height = Css.px 17
, width = Css.px 17
, disabled = False
, customAttributes = []
, customStyles = []
, tooltip = Nothing
, hasBorder = False
, theme = Secondary
}
type ButtonOrLink msg
= ButtonOrLink (ButtonOrLinkAttributes msg)
type alias ButtonOrLinkAttributes msg =
{ clickableAttributes : ClickableAttributes msg
, label : String
, icon : Svg
, height : Css.Px
, width : Css.Px
, disabled : Bool
, customAttributes : List (Html.Attribute msg)
, customStyles : List Style
, tooltip : Maybe (TooltipSettings msg)
, hasBorder : Bool
, theme : Theme
}
renderButton : ButtonOrLink msg -> Html msg
renderButton ((ButtonOrLink config) as button_) =
Html.button
([ Attributes.class "Nri-Ui-Clickable-Svg-V1__button"
, Attributes.type_ "button"
, Attributes.css (buttonOrLinkStyles config ++ config.customStyles)
, Attributes.disabled config.disabled
, Widget.label config.label
]
++ ClickableAttributes.toButtonAttributes config.clickableAttributes
++ config.customAttributes
)
[ renderIcon config
]
|> showTooltip config.label config.tooltip
type Link
= Default
| WithTracking
| SinglePageApp
| WithMethod String
| External
| ExternalWithTracking
renderLink : ButtonOrLink msg -> Html msg
renderLink ((ButtonOrLink config) as link_) =
let
( linkFunctionName, extraAttrs ) =
ClickableAttributes.toLinkAttributes config.clickableAttributes
in
Html.a
([ Attributes.class ("Nri-Ui-Clickable-Svg-" ++ linkFunctionName)
, Attributes.css (buttonOrLinkStyles config ++ config.customStyles)
, Widget.disabled config.disabled
, Widget.label config.label
]
++ (if not config.disabled then
extraAttrs
else
[]
)
++ config.customAttributes
)
[ renderIcon config
]
|> showTooltip config.label config.tooltip
renderIcon : ButtonOrLinkAttributes msg -> Html msg
renderIcon config =
config.icon
|> Svg.withCss
(if config.hasBorder then
[ Css.width
(Css.calc config.width
Css.minus
(Css.px <|
(2 * withBorderHorizontalPadding)
+ withBorderLeftBorderWidth
+ withBorderRightBorderWidth
)
)
, Css.height
(Css.calc config.height
Css.minus
(Css.px <|
withBorderTopPadding
+ withBorderBottomPadding
+ withBorderTopBorderWidth
+ withBorderBottomBorderWidth
)
)
]
else
[ Css.width config.width
, Css.height config.height
]
)
|> Svg.toHtml
buttonOrLinkStyles : ButtonOrLinkAttributes msg -> List Style
buttonOrLinkStyles config =
let
( { main_, mainHovered, background, backgroundHovered }, cursor ) =
if config.disabled then
( disabledTheme, Css.notAllowed )
else
( applyTheme config.theme, Css.pointer )
in
[ Css.property "transition"
"background-color 0.2s, color 0.2s, border-width 0s, border-color 0.2s"
-- Colors, text decoration, cursor
, Css.textDecoration Css.none
, Css.color main_
, Css.visited [ Css.color main_ ]
, Css.hover
[ Css.textDecoration Css.none
, Css.color mainHovered
, Css.cursor cursor
]
-- Margins, borders, padding
, Css.margin Css.zero
, Css.textAlign Css.center
, Css.batch <|
if config.hasBorder then
[ Css.borderRadius (Css.px 8)
, Css.borderColor main_
, Css.borderStyle Css.solid
, Css.borderTopWidth (Css.px withBorderTopBorderWidth)
, Css.borderRightWidth (Css.px withBorderRightBorderWidth)
, Css.borderBottomWidth (Css.px withBorderBottomBorderWidth)
, Css.borderLeftWidth (Css.px withBorderLeftBorderWidth)
, Css.backgroundColor background
, Css.hover
[ Css.borderColor mainHovered
, Css.backgroundColor backgroundHovered
]
, Css.padding3
(Css.px withBorderTopPadding)
(Css.px withBorderHorizontalPadding)
(Css.px withBorderBottomPadding)
]
else
[ Css.borderWidth Css.zero
, Css.padding Css.zero
, Css.backgroundColor Css.transparent
]
-- Sizing
, Css.display Css.inlineBlock
, Css.boxSizing Css.borderBox
, Css.width config.width
, Css.height config.height
, Css.lineHeight (Css.num 1)
]
withBorderTopBorderWidth : Float
withBorderTopBorderWidth =
1
withBorderRightBorderWidth : Float
withBorderRightBorderWidth =
1
withBorderBottomBorderWidth : Float
withBorderBottomBorderWidth =
2
withBorderLeftBorderWidth : Float
withBorderLeftBorderWidth =
1
withBorderTopPadding : Float
withBorderTopPadding =
4
withBorderBottomPadding : Float
withBorderBottomPadding =
3
withBorderHorizontalPadding : Float
withBorderHorizontalPadding =
5

View File

@ -13,14 +13,14 @@ module Nri.Ui.Colors.Extra exposing
-}
import Color
import Css
import SolidColor exposing (SolidColor)
{-| -}
fromCssColor : Css.Color -> Color.Color
fromCssColor : Css.Color -> SolidColor
fromCssColor color =
Color.fromRGB
SolidColor.fromRGB
( toFloat color.red
, toFloat color.green
, toFloat color.blue
@ -28,11 +28,11 @@ fromCssColor color =
{-| -}
toCssColor : Color.Color -> Css.Color
toCssColor : SolidColor -> Css.Color
toCssColor color =
let
( red, green, blue ) =
Color.toRGB color
SolidColor.toRGB color
in
Css.rgb (round red) (round green) (round blue)

View File

@ -1,901 +0,0 @@
module Nri.Ui.Icon.V3 exposing
( icon, decorativeIcon, link, linkExternal, linkSpa, button
, IconType, IconSize(..), IconLinkSpaModel
, activity
, add
, arrowDown
, arrowLeft
, arrowRight
, assignmentStartButtonPrimary
, assignmentStartButtonSecondary
, assignmentTypeDiagnostic
, assignmentTypePeerReview
, assignmentTypeSelfReview
, assignmentTypePractice
, assignmentTypeQuickWrite
, assignmentTypeQuiz
, assignmentTypeWritingCycle
, attention
, bang
, bulb
, calendar
, caret
, checkMark
, checkMarkSquiggily
, checkMarkSvg
, class
, clever
, clock
, close
, compassSvg
, copy
, custom
, darkBlueCheckMark
, document
, download
, edit
, editWriting
, equalitySign
, exclamation
, facebook
, flag
, flipper
, footsteps
, gardening
, gear
, greenCheckMark
, guidedWrite
, hat
, help
, helpSvg
, highFive
, key
, keychain
, late
, leaderboard
, lightBulb
, lock
, lockDeprecated
, logo
, masteryBadge
, newspaper
, notStarred
, okay
, openClose
, peerReview
, pen
, performance
, personBlue
, preview
, quickWrite
, seeMore
, share
, skip
, sort
, sortArrow
, speedometer
, starred
, submitting, rating, revising
, thumbsUp
, twitter
, unarchive
, writingAssignment
, x
, xSvg
)
{-|
@docs icon, decorativeIcon, link, linkExternal, linkSpa, button
@docs IconType, IconSize, IconLinkSpaModel
@docs activity
@docs add
@docs arrowDown
@docs arrowLeft
@docs arrowRight
@docs assignmentStartButtonPrimary
@docs assignmentStartButtonSecondary
@docs assignmentTypeDiagnostic
@docs assignmentTypePeerReview
@docs assignmentTypeSelfReview
@docs assignmentTypePractice
@docs assignmentTypeQuickWrite
@docs assignmentTypeQuiz
@docs assignmentTypeWritingCycle
@docs attention
@docs bang
@docs bulb
@docs calendar
@docs caret
@docs checkMark
@docs checkMarkSquiggily
@docs checkMarkSvg
@docs class
@docs clever
@docs clock
@docs close
@docs compassSvg
@docs copy
@docs custom
@docs darkBlueCheckMark
@docs document
@docs download
@docs edit
@docs editWriting
@docs equalitySign
@docs exclamation
@docs facebook
@docs flag
@docs flipper
@docs footsteps
@docs gardening
@docs gear
@docs greenCheckMark
@docs guidedWrite
@docs hat
@docs help
@docs helpSvg
@docs highFive
@docs key
@docs keychain
@docs late
@docs leaderboard
@docs lightBulb
@docs lock
@docs lockDeprecated
@docs logo
@docs masteryBadge
@docs newspaper
@docs notStarred
@docs okay
@docs openClose
@docs peerReview
@docs pen
@docs performance
@docs personBlue
@docs preview
@docs quickWrite
@docs seeMore
@docs share
@docs skip
@docs sort
@docs sortArrow
@docs speedometer
@docs starred
@docs submitting, rating, revising
@docs thumbsUp
@docs twitter
@docs unarchive
@docs writingAssignment
@docs x
@docs xSvg
-}
import Accessibility.Role as Role
import Accessibility.Styled exposing (..)
import Css exposing (..)
import EventExtras
import Html as RootHtml
import Html.Attributes as RootAttr exposing (..)
import Html.Styled
import Html.Styled.Attributes as Attributes exposing (css)
import Html.Styled.Events as Events
import Nri.Ui.AssetPath exposing (Asset(..))
import Nri.Ui.Colors.V1
import Svg exposing (svg, use)
import Svg.Attributes exposing (xlinkHref)
{-| -}
type alias IconLinkModel =
{ alt : String
, url : String
, icon : IconType
, disabled : Bool
, size : IconSize
}
{-| -}
type alias IconLinkSpaModel route =
{ alt : String
, icon : IconType
, disabled : Bool
, size : IconSize
, route : route
}
type alias IconButtonModel msg =
{ alt : String
, msg : msg
, icon : IconType
, disabled : Bool
, size : IconSize
}
{-| An icon that can be rendered using the functions provided by this module.
-}
type IconType
= ImgIcon Asset
| SvgIcon String
{-| Used for determining sizes on Icon.buttons and Icon.links
-}
type IconSize
= Small
| Medium
{-| Create an icon that links to a part of NRI
Uses our default icon styles (25 x 25 px, azure)
-}
link : IconLinkModel -> Html msg
link =
linkBase [ Attributes.target "_self" ]
{-| Create an accessible icon button with an onClick handler
Uses our default icon styles (25 x 25 px, azure)
-}
button : IconButtonModel msg -> Html msg
button model =
Accessibility.Styled.button
[ css
[ Css.batch
[ backgroundColor transparent
, border zero
, color Nri.Ui.Colors.V1.azure
, fontFamily inherit
, Css.property "cursor" "pointer"
, padding zero
, focus
[ backgroundColor transparent
]
]
, sizeStyles model.size
]
, Events.onClick model.msg
, Attributes.disabled model.disabled
, Attributes.type_ "button"
]
[ icon
{ alt = model.alt
, icon = model.icon
}
]
{-| -}
icon : { alt : String, icon : IconType } -> Html msg
icon config =
case config.icon of
SvgIcon iconId ->
svg svgStyle
[ Svg.title [] [ RootHtml.text config.alt ]
, use [ xlinkHref ("#" ++ iconId) ] []
]
|> Html.Styled.fromUnstyled
ImgIcon assetPath ->
img config.alt
[ Attributes.src (Nri.Ui.AssetPath.url assetPath)
]
{-| Use this icon for purely decorative content that would be distracting
rather than helpful on a screenreader.
-}
decorativeIcon : IconType -> Html msg
decorativeIcon iconType =
case iconType of
SvgIcon iconId ->
svg
(Role.img :: svgStyle)
[ use [ xlinkHref ("#" ++ iconId) ] []
]
|> Html.Styled.fromUnstyled
ImgIcon assetPath ->
decorativeImg [ Attributes.src (Nri.Ui.AssetPath.url assetPath) ]
{-| Use this link for routing within a single page app.
This will make a normal <a> tag, but change the onClick behavior to avoid reloading the page.
-}
linkSpa : (route -> String) -> (route -> msg) -> IconLinkSpaModel route -> Html msg
linkSpa toUrl toMsg config =
linkBase
[ EventExtras.onClickPreventDefaultForLinkWithHref (toMsg config.route)
]
{ alt = config.alt
, url = toUrl config.route
, icon = config.icon
, disabled = config.disabled
, size = config.size
}
{-| Create an icon that links to an external site
Uses our default icon styles (25 x 25 px, azure)
-}
linkExternal : IconLinkModel -> Html msg
linkExternal =
linkBase [ Attributes.target "_blank" ]
linkBase : List (Attribute msg) -> IconLinkModel -> Html msg
linkBase linkAttributes model =
span
[]
[ Html.Styled.a
(linkAttributes ++ defaultLinkAttributes model)
[ icon { alt = model.alt, icon = model.icon }
]
]
defaultLinkAttributes : IconLinkModel -> List (Attribute msg)
defaultLinkAttributes model =
if model.disabled then
[ css
[ Css.cursor Css.notAllowed
, linkStyles
, sizeStyles model.size
]
]
else
[ css [ linkStyles, sizeStyles model.size ]
, Attributes.href model.url
]
linkStyles : Style
linkStyles =
Css.batch
[ color Nri.Ui.Colors.V1.azure
, display inlineBlock
, fontFamily inherit
, Css.property "cursor" "pointer"
, padding zero
, visited [ color Nri.Ui.Colors.V1.azure ]
]
sizeStyles : IconSize -> Style
sizeStyles size =
Css.batch <|
case size of
Small ->
[ Css.width (px 20)
, Css.height (px 20)
]
Medium ->
[ Css.width (px 25)
, Css.height (px 25)
]
{-| -}
activity : { r | activity : String } -> IconType
activity assets =
SvgIcon assets.activity
{-| -}
add : { r | icons_plusBlue_svg : Asset } -> IconType
add assets =
ImgIcon assets.icons_plusBlue_svg
{-| -}
arrowDown : { r | arrowDown : String } -> IconType
arrowDown assets =
SvgIcon assets.arrowDown
{-| -}
arrowLeft : { r | leftArrowBlue_png : Asset } -> IconType
arrowLeft assets =
ImgIcon assets.leftArrowBlue_png
{-| -}
arrowRight : { r | icons_arrowRightBlue_svg : Asset } -> IconType
arrowRight assets =
ImgIcon assets.icons_arrowRightBlue_svg
{-| -}
assignmentStartButtonPrimary : { r | assignmentStartButtonPrimary_svg : Asset } -> IconType
assignmentStartButtonPrimary assets =
ImgIcon assets.assignmentStartButtonPrimary_svg
{-| -}
assignmentStartButtonSecondary : { r | assignmentStartButtonSecondary_svg : Asset } -> IconType
assignmentStartButtonSecondary assets =
ImgIcon assets.assignmentStartButtonSecondary_svg
{-| -}
assignmentTypeDiagnostic : { r | diagnostic : String } -> IconType
assignmentTypeDiagnostic assets =
SvgIcon assets.diagnostic
{-| -}
assignmentTypePeerReview : { r | icons_peerReviewWhite_svg : Asset } -> IconType
assignmentTypePeerReview assets =
ImgIcon assets.icons_peerReviewWhite_svg
{-| -}
assignmentTypeSelfReview : { r | icons_selfReviewWhite_svg : Asset } -> IconType
assignmentTypeSelfReview assets =
ImgIcon assets.icons_selfReviewWhite_svg
{-| -}
assignmentTypePractice : { r | practice : String } -> IconType
assignmentTypePractice assets =
SvgIcon assets.practice
{-| -}
assignmentTypeQuickWrite : { r | icons_quickWriteWhite_svg : Asset } -> IconType
assignmentTypeQuickWrite assets =
ImgIcon assets.icons_quickWriteWhite_svg
{-| -}
assignmentTypeQuiz : { r | quiz : String } -> IconType
assignmentTypeQuiz assets =
SvgIcon assets.quiz
{-| -}
assignmentTypeWritingCycle : { r | writingcycle : String } -> IconType
assignmentTypeWritingCycle assets =
SvgIcon assets.writingcycle
{-| -}
attention : { r | attention_svg : Asset } -> IconType
attention assets =
ImgIcon assets.attention_svg
{-| -}
bang : { r | exclamationPoint_svg : Asset } -> IconType
bang assets =
ImgIcon assets.exclamationPoint_svg
{-| -}
bulb : { r | bulb : String } -> IconType
bulb assets =
SvgIcon assets.bulb
{-| -}
calendar : { r | calendar : String } -> IconType
calendar assets =
SvgIcon assets.calendar
{-| -}
caret : { r | icons_arrowDownBlue_svg : Asset } -> IconType
caret assets =
ImgIcon assets.icons_arrowDownBlue_svg
{-| -}
checkMark : { r | iconCheck_png : Asset } -> IconType
checkMark assets =
ImgIcon assets.iconCheck_png
{-| -}
checkMarkSquiggily : { r | squiggly_png : Asset } -> IconType
checkMarkSquiggily assets =
ImgIcon assets.squiggly_png
{-| -}
checkMarkSvg : { r | checkmark : String } -> IconType
checkMarkSvg assets =
SvgIcon assets.checkmark
{-| -}
class : { r | class : String } -> IconType
class assets =
SvgIcon assets.class
{-| -}
clever : { r | clever : String } -> IconType
clever assets =
SvgIcon assets.clever
{-| -}
clock : { r | clock : String } -> IconType
clock assets =
SvgIcon assets.clock
{-| -}
close : { r | icons_xBlue_svg : Asset } -> IconType
close assets =
ImgIcon assets.icons_xBlue_svg
{-| -}
copy : { r | teach_assignments_copyWhite_svg : Asset } -> IconType
copy assets =
ImgIcon assets.teach_assignments_copyWhite_svg
{-| -}
compassSvg : { r | compass : String } -> IconType
compassSvg assets =
SvgIcon assets.compass
{-| -}
custom : Asset -> IconType
custom asset =
ImgIcon asset
{-| -}
darkBlueCheckMark : { r | darkBlueCheckmark_svg : Asset } -> IconType
darkBlueCheckMark assets =
ImgIcon assets.darkBlueCheckmark_svg
{-| -}
document : { r | document : String } -> IconType
document assets =
SvgIcon assets.document
{-| -}
download : { r | download : String } -> IconType
download assets =
SvgIcon assets.download
{-| -}
edit : { r | edit : String } -> IconType
edit assets =
SvgIcon assets.edit
{-| -}
editWriting : { r | editWriting : String } -> IconType
editWriting assets =
SvgIcon assets.editWriting
{-| -}
equalitySign : { r | icons_equals_svg : Asset } -> IconType
equalitySign assets =
ImgIcon assets.icons_equals_svg
{-| -}
exclamation : { r | exclamation : String } -> IconType
exclamation assets =
SvgIcon assets.exclamation
{-| -}
facebook : { r | facebookBlue_svg : Asset } -> IconType
facebook assets =
ImgIcon assets.facebookBlue_svg
{-| -}
flag : { r | iconFlag_png : Asset } -> IconType
flag assets =
ImgIcon assets.iconFlag_png
{-| -}
flipper : { r | flipper : String } -> IconType
flipper assets =
SvgIcon assets.flipper
{-| -}
footsteps : { r | footsteps : String } -> IconType
footsteps assets =
SvgIcon assets.footsteps
{-| -}
gardening : { r | startingOffBadge_png : Asset } -> IconType
gardening assets =
ImgIcon assets.startingOffBadge_png
{-| -}
gear : { r | gear : String } -> IconType
gear assets =
SvgIcon assets.gear
{-| -}
greenCheckMark : { r | smallCheckmark_png : Asset } -> IconType
greenCheckMark assets =
ImgIcon assets.smallCheckmark_png
{-| -}
guidedWrite : { r | icons_guidedWrite_svg : Asset } -> IconType
guidedWrite assets =
ImgIcon assets.icons_guidedWrite_svg
{-| -}
hat : { r | hat : String } -> IconType
hat assets =
SvgIcon assets.hat
{-| -}
help : { r | icons_helpBlue_svg : Asset } -> IconType
help assets =
ImgIcon assets.icons_helpBlue_svg
{-| -}
helpSvg : { r | help : String } -> IconType
helpSvg assets =
SvgIcon assets.help
{-| -}
highFive : { r | level3Badge_png : Asset } -> IconType
highFive assets =
ImgIcon assets.level3Badge_png
{-| -}
key : { r | key : String } -> IconType
key assets =
SvgIcon assets.key
{-| -}
keychain : { r | keychain : String } -> IconType
keychain assets =
SvgIcon assets.keychain
{-| -}
late : { r | icons_clockRed_svg : Asset } -> IconType
late assets =
ImgIcon assets.icons_clockRed_svg
{-| -}
leaderboard : { r | leaderboard : String } -> IconType
leaderboard assets =
SvgIcon assets.leaderboard
{-| -}
lightBulb : { r | hint_png : Asset } -> IconType
lightBulb assets =
ImgIcon assets.hint_png
{-| -}
lock : { r | lock : String } -> IconType
lock assets =
SvgIcon assets.lock
{-| -}
lockDeprecated : { r | premiumLock_svg : Asset } -> IconType
lockDeprecated assets =
ImgIcon assets.premiumLock_svg
{-| -}
logo : { r | logoRedBlack_svg : Asset } -> IconType
logo assets =
ImgIcon assets.logoRedBlack_svg
{-| -}
masteryBadge : { r | masteryBadge : String } -> IconType
masteryBadge assets =
SvgIcon assets.masteryBadge
{-| -}
newspaper : { r | newspaper : String } -> IconType
newspaper assets =
SvgIcon assets.newspaper
{-| -}
notStarred : { r | commentNotStarred_png : Asset } -> IconType
notStarred assets =
ImgIcon assets.commentNotStarred_png
{-| -}
okay : { r | level2Badge_png : Asset } -> IconType
okay assets =
ImgIcon assets.level2Badge_png
{-| -}
openClose : { r | openClose : String } -> IconType
openClose assets =
SvgIcon assets.openClose
{-| -}
peerReview : { r | icons_peerReview_svg : Asset } -> IconType
peerReview assets =
ImgIcon assets.icons_peerReview_svg
{-| -}
pen : { r | pen : Asset } -> IconType
pen assets =
ImgIcon assets.pen
{-| -}
performance : { r | performance : String } -> IconType
performance assets =
SvgIcon assets.performance
{-| -}
personBlue : { r | personBlue_svg : Asset } -> IconType
personBlue assets =
ImgIcon assets.personBlue_svg
{-| -}
preview : { r | preview : String } -> IconType
preview assets =
SvgIcon assets.preview
{-| -}
quickWrite : { r | icons_quickWrite_svg : Asset } -> IconType
quickWrite assets =
ImgIcon assets.icons_quickWrite_svg
{-| -}
seeMore : { r | seemore : String } -> IconType
seeMore assets =
SvgIcon assets.seemore
{-| -}
share : { r | share : String } -> IconType
share assets =
SvgIcon assets.share
{-| -}
skip : { r | skip : String } -> IconType
skip assets =
SvgIcon assets.skip
{-| -}
sort : { r | sort : String } -> IconType
sort assets =
SvgIcon assets.sort
{-| -}
sortArrow : { r | sortArrow : String } -> IconType
sortArrow assets =
SvgIcon assets.sortArrow
{-| -}
speedometer : { r | speedometer : String } -> IconType
speedometer assets =
SvgIcon assets.speedometer
{-| -}
starred : { r | commentStarred_png : Asset } -> IconType
starred assets =
ImgIcon assets.commentStarred_png
{-| -}
thumbsUp : { r | level1Badge_png : Asset } -> IconType
thumbsUp assets =
ImgIcon assets.level1Badge_png
{-| -}
twitter : { r | twitterBlue_svg : Asset } -> IconType
twitter assets =
ImgIcon assets.twitterBlue_svg
{-| -}
unarchive : { r | unarchiveBlue2x_png : Asset } -> IconType
unarchive assets =
ImgIcon assets.unarchiveBlue2x_png
{-| -}
writingAssignment : { r | writingAssignment : String } -> IconType
writingAssignment assets =
SvgIcon assets.writingAssignment
{-| -}
x : { r | xWhite_svg : Asset } -> IconType
x assets =
ImgIcon assets.xWhite_svg
{-| -}
xSvg : { r | x : String } -> IconType
xSvg assets =
SvgIcon assets.x
{-| -}
submitting : { r | submitting : String } -> IconType
submitting assets =
SvgIcon assets.submitting
{-| -}
rating : { r | rating : String } -> IconType
rating assets =
SvgIcon assets.rating
{-| -}
revising : { r | revising : String } -> IconType
revising assets =
SvgIcon assets.revising
{-| Inlining SVG styles because styles.class doesn't work on SVG elements.
The `className` property of an SVG element isn't a string, it's an object and so
`styles.class` causes a runtime exception by attempting to overwrite it with
a string. Another workaround is to use the `Svg.Attributes.class` attribute but
since `withNamespace` hides a call to `Html.Attributes.class` we can't do it
properly.
-}
svgStyle : List (RootHtml.Attribute msg)
svgStyle =
[ RootAttr.style "fill" "currentColor"
, RootAttr.style "width" "100%"
, RootAttr.style "height" "100%"
-- don't allow SVG to capture pointer events. This means that we can use it
-- in links. See https://css-tricks.com/links-inline-svg-staying-target-events/
-- for more details.
, RootAttr.style "pointer-events" "none"
]

View File

@ -1,948 +0,0 @@
module Nri.Ui.Icon.V4 exposing
( icon, decorativeIcon
, IconType, IconSize(..)
, IconLinkModel, link, linkExternal
, IconButtonModel, button
, IconLinkSpaModel, linkSpa
, activity
, add
, arrowDown
, arrowLeft
, arrowRight
, assignmentStartButtonPrimary
, assignmentStartButtonSecondary
, assignmentTypeDiagnostic
, assignmentTypeGuidedDraft
, assignmentTypePeerReview
, assignmentTypePractice
, assignmentTypeQuickWrite
, assignmentTypeQuiz
, assignmentTypeSelfReview
, assignmentTypeWritingCycle
, attention
, bang
, bulb
, calendar
, caret
, checkMark
, checkMarkSquiggily
, checkMarkSvg
, class
, clever
, clock
, close
, compassSvg
, copy
, custom
, darkBlueCheckMark
, document
, download
, edit
, editWriting
, equalitySign
, exclamation
, facebook
, flag
, flipper
, footsteps
, gardening
, gear
, greenCheckMark
, guidedWrite
, hat
, help
, helpSvg
, highFive
, highlighter
, key
, keychain
, late
, leaderboard
, lightBulb
, lock
, lockDeprecated
, logo
, masteryBadge
, microscope
, newspaper
, notStarred
, okay
, openClose
, peerReview
, pen
, performance
, personBlue
, preview
, quickWrite
, scale
, search
, seeMore
, share
, skip
, sort
, sortArrow
, speedometer
, starred
, submitting, rating, revising
, thumbsUp
, twitter
, unarchive
, writingAssignment
, x
, xSvg
)
{-|
@docs icon, decorativeIcon
@docs IconType, IconSize
@docs IconLinkModel, link, linkExternal
@docs IconButtonModel, button
@docs IconLinkSpaModel, linkSpa
@docs activity
@docs add
@docs arrowDown
@docs arrowLeft
@docs arrowRight
@docs assignmentStartButtonPrimary
@docs assignmentStartButtonSecondary
@docs assignmentTypeDiagnostic
@docs assignmentTypeGuidedDraft
@docs assignmentTypePeerReview
@docs assignmentTypePractice
@docs assignmentTypeQuickWrite
@docs assignmentTypeQuiz
@docs assignmentTypeSelfReview
@docs assignmentTypeWritingCycle
@docs attention
@docs bang
@docs bulb
@docs calendar
@docs caret
@docs checkMark
@docs checkMarkSquiggily
@docs checkMarkSvg
@docs class
@docs clever
@docs clock
@docs close
@docs compassSvg
@docs copy
@docs custom
@docs darkBlueCheckMark
@docs document
@docs download
@docs edit
@docs editWriting
@docs equalitySign
@docs exclamation
@docs facebook
@docs flag
@docs flipper
@docs footsteps
@docs gardening
@docs gear
@docs greenCheckMark
@docs guidedWrite
@docs hat
@docs help
@docs helpSvg
@docs highFive
@docs highlighter
@docs key
@docs keychain
@docs late
@docs leaderboard
@docs lightBulb
@docs lock
@docs lockDeprecated
@docs logo
@docs masteryBadge
@docs microscope
@docs newspaper
@docs notStarred
@docs okay
@docs openClose
@docs peerReview
@docs pen
@docs performance
@docs personBlue
@docs preview
@docs quickWrite
@docs scale
@docs search
@docs seeMore
@docs share
@docs skip
@docs sort
@docs sortArrow
@docs speedometer
@docs starred
@docs submitting, rating, revising
@docs thumbsUp
@docs twitter
@docs unarchive
@docs writingAssignment
@docs x
@docs xSvg
-}
import Accessibility.Role as Role
import Accessibility.Styled exposing (..)
import Css exposing (..)
import EventExtras
import Html as RootHtml
import Html.Attributes as RootAttr exposing (..)
import Html.Styled
import Html.Styled.Attributes as Attributes exposing (css)
import Html.Styled.Events as Events
import Nri.Ui.AssetPath exposing (Asset(..))
import Nri.Ui.Colors.V1
import Svg exposing (svg, use)
import Svg.Attributes exposing (xlinkHref)
{-| -}
type alias IconLinkModel =
{ alt : String
, url : String
, icon : IconType
, disabled : Bool
, size : IconSize
}
{-| -}
type alias IconLinkSpaModel route =
{ alt : String
, icon : IconType
, disabled : Bool
, size : IconSize
, route : route
}
{-| -}
type alias IconButtonModel msg =
{ alt : String
, msg : msg
, icon : IconType
, disabled : Bool
, size : IconSize
}
{-| An icon that can be rendered using the functions provided by this module.
-}
type IconType
= ImgIcon Asset
| SvgIcon String
{-| Used for determining sizes on Icon.buttons and Icon.links
-}
type IconSize
= Small
| Medium
{-| Create an icon that links to a part of NRI
Uses our default icon styles (25 x 25 px, azure)
-}
link : IconLinkModel -> Html msg
link =
linkBase [ Attributes.target "_self" ]
{-| Create an accessible icon button with an onClick handler
Uses our default icon styles (25 x 25 px, azure)
-}
button : IconButtonModel msg -> Html msg
button model =
Accessibility.Styled.button
[ css
[ Css.batch
[ backgroundColor transparent
, border zero
, color Nri.Ui.Colors.V1.azure
, fontFamily inherit
, Css.property "cursor" "pointer"
, padding zero
, focus
[ backgroundColor transparent
]
]
, sizeStyles model.size
]
, Events.onClick model.msg
, Attributes.disabled model.disabled
, Attributes.type_ "button"
]
[ icon
{ alt = model.alt
, icon = model.icon
}
]
{-| -}
icon : { alt : String, icon : IconType } -> Html msg
icon config =
case config.icon of
SvgIcon iconId ->
svg svgStyle
[ Svg.title [] [ RootHtml.text config.alt ]
, use [ xlinkHref ("#" ++ iconId) ] []
]
|> Html.Styled.fromUnstyled
ImgIcon assetPath ->
img config.alt
[ Attributes.src (Nri.Ui.AssetPath.url assetPath)
]
{-| Use this icon for purely decorative content that would be distracting
rather than helpful on a screenreader.
-}
decorativeIcon : IconType -> Html msg
decorativeIcon iconType =
case iconType of
SvgIcon iconId ->
svg
(Role.img :: svgStyle)
[ use [ xlinkHref ("#" ++ iconId) ] []
]
|> Html.Styled.fromUnstyled
ImgIcon assetPath ->
decorativeImg [ Attributes.src (Nri.Ui.AssetPath.url assetPath) ]
{-| Use this link for routing within a single page app.
This will make a normal <a> tag, but change the onClick behavior to avoid reloading the page.
-}
linkSpa : (route -> String) -> (route -> msg) -> IconLinkSpaModel route -> Html msg
linkSpa toUrl toMsg config =
linkBase
[ EventExtras.onClickPreventDefaultForLinkWithHref (toMsg config.route)
]
{ alt = config.alt
, url = toUrl config.route
, icon = config.icon
, disabled = config.disabled
, size = config.size
}
{-| Create an icon that links to an external site
Uses our default icon styles (25 x 25 px, azure)
-}
linkExternal : IconLinkModel -> Html msg
linkExternal =
linkBase [ Attributes.target "_blank" ]
linkBase : List (Attribute msg) -> IconLinkModel -> Html msg
linkBase linkAttributes model =
span
[]
[ Html.Styled.a
(linkAttributes ++ defaultLinkAttributes model)
[ icon { alt = model.alt, icon = model.icon }
]
]
defaultLinkAttributes : IconLinkModel -> List (Attribute msg)
defaultLinkAttributes model =
if model.disabled then
[ css
[ Css.cursor Css.notAllowed
, linkStyles
, sizeStyles model.size
]
]
else
[ css [ linkStyles, sizeStyles model.size ]
, Attributes.href model.url
]
linkStyles : Style
linkStyles =
Css.batch
[ color Nri.Ui.Colors.V1.azure
, display inlineBlock
, fontFamily inherit
, Css.property "cursor" "pointer"
, padding zero
, visited [ color Nri.Ui.Colors.V1.azure ]
]
sizeStyles : IconSize -> Style
sizeStyles size =
Css.batch <|
case size of
Small ->
[ Css.width (px 20)
, Css.height (px 20)
]
Medium ->
[ Css.width (px 25)
, Css.height (px 25)
]
{-| -}
activity : { r | activity : String } -> IconType
activity assets =
SvgIcon assets.activity
{-| -}
add : { r | icons_plusBlue_svg : Asset } -> IconType
add assets =
ImgIcon assets.icons_plusBlue_svg
{-| -}
arrowDown : { r | arrowDown : String } -> IconType
arrowDown assets =
SvgIcon assets.arrowDown
{-| -}
arrowLeft : { r | leftArrowBlue_png : Asset } -> IconType
arrowLeft assets =
ImgIcon assets.leftArrowBlue_png
{-| -}
arrowRight : { r | icons_arrowRightBlue_svg : Asset } -> IconType
arrowRight assets =
ImgIcon assets.icons_arrowRightBlue_svg
{-| -}
assignmentStartButtonPrimary : { r | assignmentStartButtonPrimary_svg : Asset } -> IconType
assignmentStartButtonPrimary assets =
ImgIcon assets.assignmentStartButtonPrimary_svg
{-| -}
assignmentStartButtonSecondary : { r | assignmentStartButtonSecondary_svg : Asset } -> IconType
assignmentStartButtonSecondary assets =
ImgIcon assets.assignmentStartButtonSecondary_svg
{-| -}
assignmentTypeDiagnostic : { r | diagnostic : String } -> IconType
assignmentTypeDiagnostic assets =
SvgIcon assets.diagnostic
{-| -}
assignmentTypeGuidedDraft : { r | guidedDraft : String } -> IconType
assignmentTypeGuidedDraft assets =
SvgIcon assets.guidedDraft
{-| -}
assignmentTypePeerReview : { r | peerReview : String } -> IconType
assignmentTypePeerReview assets =
SvgIcon assets.peerReview
{-| -}
assignmentTypeSelfReview : { r | selfReview : String } -> IconType
assignmentTypeSelfReview assets =
SvgIcon assets.selfReview
{-| -}
assignmentTypePractice : { r | practice : String } -> IconType
assignmentTypePractice assets =
SvgIcon assets.practice
{-| -}
assignmentTypeQuickWrite : { r | quickWrite : String } -> IconType
assignmentTypeQuickWrite assets =
SvgIcon assets.quickWrite
{-| -}
assignmentTypeQuiz : { r | quiz : String } -> IconType
assignmentTypeQuiz assets =
SvgIcon assets.quiz
{-| -}
assignmentTypeWritingCycle : { r | writingcycle : String } -> IconType
assignmentTypeWritingCycle assets =
SvgIcon assets.writingcycle
{-| -}
attention : { r | attention_svg : Asset } -> IconType
attention assets =
ImgIcon assets.attention_svg
{-| -}
bang : { r | exclamationPoint_svg : Asset } -> IconType
bang assets =
ImgIcon assets.exclamationPoint_svg
{-| -}
bulb : { r | bulb : String } -> IconType
bulb assets =
SvgIcon assets.bulb
{-| -}
calendar : { r | calendar : String } -> IconType
calendar assets =
SvgIcon assets.calendar
{-| -}
caret : { r | icons_arrowDownBlue_svg : Asset } -> IconType
caret assets =
ImgIcon assets.icons_arrowDownBlue_svg
{-| -}
checkMark : { r | iconCheck_png : Asset } -> IconType
checkMark assets =
ImgIcon assets.iconCheck_png
{-| -}
checkMarkSquiggily : { r | squiggly_png : Asset } -> IconType
checkMarkSquiggily assets =
ImgIcon assets.squiggly_png
{-| -}
checkMarkSvg : { r | checkmark : String } -> IconType
checkMarkSvg assets =
SvgIcon assets.checkmark
{-| -}
class : { r | class : String } -> IconType
class assets =
SvgIcon assets.class
{-| -}
clever : { r | clever : String } -> IconType
clever assets =
SvgIcon assets.clever
{-| -}
clock : { r | clock : String } -> IconType
clock assets =
SvgIcon assets.clock
{-| -}
close : { r | icons_xBlue_svg : Asset } -> IconType
close assets =
ImgIcon assets.icons_xBlue_svg
{-| -}
copy : { r | teach_assignments_copyWhite_svg : Asset } -> IconType
copy assets =
ImgIcon assets.teach_assignments_copyWhite_svg
{-| -}
compassSvg : { r | compass : String } -> IconType
compassSvg assets =
SvgIcon assets.compass
{-| -}
custom : Asset -> IconType
custom asset =
ImgIcon asset
{-| -}
darkBlueCheckMark : { r | darkBlueCheckmark_svg : Asset } -> IconType
darkBlueCheckMark assets =
ImgIcon assets.darkBlueCheckmark_svg
{-| -}
document : { r | document : String } -> IconType
document assets =
SvgIcon assets.document
{-| -}
download : { r | download : String } -> IconType
download assets =
SvgIcon assets.download
{-| -}
edit : { r | edit : String } -> IconType
edit assets =
SvgIcon assets.edit
{-| -}
editWriting : { r | editWriting : String } -> IconType
editWriting assets =
SvgIcon assets.editWriting
{-| -}
equalitySign : { r | icons_equals_svg : Asset } -> IconType
equalitySign assets =
ImgIcon assets.icons_equals_svg
{-| -}
exclamation : { r | exclamation : String } -> IconType
exclamation assets =
SvgIcon assets.exclamation
{-| -}
facebook : { r | facebookBlue_svg : Asset } -> IconType
facebook assets =
ImgIcon assets.facebookBlue_svg
{-| -}
flag : { r | iconFlag_png : Asset } -> IconType
flag assets =
ImgIcon assets.iconFlag_png
{-| -}
flipper : { r | flipper : String } -> IconType
flipper assets =
SvgIcon assets.flipper
{-| -}
footsteps : { r | footsteps : String } -> IconType
footsteps assets =
SvgIcon assets.footsteps
{-| -}
gardening : { r | startingOffBadge_png : Asset } -> IconType
gardening assets =
ImgIcon assets.startingOffBadge_png
{-| -}
gear : { r | gear : String } -> IconType
gear assets =
SvgIcon assets.gear
{-| -}
greenCheckMark : { r | smallCheckmark_png : Asset } -> IconType
greenCheckMark assets =
ImgIcon assets.smallCheckmark_png
{-| -}
guidedWrite : { r | icons_guidedWrite_svg : Asset } -> IconType
guidedWrite assets =
ImgIcon assets.icons_guidedWrite_svg
{-| -}
hat : { r | hat : String } -> IconType
hat assets =
SvgIcon assets.hat
{-| -}
help : { r | icons_helpBlue_svg : Asset } -> IconType
help assets =
ImgIcon assets.icons_helpBlue_svg
{-| -}
helpSvg : { r | help : String } -> IconType
helpSvg assets =
SvgIcon assets.help
{-| -}
highFive : { r | level3Badge_png : Asset } -> IconType
highFive assets =
ImgIcon assets.level3Badge_png
{-| -}
highlighter : { r | highlighter : String } -> IconType
highlighter assets =
SvgIcon assets.highlighter
{-| -}
key : { r | key : String } -> IconType
key assets =
SvgIcon assets.key
{-| -}
keychain : { r | keychain : String } -> IconType
keychain assets =
SvgIcon assets.keychain
{-| -}
late : { r | icons_clockRed_svg : Asset } -> IconType
late assets =
ImgIcon assets.icons_clockRed_svg
{-| -}
leaderboard : { r | leaderboard : String } -> IconType
leaderboard assets =
SvgIcon assets.leaderboard
{-| -}
lightBulb : { r | hint_png : Asset } -> IconType
lightBulb assets =
ImgIcon assets.hint_png
{-| -}
lock : { r | lock : String } -> IconType
lock assets =
SvgIcon assets.lock
{-| -}
lockDeprecated : { r | premiumLock_svg : Asset } -> IconType
lockDeprecated assets =
ImgIcon assets.premiumLock_svg
{-| -}
logo : { r | logoRedBlack_svg : Asset } -> IconType
logo assets =
ImgIcon assets.logoRedBlack_svg
{-| -}
masteryBadge : { r | masteryBadge : String } -> IconType
masteryBadge assets =
SvgIcon assets.masteryBadge
{-| -}
microscope : { r | microscope : String } -> IconType
microscope assets =
SvgIcon assets.microscope
{-| -}
newspaper : { r | newspaper : String } -> IconType
newspaper assets =
SvgIcon assets.newspaper
{-| -}
notStarred : { r | commentNotStarred_png : Asset } -> IconType
notStarred assets =
ImgIcon assets.commentNotStarred_png
{-| -}
okay : { r | level2Badge_png : Asset } -> IconType
okay assets =
ImgIcon assets.level2Badge_png
{-| -}
openClose : { r | openClose : String } -> IconType
openClose assets =
SvgIcon assets.openClose
{-| -}
peerReview : { r | icons_peerReview_svg : Asset } -> IconType
peerReview assets =
ImgIcon assets.icons_peerReview_svg
{-| -}
pen : { r | pen : Asset } -> IconType
pen assets =
ImgIcon assets.pen
{-| -}
performance : { r | performance : String } -> IconType
performance assets =
SvgIcon assets.performance
{-| -}
personBlue : { r | personBlue_svg : Asset } -> IconType
personBlue assets =
ImgIcon assets.personBlue_svg
{-| -}
preview : { r | preview : String } -> IconType
preview assets =
SvgIcon assets.preview
{-| -}
quickWrite : { r | icons_quickWrite_svg : Asset } -> IconType
quickWrite assets =
ImgIcon assets.icons_quickWrite_svg
{-| -}
scale : { r | scale : String } -> IconType
scale assets =
SvgIcon assets.scale
{-| -}
search : { r | search : String } -> IconType
search assets =
SvgIcon assets.search
{-| -}
seeMore : { r | seemore : String } -> IconType
seeMore assets =
SvgIcon assets.seemore
{-| -}
share : { r | share : String } -> IconType
share assets =
SvgIcon assets.share
{-| -}
skip : { r | skip : String } -> IconType
skip assets =
SvgIcon assets.skip
{-| -}
sort : { r | sort : String } -> IconType
sort assets =
SvgIcon assets.sort
{-| -}
sortArrow : { r | sortArrow : String } -> IconType
sortArrow assets =
SvgIcon assets.sortArrow
{-| -}
speedometer : { r | speedometer : String } -> IconType
speedometer assets =
SvgIcon assets.speedometer
{-| -}
starred : { r | commentStarred_png : Asset } -> IconType
starred assets =
ImgIcon assets.commentStarred_png
{-| -}
thumbsUp : { r | level1Badge_png : Asset } -> IconType
thumbsUp assets =
ImgIcon assets.level1Badge_png
{-| -}
twitter : { r | twitterBlue_svg : Asset } -> IconType
twitter assets =
ImgIcon assets.twitterBlue_svg
{-| -}
unarchive : { r | unarchiveBlue2x_png : Asset } -> IconType
unarchive assets =
ImgIcon assets.unarchiveBlue2x_png
{-| -}
writingAssignment : { r | writingAssignment : String } -> IconType
writingAssignment assets =
SvgIcon assets.writingAssignment
{-| -}
x : { r | xWhite_svg : Asset } -> IconType
x assets =
ImgIcon assets.xWhite_svg
{-| -}
xSvg : { r | x : String } -> IconType
xSvg assets =
SvgIcon assets.x
{-| -}
submitting : { r | submitting : String } -> IconType
submitting assets =
SvgIcon assets.submitting
{-| -}
rating : { r | rating : String } -> IconType
rating assets =
SvgIcon assets.rating
{-| -}
revising : { r | revising : String } -> IconType
revising assets =
SvgIcon assets.revising
{-| Inlining SVG styles because styles.class doesn't work on SVG elements.
The `className` property of an SVG element isn't a string, it's an object and so
`styles.class` causes a runtime exception by attempting to overwrite it with
a string. Another workaround is to use the `Svg.Attributes.class` attribute but
since `withNamespace` hides a call to `Html.Attributes.class` we can't do it
properly.
-}
svgStyle : List (RootHtml.Attribute msg)
svgStyle =
[ RootAttr.style "fill" "currentColor"
, RootAttr.style "width" "100%"
, RootAttr.style "height" "100%"
-- don't allow SVG to capture pointer events. This means that we can use it
-- in links. See https://css-tricks.com/links-inline-svg-staying-target-events/
-- for more details.
, RootAttr.style "pointer-events" "none"
]

View File

@ -1,754 +0,0 @@
module Nri.Ui.Icon.V5 exposing
( gardening, highFive, okay, thumbsUp, masteryBadge
, starred, notStarred, flag
, assignmentTypeDiagnostic, assignmentTypePractice, assignmentTypeQuiz, assignmentTypeQuickWrite, assignmentTypeGuidedDraft, assignmentTypePeerReview, assignmentTypeSelfReview, submitting, rating, revising, guidedWrite, assignmentTypeWritingCycle, writingAssignment
, assignmentStartButtonPrimary, assignmentStartButtonSecondary
, unarchive, share, seeMore, preview, performance, openClose, download
, edit, editWriting
, class, leaderboard, personBlue
, facebook, twitter, clever
, arrowDown, sortArrow
, checkMarkSvg
, xSvg
, exclamation, attention
, bulb, lightBulb, helpSvg
, key, lock
, calendar, clock
, activity, compassSvg, document, flipper, footsteps
, gear, pen, newspaper, sort, speedometer
, skip, equalitySign
, logo
, IconSize(..), IconType
, decorativeIcon, icon
, IconButtonModel, button
, IconLinkModel, link, linkExternal
, IconLinkSpaModel, linkSpa
)
{-|
# Changes from V4
- Removes old icons
# Icon types
## Mastery Icons
@docs gardening, highFive, okay, thumbsUp, masteryBadge
## Stars and Flags
@docs starred, notStarred, flag
## Assignment Types
@docs assignmentTypeDiagnostic, assignmentTypePractice, assignmentTypeQuiz, assignmentTypeQuickWrite, assignmentTypeGuidedDraft, assignmentTypePeerReview, assignmentTypeSelfReview, submitting, rating, revising, guidedWrite, assignmentTypeWritingCycle, writingAssignment
## Student Assignment Actions
@docs assignmentStartButtonPrimary, assignmentStartButtonSecondary
## Teacher Assignment Actions
@docs unarchive, share, seeMore, preview, performance, openClose, download
## Edit
@docs edit, editWriting
## Humans
@docs class, leaderboard, personBlue
## Social Media
@docs facebook, twitter, clever
## Arrows and Carets
@docs arrowDown, sortArrow
## Checkmarks
@docs checkMarkSvg
## Xs
@docs xSvg
## Bangs
@docs exclamation, attention
## Bulbs and Tips
@docs bulb, lightBulb, helpSvg
## Locks and keys
@docs key, lock
## Time
@docs calendar, clock
## Uncategorized (SVGs)
@docs activity, compassSvg, document, flipper, footsteps
@docs gear, pen, newspaper, sort, speedometer
@docs skip, equalitySign
@docs logo
# Using Icons
@docs IconSize, IconType
@docs decorativeIcon, icon
## Buttons
@docs IconButtonModel, button
## Links
@docs IconLinkModel, link, linkExternal
@docs IconLinkSpaModel, linkSpa
-}
import Accessibility.Role as Role
import Accessibility.Styled exposing (..)
import Css exposing (..)
import EventExtras
import Html as RootHtml
import Html.Attributes as RootAttr exposing (..)
import Html.Styled
import Html.Styled.Attributes as Attributes exposing (css)
import Html.Styled.Events as Events
import Nri.Ui.AssetPath exposing (Asset(..))
import Nri.Ui.Colors.V1
import Nri.Ui.Html.Attributes.V2 as AttributeExtras
import Svg exposing (svg, use)
import Svg.Attributes exposing (xlinkHref)
{-| -}
type alias IconLinkModel =
{ alt : String
, url : String
, icon : IconType
, disabled : Bool
, size : IconSize
}
{-| -}
type alias IconLinkSpaModel route =
{ alt : String
, icon : IconType
, disabled : Bool
, size : IconSize
, route : route
}
{-| -}
type alias IconButtonModel msg =
{ alt : String
, msg : msg
, icon : IconType
, disabled : Bool
, size : IconSize
}
{-| An icon that can be rendered using the functions provided by this module.
-}
type IconType
= ImgIcon Asset
| SvgIcon String
{-| Used for determining sizes on Icon.buttons and Icon.links
-}
type IconSize
= Small
| Medium
{-| Create an icon that links to a part of NRI
Uses our default icon styles (25 x 25 px, azure)
-}
link : IconLinkModel -> Html msg
link =
linkBase [ Attributes.target "_self" ]
{-| Create an accessible icon button with an onClick handler
Uses our default icon styles (25 x 25 px, azure)
-}
button : IconButtonModel msg -> Html msg
button model =
Accessibility.Styled.button
[ css
[ Css.batch
[ backgroundColor transparent
, border zero
, color Nri.Ui.Colors.V1.azure
, fontFamily inherit
, Css.property "cursor" "pointer"
, padding zero
, focus
[ backgroundColor transparent
]
]
, sizeStyles model.size
]
, Events.onClick model.msg
, Attributes.disabled model.disabled
, Attributes.type_ "button"
]
[ icon
{ alt = model.alt
, icon = model.icon
}
]
{-| -}
icon : { alt : String, icon : IconType } -> Html msg
icon config =
case config.icon of
SvgIcon iconId ->
svg svgStyle
[ Svg.title [] [ RootHtml.text config.alt ]
, use [ xlinkHref ("#" ++ iconId) ] []
]
|> Html.Styled.fromUnstyled
ImgIcon assetPath ->
img config.alt
[ Attributes.src (Nri.Ui.AssetPath.url assetPath)
]
{-| Use this icon for purely decorative content that would be distracting
rather than helpful on a screenreader.
-}
decorativeIcon : IconType -> Html msg
decorativeIcon iconType =
case iconType of
SvgIcon iconId ->
svg
(Role.img :: svgStyle)
[ use [ xlinkHref ("#" ++ iconId) ] []
]
|> Html.Styled.fromUnstyled
ImgIcon assetPath ->
decorativeImg [ Attributes.src (Nri.Ui.AssetPath.url assetPath) ]
{-| Use this link for routing within a single page app.
This will make a normal <a> tag, but change the onClick behavior to avoid reloading the page.
-}
linkSpa : (route -> String) -> (route -> msg) -> IconLinkSpaModel route -> Html msg
linkSpa toUrl toMsg config =
linkBase
[ EventExtras.onClickPreventDefaultForLinkWithHref (toMsg config.route)
]
{ alt = config.alt
, url = toUrl config.route
, icon = config.icon
, disabled = config.disabled
, size = config.size
}
{-| Create an icon that links to an external site
Uses our default icon styles (25 x 25 px, azure)
-}
linkExternal : IconLinkModel -> Html msg
linkExternal =
linkBase AttributeExtras.targetBlank
linkBase : List (Attribute msg) -> IconLinkModel -> Html msg
linkBase linkAttributes model =
span
[]
[ Html.Styled.a
(linkAttributes ++ defaultLinkAttributes model)
[ icon { alt = model.alt, icon = model.icon }
]
]
defaultLinkAttributes : IconLinkModel -> List (Attribute msg)
defaultLinkAttributes model =
if model.disabled then
[ css
[ Css.cursor Css.notAllowed
, linkStyles
, sizeStyles model.size
]
]
else
[ css [ linkStyles, sizeStyles model.size ]
, Attributes.href model.url
]
linkStyles : Style
linkStyles =
Css.batch
[ color Nri.Ui.Colors.V1.azure
, display inlineBlock
, fontFamily inherit
, Css.property "cursor" "pointer"
, padding zero
, visited [ color Nri.Ui.Colors.V1.azure ]
]
sizeStyles : IconSize -> Style
sizeStyles size =
Css.batch <|
case size of
Small ->
[ Css.width (px 20)
, Css.height (px 20)
]
Medium ->
[ Css.width (px 25)
, Css.height (px 25)
]
{-| -}
activity : { r | activity : String } -> IconType
activity assets =
SvgIcon assets.activity
{-| -}
arrowDown : { r | arrowDown : String } -> IconType
arrowDown assets =
SvgIcon assets.arrowDown
{-| -}
assignmentStartButtonPrimary : { r | assignmentStartButtonPrimary_svg : Asset } -> IconType
assignmentStartButtonPrimary assets =
ImgIcon assets.assignmentStartButtonPrimary_svg
{-| -}
assignmentStartButtonSecondary : { r | assignmentStartButtonSecondary_svg : Asset } -> IconType
assignmentStartButtonSecondary assets =
ImgIcon assets.assignmentStartButtonSecondary_svg
{-| -}
assignmentTypeDiagnostic : { r | diagnostic : String } -> IconType
assignmentTypeDiagnostic assets =
SvgIcon assets.diagnostic
{-| -}
assignmentTypeGuidedDraft : { r | guidedDraft : String } -> IconType
assignmentTypeGuidedDraft assets =
SvgIcon assets.guidedDraft
{-| -}
assignmentTypePeerReview : { r | peerReview : String } -> IconType
assignmentTypePeerReview assets =
SvgIcon assets.peerReview
{-| -}
assignmentTypeSelfReview : { r | selfReview : String } -> IconType
assignmentTypeSelfReview assets =
SvgIcon assets.selfReview
{-| -}
assignmentTypePractice : { r | practice : String } -> IconType
assignmentTypePractice assets =
SvgIcon assets.practice
{-| -}
assignmentTypeQuickWrite : { r | quickWrite : String } -> IconType
assignmentTypeQuickWrite assets =
SvgIcon assets.quickWrite
{-| -}
assignmentTypeQuiz : { r | quiz : String } -> IconType
assignmentTypeQuiz assets =
SvgIcon assets.quiz
{-| -}
assignmentTypeWritingCycle : { r | writingcycle : String } -> IconType
assignmentTypeWritingCycle assets =
SvgIcon assets.writingcycle
{-| -}
attention : { r | attention_svg : Asset } -> IconType
attention assets =
ImgIcon assets.attention_svg
{-| -}
bulb : { r | bulb : String } -> IconType
bulb assets =
SvgIcon assets.bulb
{-| -}
calendar : { r | calendar : String } -> IconType
calendar assets =
SvgIcon assets.calendar
{-| -}
checkMarkSvg : { r | checkmark : String } -> IconType
checkMarkSvg assets =
SvgIcon assets.checkmark
{-| -}
class : { r | class : String } -> IconType
class assets =
SvgIcon assets.class
{-| -}
clever : { r | clever : String } -> IconType
clever assets =
SvgIcon assets.clever
{-| -}
clock : { r | clock : String } -> IconType
clock assets =
SvgIcon assets.clock
{-| -}
compassSvg : { r | compass : String } -> IconType
compassSvg assets =
SvgIcon assets.compass
{-| -}
document : { r | document : String } -> IconType
document assets =
SvgIcon assets.document
{-| -}
download : { r | download : String } -> IconType
download assets =
SvgIcon assets.download
{-| -}
edit : { r | edit : String } -> IconType
edit assets =
SvgIcon assets.edit
{-| -}
editWriting : { r | editWriting : String } -> IconType
editWriting assets =
SvgIcon assets.editWriting
{-| -}
equalitySign : { r | icons_equals_svg : Asset } -> IconType
equalitySign assets =
ImgIcon assets.icons_equals_svg
{-| -}
exclamation : { r | exclamation : String } -> IconType
exclamation assets =
SvgIcon assets.exclamation
{-| -}
facebook : { r | facebookBlue_svg : Asset } -> IconType
facebook assets =
ImgIcon assets.facebookBlue_svg
{-| -}
flag : { r | iconFlag_png : Asset } -> IconType
flag assets =
ImgIcon assets.iconFlag_png
{-| -}
flipper : { r | flipper : String } -> IconType
flipper assets =
SvgIcon assets.flipper
{-| -}
footsteps : { r | footsteps : String } -> IconType
footsteps assets =
SvgIcon assets.footsteps
{-| -}
gardening : { r | startingOffBadge_png : Asset } -> IconType
gardening assets =
ImgIcon assets.startingOffBadge_png
{-| -}
gear : { r | gear : String } -> IconType
gear assets =
SvgIcon assets.gear
{-| -}
guidedWrite : { r | icons_guidedWrite_svg : Asset } -> IconType
guidedWrite assets =
ImgIcon assets.icons_guidedWrite_svg
{-| -}
helpSvg : { r | help : String } -> IconType
helpSvg assets =
SvgIcon assets.help
{-| -}
highFive : { r | level3Badge_png : Asset } -> IconType
highFive assets =
ImgIcon assets.level3Badge_png
{-| -}
key : { r | key : String } -> IconType
key assets =
SvgIcon assets.key
{-| -}
leaderboard : { r | leaderboard : String } -> IconType
leaderboard assets =
SvgIcon assets.leaderboard
{-| -}
lightBulb : { r | hint_png : Asset } -> IconType
lightBulb assets =
ImgIcon assets.hint_png
{-| -}
lock : { r | lock : String } -> IconType
lock assets =
SvgIcon assets.lock
{-| -}
logo : { r | logoRedBlack_svg : Asset } -> IconType
logo assets =
ImgIcon assets.logoRedBlack_svg
{-| -}
masteryBadge : { r | masteryBadge : String } -> IconType
masteryBadge assets =
SvgIcon assets.masteryBadge
{-| -}
newspaper : { r | newspaper : String } -> IconType
newspaper assets =
SvgIcon assets.newspaper
{-| -}
notStarred : { r | commentNotStarred_png : Asset } -> IconType
notStarred assets =
ImgIcon assets.commentNotStarred_png
{-| -}
okay : { r | level2Badge_png : Asset } -> IconType
okay assets =
ImgIcon assets.level2Badge_png
{-| -}
openClose : { r | openClose : String } -> IconType
openClose assets =
SvgIcon assets.openClose
{-| -}
pen : { r | pen : Asset } -> IconType
pen assets =
ImgIcon assets.pen
{-| -}
performance : { r | performance : String } -> IconType
performance assets =
SvgIcon assets.performance
{-| -}
personBlue : { r | personBlue_svg : Asset } -> IconType
personBlue assets =
ImgIcon assets.personBlue_svg
{-| -}
preview : { r | preview : String } -> IconType
preview assets =
SvgIcon assets.preview
{-| -}
seeMore : { r | seemore : String } -> IconType
seeMore assets =
SvgIcon assets.seemore
{-| -}
share : { r | share : String } -> IconType
share assets =
SvgIcon assets.share
{-| -}
skip : { r | skip : String } -> IconType
skip assets =
SvgIcon assets.skip
{-| -}
sort : { r | sort : String } -> IconType
sort assets =
SvgIcon assets.sort
{-| -}
sortArrow : { r | sortArrow : String } -> IconType
sortArrow assets =
SvgIcon assets.sortArrow
{-| -}
speedometer : { r | speedometer : String } -> IconType
speedometer assets =
SvgIcon assets.speedometer
{-| -}
starred : { r | commentStarred_png : Asset } -> IconType
starred assets =
ImgIcon assets.commentStarred_png
{-| -}
thumbsUp : { r | level1Badge_png : Asset } -> IconType
thumbsUp assets =
ImgIcon assets.level1Badge_png
{-| -}
twitter : { r | twitterBlue_svg : Asset } -> IconType
twitter assets =
ImgIcon assets.twitterBlue_svg
{-| -}
unarchive : { r | unarchiveBlue2x_png : Asset } -> IconType
unarchive assets =
ImgIcon assets.unarchiveBlue2x_png
{-| -}
writingAssignment : { r | writingAssignment : String } -> IconType
writingAssignment assets =
SvgIcon assets.writingAssignment
{-| -}
xSvg : { r | x : String } -> IconType
xSvg assets =
SvgIcon assets.x
{-| -}
submitting : { r | submitting : String } -> IconType
submitting assets =
SvgIcon assets.submitting
{-| -}
rating : { r | rating : String } -> IconType
rating assets =
SvgIcon assets.rating
{-| -}
revising : { r | revising : String } -> IconType
revising assets =
SvgIcon assets.revising
{-| Inlining SVG styles because styles.class doesn't work on SVG elements.
The `className` property of an SVG element isn't a string, it's an object and so
`styles.class` causes a runtime exception by attempting to overwrite it with
a string. Another workaround is to use the `Svg.Attributes.class` attribute but
since `withNamespace` hides a call to `Html.Attributes.class` we can't do it
properly.
-}
svgStyle : List (RootHtml.Attribute msg)
svgStyle =
[ RootAttr.style "fill" "currentColor"
, RootAttr.style "width" "100%"
, RootAttr.style "height" "100%"
-- don't allow SVG to capture pointer events. This means that we can use it
-- in links. See https://css-tricks.com/links-inline-svg-staying-target-events/
-- for more details.
, RootAttr.style "pointer-events" "none"
]

View File

@ -1,222 +0,0 @@
module Nri.Ui.InputStyles.V2 exposing
( label, Theme(..), input
, inputPaddingVertical, inputLineHeight, textAreaHeight, writingLineHeight, writingPadding, writingPaddingTop, writingMinHeight
)
{-| InputStyles used by the TextInput and TextArea widgets.
@docs label, Theme, input
## Shared hardcoded values
@docs inputPaddingVertical, inputLineHeight, textAreaHeight, writingLineHeight, writingPadding, writingPaddingTop, writingMinHeight
-}
import Css exposing (..)
import Css.Global
import Nri.Ui.Colors.V1 exposing (..)
import Nri.Ui.Fonts.V1
{-| -}
type Theme
= ContentCreation
| Standard
| Writing
{-| -}
label : Theme -> Bool -> Style
label theme inError =
let
sharedStyles =
batch
[ backgroundColor white
, left (px 10)
, top (px 1)
, fontSize (px 12)
, Nri.Ui.Fonts.V1.baseFont
, position absolute
, fontWeight (int 600)
, property "transition" "all 0.4s ease"
]
in
case theme of
Standard ->
batch
[ sharedStyles
, padding2 zero (px 5)
, fontSize (px 12)
, color navy
, if inError then
batch [ color purple ]
else
batch []
]
ContentCreation ->
batch
[ sharedStyles
, border3 (px 1) solid gray75
, borderRadius (px 4)
, padding2 zero (px 5)
, fontSize (Css.px 11)
, color gray45
, padding2 (px 2) (px 5)
]
Writing ->
batch
[ sharedStyles
, padding2 zero (px 5)
, border3 (px 1) solid gray75
, borderRadius (px 4)
, fontSize (px 15)
, color navy
, if inError then
batch
[ color purple
, backgroundColor white
, borderColor purple
]
else
batch []
]
{-| In order to use these styles in an input module, you will need to add the class "override-sass-styles". This is because sass styles in the monolith have higher precendence than the class styles here.
-}
input : Theme -> Bool -> Style
input theme isInError =
let
sharedStyles =
batch
[ border3 (px 1) solid gray75
, width (pct 100)
, borderRadius (px 8)
, pseudoClass "placeholder"
[ color gray45
]
, color gray20
-- fix bootstrap
, display inlineBlock
, verticalAlign top
, marginBottom zero
, marginTop (px 9)
, boxShadow6 inset zero (px 3) zero zero gray92
, property "transition" "border-color 0.4s ease"
, boxSizing borderBox
, focus
[ borderColor azure
, outline none
, boxShadow6 inset zero (px 3) zero zero glacier
]
, if isInError then
batch
[ borderColor purple
, boxShadow6 inset zero (px 3) zero zero purpleLight
, focus
[ borderColor purple
, boxShadow6 inset zero (px 3) zero zero purpleLight
]
]
else
batch []
]
in
batch
[ Css.Global.withClass "override-sass-styles"
[ case theme of
Standard ->
batch
[ sharedStyles
, padding2 inputPaddingVertical (px 15)
, fontSize (px 15)
, Nri.Ui.Fonts.V1.baseFont
]
Writing ->
batch
[ sharedStyles
, Nri.Ui.Fonts.V1.quizFont
, fontSize (px 18)
, lineHeight writingLineHeight
, padding writingPadding
, paddingTop writingPaddingTop
, focus
[ Css.Global.adjacentSiblings
[ Css.Global.label
[ backgroundColor azure
, color white
, borderColor azure
, if isInError then
batch
[ backgroundColor purple
, color white
, borderColor purple
]
else
batch []
]
]
]
]
ContentCreation ->
batch
[ sharedStyles
, padding2 inputPaddingVertical (px 15)
, fontSize (px 15)
, Nri.Ui.Fonts.V1.baseFont
]
]
]
{-| -}
inputPaddingVertical : Px
inputPaddingVertical =
px 12
{-| -}
inputLineHeight : Px
inputLineHeight =
px 21
{-| -}
textAreaHeight : Px
textAreaHeight =
px 100
{-| -}
writingLineHeight : Px
writingLineHeight =
px 27
{-| -}
writingPadding : Px
writingPadding =
px 15
{-| -}
writingPaddingTop : Px
writingPaddingTop =
px 20
{-| -}
writingMinHeight : Px
writingMinHeight =
px 150

View File

@ -307,9 +307,6 @@ viewEntry entry_ =
{-| Display an icon button consistent with menu button.
Prefer to use ClickableSvg with the `withTooltipAbove` helper.
-}
iconButton :
{ icon : Svg.Svg
@ -434,9 +431,6 @@ iconButtonWithMenu config =
{-| Display an icon link consistent with menu button styles.
Prefer to use ClickableSvg with the `withTooltipAbove` helper.
-}
iconLink :
{ icon : Svg.Svg

View File

@ -1,553 +0,0 @@
module Nri.Ui.Message.V1 exposing
( tiny, large, banner
, Theme(..), Content(..), mapContent, BannerAttribute
, onDismiss
, somethingWentWrong
)
{-|
@docs tiny, large, banner
@docs Theme, Content, mapContent, BannerAttribute
@docs onDismiss
@docs somethingWentWrong
-}
import Accessibility.Styled as Html exposing (..)
import Accessibility.Styled.Widget as Widget
import Css exposing (..)
import Css.Global
import Html.Styled exposing (styled)
import Html.Styled.Attributes exposing (css)
import Html.Styled.Events exposing (onClick)
import Markdown
import Nri.Ui
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.Fonts.V1 as Fonts
import Nri.Ui.Svg.V1 as NriSvg exposing (Svg)
import Nri.Ui.UiIcon.V1 as UiIcon
{-| `Error` / `Alert` / `Tip` / `Success`
-}
type Theme
= Error
| Alert
| Tip
| Success
| Custom
{ color : Color
, backgroundColor : Color
, icon : Svg
}
{-| Prefer using the simplest variant that meets your needs.
- `Plain`: provide a plain-text string
- `Markdown`: provide a string that will be rendered as markdown
- `Html`: provide custom HTML
-}
type Content msg
= Plain String
| Markdown String
| Html (List (Html msg))
{-| Transform the messages produced by some `Content`.
-}
mapContent : (a -> b) -> Content a -> Content b
mapContent f content =
case content of
Plain string ->
Plain string
Markdown string ->
Markdown string
Html html ->
Html (List.map (Html.map f) html)
{-| PRIVATE
-}
contentToHtml : Content msg -> List (Html msg)
contentToHtml content =
case content of
Plain stringContent ->
[ text stringContent ]
Markdown markdownContent ->
Markdown.toHtml Nothing markdownContent |> List.map fromUnstyled
Html html ->
html
{-| Shows a tiny alert message. We commonly use these for validation errors and small hints to users.
import Nri.Ui.Message.V1 as Message
view =
Message.tiny Message.Tip (Message.Markdown "Don't tip too much, or your waitress will **fall over**!")
NOTE: When using a `Custom` theme, `tiny` ignores the custom `backgroundColor`.
-}
tiny : Theme -> Content msg -> Html msg
tiny theme content =
let
config =
case theme of
Error ->
{ icon =
UiIcon.exclamation
|> NriSvg.withColor Colors.purple
|> NriSvg.withLabel "Error"
, fontColor = Colors.purple
}
Alert ->
{ icon =
UiIcon.exclamation
|> NriSvg.withColor Colors.red
|> NriSvg.withLabel "Alert"
, fontColor = Colors.redDark
}
Tip ->
{ icon =
UiIcon.bulb
|> NriSvg.withColor Colors.yellow
|> NriSvg.withLabel "Tip"
, fontColor = Colors.navy
}
Success ->
{ icon =
UiIcon.checkmarkInCircle
|> NriSvg.withColor Colors.green
|> NriSvg.withLabel "Success"
, fontColor = Colors.greenDarkest
}
Custom customTheme ->
{ icon = customTheme.icon
, fontColor = customTheme.color
}
in
Nri.Ui.styled div
"Nri-Ui-Message-V1--tiny"
[ displayFlex
, justifyContent start
, paddingTop (px 6)
, paddingBottom (px 8)
]
[]
[ styled div
[]
[]
[ Nri.Ui.styled div
"Nri-Ui-Message-V1--tinyIconContainer"
[ -- Content positioning
displayFlex
, alignItems center
, justifyContent center
, marginRight (px 5)
, lineHeight (px 13)
, flexShrink zero
-- Size
, borderRadius (px 13)
, height (px 20)
, width (px 20)
]
[]
[ NriSvg.toHtml config.icon ]
]
, styled div
[ displayFlex
, alignItems center
]
[]
[ Nri.Ui.styled div
"Nri-Ui-Message-V1--alert"
[ color config.fontColor
, Fonts.baseFont
, fontSize (px 13)
--, lineHeight (px 20)
, listStyleType none
-- This global selector and overrides are necessary due to
-- old stylesheets used on the monolith that set the
-- `.txt p { font-size: 18px; }` -- without these overrides,
-- we may see giant ugly alerts.
-- Remove these if you want to! but be emotionally prepped
-- to deal with visual regressions. 🙏
, Css.Global.descendants
[ Css.Global.p
[ margin zero
--, lineHeight (px 20)
, fontSize (px 13)
, Fonts.baseFont
]
]
]
[]
(contentToHtml content)
]
]
{-| Shows a large alert or callout message. We commonly use these for highlighted tips, instructions, or asides in page copy.
import Nri.Ui.Message.V1 as Message
view =
Message.large Message.Tip (Message.Plain "Two out of two parents agree: NoRedInk sounds like a fun place to work.")
-}
large : Theme -> Content msg -> Html msg
large theme content =
let
config =
case theme of
Error ->
{ backgroundColor = Colors.purpleLight
, fontColor = Colors.purpleDark
, icon =
UiIcon.exclamation
|> NriSvg.withColor Colors.purple
|> NriSvg.withLabel "Error"
}
Alert ->
{ backgroundColor = Colors.sunshine
, fontColor = Colors.navy
, icon =
UiIcon.exclamation
|> NriSvg.withColor Colors.ochre
|> NriSvg.withLabel "Alert"
}
Tip ->
{ backgroundColor = Colors.sunshine
, fontColor = Colors.navy
, icon =
UiIcon.bulb
|> NriSvg.withColor Colors.navy
|> NriSvg.withLabel "Tip"
}
Success ->
{ backgroundColor = Colors.greenLightest
, fontColor = Colors.greenDarkest
, icon =
UiIcon.checkmarkInCircle
|> NriSvg.withColor Colors.green
|> NriSvg.withLabel "Success"
}
Custom customTheme ->
{ backgroundColor = customTheme.backgroundColor
, fontColor = customTheme.color
, icon = customTheme.icon
}
in
Nri.Ui.styled div
"Nri-Ui-Message-V1--large"
[ width (pct 100)
, backgroundColor config.backgroundColor
, Fonts.baseFont
, fontSize (px 15)
, lineHeight (px 21)
, fontWeight (int 600)
, boxSizing borderBox
, padding (px 20)
, borderRadius (px 8)
, color config.fontColor
, displayFlex
, alignItems center
, Css.Global.descendants
[ Css.Global.a
[ textDecoration none
, color Colors.azure
, borderBottom3 (px 1) solid Colors.azure
, visited [ color Colors.azure ]
]
]
]
[]
[ styled div
[ width (px 35)
, marginRight (px 10)
]
[]
[ NriSvg.toHtml config.icon
]
, styled div
[ minWidth (px 100)
, flexBasis (px 100)
, flexGrow (int 1)
]
[]
(contentToHtml content)
]
{-| PRIVATE
-}
type BannerAttribute msg
= BannerAttribute (BannerConfig msg -> BannerConfig msg)
{-| Adds a dismiss ("X" icon) to a banner which will produce the given `msg` when clicked.
-}
onDismiss : msg -> BannerAttribute msg
onDismiss msg =
BannerAttribute <|
\config ->
{ config | onDismiss = Just msg }
{-| PRIVATE
-}
type alias BannerConfig msg =
{ onDismiss : Maybe msg
}
{-| PRIVATE
-}
bannerConfigFromAttributes : List (BannerAttribute msg) -> BannerConfig msg
bannerConfigFromAttributes attr =
List.foldl (\(BannerAttribute set) -> set)
{ onDismiss = Nothing }
attr
{-| Shows a banner alert message. This is even more prominent than `Message.large`.
We commonly use these for flash messages at the top of pages.
import Nri.Ui.Message.V1 as Message
view =
Message.banner Message.Success (Message.Plain "John Jacob Jingleheimer Schmidt has been dropped from First Period English.")
-}
banner : Theme -> Content msg -> List (BannerAttribute msg) -> Html msg
banner theme content attr =
let
config =
case theme of
Error ->
{ backgroundColor = Colors.purpleLight
, color = Colors.purpleDark
, icon =
UiIcon.exclamation
|> NriSvg.withColor Colors.purple
|> NriSvg.withLabel "Error"
|> NriSvg.toHtml
}
Alert ->
{ backgroundColor = Colors.sunshine
, color = Colors.navy
, icon =
UiIcon.exclamation
|> NriSvg.withColor Colors.ochre
|> NriSvg.withLabel "Alert"
|> NriSvg.toHtml
}
Tip ->
{ backgroundColor = Colors.frost
, color = Colors.navy
, icon =
inCircle
{ backgroundColor = Colors.navy
, color = Colors.mustard
, height = Css.px 32
, icon = UiIcon.bulb
}
}
Success ->
{ backgroundColor = Colors.greenLightest
, color = Colors.greenDarkest
, icon =
UiIcon.checkmarkInCircle
|> NriSvg.withColor Colors.green
|> NriSvg.withLabel "Success"
|> NriSvg.toHtml
}
Custom customTheme ->
{ backgroundColor = customTheme.backgroundColor
, color = customTheme.color
, icon = NriSvg.toHtml customTheme.icon
}
attributes =
bannerConfigFromAttributes attr
in
styled div
[ displayFlex
, justifyContent center
, alignItems center
, backgroundColor config.backgroundColor
, color config.color
]
[]
[ styled span
[ alignItems center
, displayFlex
, justifyContent center
, padding (px 20)
, width (Css.pct 100)
, Css.Global.children
[ Css.Global.button
[ position relative
, right (px 15)
]
]
]
[]
[ styled div
[ width (px 50)
, height (px 50)
, marginRight (px 20)
, -- NOTE: I think it's normally best to avoid relying on flexShrink (and use flexGrow/flexBasis) instead,
-- But using shrink here and on the next div lets us have the text content be centered rather than
-- left-aligned when the content is shorter than one line
flexShrink zero
]
[]
[ config.icon ]
, Nri.Ui.styled div
"banner-alert-notification"
[ fontSize (px 20)
, fontWeight (int 700)
, lineHeight (px 27)
, maxWidth (px 600)
, minWidth (px 100)
, flexShrink (int 1)
, Fonts.baseFont
, Css.Global.descendants
[ Css.Global.a
[ textDecoration none
, color Colors.azure
, borderBottom3 (px 1) solid Colors.azure
, visited [ color Colors.azure ]
]
]
]
[]
(contentToHtml content)
]
, case attributes.onDismiss of
Nothing ->
text ""
Just msg ->
bannerDismissButton msg
]
{-| Shows an appropriate error message for when something unhandled happened.
import Nri.Ui.Message.V1 as Message
view maybeDetailedErrorMessage =
viewMaybe Message.somethingWentWrong maybeDetailedErrorMessage
-}
somethingWentWrong : String -> Html msg
somethingWentWrong errorMessageForEngineers =
div []
[ tiny Error (Plain "Sorry, something went wrong. Please try again later.")
, details []
[ summary
[ css
[ Fonts.baseFont
, fontSize (px 14)
, color Colors.gray45
]
]
[ text "Details for NoRedInk engineers" ]
, code
[ css
[ display block
, whiteSpace normal
, overflowWrap breakWord
, color Colors.gray45
, backgroundColor Colors.gray96
, border3 (px 1) solid Colors.gray92
, borderRadius (px 3)
, padding2 (px 2) (px 4)
, fontSize (px 12)
, fontFamily monospace
]
]
[ text errorMessageForEngineers ]
]
]
--
-- PRIVATE
--
inCircle :
{ backgroundColor : Css.Color
, color : Css.Color
, height : Css.Px
, icon : Svg
}
-> Html msg
inCircle config =
styled div
[ borderRadius (pct 50)
, height (pct 100)
, backgroundColor config.backgroundColor
, displayFlex
, alignItems center
, justifyContent center
]
[]
[ config.icon
|> NriSvg.withColor config.color
|> NriSvg.withHeight config.height
|> NriSvg.toHtml
]
bannerDismissButton : msg -> Html msg
bannerDismissButton msg =
Nri.Ui.styled div
"dismiss-button-container"
[ padding (px 25)
]
[]
[ styled button
[ borderWidth zero
, backgroundColor unset
, color Colors.azure
, width (px 30)
, height (px 30)
, padding2 zero (px 7)
, cursor pointer
]
[ onClick msg
, Widget.label "Dismiss banner"
]
[ NriSvg.toHtml UiIcon.x
]
]

View File

@ -1,723 +0,0 @@
module Nri.Ui.Message.V2 exposing
( somethingWentWrong
, view, Attribute
, tiny, large, banner
, plaintext, markdown, html
, tip, error, alert, success, customTheme
, alertRole, alertDialogRole
, onDismiss
)
{-| Changes from V1:
- adds `alertRole`, `alertDialogRole` role attributes
- rename `BannerAttribute` -> `Attribute`
- accept `Attribute`s on any `Message` type
- remove `mapContent`
- expose `plaintext`, `markdown`, and `html` Attribute helpers instead of having `Content(..)` in the view APIs
- expose theme `Attribute` helpers instead of having `Theme(..)` in the view APIs
- exposes a singular `view` function (`tiny`, `large`, and `banner` are now `Attribute`s)
- uses `alertRole` in `somethingWentWrong`
# View
@docs somethingWentWrong
@docs view, Attribute
## Size
@docs tiny, large, banner
## Content
@docs plaintext, markdown, html
## Theme
@docs tip, error, alert, success, customTheme
## Role
@docs alertRole, alertDialogRole
## Actions
@docs onDismiss
-}
import Accessibility.Styled as Html exposing (..)
import Accessibility.Styled.Role as Role
import Accessibility.Styled.Widget as Widget
import Css exposing (..)
import Css.Global
import Html.Styled.Attributes exposing (css)
import Html.Styled.Events exposing (onClick)
import Markdown
import Nri.Ui
import Nri.Ui.ClickableSvg.V2 as ClickableSvg
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.Fonts.V1 as Fonts
import Nri.Ui.Svg.V1 as NriSvg exposing (Svg)
import Nri.Ui.UiIcon.V1 as UiIcon
{-|
view =
Message.view
[ Message.tip
, Message.markdown "Don't tip too much, or your waitress will **fall over**!"
]
-}
view : List (Attribute msg) -> Html msg
view attributes_ =
let
attributes =
configFromAttributes attributes_
role =
getRoleAttribute attributes.role
html_ =
contentToHtml attributes.content
backgroundColor_ =
getBackgroundColor attributes.size attributes.theme
color_ =
getColor attributes.size attributes.theme
icon =
getIcon attributes.size attributes.theme
in
Nri.Ui.styled div
"Nri-Ui-Message-V2"
[ Fonts.baseFont
, color color_
, boxSizing borderBox
, styleOverrides
]
role
[ case attributes.size of
Tiny ->
Nri.Ui.styled div
"Nri-Ui-Message--tiny"
[ displayFlex
, justifyContent start
, alignItems center
, paddingTop (px 6)
, paddingBottom (px 8)
, fontSize (px 13)
]
[]
[ Nri.Ui.styled div "Nri-Ui-Message--icon" [ alignSelf flexStart ] [] [ icon ]
, div [] html_
, case attributes.onDismiss of
Nothing ->
text ""
Just msg ->
tinyDismissButton msg
]
Large ->
Nri.Ui.styled div
"Nri-Ui-Message-large"
[ displayFlex
, alignItems center
-- Box
, borderRadius (px 8)
, padding (px 20)
, backgroundColor_
-- Fonts
, fontSize (px 15)
, fontWeight (int 600)
, lineHeight (px 21)
]
[]
[ icon
, div
[ css
[ minWidth (px 100)
, flexBasis (px 100)
, flexGrow (int 1)
]
]
html_
, case attributes.onDismiss of
Nothing ->
text ""
Just msg ->
largeDismissButton msg
]
Banner ->
Nri.Ui.styled div
"Nri-Ui-Message-banner"
[ displayFlex
, justifyContent center
, alignItems center
, backgroundColor_
-- Fonts
, fontSize (px 20)
, fontWeight (int 700)
, lineHeight (px 27)
]
[]
[ span
[ css
[ alignItems center
, displayFlex
, justifyContent center
, padding (px 20)
, width (Css.pct 100)
]
]
[ icon
, Nri.Ui.styled div
"banner-alert-notification"
[ fontSize (px 20)
, fontWeight (int 700)
, lineHeight (px 27)
, maxWidth (px 600)
, minWidth (px 100)
, flexShrink (int 1)
, Fonts.baseFont
]
[]
html_
]
, case attributes.onDismiss of
Nothing ->
text ""
Just msg ->
bannerDismissButton msg
]
]
{-| Shows an appropriate error message for when something unhandled happened.
view maybeDetailedErrorMessage =
viewMaybe Message.somethingWentWrong maybeDetailedErrorMessage
-}
somethingWentWrong : String -> Html msg
somethingWentWrong errorMessageForEngineers =
div []
[ view
[ tiny
, error
, alertRole
, plaintext "Sorry, something went wrong. Please try again later."
]
, details []
[ summary
[ css
[ Fonts.baseFont
, fontSize (px 14)
, color Colors.gray45
]
]
[ text "Details for NoRedInk engineers" ]
, code
[ css
[ display block
, whiteSpace normal
, overflowWrap breakWord
, color Colors.gray45
, backgroundColor Colors.gray96
, border3 (px 1) solid Colors.gray92
, borderRadius (px 3)
, padding2 (px 2) (px 4)
, fontSize (px 12)
, fontFamily monospace
]
]
[ text errorMessageForEngineers ]
]
]
{-| Shows a tiny alert message. We commonly use these for validation errors and small hints to users.
Message.view [ Message.tiny ]
This is the default size for a Message.
-}
tiny : Attribute msg
tiny =
Attribute <| \config -> { config | size = Tiny }
{-| Shows a large alert or callout message. We commonly use these for highlighted tips, instructions, or asides in page copy.
Message.view [ Message.large ]
-}
large : Attribute msg
large =
Attribute <| \config -> { config | size = Large }
{-| Shows a banner alert message. This is even more prominent than `Message.large`.
We commonly use these for flash messages at the top of pages.
Message.view [ Message.banner ]
-}
banner : Attribute msg
banner =
Attribute <| \config -> { config | size = Banner }
{-| -}
plaintext : String -> Attribute msg
plaintext content =
Attribute <| \config -> { config | content = Plain content }
{-| -}
markdown : String -> Attribute msg
markdown content =
Attribute <| \config -> { config | content = Markdown content }
{-| -}
html : List (Html msg) -> Attribute msg
html content =
Attribute <| \config -> { config | content = Html content }
{-| This is the default theme for a Message.
-}
tip : Attribute msg
tip =
Attribute <| \config -> { config | theme = Tip }
{-| -}
error : Attribute msg
error =
Attribute <| \config -> { config | theme = Error }
{-| -}
alert : Attribute msg
alert =
Attribute <| \config -> { config | theme = Alert }
{-| -}
success : Attribute msg
success =
Attribute <| \config -> { config | theme = Success }
{-| -}
customTheme : { color : Color, backgroundColor : Color, icon : Svg } -> Attribute msg
customTheme custom_ =
Attribute <| \config -> { config | theme = Custom custom_ }
{-| Adds a dismiss ("X" icon) to a message which will produce the given `msg` when clicked.
-}
onDismiss : msg -> Attribute msg
onDismiss msg =
Attribute <| \config -> { config | onDismiss = Just msg }
{-| Use this attribute when a user's immediate attention on the Message is required.
For example, use this attribute when:
> - An invalid value was entered into a form field
> - The user's login session is about to expire
> - The connection to the server was lost, local changes will not be saved
-- Excerpted from [Using the alert role MDN docs](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_alert_role)
-}
alertRole : Attribute msg
alertRole =
Attribute <| \config -> { config | role = Just AlertRole }
{-| Use this attribute when (1) a user's immediate attention on the Message is required,
(2) the Message contains interactible elements, and (3) you've correctly set up the Message to be
modal (i.e., you've set up tab-wrapping, the body's overflow is hidden, the user
can't interact with elements apart from the Message's contents...)
When you use this role, verify that you are using it correctly using [this
MDN article](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_alertdialog_role).
-}
alertDialogRole : Attribute msg
alertDialogRole =
Attribute <| \config -> { config | role = Just AlertDialog }
--
-- PRIVATE
--
{-| Construct an `Attribute` using a helper like `onDismiss` or `alert`.
-}
type Attribute msg
= Attribute (BannerConfig msg -> BannerConfig msg)
{-| PRIVATE
-}
type alias BannerConfig msg =
{ onDismiss : Maybe msg
, role : Maybe Role
, content : Content msg
, theme : Theme
, size : Size
}
{-| PRIVATE
-}
configFromAttributes : List (Attribute msg) -> BannerConfig msg
configFromAttributes attr =
List.foldl (\(Attribute set) -> set)
{ onDismiss = Nothing
, role = Nothing
, content = Plain ""
, theme = Tip
, size = Tiny
}
attr
-- Size
type Size
= Tiny
| Large
| Banner
-- Message contents
{-| Prefer using the simplest variant that meets your needs.
- `Plain`: provide a plain-text string
- `Markdown`: provide a string that will be rendered as markdown
- `Html`: provide custom HTML
-}
type Content msg
= Plain String
| Markdown String
| Html (List (Html msg))
contentToHtml : Content msg -> List (Html msg)
contentToHtml content =
case content of
Plain stringContent ->
[ text stringContent ]
Markdown markdownContent ->
Markdown.toHtml Nothing markdownContent |> List.map fromUnstyled
Html html_ ->
html_
-- Themes
{-| `Error` / `Alert` / `Tip` / `Success`
-}
type Theme
= Error
| Alert
| Tip
| Success
| Custom
{ color : Color
, backgroundColor : Color
, icon : Svg
}
getColor : Size -> Theme -> Color
getColor size theme =
case theme of
Custom { color } ->
color
Error ->
case size of
Tiny ->
Colors.purple
_ ->
Colors.purpleDark
Alert ->
case size of
Tiny ->
Colors.redDark
_ ->
Colors.navy
Tip ->
Colors.navy
Success ->
Colors.greenDarkest
getBackgroundColor : Size -> Theme -> Style
getBackgroundColor size theme =
case ( size, theme ) of
( Tiny, _ ) ->
Css.batch []
( Large, Tip ) ->
Css.backgroundColor Colors.sunshine
( Banner, Tip ) ->
Css.backgroundColor Colors.frost
( _, Error ) ->
Css.backgroundColor Colors.purpleLight
( _, Alert ) ->
Css.backgroundColor Colors.sunshine
( _, Success ) ->
Css.backgroundColor Colors.greenLightest
( _, Custom { backgroundColor } ) ->
Css.backgroundColor backgroundColor
getIcon : Size -> Theme -> Html msg
getIcon size theme =
let
( iconSize, marginRight ) =
case size of
Tiny ->
( px 20, Css.marginRight (Css.px 5) )
Large ->
( px 35, Css.marginRight (Css.px 10) )
Banner ->
( px 50, Css.marginRight (Css.px 20) )
in
case theme of
Error ->
UiIcon.exclamation
|> NriSvg.withColor Colors.purple
|> NriSvg.withWidth iconSize
|> NriSvg.withHeight iconSize
|> NriSvg.withCss [ marginRight, Css.flexShrink Css.zero ]
|> NriSvg.withLabel "Error"
|> NriSvg.toHtml
Alert ->
let
color =
case size of
Tiny ->
Colors.red
_ ->
Colors.ochre
in
UiIcon.exclamation
|> NriSvg.withColor color
|> NriSvg.withWidth iconSize
|> NriSvg.withHeight iconSize
|> NriSvg.withCss [ marginRight, Css.flexShrink Css.zero ]
|> NriSvg.withLabel "Alert"
|> NriSvg.toHtml
Tip ->
case size of
Tiny ->
UiIcon.bulb
|> NriSvg.withColor Colors.yellow
|> NriSvg.withWidth iconSize
|> NriSvg.withHeight iconSize
|> NriSvg.withCss [ marginRight, Css.flexShrink Css.zero ]
|> NriSvg.withLabel "Tip"
|> NriSvg.toHtml
Large ->
UiIcon.bulb
|> NriSvg.withColor Colors.navy
|> NriSvg.withWidth iconSize
|> NriSvg.withHeight iconSize
|> NriSvg.withCss [ marginRight, Css.flexShrink Css.zero ]
|> NriSvg.withLabel "Tip"
|> NriSvg.toHtml
Banner ->
div
[ css
[ borderRadius (pct 50)
, height (px 50)
, width (px 50)
, Css.marginRight (Css.px 20)
, backgroundColor Colors.navy
, displayFlex
, Css.flexShrink Css.zero
, alignItems center
, justifyContent center
]
]
[ UiIcon.bulb
|> NriSvg.withColor Colors.mustard
|> NriSvg.withWidth (Css.px 32)
|> NriSvg.withHeight (Css.px 32)
|> NriSvg.toHtml
]
Success ->
UiIcon.checkmarkInCircle
|> NriSvg.withColor Colors.green
|> NriSvg.withWidth iconSize
|> NriSvg.withHeight iconSize
|> NriSvg.withCss [ marginRight, Css.flexShrink Css.zero ]
|> NriSvg.withLabel "Success"
|> NriSvg.toHtml
Custom { icon } ->
icon
|> NriSvg.withWidth iconSize
|> NriSvg.withHeight iconSize
|> NriSvg.withCss [ marginRight, Css.flexShrink Css.zero ]
|> NriSvg.toHtml
-- Role
type Role
= AlertRole
| AlertDialog
getRoleAttribute : Maybe Role -> List (Html.Attribute msg)
getRoleAttribute role =
case role of
Just AlertRole ->
[ Role.alert ]
Just AlertDialog ->
[ Role.alertDialog ]
Nothing ->
[]
-- Style overrides
styleOverrides : Style
styleOverrides =
Css.Global.descendants
[ Css.Global.a
[ textDecoration none
, color Colors.azure
, borderBottom3 (px 1) solid Colors.azure
, visited [ color Colors.azure ]
]
, -- This global selector and overrides are necessary due to
-- old stylesheets used on the monolith that set the
-- `.txt p { font-size: 18px; }` -- without these overrides,
-- we may see giant ugly alerts.
-- Remove these if you want to! but be emotionally prepped
-- to deal with visual regressions. 🙏
Css.Global.p
[ margin zero
, fontSize (px 13)
, Fonts.baseFont
]
]
-- Dismiss buttons
tinyDismissButton : msg -> Html msg
tinyDismissButton msg =
Nri.Ui.styled div
"dismiss-button-container"
[]
[]
[ ClickableSvg.button "Dismiss message"
UiIcon.x
[ ClickableSvg.onClick msg
, ClickableSvg.exactWidth 16
, ClickableSvg.exactHeight 16
, ClickableSvg.css
[ Css.verticalAlign Css.middle
, Css.marginLeft (Css.px 5)
]
]
]
largeDismissButton : msg -> Html msg
largeDismissButton msg =
Nri.Ui.styled div
"dismiss-button-container"
[ padding2 Css.zero (px 20)
]
[]
[ ClickableSvg.button "Dismiss message"
UiIcon.x
[ ClickableSvg.onClick msg
, ClickableSvg.exactWidth 16
, ClickableSvg.exactHeight 16
]
]
bannerDismissButton : msg -> Html msg
bannerDismissButton msg =
Nri.Ui.styled div
"dismiss-button-container"
[ padding2 (px 30) (px 40) ]
[]
[ ClickableSvg.button "Dismiss banner"
UiIcon.x
[ ClickableSvg.onClick msg
, ClickableSvg.exactWidth 16
, ClickableSvg.exactHeight 16
]
]

View File

@ -53,7 +53,6 @@ import Accessibility.Styled.Widget as Widget
import Browser
import Browser.Dom as Dom
import Browser.Events
import Color.Transparent as Transparent
import Css exposing (..)
import Css.Transitions
import Html.Styled as Root
@ -65,6 +64,7 @@ import Nri.Ui.Fonts.V1 as Fonts
import Nri.Ui.SpriteSheet
import Nri.Ui.Svg.V1
import Task
import TransparentColor as Transparent
{-| -}

View File

@ -165,7 +165,6 @@ import Accessibility.Styled.Widget as Widget
import Browser
import Browser.Dom as Dom
import Browser.Events
import Color.Transparent as Transparent
import Css exposing (..)
import Css.Transitions
import Html.Styled as Root
@ -180,6 +179,7 @@ import Nri.Ui.Html.Attributes.V2 as ExtraAttributes
import Nri.Ui.SpriteSheet
import Nri.Ui.Svg.V1
import Task
import TransparentColor as Transparent
{-| -}

View File

@ -1,246 +0,0 @@
module Nri.Ui.Modal.V3 exposing
( Model
, info
, warning
)
{-| Changes from V2:
- Add assets for close button
@docs Model
@docs info
@docs warning
-}
import Accessibility.Styled as Html exposing (..)
import Accessibility.Styled.Role as Role
import Accessibility.Styled.Widget as Widget
import Css
import Css.Global exposing (Snippet, body, children, descendants, everything, selector)
import Html.Styled
import Html.Styled.Events exposing (onClick)
import Nri.Ui
import Nri.Ui.AssetPath exposing (Asset(..))
import Nri.Ui.Colors.Extra
import Nri.Ui.Colors.V1
import Nri.Ui.Fonts.V1 as Fonts
import Nri.Ui.Icon.V3 as Icon
{-|
- `onDismiss`: If `Nothing`, the modal will not be dismissable
- `visibleTitle`: If `False`, the title will still be used for screen readers
- `content`: This will be placed in a `width:100%` div in the main area of the modal
- `footerContent`: The optional items here will be stacked below the main content area and center-aligned.
Commonly you will either give a list of Nri.Ui.Buttons,
or an empty list.
-}
type alias Model msg =
{ title : String
, visibleTitle : Bool
, content : Html msg
, footerContent : List (Html msg)
, onDismiss : Maybe msg
, width : Maybe Int
}
type alias Assets r =
{ r | icons_xBlue_svg : Asset }
type ModalType
= Info
| Warning
{-| -}
info : Assets r -> Model msg -> Html msg
info assets =
view assets Info
{-| -}
warning : Assets r -> Model msg -> Html msg
warning assets =
view assets Warning
view : Assets r -> ModalType -> Model msg -> Html msg
view assets modalType { title, visibleTitle, content, onDismiss, footerContent, width } =
Nri.Ui.styled div
"modal-backdrop-container"
((case modalType of
Info ->
Css.backgroundColor (Nri.Ui.Colors.Extra.withAlpha 0.9 Nri.Ui.Colors.V1.navy)
Warning ->
Css.backgroundColor (Nri.Ui.Colors.Extra.withAlpha 0.9 Nri.Ui.Colors.V1.gray20)
)
:: [ Css.height (Css.vh 100)
, Css.left Css.zero
, Css.overflow Css.hidden
, Css.position Css.fixed
, Css.top Css.zero
, Css.width (Css.pct 100)
, Css.zIndex (Css.int 200)
, Css.displayFlex
, Css.alignItems Css.center
, Css.justifyContent Css.center
]
)
[ Role.dialog
, Widget.label title
, Widget.modal True
]
[ Nri.Ui.styled Html.Styled.div
"modal-click-catcher"
[ Css.bottom Css.zero
, Css.left Css.zero
, Css.position Css.absolute
, Css.right Css.zero
, Css.top Css.zero
]
(case onDismiss of
Nothing ->
[]
Just msg ->
[ onClick msg ]
)
[]
, Nri.Ui.styled div
"modal-container"
[ Css.width (Css.px 600)
, Css.maxHeight <| Css.calc (Css.vh 100) Css.minus (Css.px 100)
, Css.padding4 (Css.px 40) Css.zero (Css.px 40) Css.zero
, Css.margin2 (Css.px 75) Css.auto
, Css.backgroundColor Nri.Ui.Colors.V1.white
, Css.borderRadius (Css.px 20)
, Css.property "box-shadow" "0 1px 10px 0 rgba(0, 0, 0, 0.35)"
, Css.position Css.relative -- required for closeButtonContainer
, Css.displayFlex
, Css.alignItems Css.center
, Css.flexDirection Css.column
, Css.flexWrap Css.noWrap
, Fonts.baseFont
]
[]
[ -- This global <style> node sets overflow to hidden on the body element,
-- thereby preventing the page from scrolling behind the backdrop when the modal is
-- open (and this node is present on the page).
Css.Global.global
[ Css.Global.body
[ Css.overflow Css.hidden ]
]
, case onDismiss of
Just msg ->
closeButton assets msg
Nothing ->
text ""
, if visibleTitle then
viewHeader modalType title
else
text ""
, viewContent modalType content
, viewFooter footerContent
]
]
closeButton : Assets r -> msg -> Html msg
closeButton assets msg =
Nri.Ui.styled div
"close-button-container"
[ Css.position Css.absolute
, Css.top Css.zero
, Css.right Css.zero
, Css.padding (Css.px 25)
]
[]
[ Icon.button
{ alt = "Close"
, msg = msg
, icon = Icon.close assets
, disabled = False
, size = Icon.Medium
}
]
viewHeader : ModalType -> String -> Html msg
viewHeader modalType title =
Nri.Ui.styled Html.h3
"modal-header"
((case modalType of
Info ->
Css.color Nri.Ui.Colors.V1.navy
Warning ->
Css.color Nri.Ui.Colors.V1.red
)
:: [ Css.fontWeight (Css.int 700)
, Css.lineHeight (Css.px 27)
, Css.margin2 Css.zero (Css.px 49)
, Css.fontSize (Css.px 20)
, Fonts.baseFont
, Css.textAlign Css.center
]
)
[]
[ Html.text title
]
viewContent : ModalType -> Html msg -> Html msg
viewContent modalType content =
Nri.Ui.styled div
"modal-content"
[ Css.overflowY Css.auto
, Css.padding2 (Css.px 30) (Css.px 40)
, Css.width (Css.pct 100)
, Css.minHeight (Css.px 150)
, Css.boxSizing Css.borderBox
]
[]
[ content ]
viewFooter : List (Html msg) -> Html msg
viewFooter footerContent =
case footerContent of
[] ->
Html.text ""
_ ->
Nri.Ui.styled div
"modal-footer"
[ Css.alignItems Css.center
, Css.displayFlex
, Css.flexDirection Css.column
, Css.flexGrow (Css.int 2)
, Css.flexWrap Css.noWrap
, Css.margin4 (Css.px 20) Css.zero Css.zero Css.zero
, Css.width (Css.pct 100)
]
[]
(List.map
(\x ->
Nri.Ui.styled div
"modal-footer-item"
[ Css.margin4 (Css.px 10) Css.zero Css.zero Css.zero
, Css.firstChild
[ Css.margin Css.zero
]
]
[]
[ x ]
)
footerContent
)

View File

@ -17,8 +17,8 @@ import Html.Styled as Html exposing (Html)
import Html.Styled.Attributes as Attributes
import Http
import Nri.Ui.Button.V10 as Button
import Nri.Ui.Heading.V2 as Heading
import Nri.Ui.Html.V3 exposing (viewIf)
import Nri.Ui.Text.V2 as Text
{-| The default page information is for the button
@ -201,8 +201,8 @@ view : Config msg -> Html msg
view config =
viewContainer
[ viewEmoji [ Html.text config.emoji ]
, Text.heading [ Html.text config.title ]
, Text.tagline [ Html.text config.subtitle ]
, Heading.h1 [] [ Html.text config.title ]
, Heading.h2 [] [ Html.text config.subtitle ]
, viewButton
[ viewExit config ]
, viewIf

View File

@ -1,276 +0,0 @@
module Nri.Ui.SegmentedControl.V11 exposing
( Option, view
, Radio, viewRadioGroup
, Width(..)
)
{-| Changes from V10:
- change selection using left/right arrow keys
- only currently-selected or first control is tabbable
- tabpanel is tabbable
- Uses TabsInternal under the hood
- `viewSelect` renamed to `viewRadioGroup`, `SelectOption` renamed to `Radio`
- `viewRadioGroup` uses native HTML radio input internally
@docs Option, view
@docs Radio, viewRadioGroup
@docs Width
-}
import Accessibility.Styled exposing (..)
import Accessibility.Styled.Aria as Aria
import Accessibility.Styled.Role as Role
import Accessibility.Styled.Style as Style
import Accessibility.Styled.Widget as Widget
import Css exposing (..)
import EventExtras
import Html.Styled
import Html.Styled.Attributes as Attributes exposing (css, href)
import Html.Styled.Events as Events
import Json.Encode as Encode
import Nri.Ui
import Nri.Ui.Colors.Extra exposing (withAlpha)
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.Fonts.V1 as Fonts
import Nri.Ui.Html.Attributes.V2 as AttributesExtra
import Nri.Ui.Svg.V1 as Svg exposing (Svg)
import Nri.Ui.Util exposing (dashify)
import TabsInternal
{-| -}
type Width
= FitContent
| FillContainer
{-| -}
type alias Radio value msg =
{ value : value
, label : String
, attributes : List (Attribute msg)
, icon : Maybe Svg
}
{-| Creates a set of radio buttons styled to look like a segmented control.
- `onSelect`: the message to produce when an option is selected (clicked) by the user
- `toString`: function to get the radio value as a string
- `options`: the list of options available
- `selected`: if present, the value of the currently-selected option
- `width`: how to size the segmented control
- `legend`:
- value read to screenreader users to explain the radio group's purpose <https://dequeuniversity.com/rules/axe/3.3/radiogroup?application=axeAPI>
- after lowercasing & dashifying, this value is used to group the radio buttons together
-}
viewRadioGroup :
{ onSelect : a -> msg
, toString : a -> String
, options : List (Radio a msg)
, selected : Maybe a
, width : Width
, legend : String
}
-> Html msg
viewRadioGroup config =
let
viewRadio option =
let
isSelected =
Just option.value == config.selected
in
labelAfter
[ css
-- ensure that the focus state is visible, even
-- though the radio button that technically has focus
-- is not
(Css.pseudoClass "focus-within"
[ Css.property "outline-style" "auto" ]
:: styles config.width isSelected
)
]
(div [] [ viewIcon option.icon, text option.label ])
(radio name (config.toString option.value) isSelected <|
(Events.onCheck (\_ -> config.onSelect option.value)
:: css [ Css.opacity Css.zero ]
:: Attributes.attribute "data-nri-checked"
(if isSelected then
"true"
else
"false"
)
:: Style.invisible
)
)
name =
dashify (String.toLower config.legend)
legendId =
"legend-" ++ name
in
div
[ Role.radioGroup
, Aria.labelledBy legendId
, css [ displayFlex, cursor pointer ]
]
(p (Attributes.id legendId :: Style.invisible) [ text config.legend ]
:: List.map viewRadio config.options
)
{-| -}
type alias Option value msg =
{ value : value
, label : String
, attributes : List (Attribute msg)
, icon : Maybe Svg
, content : Html msg
}
{-|
- `onSelect` : the message to produce when an option is selected by the user
- `onFocus` : the message to focus an element by id string
- `toString` : function to get the option value as a string
- `options`: the list of options available
- `selected`: the value of the currently-selected option
- `width`: how to size the segmented control
- `toUrl`: a optional function that takes a `route` and returns the URL of that route. You should always use pass a `toUrl` function when the segmented control options correspond to routes in your SPA.
-}
view :
{ onSelect : a -> msg
, onFocus : String -> msg
, toString : a -> String
, options : List (Option a msg)
, selected : a
, width : Width
, toUrl : Maybe (a -> String)
}
-> Html msg
view config =
let
toInternalTab : Option a msg -> TabsInternal.Tab a msg
toInternalTab option =
{ id = option.value
, idString = config.toString option.value
, tabAttributes = option.attributes
, tabView = [ viewIcon option.icon, text option.label ]
, panelView = option.content
, spaHref = Maybe.map (\toUrl -> toUrl option.value) config.toUrl
}
{ tabList, tabPanels } =
TabsInternal.views
{ onSelect = config.onSelect
, onFocus = config.onFocus
, selected = config.selected
, tabs = List.map toInternalTab config.options
, tabListStyles = [ displayFlex, cursor pointer, marginBottom (px 10) ]
, tabStyles = styles config.width
}
in
div []
[ tabList
, tabPanels
]
viewIcon : Maybe Svg.Svg -> Html msg
viewIcon icon =
case icon of
Nothing ->
text ""
Just svg ->
svg
|> Svg.withWidth (px 18)
|> Svg.withHeight (px 18)
|> Svg.withCss
[ display inlineBlock
, verticalAlign textTop
, lineHeight (px 15)
, marginRight (px 8)
]
|> Svg.toHtml
styles : Width -> Bool -> List Style
styles width isSelected =
[ sharedSegmentStyles
, if isSelected then
focusedSegmentStyles
else
unFocusedSegmentStyles
, case width of
FitContent ->
Css.batch []
FillContainer ->
expandingTabStyles
]
sharedSegmentStyles : Style
sharedSegmentStyles =
[ padding2 (px 6) (px 20)
, height (px 45)
, Fonts.baseFont
, fontSize (px 15)
, fontWeight bold
, lineHeight (px 30)
, margin zero
, firstOfType
[ borderTopLeftRadius (px 8)
, borderBottomLeftRadius (px 8)
, borderLeft3 (px 1) solid Colors.azure
]
, lastOfType
[ borderTopRightRadius (px 8)
, borderBottomRightRadius (px 8)
]
, border3 (px 1) solid Colors.azure
, borderLeft (px 0)
, boxSizing borderBox
, cursor pointer
, property "transition" "background-color 0.2s, color 0.2s, box-shadow 0.2s, border 0.2s, border-width 0s"
, textDecoration none
, hover [ textDecoration none ]
, focus [ textDecoration none ]
]
|> Css.batch
focusedSegmentStyles : Style
focusedSegmentStyles =
[ backgroundColor Colors.glacier
, boxShadow5 inset zero (px 3) zero (withAlpha 0.2 Colors.gray20)
, color Colors.navy
]
|> Css.batch
unFocusedSegmentStyles : Style
unFocusedSegmentStyles =
[ backgroundColor Colors.white
, boxShadow5 inset zero (px -2) zero Colors.azure
, color Colors.azure
, hover [ backgroundColor Colors.frost ]
]
|> Css.batch
expandingTabStyles : Style
expandingTabStyles =
[ flexGrow (int 1)
, textAlign center
]
|> Css.batch

View File

@ -1,300 +0,0 @@
module Nri.Ui.SegmentedControl.V12 exposing
( Option, view
, Radio, viewRadioGroup
, Positioning(..), Width(..)
)
{-| Changes from V11:
- allow HTML in labels
- [use idString instead of toString](https://github.com/NoRedInk/noredink-ui/issues/575)
- allow control to be centered
@docs Option, view
@docs Radio, viewRadioGroup
@docs Positioning, Width
-}
import Accessibility.Styled exposing (..)
import Accessibility.Styled.Aria as Aria
import Accessibility.Styled.Role as Role
import Accessibility.Styled.Style as Style
import Accessibility.Styled.Widget as Widget
import Css exposing (..)
import EventExtras
import Html.Styled
import Html.Styled.Attributes as Attributes exposing (css, href)
import Html.Styled.Events as Events
import Json.Encode as Encode
import Nri.Ui
import Nri.Ui.Colors.Extra exposing (withAlpha)
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.Fonts.V1 as Fonts
import Nri.Ui.Html.Attributes.V2 as AttributesExtra
import Nri.Ui.Svg.V1 as Svg exposing (Svg)
import Nri.Ui.Util exposing (dashify)
import TabsInternal
{-| -}
type Positioning
= Left Width
| Center
{-| -}
type Width
= FitContent
| FillContainer
{-| -}
type alias Radio value msg =
{ value : value
, idString : String
, label : Html msg
, attributes : List (Attribute msg)
, icon : Maybe Svg
}
{-| Creates a set of radio buttons styled to look like a segmented control.
- `onSelect`: the message to produce when an option is selected (clicked) by the user
- `toString`: function to get the radio value as a string
- `options`: the list of options available
- `selected`: if present, the value of the currently-selected option
- `positioning`: how to position and size the segmented control
- `legend`:
- value read to screenreader users to explain the radio group's purpose <https://dequeuniversity.com/rules/axe/3.3/radiogroup?application=axeAPI>
- after lowercasing & dashifying, this value is used to group the radio buttons together
-}
viewRadioGroup :
{ onSelect : a -> msg
, options : List (Radio a msg)
, selected : Maybe a
, positioning : Positioning
, legend : String
}
-> Html msg
viewRadioGroup config =
let
viewRadio option =
let
isSelected =
Just option.value == config.selected
in
Html.Styled.label
[ css
-- ensure that the focus state is visible, even
-- though the radio button that technically has focus
-- is not
(Css.pseudoClass "focus-within"
[ Css.property "outline-style" "auto" ]
:: styles config.positioning isSelected
)
]
[ radio name option.idString isSelected <|
(Events.onCheck (\_ -> config.onSelect option.value)
:: css [ Css.opacity Css.zero ]
:: Attributes.attribute "data-nri-checked"
(if isSelected then
"true"
else
"false"
)
:: Style.invisible
)
, div [] [ viewIcon option.icon, option.label ]
]
name =
dashify (String.toLower config.legend)
legendId =
"legend-" ++ name
in
div
[ Role.radioGroup
, Aria.labelledBy legendId
, css
[ displayFlex
, cursor pointer
, case config.positioning of
Left _ ->
justifyContent flexStart
Center ->
justifyContent center
]
]
(p (Attributes.id legendId :: Style.invisible) [ text config.legend ]
:: List.map viewRadio config.options
)
{-| -}
type alias Option value msg =
{ value : value
, idString : String
, label : Html msg
, attributes : List (Attribute msg)
, icon : Maybe Svg
, content : Html msg
}
{-|
- `onSelect` : the message to produce when an option is selected by the user
- `onFocus` : the message to focus an element by id string
- `options`: the list of options available
- `selected`: the value of the currently-selected option
- `positioning`: how to position and size the segmented control
- `toUrl`: a optional function that takes a `route` and returns the URL of that route. You should always use pass a `toUrl` function when the segmented control options correspond to routes in your SPA.
-}
view :
{ onSelect : a -> msg
, onFocus : String -> msg
, options : List (Option a msg)
, selected : a
, positioning : Positioning
, toUrl : Maybe (a -> String)
}
-> Html msg
view config =
let
toInternalTab : Option a msg -> TabsInternal.Tab a msg
toInternalTab option =
{ id = option.value
, idString = option.idString
, tabAttributes = option.attributes
, tabView = [ viewIcon option.icon, option.label ]
, panelView = option.content
, spaHref = Maybe.map (\toUrl -> toUrl option.value) config.toUrl
}
{ tabList, tabPanels } =
TabsInternal.views
{ onSelect = config.onSelect
, onFocus = config.onFocus
, selected = config.selected
, tabs = List.map toInternalTab config.options
, tabListStyles =
[ displayFlex
, cursor pointer
, marginBottom (px 10)
, case config.positioning of
Left _ ->
justifyContent flexStart
Center ->
justifyContent center
]
, tabStyles = styles config.positioning
}
in
div []
[ tabList
, tabPanels
]
viewIcon : Maybe Svg.Svg -> Html msg
viewIcon icon =
case icon of
Nothing ->
text ""
Just svg ->
svg
|> Svg.withWidth (px 18)
|> Svg.withHeight (px 18)
|> Svg.withCss
[ display inlineBlock
, verticalAlign textTop
, lineHeight (px 15)
, marginRight (px 8)
]
|> Svg.toHtml
styles : Positioning -> Bool -> List Style
styles positioning isSelected =
[ sharedSegmentStyles
, if isSelected then
focusedSegmentStyles
else
unFocusedSegmentStyles
, case positioning of
Left FitContent ->
Css.batch []
Left FillContainer ->
expandingTabStyles
Center ->
Css.batch []
]
sharedSegmentStyles : Style
sharedSegmentStyles =
[ padding2 (px 6) (px 20)
, height (px 45)
, Fonts.baseFont
, fontSize (px 15)
, fontWeight bold
, lineHeight (px 30)
, margin zero
, firstOfType
[ borderTopLeftRadius (px 8)
, borderBottomLeftRadius (px 8)
, borderLeft3 (px 1) solid Colors.azure
]
, lastOfType
[ borderTopRightRadius (px 8)
, borderBottomRightRadius (px 8)
]
, border3 (px 1) solid Colors.azure
, borderLeft (px 0)
, boxSizing borderBox
, cursor pointer
, property "transition" "background-color 0.2s, color 0.2s, box-shadow 0.2s, border 0.2s, border-width 0s"
, textDecoration none
, hover [ textDecoration none ]
, focus [ textDecoration none ]
]
|> Css.batch
focusedSegmentStyles : Style
focusedSegmentStyles =
[ backgroundColor Colors.glacier
, boxShadow5 inset zero (px 3) zero (withAlpha 0.2 Colors.gray20)
, color Colors.navy
]
|> Css.batch
unFocusedSegmentStyles : Style
unFocusedSegmentStyles =
[ backgroundColor Colors.white
, boxShadow5 inset zero (px -2) zero Colors.azure
, color Colors.azure
, hover [ backgroundColor Colors.frost ]
]
|> Css.batch
expandingTabStyles : Style
expandingTabStyles =
[ flexGrow (int 1)
, textAlign center
]
|> Css.batch

View File

@ -1,312 +0,0 @@
module Nri.Ui.SegmentedControl.V13 exposing
( Option, view
, Radio, viewRadioGroup
, Positioning(..), Width(..)
)
{-| Post-release patches:
- Fixes <https://github.com/NoRedInk/noredink-ui/issues/608>
Changes from V12:
- Adds tooltip support
- combine onFocus and onSelect into focusAndSelect msg handler (for tooltips)
@docs Option, view
@docs Radio, viewRadioGroup
@docs Positioning, Width
-}
import Accessibility.Styled exposing (..)
import Accessibility.Styled.Aria as Aria
import Accessibility.Styled.Role as Role
import Accessibility.Styled.Style as Style
import Accessibility.Styled.Widget as Widget
import Css exposing (..)
import EventExtras
import Html.Styled
import Html.Styled.Attributes as Attributes exposing (css, href)
import Html.Styled.Events as Events
import Json.Encode as Encode
import Nri.Ui
import Nri.Ui.Colors.Extra exposing (withAlpha)
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.Fonts.V1 as Fonts
import Nri.Ui.Html.Attributes.V2 as AttributesExtra
import Nri.Ui.Svg.V1 as Svg exposing (Svg)
import Nri.Ui.Tooltip.V2 as Tooltip
import Nri.Ui.Util exposing (dashify)
import TabsInternal.V2 as TabsInternal
{-| -}
type Positioning
= Left Width
| Center
{-| -}
type Width
= FitContent
| FillContainer
{-| -}
type alias Radio value msg =
{ value : value
, idString : String
, label : Html msg
, attributes : List (Attribute msg)
, icon : Maybe Svg
}
{-| Creates a set of radio buttons styled to look like a segmented control.
- `onSelect`: the message to produce when an option is selected (clicked) by the user
- `toString`: function to get the radio value as a string
- `options`: the list of options available
- `selected`: if present, the value of the currently-selected option
- `positioning`: how to position and size the segmented control
- `legend`:
- value read to screenreader users to explain the radio group's purpose <https://dequeuniversity.com/rules/axe/3.3/radiogroup?application=axeAPI>
- after lowercasing & dashifying, this value is used to group the radio buttons together
-}
viewRadioGroup :
{ onSelect : a -> msg
, options : List (Radio a msg)
, selected : Maybe a
, positioning : Positioning
, legend : String
}
-> Html msg
viewRadioGroup config =
let
numOptions =
List.length config.options
viewRadio index option =
let
isSelected =
Just option.value == config.selected
in
Html.Styled.label
[ css
-- ensure that the focus state is visible, even
-- though the radio button that technically has focus
-- is not
(Css.pseudoClass "focus-within"
[ Css.property "outline-style" "auto" ]
:: styles config.positioning numOptions index isSelected
)
]
[ radio name option.idString isSelected <|
(Events.onCheck (\_ -> config.onSelect option.value)
:: css [ Css.opacity Css.zero ]
:: Attributes.attribute "data-nri-checked"
(if isSelected then
"true"
else
"false"
)
:: Style.invisible
)
, div [] [ viewIcon option.icon, option.label ]
]
name =
dashify (String.toLower config.legend)
legendId =
"legend-" ++ name
in
div
[ Role.radioGroup
, Aria.labelledBy legendId
, css
[ displayFlex
, cursor pointer
, case config.positioning of
Left _ ->
justifyContent flexStart
Center ->
justifyContent center
]
]
(p (Attributes.id legendId :: Style.invisible) [ text config.legend ]
:: List.indexedMap viewRadio config.options
)
{-| Tooltip defaults: `[Tooltip.smallPadding, Tooltip.onBottom, Tooltip.fitToContent]`
-}
type alias Option value msg =
{ value : value
, idString : String
, label : Html msg
, attributes : List (Attribute msg)
, tabTooltip : List (Tooltip.Attribute msg)
, icon : Maybe Svg
, content : Html msg
}
{-|
- `focusAndSelect` : the message to produce when an option is selected by the user
- `options`: the list of options available
- `selected`: the value of the currently-selected option
- `positioning`: how to position and size the segmented control
- `toUrl`: a optional function that takes a `route` and returns the URL of that route. You should always use pass a `toUrl` function when the segmented control options correspond to routes in your SPA.
-}
view :
{ focusAndSelect : { select : a, focus : Maybe String } -> msg
, options : List (Option a msg)
, selected : a
, positioning : Positioning
, toUrl : Maybe (a -> String)
}
-> Html msg
view config =
let
toInternalTab : Option a msg -> TabsInternal.Tab a msg
toInternalTab option =
{ id = option.value
, idString = option.idString
, tabAttributes = option.attributes
, tabTooltip =
case config.positioning of
Left FillContainer ->
Tooltip.containerCss [ Css.width (Css.pct 100) ] :: option.tabTooltip
_ ->
option.tabTooltip
, tabView = [ viewIcon option.icon, option.label ]
, panelView = option.content
, spaHref = Maybe.map (\toUrl -> toUrl option.value) config.toUrl
, disabled = False
, labelledBy = Nothing
}
{ tabList, tabPanels } =
TabsInternal.views
{ focusAndSelect = config.focusAndSelect
, selected = config.selected
, tabs = List.map toInternalTab config.options
, tabListStyles =
[ displayFlex
, cursor pointer
, marginBottom (px 10)
, case config.positioning of
Left _ ->
justifyContent flexStart
Center ->
justifyContent center
]
, tabStyles = styles config.positioning (List.length config.options)
}
in
div []
[ tabList
, tabPanels
]
viewIcon : Maybe Svg.Svg -> Html msg
viewIcon icon =
case icon of
Nothing ->
text ""
Just svg ->
svg
|> Svg.withWidth (px 18)
|> Svg.withHeight (px 18)
|> Svg.withCss
[ display inlineBlock
, verticalAlign textTop
, lineHeight (px 15)
, marginRight (px 8)
]
|> Svg.toHtml
styles : Positioning -> Int -> Int -> Bool -> List Style
styles positioning numEntries index isSelected =
[ sharedSegmentStyles numEntries index
, if isSelected then
focusedSegmentStyles
else
unFocusedSegmentStyles
, Css.batch <|
case positioning of
Left FillContainer ->
[ width (Css.pct 100)
, flexGrow (int 1)
, textAlign center
]
_ ->
[]
]
sharedSegmentStyles : Int -> Int -> Style
sharedSegmentStyles numEntries index =
[ padding2 (px 6) (px 15)
, height (px 45)
, Fonts.baseFont
, fontSize (px 15)
, fontWeight bold
, lineHeight (px 30)
, margin zero
, border3 (px 1) solid Colors.azure
, boxSizing borderBox
, cursor pointer
, property "transition" "background-color 0.2s, color 0.2s, box-shadow 0.2s, border 0.2s, border-width 0s"
, textDecoration none
, hover [ textDecoration none ]
, focus [ textDecoration none ]
]
++ (if index == 0 then
[ borderTopLeftRadius (px 8)
, borderBottomLeftRadius (px 8)
]
else if index == numEntries - 1 then
[ borderTopRightRadius (px 8)
, borderBottomRightRadius (px 8)
, borderLeft (px 0)
]
else
[ borderLeft (px 0) ]
)
|> Css.batch
focusedSegmentStyles : Style
focusedSegmentStyles =
[ backgroundColor Colors.glacier
, boxShadow5 inset zero (px 3) zero (withAlpha 0.2 Colors.gray20)
, color Colors.navy
]
|> Css.batch
unFocusedSegmentStyles : Style
unFocusedSegmentStyles =
[ backgroundColor Colors.white
, boxShadow5 inset zero (px -2) zero Colors.azure
, color Colors.azure
, hover [ backgroundColor Colors.frost ]
]
|> Css.batch

View File

@ -6,7 +6,6 @@ module Nri.Ui.Select.V7 exposing (Choice, view)
-}
import Color
import Css
import Dict
import Html.Styled as Html exposing (Html)
@ -19,6 +18,7 @@ import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.CssVendorPrefix.V1 as VendorPrefixed
import Nri.Ui.Fonts.V1 as Fonts
import Nri.Ui.Util
import SolidColor
{-| A single possible choice.
@ -153,7 +153,7 @@ selectArrowsCss : Css.Style
selectArrowsCss =
let
color =
Color.toRGBString (ColorsExtra.fromCssColor Colors.azure)
SolidColor.toRGBString (ColorsExtra.fromCssColor Colors.azure)
in
Css.batch
[ """<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="12px" height="16px" viewBox="0 0 12 16"><g fill=" """

View File

@ -17,7 +17,6 @@ import Accessibility.Styled.Aria exposing (labelledBy)
import Accessibility.Styled.Role as Role
import Accessibility.Styled.Style
import Accessibility.Styled.Widget as Widget
import Color
import Css
import Css.Animations
import Css.Global
@ -31,8 +30,9 @@ import Nri.Ui.Button.V8 as Button
import Nri.Ui.Colors.Extra
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.Fonts.V1 as Fonts
import Nri.Ui.Heading.V2 as Heading
import Nri.Ui.Slide.V1 as Slide exposing (AnimationDirection(..))
import Nri.Ui.Text.V2 as Text
import SolidColor
{-| -}
@ -148,7 +148,7 @@ viewModal config (State { previousPanel }) summary =
, panelContainer config.height
[ Slide.animateOut direction ]
[ viewIcon panelView.icon
, Text.subHeading
, Heading.h4 []
[ span [ Html.Styled.Attributes.id (panelId panelView) ] [ Html.text panelView.title ]
]
, viewContent panelView.content
@ -167,7 +167,7 @@ viewModalContent config summary styles =
, panelContainer config.height
styles
[ viewIcon summary.current.icon
, Text.subHeading
, Heading.h4 []
[ span
[ Html.Styled.Attributes.id (panelId summary.current)
, css [ Css.margin2 Css.zero (Css.px 21) ]
@ -412,7 +412,7 @@ dot type_ =
animateBackgroundColor color =
Nri.Ui.Colors.Extra.fromCssColor color
|> Color.toRGBString
|> SolidColor.toRGBString
|> Css.Animations.property "background-color"
in
case type_ of

View File

@ -14,7 +14,6 @@ module Nri.Ui.SortableTable.V2 exposing
-}
import Color
import Css exposing (..)
import Css.Global exposing (Snippet, adjacentSiblings, children, class, descendants, each, everything, media, selector, withClass)
import Html.Styled as Html exposing (Html)
@ -24,6 +23,7 @@ import Nri.Ui.Colors.Extra
import Nri.Ui.Colors.V1
import Nri.Ui.CssVendorPrefix.V1 as CssVendorPrefix
import Nri.Ui.Table.V5
import SolidColor
import Svg.Styled as Svg exposing (Svg)
import Svg.Styled.Attributes as SvgAttributes
@ -365,4 +365,4 @@ sortArrow direction active =
toCssString : Css.Color -> String
toCssString =
Color.toRGBString << Nri.Ui.Colors.Extra.fromCssColor
SolidColor.toRGBString << Nri.Ui.Colors.Extra.fromCssColor

View File

@ -1,258 +0,0 @@
module Nri.Ui.Text.V2 exposing
( caption, heading, mediumBody, smallBody, smallBodyGray, subHeading, smallHeading, tagline
, ugMediumBody, ugSmallBody
, noWidow
)
{-|
## Semantic text types:
@docs caption, heading, mediumBody, smallBody, smallBodyGray, subHeading, smallHeading, tagline
## User-generated text styles:
@docs ugMediumBody, ugSmallBody
## Modifying strings to display nicely:
@docs noWidow
-}
import Css exposing (..)
import Html.Styled exposing (..)
import Html.Styled.Attributes exposing (css)
import Nri.Ui.Colors.V1 exposing (..)
import Nri.Ui.Fonts.V1 as Fonts
{-| This is a Page Heading.
-}
heading : List (Html msg) -> Html msg
heading content =
h1
[ css
(textStyles
++ [ Fonts.baseFont
, fontSize (px 30)
, color navy
, lineHeight (px 40.5)
, fontWeight (int 700)
, margin zero
]
)
]
content
{-| This is a tagline for a page heading.
-}
tagline : List (Html msg) -> Html msg
tagline content =
h2
[ css
(textStyles
++ [ Fonts.baseFont
, fontSize (px 20)
, color gray45
, lineHeight (px 27)
, fontWeight (int 400)
, margin4 (px 5) (px 0) (px 0) (px 0)
]
)
]
content
{-| This is a subhead.
-}
subHeading : List (Html msg) -> Html msg
subHeading content =
h3
[ css
(textStyles
++ [ Fonts.baseFont
, fontSize (px 20)
, color navy
, lineHeight (px 27)
, fontWeight (int 700)
, margin4 (px 20) (px 0) (px 10) (px 0)
]
)
]
content
{-| This is a small Page Heading.
-}
smallHeading : List (Html msg) -> Html msg
smallHeading content =
h4
[ css
(textStyles
++ [ Fonts.baseFont
, fontSize (px 16)
, color gray20
, lineHeight (px 23)
, fontWeight (int 700)
, margin zero
]
)
]
content
{-| This is some medium body copy.
-}
mediumBody : List (Html msg) -> Html msg
mediumBody content =
p
[ css
(textStyles
++ [ Fonts.baseFont
, fontSize (px 18)
, color gray20
, lineHeight (px 27)
, fontWeight (int 400)
, margin4 (px 10) (px 0) (px 0) (px 0)
]
)
]
content
{-| This is some small body copy.
-}
smallBody : List (Html msg) -> Html msg
smallBody content =
p
[ css
(textStyles
++ [ Fonts.baseFont
, fontSize (px 15)
, color gray20
, lineHeight (px 23)
, fontWeight (int 400)
, margin4 (px 7) (px 0) (px 0) (px 0)
]
)
]
content
{-| This is some small body copy but it's gray.
-}
smallBodyGray : List (Html msg) -> Html msg
smallBodyGray content =
p
[ css
(textStyles
++ [ Fonts.baseFont
, fontSize (px 15)
, color gray45
, lineHeight (px 23)
, fontWeight (int 400)
, margin4 (px 7) (px 0) (px 0) (px 0)
]
)
]
content
textStyles =
[ padding zero
, textAlign left
, firstChild
[ margin zero
]
]
{-| This is a little note or caption.
-}
caption : List (Html msg) -> Html msg
caption content =
p
[ css
[ Fonts.baseFont
, fontSize (px 13)
, color gray45
, lineHeight (px 18)
, fontWeight (int 400)
, margin4 (px 5) (px 0) (px 0) (px 0)
]
]
content
{-| User-generated text.
-}
ugMediumBody : List (Html msg) -> Html msg
ugMediumBody =
p
[ css
[ Fonts.quizFont
, fontSize (px 18)
, lineHeight (px 30)
, whiteSpace preLine
, color gray20
, margin4 (px 10) (px 0) (px 0) (px 0)
, firstChild [ margin zero ]
, firstOfType [ margin zero ]
]
]
{-| User-generated text.
-}
ugSmallBody : List (Html msg) -> Html msg
ugSmallBody =
p
[ css
[ Fonts.quizFont
, fontSize (px 16)
, lineHeight (px 25)
, whiteSpace preLine
, color gray20
, margin4 (px 7) (px 0) (px 0) (px 0)
, firstChild [ margin zero ]
, firstOfType [ margin zero ]
]
]
{-| Eliminate widows (single words on their own line caused by
wrapping) by inserting a non-breaking space if there are at least two
words.
-}
noWidow : String -> String
noWidow inputs =
let
-- this value is a unicode non-breaking space since Elm
-- doesn't support named character entities
nbsp =
"\u{00A0}"
words =
String.split " " inputs
insertPoint =
List.length words - 1
in
words
|> List.indexedMap
(\i word ->
if i == 0 then
word
else if i == insertPoint && insertPoint > 0 then
nbsp ++ word
else
" " ++ word
)
|> String.join ""

View File

@ -1,223 +0,0 @@
module Nri.Ui.Text.V4 exposing
( caption, mediumBody, smallBody, smallBodyGray
, ugMediumBody, ugSmallBody
, noWidow
)
{-| Post-release patches
- adjusts link styles
Changes from V3:
- Removes Headings (they now live in Nri.Ui.Heading.V2)
## Understanding spacing
- All text styles have a specific line-height. This is set so that when text in the given style
is long enough to wrap, the spacing between wrapped lines looks good.
- No text styles have padding.
- **Heading styles** do not have margin. It is up to the caller to add appropriate margin to the layout.
- **Paragraph styles** only have bottom margin, but with **:last-child bottom margin set to zero**.
This bottom margin is set to look good when multiple paragraphs of the same style follow one another.
- If you want content after the paragraph and don't want the margin, put the paragraph in a `div` so that it will be the last-child, which will get rid of the bottom margin.
- **User-authored content blocks** preserve line breaks and do not have margin.
## Headings
Headings now live in Nri.Ui.Heading.V2. Here's a mapping to help with upgrades:
| Nri.Ui.Text.V3 | Nri.Ui.Heading.V2 |
|===================|===================|
| Text.heading | Heading.h1 |
| Text.tagline | Heading.h2 |
| Text.subHeading | Heading.h3 |
| Text.smallHeading | Heading.h4 |
If you look at your new code and go "hmm, those shouldn't be at this level of
heading" then you can customize the tag apart from the style using the new
API. See the Nri.Ui.Heading.V2 docs for details.
## Paragraph styles
@docs caption, mediumBody, smallBody, smallBodyGray
## User-authored content blocks:
@docs ugMediumBody, ugSmallBody
## Modifying strings to display nicely:
@docs noWidow
-}
import Css exposing (..)
import Css.Global exposing (a, descendants)
import Html.Styled exposing (..)
import Html.Styled.Attributes exposing (css)
import Nri.Ui.Colors.V1 exposing (..)
import Nri.Ui.Fonts.V1 as Fonts
{-| This is some medium body copy.
-}
mediumBody : List (Html msg) -> Html msg
mediumBody content =
p
[ paragraphStyles
{ font = Fonts.baseFont
, color = gray20
, size = 18
, lineHeight = 28
, weight = 400
, margin = 10
}
]
content
{-| This is some small body copy.
-}
smallBody : List (Html msg) -> Html msg
smallBody content =
p
[ paragraphStyles
{ font = Fonts.baseFont
, color = gray20
, size = 15
, lineHeight = 23
, weight = 400
, margin = 7
}
]
content
{-| This is some small body copy but it's gray.
-}
smallBodyGray : List (Html msg) -> Html msg
smallBodyGray content =
p
[ paragraphStyles
{ font = Fonts.baseFont
, color = gray45
, size = 15
, lineHeight = 23
, weight = 400
, margin = 7
}
]
content
paragraphStyles config =
css
[ config.font
, fontSize (px config.size)
, color config.color
, lineHeight (px config.lineHeight)
, fontWeight (int config.weight)
, padding zero
, textAlign left
, margin4 (px 0) (px 0) (px config.margin) (px 0)
, Css.Global.descendants
[ Css.Global.a
[ textDecoration none
, color azure
, borderBottom3 (px 1) solid azure
, visited
[ color azure ]
]
]
, lastChild
[ margin zero
]
]
{-| This is a little note or caption.
-}
caption : List (Html msg) -> Html msg
caption content =
p
[ paragraphStyles
{ font = Fonts.baseFont
, color = gray45
, size = 13
, lineHeight = 18
, weight = 400
, margin = 5
}
]
content
{-| User-generated text.
-}
ugMediumBody : List (Html msg) -> Html msg
ugMediumBody =
p
[ css
[ Fonts.quizFont
, fontSize (px 18)
, lineHeight (px 30)
, whiteSpace preLine
, color gray20
, margin zero
]
]
{-| User-generated text.
-}
ugSmallBody : List (Html msg) -> Html msg
ugSmallBody =
p
[ css
[ Fonts.quizFont
, fontSize (px 16)
, lineHeight (px 25)
, whiteSpace preLine
, color gray20
, margin zero
]
]
{-| Eliminate widows (single words on their own line caused by
wrapping) by inserting a non-breaking space if there are at least two
words.
-}
noWidow : String -> String
noWidow inputs =
let
-- this value is a unicode non-breaking space since Elm
-- doesn't support named character entities
nbsp =
"\u{00A0}"
words =
String.split " " inputs
insertPoint =
List.length words - 1
in
words
|> List.indexedMap
(\i word ->
if i == 0 then
word
else if i == insertPoint && insertPoint > 0 then
nbsp ++ word
else
" " ++ word
)
|> String.join ""

View File

@ -1,77 +0,0 @@
module AtomicDesignType exposing
( AtomicDesignType(..)
, all, sorter, toString
)
{-|
@docs AtomicDesignType
@docs all, sorter, toString
-}
import Sort exposing (Sorter)
{-| -}
type AtomicDesignType
= Atom
| Molecule
| Organism
| Template
| Page
{-| -}
all : List AtomicDesignType
all =
[ Atom
, Molecule
, Organism
, Template
, Page
]
{-| -}
sorter : Sorter AtomicDesignType
sorter =
Sort.by
(\v ->
case v of
Atom ->
0
Molecule ->
1
Organism ->
2
Template ->
3
Page ->
4
)
Sort.increasing
{-| -}
toString : AtomicDesignType -> String
toString atomicDesignType =
case atomicDesignType of
Atom ->
"Atom"
Molecule ->
"Molecule"
Organism ->
"Organism"
Template ->
"Template"
Page ->
"Page"

View File

@ -1,6 +1,5 @@
module Example exposing (Example, view, wrapMsg, wrapState)
import AtomicDesignType exposing (AtomicDesignType)
import Category exposing (Category)
import Css exposing (..)
import Css.Global exposing (a, descendants)
@ -21,7 +20,6 @@ type alias Example state msg =
, subscriptions : state -> Sub msg
, view : state -> List (Html msg)
, categories : List Category
, atomicDesignType : AtomicDesignType
, keyboardSupport : List KeyboardSupport
}
@ -47,7 +45,6 @@ wrapMsg wrapMsg_ unwrapMsg example =
, subscriptions = \state -> Sub.map wrapMsg_ (example.subscriptions state)
, view = \state -> List.map (Html.map wrapMsg_) (example.view state)
, categories = example.categories
, atomicDesignType = example.atomicDesignType
, keyboardSupport = example.keyboardSupport
}
@ -79,7 +76,6 @@ wrapState wrapState_ unwrapState example =
>> Maybe.map example.view
>> Maybe.withDefault []
, categories = example.categories
, atomicDesignType = example.atomicDesignType
, keyboardSupport = example.keyboardSupport
}

View File

@ -14,7 +14,6 @@ import Examples.DisclosureIndicator as DisclosureIndicator
import Examples.Divider as Divider
import Examples.Fonts as Fonts
import Examples.Heading as Heading
import Examples.Icon as Icon
import Examples.Loading as Loading
import Examples.Logo as Logo
import Examples.MasteryIcon as MasteryIcon
@ -287,25 +286,6 @@ all =
HeadingState childState ->
Just childState
_ ->
Nothing
)
, Icon.example
|> Example.wrapMsg IconMsg
(\msg ->
case msg of
IconMsg childMsg ->
Just childMsg
_ ->
Nothing
)
|> Example.wrapState IconState
(\msg ->
case msg of
IconState childState ->
Just childState
_ ->
Nothing
)
@ -782,7 +762,6 @@ type State
| DividerState Divider.State
| FontsState Fonts.State
| HeadingState Heading.State
| IconState Icon.State
| LoadingState Loading.State
| LogoState Logo.State
| MasteryIconState MasteryIcon.State
@ -823,7 +802,6 @@ type Msg
| DividerMsg Divider.Msg
| FontsMsg Fonts.Msg
| HeadingMsg Heading.Msg
| IconMsg Icon.Msg
| LoadingMsg Loading.Msg
| LogoMsg Logo.Msg
| MasteryIconMsg MasteryIcon.Msg

View File

@ -11,7 +11,6 @@ module Examples.Accordion exposing
-}
import Accessibility.Styled as Html exposing (Html)
import AtomicDesignType exposing (AtomicDesignType(..))
import Browser.Dom as Dom
import Category exposing (Category(..))
import Css exposing (..)
@ -26,7 +25,6 @@ import Nri.Ui.DisclosureIndicator.V2 as DisclosureIndicator
import Nri.Ui.Fonts.V1 as Fonts
import Nri.Ui.Heading.V2 as Heading
import Nri.Ui.Svg.V1 as Svg
import Nri.Ui.Text.V4 as Text
import Nri.Ui.UiIcon.V1 as UiIcon
import Set exposing (Set)
import Task
@ -42,7 +40,6 @@ example =
, subscriptions = \_ -> Sub.none
, view = view
, categories = [ Layout ]
, atomicDesignType = Molecule
, keyboardSupport =
[ { keys = [ Arrow KeyboardSupport.Up ]
, result = "Moves the focus to the previous accordion header button (wraps focus to the last header button)"

View File

@ -6,13 +6,11 @@ module Examples.AssignmentIcon exposing (example, State, Msg)
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Example exposing (Example)
import Examples.IconExamples as IconExamples
import KeyboardSupport exposing (Direction(..), Key(..))
import Nri.Ui.AssignmentIcon.V2 as AssignmentIcon
import Nri.Ui.Icon.V5 as Icon
{-| -}
@ -31,7 +29,6 @@ example =
{ name = "AssignmentIcon"
, version = 2
, categories = [ Icons ]
, atomicDesignType = Atom
, keyboardSupport = []
, state = ()
, update = \_ state -> ( state, Cmd.none )

View File

@ -6,7 +6,6 @@ module Examples.Button exposing (Msg, State, example)
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Css exposing (middle, verticalAlign)
import Debug.Control as Control exposing (Control)
@ -30,7 +29,6 @@ example =
, subscriptions = \_ -> Sub.none
, view = \state -> [ viewButtonExamples state ]
, categories = [ Buttons ]
, atomicDesignType = Atom
, keyboardSupport = []
}

View File

@ -7,7 +7,6 @@ module Examples.Callout exposing (example, State, Msg)
-}
import Accessibility.Styled exposing (text)
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Css
import Example exposing (Example)
@ -33,7 +32,6 @@ example =
{ name = "Callout"
, version = 1
, categories = [ Messaging ]
, atomicDesignType = Molecule
, keyboardSupport = []
, state = ()
, update = \_ state -> ( state, Cmd.none )

View File

@ -6,7 +6,6 @@ module Examples.Checkbox exposing (Msg, State, example)
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Css
import Example exposing (Example)
@ -17,7 +16,6 @@ import Nri.Ui.Checkbox.V5 as Checkbox
import Nri.Ui.Data.PremiumLevel as PremiumLevel exposing (PremiumLevel(..))
import Nri.Ui.PremiumCheckbox.V6 as PremiumCheckbox
import Set exposing (Set)
import Sort.Set
{-| -}
@ -51,7 +49,6 @@ example =
, viewPremiumCheckboxes state
]
, categories = [ Inputs ]
, atomicDesignType = Molecule
, keyboardSupport =
[ { keys = [ Space ]
, result = "Select or deselect the checkbox (may cause page scroll)"

View File

@ -6,9 +6,7 @@ module Examples.ClickableSvg exposing (Msg, State, example)
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Color exposing (Color)
import Css
import Debug.Control as Control exposing (Control)
import EventExtras
@ -34,7 +32,6 @@ example =
{ name = "ClickableSvg"
, version = 2
, categories = [ Buttons, Icons ]
, atomicDesignType = Molecule
, keyboardSupport = []
, state = init
, update = update

View File

@ -6,7 +6,6 @@ module Examples.ClickableText exposing (Msg, State, example)
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Css exposing (middle, verticalAlign)
import Debug.Control as Control exposing (Control)
@ -35,7 +34,6 @@ example =
, subscriptions = \_ -> Sub.none
, view = \state -> [ viewExamples state ]
, categories = [ Buttons ]
, atomicDesignType = Molecule
, keyboardSupport = []
}

View File

@ -6,9 +6,7 @@ module Examples.Colors exposing (example, State, Msg)
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Color exposing (highContrast)
import Css
import Example exposing (Example)
import Html.Styled as Html
@ -17,6 +15,7 @@ import KeyboardSupport exposing (Direction(..), Key(..))
import Nri.Ui.Colors.Extra
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.Heading.V2 as Heading
import SolidColor exposing (highContrast)
type alias ColorExample =
@ -38,7 +37,6 @@ example =
{ name = "Colors"
, version = 1
, categories = [ Colors ]
, atomicDesignType = Atom
, keyboardSupport = []
, state = ()
, update = \_ state -> ( state, Cmd.none )

View File

@ -6,7 +6,6 @@ module Examples.Confetti exposing (example, State, Msg)
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Browser.Events
import Category exposing (Category(..))
import Css exposing (Color)
@ -25,7 +24,6 @@ example =
{ name = "Confetti"
, version = 2
, categories = [ Animations ]
, atomicDesignType = Molecule
, keyboardSupport = []
, state = Confetti.init 700
, update = update

View File

@ -6,7 +6,6 @@ module Examples.DisclosureIndicator exposing (Msg, State, example)
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Css
import Example exposing (Example)
@ -17,7 +16,7 @@ import KeyboardSupport exposing (Direction(..), Key(..))
import Nri.Ui.Button.V10 as Button
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.DisclosureIndicator.V2 as DisclosureIndicator
import Nri.Ui.Text.V2 as Text
import Nri.Ui.Text.V5 as Text
{-| -}
@ -33,14 +32,13 @@ example =
{ name = "DisclosureIndicator"
, version = 2
, categories = [ Widgets ]
, atomicDesignType = Atom
, keyboardSupport = []
, state = init
, update = update
, subscriptions = \_ -> Sub.none
, view =
\state ->
[ Text.smallBodyGray [ Html.text "The disclosure indicator is only the caret. It is NOT a button -- you must create a button or clickabletext yourself!" ]
[ Text.smallBodyGray [] [ Html.text "The disclosure indicator is only the caret. It is NOT a button -- you must create a button or clickabletext yourself!" ]
, Html.div [ css [ Css.displayFlex, Css.padding (Css.px 8) ] ]
[ Button.button "Toggle large indicator"
[ Button.onClick ToggleLarge, Button.small, Button.secondary ]

View File

@ -6,7 +6,6 @@ module Examples.Divider exposing (Msg, State, example)
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Css
import Example exposing (Example)
@ -32,7 +31,6 @@ example =
{ name = "Divider"
, version = 2
, categories = [ Layout ]
, atomicDesignType = Atom
, keyboardSupport = []
, state = {}
, update = \_ state -> ( state, Cmd.none )

View File

@ -6,7 +6,6 @@ module Examples.Fonts exposing (example, State, Msg)
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Example exposing (Example)
import Html.Styled as Html
@ -32,7 +31,6 @@ example =
{ name = "Fonts"
, version = 1
, categories = [ Text ]
, atomicDesignType = Atom
, keyboardSupport = []
, state = ()
, update = \_ state -> ( state, Cmd.none )

View File

@ -6,7 +6,6 @@ module Examples.Heading exposing (example, State, Msg)
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Css
import Example exposing (Example)
@ -32,7 +31,6 @@ example =
{ name = "Heading"
, version = 2
, categories = [ Text, Layout ]
, atomicDesignType = Atom
, keyboardSupport = []
, state = ()
, update = \_ state -> ( state, Cmd.none )

View File

@ -1,114 +0,0 @@
module Examples.Icon exposing (example, State, Msg)
{-|
@docs example, State, Msg
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Css
import Css.Global
import Example exposing (Example)
import Html.Styled as Html exposing (Html)
import Html.Styled.Attributes exposing (css)
import KeyboardSupport exposing (Direction(..), Key(..))
import Nri.Ui.AssetPath as AssetPath exposing (Asset(..))
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.Heading.V2 as Heading
import Nri.Ui.Icon.V5 as Icon
import Nri.Ui.Text.V4 as Text
{-| -}
type alias State =
()
{-| -}
type alias Msg =
()
{-| -}
example : Example State Msg
example =
{ name = "Icon"
, version = 5
, categories = [ Icons ]
, atomicDesignType = Atom
, keyboardSupport = []
, state = ()
, update = \_ state -> ( state, Cmd.none )
, subscriptions = \_ -> Sub.none
, view =
\_ ->
[ viewLarge "Bulbs and Tips"
[ deprecatedIcon { icon = Icon.lightBulb { hint_png = Asset "assets/images/hint.png" }, background = Colors.frost, alt = "LightBulb" }
]
]
}
viewLarge :
String
-> List ( String, Html msg )
-> Html msg
viewLarge headerText icons =
Html.section [ css [ Css.marginTop (Css.px 16) ] ]
[ Heading.h2 [] [ Html.text headerText ]
, Html.div [ css [ Css.displayFlex, Css.flexWrap Css.wrap ] ]
(List.map viewIcon icons)
]
viewIcon : ( String, Html msg ) -> Html msg
viewIcon ( name, assignmentIcon ) =
Html.div
[ css
[ Css.margin (Css.px 10)
, Css.width (Css.px 160)
, Css.boxShadow4 (Css.px 10) (Css.px 5) (Css.px 5) Colors.navy
, Css.displayFlex
, Css.flexDirection Css.column
, Css.alignItems Css.center
, Css.justifyContent Css.flexStart
]
]
[ Html.div
[ css
[ Css.height (Css.px 80)
, Css.width (Css.px 80)
, Css.margin (Css.px 10)
, Css.color Colors.green
]
]
[ assignmentIcon
]
, Text.mediumBody [ Html.text name ]
]
deprecatedIcon : { alt : String, background : Css.Color, icon : Icon.IconType } -> ( String, Html msg )
deprecatedIcon { alt, background, icon } =
( alt
, Html.div
[ css
[ Css.backgroundColor background
, Css.height (Css.px 80)
, Css.width (Css.px 80)
, Css.displayFlex
, Css.alignItems Css.center
, Css.justifyContent Css.center
, Css.Global.descendants
[ Css.Global.img
[ Css.maxWidth (Css.pct 100)
, Css.maxHeight (Css.pct 100)
]
]
]
]
[ Icon.icon { alt = alt, icon = icon }
]
)

View File

@ -6,7 +6,7 @@ import Html.Styled.Attributes exposing (css, style, title)
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.Heading.V2 as Heading
import Nri.Ui.Svg.V1 as Svg
import Nri.Ui.Text.V4 as Text
import Nri.Ui.Text.V5 as Text
view : String -> List ( String, Svg.Svg ) -> Html msg
@ -55,5 +55,5 @@ viewIcon ( name, icon, style ) =
]
]
[ Html.div [ css style ] [ Svg.toHtml icon ]
, Text.smallBody [ Html.text name ]
, Text.smallBody [] [ Html.text name ]
]

View File

@ -6,7 +6,6 @@ module Examples.Loading exposing (example, State, Msg)
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Browser.Events
import Category exposing (Category(..))
import Css
@ -21,7 +20,7 @@ import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.Heading.V2 as Heading
import Nri.Ui.Loading.V1 as Loading
import Nri.Ui.Svg.V1 as Svg
import Nri.Ui.Text.V4 as Text
import Nri.Ui.Text.V5 as Text
{-| -}
@ -91,7 +90,6 @@ example =
{ name = "Loading"
, version = 1
, categories = [ Pages ]
, atomicDesignType = Page
, keyboardSupport = []
, state = init
, update = update
@ -115,7 +113,7 @@ example =
[ Loading.spinningPencil
|> Svg.withColor Colors.blue
|> Svg.toHtml
, Text.caption [ Html.text "By default, the spinningPencil is white. Showing as blue for visibility." ]
, Text.caption [] [ Html.text "By default, the spinningPencil is white. Showing as blue for visibility." ]
, Loading.spinningDots
|> Svg.toHtml
]

View File

@ -6,7 +6,6 @@ module Examples.Logo exposing (example, State, Msg)
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Css
import Example exposing (Example)
@ -32,7 +31,6 @@ example =
{ name = "Logo"
, version = 1
, categories = [ Icons ]
, atomicDesignType = Atom
, keyboardSupport = []
, state = ()
, update = \_ state -> ( state, Cmd.none )

View File

@ -6,7 +6,6 @@ module Examples.MasteryIcon exposing (example, State, Msg)
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Example exposing (Example)
import Examples.IconExamples as IconExamples
@ -31,7 +30,6 @@ example =
{ name = "MasteryIcon"
, version = 1
, categories = [ Icons ]
, atomicDesignType = Atom
, keyboardSupport = []
, state = ()
, update = \_ state -> ( state, Cmd.none )

View File

@ -7,7 +7,6 @@ module Examples.Menu exposing (Msg, State, example)
-}
import Accessibility.Styled as Html exposing (..)
import AtomicDesignType exposing (AtomicDesignType(..))
import Browser.Dom as Dom
import Category exposing (Category(..))
import Css
@ -35,7 +34,6 @@ example =
, update = update
, subscriptions = \_ -> Sub.none
, categories = [ Widgets ]
, atomicDesignType = Molecule
, keyboardSupport =
[ { keys = [ Space ], result = "Opens the menu" }
, { keys = [ Enter ], result = "Opens the menu" }

View File

@ -1,13 +1,11 @@
module Examples.Message exposing (Msg, State, example)
import Accessibility.Styled as Html exposing (..)
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import CommonControls
import Css exposing (..)
import Debug.Control as Control exposing (Control)
import Example exposing (Example)
import Html.Styled exposing (styled)
import Html.Styled.Attributes as Attributes exposing (css, href)
import KeyboardSupport exposing (Direction(..), Key(..))
import Nri.Ui.Colors.V1 as Colors
@ -181,7 +179,6 @@ example =
{ name = "Message"
, version = 3
, categories = [ Messaging ]
, atomicDesignType = Molecule
, keyboardSupport = []
, state = init
, update = update

View File

@ -7,7 +7,6 @@ module Examples.Modal exposing (Msg, State, example)
-}
import Accessibility.Styled as Html exposing (Html, div, h3, h4, p, span, text)
import AtomicDesignType exposing (AtomicDesignType(..))
import Browser.Dom as Dom
import Category exposing (Category(..))
import Css exposing (..)
@ -22,7 +21,7 @@ import Nri.Ui.ClickableText.V3 as ClickableText
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.FocusTrap.V1 as FocusTrap
import Nri.Ui.Modal.V11 as Modal
import Nri.Ui.Text.V4 as Text
import Nri.Ui.Text.V5 as Text
import Task
@ -111,7 +110,6 @@ example =
{ name = "Modal"
, version = 11
, categories = [ Modals ]
, atomicDesignType = Organism
, keyboardSupport =
[ { keys = [ KeyboardSupport.Tab ]
, result = "Moves focus to the next button within the modal or wraps back to the first element within the modal."
@ -230,7 +228,7 @@ launchModalButton settings =
viewModalContent : String -> Html msg
viewModalContent content =
Text.mediumBody [ span [ css [ whiteSpace preLine ] ] [ text content ] ]
Text.mediumBody [] [ span [ css [ whiteSpace preLine ] ] [ text content ] ]
continueButtonId : String

View File

@ -6,7 +6,6 @@ module Examples.Page exposing (example, State, Msg)
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import CommonControls
import Css
@ -59,7 +58,6 @@ example =
{ name = "Page"
, version = 3
, categories = [ Pages ]
, atomicDesignType = Page
, keyboardSupport = []
, state = { httpError = CommonControls.httpError, recoveryText = initRecoveryText }
, update = update

View File

@ -6,7 +6,6 @@ module Examples.Pennant exposing (example, State, Msg)
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Css exposing (..)
import Example exposing (Example)
@ -35,7 +34,6 @@ example =
{ name = "Pennant"
, version = 2
, categories = [ Icons ]
, atomicDesignType = Atom
, keyboardSupport = []
, state = ()
, update = \_ state -> ( state, Cmd.none )

View File

@ -10,7 +10,6 @@ module Examples.RadioButton exposing
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Css exposing (..)
import Debug.Control as Control exposing (Control)
@ -37,7 +36,6 @@ example =
, subscriptions = subscriptions
, view = view
, categories = [ Layout ]
, atomicDesignType = Atom
, keyboardSupport =
[ { keys = [ Arrow Left ]
, result = "Move the focus & select the radio button to the left"

View File

@ -11,7 +11,6 @@ module Examples.SegmentedControl exposing
-}
import Accessibility.Styled as Html exposing (Html)
import AtomicDesignType exposing (AtomicDesignType(..))
import Browser.Dom as Dom
import Category exposing (Category(..))
import Css
@ -69,7 +68,6 @@ example =
}
]
, categories = [ Widgets, Layout ]
, atomicDesignType = Molecule
, keyboardSupport =
[ { keys = [ KeyboardSupport.Tab ]
, result = "Move focus to the currently-selected Control's content"

View File

@ -6,7 +6,6 @@ module Examples.Select exposing (Msg, State, example)
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Css
import Example exposing (Example)
@ -26,7 +25,6 @@ example =
, update = update
, subscriptions = \_ -> Sub.none
, categories = [ Inputs ]
, atomicDesignType = Molecule
, keyboardSupport = []
, view =
\state ->

View File

@ -7,7 +7,6 @@ module Examples.Slide exposing (Msg, State, example)
-}
import Accessibility.Styled as Html
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Css
import Example exposing (Example)
@ -39,7 +38,6 @@ example =
{ name = "Slide"
, version = 1
, categories = [ Animations ]
, atomicDesignType = Atom
, keyboardSupport = []
, state = init
, update = update

View File

@ -7,7 +7,6 @@ module Examples.SlideModal exposing (Msg, State, example)
-}
import Accessibility.Styled as Html exposing (Html, div, h3, p, text)
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Css
import Example exposing (Example)
@ -37,7 +36,6 @@ example =
{ name = "SlideModal"
, version = 2
, categories = [ Modals ]
, atomicDesignType = Organism
, keyboardSupport = []
, state = init
, update = update

View File

@ -6,7 +6,6 @@ module Examples.SortableTable exposing (Msg, State, example)
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Example exposing (Example)
import Html.Styled as Html
@ -38,7 +37,6 @@ example =
{ name = "SortableTable"
, version = 2
, categories = [ Tables, Layout ]
, atomicDesignType = Molecule
, keyboardSupport = []
, state = init
, update = update

View File

@ -6,9 +6,7 @@ module Examples.Svg exposing (Msg, State, example)
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Color exposing (Color)
import Css
import Example exposing (Example)
import Examples.IconExamples as IconExamples
@ -22,6 +20,7 @@ import Nri.Ui.Heading.V2 as Heading
import Nri.Ui.Select.V7 as Select
import Nri.Ui.Svg.V1 as Svg
import Nri.Ui.UiIcon.V1 as UiIcon
import SolidColor exposing (SolidColor)
{-| -}
@ -30,7 +29,6 @@ example =
{ name = "Svg"
, version = 1
, categories = [ Icons ]
, atomicDesignType = Atom
, keyboardSupport = []
, state = init
, update = update
@ -55,8 +53,8 @@ viewSettings state =
[ Html.text "Color: "
, Html.input
[ Attributes.type_ "color"
, Attributes.value (Color.toHex state.color)
, Events.onInput (SetColor << Color.fromHex)
, Attributes.value (SolidColor.toHex state.color)
, Events.onInput (SetColor << SolidColor.fromHex)
]
[]
]
@ -97,7 +95,7 @@ viewResults : State -> Html.Html Msg
viewResults state =
let
( red, green, blue ) =
Color.toRGB state.color
SolidColor.toRGB state.color
in
Html.div [ Attributes.css [ Css.displayFlex ] ]
[ Html.pre
@ -141,7 +139,7 @@ viewResults state =
{-| -}
type alias State =
{ color : Color
{ color : SolidColor
, width : Float
, height : Float
, label : String
@ -160,7 +158,7 @@ init =
{-| -}
type Msg
= SetColor (Result String Color)
= SetColor (Result String SolidColor)
| SetWidth (Maybe Float)
| SetHeight (Maybe Float)
| SetLabel String

View File

@ -6,7 +6,6 @@ module Examples.Switch exposing (Msg, State, example)
-}
import AtomicDesignType
import Category
import Example exposing (Example)
import Html.Styled as Html
@ -68,6 +67,5 @@ example =
]
]
, categories = [ Category.Inputs ]
, atomicDesignType = AtomicDesignType.Atom
, keyboardSupport = [{- TODO -}]
}

View File

@ -6,7 +6,6 @@ module Examples.Table exposing (Msg, State, example)
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Css exposing (..)
import Example exposing (Example)
@ -37,7 +36,6 @@ example =
, update = \_ state -> ( state, Cmd.none )
, subscriptions = \_ -> Sub.none
, categories = [ Tables, Layout ]
, atomicDesignType = Molecule
, keyboardSupport = []
, view =
\() ->

View File

@ -10,7 +10,6 @@ module Examples.Tabs exposing
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Browser.Dom as Dom
import Category exposing (Category(..))
import Css
@ -123,7 +122,6 @@ example =
{ name = "Tabs"
, version = 7
, categories = [ Layout ]
, atomicDesignType = Molecule
, keyboardSupport =
[ { keys = [ KeyboardSupport.Tab ]
, result = "Move focus to the currently-selected Tab's tab panel"

View File

@ -6,7 +6,6 @@ module Examples.Text exposing (example, State, Msg)
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Css
import Example exposing (Example)
@ -33,7 +32,6 @@ example =
{ name = "Text"
, version = 5
, categories = [ Text ]
, atomicDesignType = Atom
, keyboardSupport = []
, state = ()
, update = \_ state -> ( state, Cmd.none )

View File

@ -6,7 +6,6 @@ module Examples.Text.Writing exposing (example, State, Msg)
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Example exposing (Example)
import Html.Styled exposing (text)
@ -29,7 +28,6 @@ example =
{ name = "Text.Writing"
, version = 1
, categories = [ Text ]
, atomicDesignType = Atom
, keyboardSupport = []
, state = ()
, update = \_ state -> ( state, Cmd.none )

View File

@ -6,7 +6,6 @@ module Examples.TextArea exposing (Msg, State, example)
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Dict exposing (Dict)
import Example exposing (Example)
@ -44,7 +43,6 @@ example =
, update = update
, subscriptions = \_ -> Sub.none
, categories = [ Inputs ]
, atomicDesignType = Molecule
, keyboardSupport = []
, view =
\state ->

View File

@ -7,7 +7,6 @@ module Examples.TextInput exposing (Msg, State, example)
-}
import Accessibility.Styled as Html exposing (..)
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Css exposing (..)
import Debug.Control as Control exposing (Control)
@ -55,7 +54,6 @@ example =
{ name = "TextInput"
, version = 6
, categories = [ Inputs ]
, atomicDesignType = Molecule
, keyboardSupport = []
, state = init
, update = update

View File

@ -7,19 +7,18 @@ module Examples.Tooltip exposing (example, State, Msg)
-}
import Accessibility.Styled as Html exposing (Html)
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Css
import Debug.Control as Control exposing (Control)
import Example exposing (Example)
import Html.Styled.Attributes as Attributes exposing (css, href)
import KeyboardSupport exposing (Direction(..), Key(..))
import Nri.Ui.ClickableSvg.V1 as ClickableSvg
import Nri.Ui.ClickableSvg.V2 as ClickableSvg
import Nri.Ui.ClickableText.V3 as ClickableText
import Nri.Ui.Colors.V1 as Colors
import Nri.Ui.Heading.V2 as Heading
import Nri.Ui.Svg.V1 as Svg
import Nri.Ui.Text.V4 as Text
import Nri.Ui.Text.V5 as Text
import Nri.Ui.Tooltip.V2 as Tooltip
import Nri.Ui.UiIcon.V1 as UiIcon
@ -29,7 +28,6 @@ example =
{ name = "Tooltip"
, version = 2
, categories = [ Widgets ]
, atomicDesignType = Molecule
, keyboardSupport = []
, state = init
, update = update
@ -79,7 +77,7 @@ update msg model =
view : State -> List (Html Msg)
view model =
[ Heading.h3 [] [ Html.text "Using the Tooltip module" ]
, Text.mediumBody
, Text.mediumBody []
[ Html.text "Label the Tooltip as either being the "
, viewPrimaryLabelTooltip model.openTooltip
, Html.text " or the "

View File

@ -6,7 +6,6 @@ module Examples.UiIcon exposing (example, State, Msg)
-}
import AtomicDesignType exposing (AtomicDesignType(..))
import Category exposing (Category(..))
import Example exposing (Example)
import Examples.IconExamples as IconExamples
@ -30,7 +29,6 @@ example =
{ name = "UiIcon"
, version = 1
, categories = List.singleton Icons
, atomicDesignType = Atom
, keyboardSupport = []
, state = ()
, update = \_ state -> ( state, Cmd.none )

View File

@ -1,7 +1,6 @@
module Main exposing (init, main)
import Accessibility.Styled as Html exposing (Html, img, text)
import AtomicDesignType exposing (AtomicDesignType)
import Browser exposing (Document, UrlRequest(..))
import Browser.Dom
import Browser.Navigation exposing (Key)
@ -40,7 +39,6 @@ type alias Model =
{ -- Global UI
route : Route
, moduleStates : Dict String (Example Examples.State Examples.Msg)
, atomicDesignTypes : Set AtomicDesignType
, navigationKey : Key
}
@ -51,7 +49,6 @@ init () url key =
, moduleStates =
Dict.fromList
(List.map (\example -> ( example.name, example )) Examples.all)
, atomicDesignTypes = Set.fromList AtomicDesignType.sorter AtomicDesignType.all
, navigationKey = key
}
, Cmd.none
@ -62,7 +59,6 @@ type Msg
= UpdateModuleStates String Examples.Msg
| OnUrlRequest Browser.UrlRequest
| OnUrlChange Url
| ToggleAtomicDesignType AtomicDesignType Bool
| SkipToMainContent
| NoOp
@ -99,21 +95,6 @@ update action model =
OnUrlChange route ->
( { model | route = Routes.fromLocation route }, Cmd.none )
ToggleAtomicDesignType atomicDesignType isOpen ->
( { model
| atomicDesignTypes =
(if isOpen then
Set.insert
else
Set.remove
)
atomicDesignType
model.atomicDesignTypes
}
, Cmd.none
)
SkipToMainContent ->
( model
, Task.attempt (\_ -> NoOp) (Browser.Dom.focus "maincontent")
@ -141,12 +122,7 @@ view_ : Model -> Html Msg
view_ model =
let
examples filterBy =
List.filter
(\m ->
filterBy m
&& Set.memberOf model.atomicDesignTypes m.atomicDesignType
)
(Dict.values model.moduleStates)
List.filter (\m -> filterBy m) (Dict.values model.moduleStates)
mainContentHeader heading =
Heading.h1
@ -163,7 +139,7 @@ view_ model =
, minHeight (vh 100)
]
]
[ navigation model.route model.atomicDesignTypes
[ navigation model.route
, Html.main_ [ css [ flexGrow (int 1), sectionStyles ] ]
(case model.route of
Routes.Doodad doodad ->
@ -209,8 +185,8 @@ view_ model =
]
navigation : Route -> Set AtomicDesignType -> Html Msg
navigation route openAtomicDesignTypes =
navigation : Route -> Html Msg
navigation route =
let
isActive category =
case route of
@ -297,28 +273,9 @@ navigation route openAtomicDesignTypes =
[ css [ margin4 zero zero (px 40) zero, padding zero ]
, id "categories"
]
, Html.fieldset []
(Html.legend [] [ text "Atomic Design type" ]
:: List.map (checkAtomicDesignType openAtomicDesignTypes) AtomicDesignType.all
)
]
checkAtomicDesignType : Set AtomicDesignType -> AtomicDesignType -> Html Msg
checkAtomicDesignType openAtomicDesignTypes atomicDesignType =
let
isChecked =
Set.memberOf openAtomicDesignTypes atomicDesignType
name =
AtomicDesignType.toString atomicDesignType
in
Html.labelAfter [ css [ display block ] ] (text name) <|
Html.checkbox name
(Just isChecked)
[ Events.onCheck (ToggleAtomicDesignType atomicDesignType) ]
sectionStyles : Css.Style
sectionStyles =
Css.batch [ margin2 (px 40) zero ]

View File

@ -7,7 +7,7 @@
"elm-version": "0.19.1",
"dependencies": {
"direct": {
"BrianHicks/elm-particle": "1.3.1",
"BrianHicks/elm-particle": "1.5.0",
"avh4/elm-debug-controls": "2.2.1",
"elm/browser": "1.0.2",
"elm/core": "1.0.5",
@ -19,15 +19,13 @@
"elm/regex": "1.0.0",
"elm/svg": "1.0.1",
"elm/url": "1.0.0",
"elm-community/random-extra": "3.1.0",
"elm-community/random-extra": "3.2.0",
"elm-community/string-extra": "4.0.1",
"pablohirafuji/elm-markdown": "2.0.5",
"rtfeldman/elm-css": "16.1.0",
"rtfeldman/elm-css": "16.1.1",
"rtfeldman/elm-sorter-experiment": "2.1.1",
"tesk9/accessible-html": "4.0.0",
"tesk9/accessible-html-with-css": "2.1.1",
"tesk9/modal": "5.0.1",
"tesk9/palette": "2.0.0",
"tesk9/accessible-html-with-css": "2.2.0",
"tesk9/palette": "3.0.1",
"wernerdegroot/listzipper": "4.0.0"
},
"indirect": {
@ -38,7 +36,6 @@
"elm/virtual-dom": "1.0.2",
"justinmimbs/date": "3.2.1",
"justinmimbs/time-extra": "1.1.0",
"owanturist/elm-union-find": "1.0.0",
"rtfeldman/elm-hex": "1.0.0"
}
},

View File

@ -1,33 +0,0 @@
module Spec.List.Zipper.Extra exposing (fromSpec)
import Expect exposing (Expectation)
import List.Zipper
import List.Zipper.Extra
import Test exposing (..)
fromSpec : Test
fromSpec =
let
before =
[ 1, 2 ]
current =
3
after =
[ 4, 5 ]
zipper =
List.Zipper.Extra.from before current after
in
describe "List.Zipper.Extra.from before current after"
[ test "before" <|
\() ->
Expect.equal (List.Zipper.before zipper) before
, test "current" <|
\() ->
Expect.equal (List.Zipper.current zipper) current
, test "after" <|
\() -> Expect.equal (List.Zipper.after zipper) after
]

View File

@ -1,77 +0,0 @@
module Spec.Nri.Ui.SegmentedControl exposing (..)
import Expect
import Html.Attributes as Attributes
import Html.Styled
import Json.Encode as Encode
import Nri.Ui.SegmentedControl.V13 as SegmentedControl
import Test exposing (..)
import Test.Html.Query as Query
import Test.Html.Selector as Selector
spec : Test
spec =
describe "segmented controls"
[ describe "radio groups indicate when they're selected" <|
-- nb. this is tested especially since QA is including this
-- attribute in their automated tests. Make sure it doesn't break
-- them!
let
selected =
"I'm Selected!"
notSelected =
"I'm Not Selected!"
control =
SegmentedControl.viewRadioGroup
{ onSelect = identity
, options =
List.map
(\value ->
{ value = value
, idString = value
, label = Html.Styled.text value
, attributes = []
, icon = Nothing
}
)
[ selected, notSelected ]
, selected = Just selected
, positioning = SegmentedControl.Left SegmentedControl.FitContent
, legend = "A Segmented Control Example"
}
in
[ test "a checked=true attribute is added to the selected control" <|
\_ ->
Html.Styled.toUnstyled control
|> Query.fromHtml
|> Query.has
[ Selector.all
[ Selector.tag "label"
, Selector.containing [ Selector.text selected ]
, Selector.containing
[ Selector.tag "input"
, Selector.attribute (Attributes.type_ "radio")
, Selector.attribute (Attributes.attribute "data-nri-checked" "true")
]
]
]
, test "a checked=false attribute is added to a non-selected control" <|
\_ ->
Html.Styled.toUnstyled control
|> Query.fromHtml
|> Query.has
[ Selector.all
[ Selector.tag "label"
, Selector.containing [ Selector.text notSelected ]
, Selector.containing
[ Selector.tag "input"
, Selector.attribute (Attributes.type_ "radio")
, Selector.attribute (Attributes.attribute "data-nri-checked" "false")
]
]
]
]
]

View File

@ -3,14 +3,13 @@
"tests": [
"Nri.Ui",
"Nri.Ui.Accordion.V1",
"Nri.Ui.Accordion.V2",
"Nri.Ui.Accordion.V3",
"Nri.Ui.AssetPath",
"Nri.Ui.AssignmentIcon.V2",
"Nri.Ui.Button.V10",
"Nri.Ui.Button.V8",
"Nri.Ui.Callout.V1",
"Nri.Ui.Checkbox.V5",
"Nri.Ui.ClickableSvg.V1",
"Nri.Ui.ClickableSvg.V2",
"Nri.Ui.ClickableText.V3",
"Nri.Ui.Colors.Extra",
@ -26,19 +25,13 @@
"Nri.Ui.Heading.V2",
"Nri.Ui.Html.Attributes.V2",
"Nri.Ui.Html.V3",
"Nri.Ui.Icon.V3",
"Nri.Ui.Icon.V4",
"Nri.Ui.Icon.V5",
"Nri.Ui.InputStyles.V2",
"Nri.Ui.InputStyles.V3",
"Nri.Ui.Loading.V1",
"Nri.Ui.Logo.V1",
"Nri.Ui.MasteryIcon.V1",
"Nri.Ui.Menu.V1",
"Nri.Ui.Message.V1",
"Nri.Ui.Message.V2",
"Nri.Ui.Menu.V2",
"Nri.Ui.Message.V3",
"Nri.Ui.Modal.V3",
"Nri.Ui.Modal.V10",
"Nri.Ui.Modal.V11",
"Nri.Ui.Page.V3",
@ -47,9 +40,6 @@
"Nri.Ui.PremiumCheckbox.V6",
"Nri.Ui.RadioButton.V1",
"Nri.Ui.RadioButton.V2",
"Nri.Ui.SegmentedControl.V11",
"Nri.Ui.SegmentedControl.V12",
"Nri.Ui.SegmentedControl.V13",
"Nri.Ui.SegmentedControl.V14",
"Nri.Ui.Select.V5",
"Nri.Ui.Select.V7",
@ -62,8 +52,6 @@
"Nri.Ui.Table.V5",
"Nri.Ui.Tabs.V6",
"Nri.Ui.Tabs.V7",
"Nri.Ui.Text.V2",
"Nri.Ui.Text.V4",
"Nri.Ui.Text.V5",
"Nri.Ui.Text.Writing.V1",
"Nri.Ui.TextArea.V4",