Downloading...
129 MB / 1000 MB
A collection of all the components available in miso.ui
A vertically stacked set of interactive headings that each reveal a section of content.
Yes. It adheres to the WAI-ARIA design pattern.
Yes. It comes with default styles that match other component aesthetic.
Yes. It's animated by default, but you can disable it if you prefer.
-----------------------------------------------------------------------------
module MyAccordion (accordionSample) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.Html as H
import qualified Miso.Html.Property as P
import Miso.UI.Icons
import Miso.UI.Accordion
-----------------------------------------------------------------------------
accordionSample :: View context model action
accordionSample =
accordion_ defaultAccordionProps
[ accordionSection_ defaultAccordionItemProps { accordionItemOpen = True }
[ accordionHeader_ []
[ "Is it accessible?" ]
, accordionBody_ []
[ "Yes. It adheres to the WAI-ARIA design pattern." ]
]
, accordionSection_ defaultAccordionItemProps
[ accordionHeader_ []
[ "Is it styled?" ]
, accordionBody_ []
[ "Yes. It comes with default styles that match other component aesthetic." ]
]
, accordionSection_ defaultAccordionItemProps
[ accordionHeader_ []
[ "Is it animated?" ]
, accordionBody_ []
[ "Yes. It's animated by default, but you can disable it if you prefer." ]
]
]-- | Props for 'accordion_'
data AccordionProps model action
= AccordionProps
{ accordionMultiple :: Bool
-- ^ Allow several sections open at once (@data-multiple@)
, accordionClasses :: [MisoString]
-- ^ Extra classes appended to the root @section.accordion@
, accordionAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor: exclusive expand
defaultAccordionProps :: AccordionProps model action
defaultAccordionProps
= AccordionProps
{ accordionMultiple = False
, accordionClasses = []
, accordionAttrs = []
}
-----------------------------------------------------------------------------
-- | Props for 'accordionSection_'
data AccordionItemProps model action
= AccordionItemProps
{ accordionItemOpen :: Bool
-- ^ Section expanded initially
, accordionItemDisabled :: Bool
-- ^ Renders with @aria-disabled@
, accordionItemClasses :: [MisoString]
, accordionItemAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor: collapsed, enabled
defaultAccordionItemProps :: AccordionItemProps model action
defaultAccordionItemProps
= AccordionItemProps
{ accordionItemOpen = False
, accordionItemDisabled = False
, accordionItemClasses = []
, accordionItemAttrs = []
}Displays a callout for user attention.
-----------------------------------------------------------------------------
module MyAlert (alertSample) where
-----------------------------------------------------------------------------
import Miso hiding (alert)
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import Miso.UI.Icons
import Miso.UI.Types
import Miso.UI.Alert
-----------------------------------------------------------------------------
alertSample :: View context model action
alertSample =
H.div_
[ P.class_ "p-4" ]
[ H.div_ [ P.class_ "grid max-w-xl items-start gap-4" ]
[ alert_ defaultAlertProps
[ circleCheckIcon []
, alertHeader_ [] [ "Success!" ]
, alertSection_ []
[ """
Congratulations this is a
successful alert !
"""
]
]
, alert_ defaultAlertProps { alertVariant = Destructive }
[ circleAlertIcon []
, alertHeader_ [] [ "Warning!" ]
, alertSection_ []
[ """
Something bad happened :( you're getting
a destructive alert!
"""
]
]
]
]-- | Props for 'alert_'
data AlertProps model action
= AlertProps
{ alertVariant :: Variant
-- ^ 'Primary' (default) or 'Destructive'
, alertClasses :: [MisoString]
-- ^ Extra classes appended to the alert
, alertAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor: default (success-styled) alert
defaultAlertProps :: AlertProps model action
defaultAlertProps
= AlertProps
{ alertVariant = Primary
, alertClasses = []
, alertAttrs = []
}A modal dialog that interrupts the user with important content and expects a response.
-----------------------------------------------------------------------------
module MyAlertDialog (myView) where
-----------------------------------------------------------------------------
import Miso
-----------------------------------------------------------------------------
import Miso.UI.AlertDialog
-----------------------------------------------------------------------------
-- 'AlertDialogProps' lives in the props slot of the miso 'Component' and is
-- supplied at the mount site:
myView :: View context model action
myView = mountWithProps_ "alert-dialog"
defaultAlertDialogProps
{ alertDialogTitle = "Are you absolutely sure?"
, alertDialogDescription = "This action cannot be undone."
, alertDialogActionLabel = "Continue"
}
alertDialogComponent-- | Props for 'alertDialogComponent'. These live in the @props@ slot of the
-- miso 'Component' and are supplied at mount time via 'mountWithProps_'.
data AlertDialogProps
= AlertDialogProps
{ alertDialogId :: MisoString
, alertDialogTrigger :: MisoString
-- ^ Label of the trigger button
, alertDialogTitle :: MisoString
, alertDialogDescription :: MisoString
, alertDialogCancelLabel :: MisoString
, alertDialogActionLabel :: MisoString
} deriving (Show, Eq)
-----------------------------------------------------------------------------
-- | Smart constructor: destructive-action confirmation
defaultAlertDialogProps :: AlertDialogProps
defaultAlertDialogProps
= AlertDialogProps
{ alertDialogId = "alert-dialog-demo"
, alertDialogTrigger = "Open alert dialog"
, alertDialogTitle = "Are you absolutely sure?"
, alertDialogDescription =
"This action cannot be undone. This will permanently delete your \
\account and remove your data from our servers."
, alertDialogCancelLabel = "Cancel"
, alertDialogActionLabel = "Continue"
}An image element with a fallback for representing the user.
CN













-----------------------------------------------------------------------------
module MyAvatar (avatarSample) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import Miso.UI.Types
import Miso.UI.Avatar
-----------------------------------------------------------------------------
avatarSample :: View context model action
avatarSample =
H.div_
[ P.class_ "flex flex-row flex-wrap items-center gap-4" ]
[ avatar_ defaultAvatarProps
{ avatarSrc = "https://github.com/dmjio.png"
, avatarAlt = "@dmjio"
}
, avatarFallback_ [] [ "CN" ]
, avatar_ defaultAvatarProps
{ avatarSrc = "https://github.com/dmjio.png"
, avatarAlt = "@dmjio"
, avatarSize = Large
}
, avatar_ defaultAvatarProps
{ avatarSrc = "https://github.com/dmjio.png"
, avatarAlt = "@dmjio"
, avatarSquare = True
}
, avatarGroup_ DefaultSize [] members
, avatarGroup_ Large [] members
, avatarGroup_ Large
[ P.class_ "hover:space-x-1 [&_img]:transition-all [&_img]:ease-in-out [&_img]:duration-300" ]
members
]
where
members =
[ H.img_ [ P.src_ ("https://github.com/" <> user <> ".png"), P.alt_ ("@" <> user) ]
| user <- [ "dmjio", "shadcn", "adamwathan", "hunvreus" ]
]-- | Props for 'avatar_'
data AvatarProps model action
= AvatarProps
{ avatarSrc :: MisoString
, avatarAlt :: MisoString
, avatarSize :: Size
-- ^ 'DefaultSize' (@size-8@) or 'Large' (@size-12@)
, avatarSquare :: Bool
-- ^ @rounded-lg@ instead of @rounded-full@
, avatarClasses :: [MisoString]
-- ^ Extra classes appended to the @img@
, avatarAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor: small round avatar
defaultAvatarProps :: AvatarProps model action
defaultAvatarProps
= AvatarProps
{ avatarSrc = ""
, avatarAlt = ""
, avatarSize = DefaultSize
, avatarSquare = False
, avatarClasses = []
, avatarAttrs = []
}Displays a badge or a component that looks like a badge.
-----------------------------------------------------------------------------
module MyBadge (badgeSample) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import Miso.UI.Types
import Miso.UI.Badge
-----------------------------------------------------------------------------
badgeSample :: View context model action
badgeSample =
H.div_
[ P.class_ "flex flex-col gap-2" ]
[ H.div_
[ P.class_ "flex flex-wrap items-center gap-2 md:flex-row" ]
[ badge_ defaultBadgeProps [ "Primary" ]
, badge_ defaultBadgeProps { badgeVariant = Secondary } [ "Secondary" ]
, badge_ defaultBadgeProps { badgeVariant = Outline } [ "Outline" ]
, badge_ defaultBadgeProps { badgeVariant = Destructive } [ "Destructive" ]
, badge_ defaultBadgeProps { badgeRounded = True } [ "8" ]
, badge_ defaultBadgeProps { badgeRounded = True, badgeVariant = Destructive } [ "99" ]
, badge_ defaultBadgeProps
{ badgeRounded = True
, badgeVariant = Outline
, badgeClasses = [ "font-mono", "tabular-nums" ]
}
[ "20+" ]
]
, H.div_
[ P.class_ "flex flex-wrap items-center gap-2 md:flex-row" ]
[ badge_ defaultBadgeProps { badgeHref = Just "#" } [ "Link" ]
, badge_ defaultBadgeProps { badgeHref = Just "#", badgeVariant = Secondary } [ "Link" ]
, badge_ defaultBadgeProps { badgeHref = Just "#", badgeVariant = Destructive } [ "Link" ]
, badge_ defaultBadgeProps { badgeHref = Just "#", badgeVariant = Outline } [ "Link" ]
]
]-- | Props for 'badge_'
data BadgeProps model action
= BadgeProps
{ badgeVariant :: Variant
-- ^ 'Primary', 'Secondary', 'Destructive' or 'Outline'
, badgeRounded :: Bool
-- ^ Pill badge (@rounded-full@), typically for counters
, badgeHref :: Maybe MisoString
-- ^ When set, renders as a link (an anchor element)
, badgeClasses :: [MisoString]
-- ^ Extra classes appended to the computed basecoat class
, badgeAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor: primary variant, not rounded
defaultBadgeProps :: BadgeProps model action
defaultBadgeProps
= BadgeProps
{ badgeVariant = Primary
, badgeRounded = False
, badgeHref = Nothing
, badgeClasses = []
, badgeAttrs = []
}Displays the path to the current resource using a hierarchy of links.
-- | Props for 'breadcrumb_'
data BreadcrumbProps model action
= BreadcrumbProps
{ breadcrumbClasses :: [MisoString]
-- ^ Extra classes appended to the @ol@
, breadcrumbAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor
defaultBreadcrumbProps :: BreadcrumbProps model action
defaultBreadcrumbProps
= BreadcrumbProps
{ breadcrumbClasses = []
, breadcrumbAttrs = []
}Displays a button or a component that looks like a button.
-- | Props for 'button'
data ButtonProps model action
= ButtonProps
{ buttonVariant :: Variant
-- ^ 'Primary', 'Secondary', 'Destructive', 'Outline', 'Ghost' or 'Link'
, buttonSize :: Size
-- ^ 'DefaultSize', 'Small' or 'Large'
, buttonIcon :: Bool
-- ^ Square icon-only button (e.g. @btn-icon-outline@)
, buttonDisabled :: Bool
, buttonClasses :: [MisoString]
-- ^ Extra classes appended to the computed basecoat class
, buttonAttrs :: [Attribute model action]
-- ^ Extra attributes (e.g. @onClick@)
}
-----------------------------------------------------------------------------
-- | Smart constructor: primary variant, default size
defaultButtonProps :: ButtonProps model action
defaultButtonProps
= ButtonProps
{ buttonVariant = Primary
, buttonSize = DefaultSize
, buttonIcon = False
, buttonDisabled = False
, buttonClasses = []
, buttonAttrs = []
}A container that groups related buttons together.
-- | Props for 'buttonGroup_'
data ButtonGroupProps model action
= ButtonGroupProps
{ buttonGroupClasses :: [MisoString]
-- ^ Extra classes appended to @div.button-group@
, buttonGroupAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor
defaultButtonGroupProps :: ButtonGroupProps model action
defaultButtonGroupProps
= ButtonGroupProps
{ buttonGroupClasses = []
, buttonGroupAttrs = []
}Displays a card with header, content, and footer.
Enter your details below to login to your account
This is a card with a header and a description.
This is a card with a header and a content.
This is a card with a header and a footer.
This is a card with a header, content and footer.
-----------------------------------------------------------------------------
module MyCard (cardUsage) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import Miso.UI.Button
import Miso.UI.Input
import Miso.UI.Label
import Miso.UI.Types
import Miso.UI.Card
-----------------------------------------------------------------------------
cardUsage :: View context model action
cardUsage =
card_ defaultCardProps
{ cardTitle = Just "Login to your account"
, cardDescription = Just "Enter your details below to login to your account"
, cardClasses = [ "w-full", "max-w-sm" ]
, cardFooter = Just
[ button_ defaultButtonProps { buttonClasses = [ "w-full" ] } [ "Login" ] ]
}
[ H.form_
[ P.class_ "form grid gap-6" ]
[ H.div_
[ P.class_ "grid gap-2" ]
[ label_ defaultLabelProps { labelFor = Just "my-email" } [ "Email" ]
, input_ defaultInputProps
{ inputType = "email"
, inputId = Just "my-email"
}
]
]
]-- | Props for 'card_'. Title, description and footer nest other views.
data CardProps context model action
= CardProps
{ cardTitle :: Maybe (View context model action)
-- ^ Heading shown in the card header
, cardDescription :: Maybe (View context model action)
-- ^ Sub-heading shown under the title
, cardFooter :: Maybe [View context model action]
-- ^ Footer content
, cardFooterClasses :: [MisoString]
, cardClasses :: [MisoString]
-- ^ Extra classes appended to @div.card@ (e.g. @w-full max-w-sm@)
, cardAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor: bare card
defaultCardProps :: CardProps context model action
defaultCardProps
= CardProps
{ cardTitle = Nothing
, cardDescription = Nothing
, cardFooter = Nothing
, cardFooterClasses = []
, cardClasses = []
, cardAttrs = []
}A control that allows the user to toggle between checked and not checked.
By clicking this checkbox, you agree to the terms and conditions.
-----------------------------------------------------------------------------
module MyCheckbox (checkboxUsage) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import Miso.UI.Label
import Miso.UI.Checkbox
-----------------------------------------------------------------------------
checkboxUsage :: View context model action
checkboxUsage =
H.div_
[ P.class_ "flex flex-col gap-6" ]
[ checkbox_ defaultCheckboxProps [ "Accept terms and conditions" ]
, checkbox_ defaultCheckboxProps { checkboxChecked = True } [ "Checked" ]
, checkbox_ defaultCheckboxProps { checkboxDisabled = True } [ "Disabled" ]
]-- | Props for 'checkbox_'
data CheckboxProps model action
= CheckboxProps
{ checkboxId :: Maybe MisoString
, checkboxName :: Maybe MisoString
, checkboxValue :: Maybe MisoString
, checkboxChecked :: Bool
, checkboxDisabled :: Bool
, checkboxClasses :: [MisoString]
-- ^ Extra classes appended to the @input@
, checkboxLabelClasses :: [MisoString]
-- ^ Extra classes appended to the wrapping @label@
, checkboxAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor: unchecked, enabled
defaultCheckboxProps :: CheckboxProps model action
defaultCheckboxProps
= CheckboxProps
{ checkboxId = Nothing
, checkboxName = Nothing
, checkboxValue = Nothing
, checkboxChecked = False
, checkboxDisabled = False
, checkboxClasses = []
, checkboxLabelClasses = []
, checkboxAttrs = []
}Autocomplete input and command palette with a list of suggestions.
-----------------------------------------------------------------------------
module MyCombobox (comboboxUsage) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import qualified Miso.Svg as S
import qualified Miso.Svg.Property as SP
import Miso.UI.Icons
import Miso.UI.Combobox
-----------------------------------------------------------------------------
comboboxUsage :: View context model action
comboboxUsage =
combobox_ defaultComboboxProps
{ comboboxId = "my-combobox"
, comboboxLabel = [ "Next.js" ]
, comboboxValue = "Next.js"
, comboboxSearchPlaceholder = "Search framework..."
, comboboxEmptyText = "No framework found."
}
[ comboboxOption_ True "Next.js" [ "Next.js" ]
, comboboxOption_ False "SvelteKit" [ "SvelteKit" ]
, comboboxOption_ False "Nuxt.js" [ "Nuxt.js" ]
, comboboxOption_ False "Remix" [ "Remix" ]
, comboboxOption_ False "Astro" [ "Astro" ]
]-- | Props for 'combobox_'
data ComboboxProps context model action
= ComboboxProps
{ comboboxId :: MisoString
-- ^ Base id; trigger\/popover\/listbox ids are derived from it (required)
, comboboxLabel :: [View context model action]
-- ^ Content of the trigger button (current selection)
, comboboxValue :: MisoString
-- ^ Currently selected value (kept in a hidden input)
, comboboxSearchPlaceholder :: MisoString
, comboboxEmptyText :: MisoString
-- ^ Shown when the search yields nothing (@data-empty@)
, comboboxPopoverClasses :: [MisoString]
-- ^ Extra classes for the popover (e.g. @w-48@)
, comboboxTriggerClasses :: [MisoString]
-- ^ Extra classes for the trigger button
, comboboxAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor
defaultComboboxProps :: ComboboxProps context model action
defaultComboboxProps
= ComboboxProps
{ comboboxId = "combobox"
, comboboxLabel = []
, comboboxValue = ""
, comboboxSearchPlaceholder = "Search entries..."
, comboboxEmptyText = "No results found."
, comboboxPopoverClasses = [ "w-48" ]
, comboboxTriggerClasses = []
, comboboxAttrs = []
}Fast, composable command menu, opened with a keyboard shortcut.
A window overlaid on either the primary window or another dialog window.
-----------------------------------------------------------------------------
module MyDialog (dialogComponent) where
-----------------------------------------------------------------------------
import Control.Monad
import Miso
import Miso.Html.Event
import Miso.Lens
import qualified Miso.Html as H
import qualified Miso.Html.Property as P
-----------------------------------------------------------------------------
import Miso.UI.Button
import Miso.UI.Dialog
import Miso.UI.Types
-----------------------------------------------------------------------------
data Action
= ShowDialog MisoString DOMRef
| CloseDialog
| NoOp
-----------------------------------------------------------------------------
dialogComponent :: Component parent props MisoString Action
dialogComponent = component "" update_ $ \_ _ _ ->
H.div_ []
[ button_ defaultButtonProps
{ buttonVariant = Outline
, buttonAttrs = [ onClickWith (ShowDialog "my-dialog") ]
}
[ "Edit Profile" ]
, dialog_ defaultDialogProps
{ dialogId = "my-dialog"
, dialogAttrs = [ onClick CloseDialog ]
}
[ H.div_
[ onClickWithOptions stopPropagation NoOp ]
[ dialogHeader_ "my-dialog"
[ "Edit profile" ]
[ "Make changes to your profile here." ]
, dialogFooter_ []
[ button_ defaultButtonProps
{ buttonAttrs = [ onClick CloseDialog ] }
[ "Save changes" ]
]
, dialogCloseButton_ CloseDialog
]
]
]
where
update_ NoOp = pure ()
update_ (ShowDialog sel domRef) = do
this .= sel
io_ $ do
dialogRef <- nextSibling domRef
void $ dialogRef # ("showModal" :: MisoString) $ ()
update_ CloseDialog = do
sel <- use this
io_ $ do
dialog <- jsg "document"
# ("getElementById" :: MisoString)
$ [sel :: MisoString]
void $ dialog # ("close" :: MisoString) $ ()-- | Props for 'dialog_' (the native @dialog@ element)
data DialogProps model action
= DialogProps
{ dialogId :: MisoString
-- ^ id of the dialog; @-title@ \/ @-description@ ids derive from it
, dialogClasses :: [MisoString]
-- ^ Extra classes appended to @dialog.dialog@
, dialogAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor
defaultDialogProps :: DialogProps model action
defaultDialogProps
= DialogProps
{ dialogId = "dialog"
, dialogClasses = [ "w-full", "sm:max-w-[425px]", "max-h-[612px]" ]
, dialogAttrs = []
}Displays a menu to the user, triggered by a button.
-- | Props for 'dropdownMenu_'
data DropdownMenuProps context model action
= DropdownMenuProps
{ dropdownMenuId :: MisoString
-- ^ Base id; trigger\/popover\/menu ids are derived from it (required)
, dropdownMenuTrigger :: [View context model action]
-- ^ Content of the trigger button (nests other views)
, dropdownMenuTriggerClasses :: [MisoString]
-- ^ Classes of the trigger button (defaults to @btn-outline@)
, dropdownMenuAlign :: Align
-- ^ Popover alignment (@data-align@)
, dropdownMenuPopoverClasses :: [MisoString]
-- ^ Extra classes for the popover (e.g. @min-w-56@)
, dropdownMenuAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor: outline trigger button, no alignment override
defaultDropdownMenuProps :: DropdownMenuProps context model action
defaultDropdownMenuProps
= DropdownMenuProps
{ dropdownMenuId = "dropdown-menu"
, dropdownMenuTrigger = []
, dropdownMenuTriggerClasses = [ "btn-outline" ]
, dropdownMenuAlign = CenterAlign
, dropdownMenuPopoverClasses = [ "min-w-56" ]
, dropdownMenuAttrs = []
}A placeholder shown when there is no content to display.
You haven't created any projects yet. Get started by creating your first project.
-----------------------------------------------------------------------------
module MyEmpty (emptySample) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import qualified Miso.Svg as S
import qualified Miso.Svg.Property as SP
import Miso.UI.Button
import Miso.UI.Icons
import Miso.UI.Types
import Miso.UI.Empty
-----------------------------------------------------------------------------
emptySample :: View context model action
emptySample =
empty_ defaultEmptyProps
{ emptyIcon = Just folderIcon
, emptyTitle = Just "No Projects Yet"
, emptyDescription = Just
"You haven't created any projects yet. Get started by creating your first project."
, emptyFooter =
[ H.a_
[ P.class_ "inline-flex items-center justify-center whitespace-nowrap text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive underline-offset-4 hover:underline h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5 text-muted-foreground"
, P.href_ "#"
]
[ "Learn More"
, arrowUpRightIcon
]
]
}
[ button_ defaultButtonProps [ "Create Project" ]
, button_ defaultButtonProps { buttonVariant = Outline } [ "Import Project" ]
]
where
folderIcon = lucide_ []
[ S.path_ [ SP.d_ "M10 10.5 8 13l2 2.5" ]
, S.path_ [ SP.d_ "m14 10.5 2 2.5-2 2.5" ]
, S.path_
[ SP.d_ "M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2z"
]
]
arrowUpRightIcon = lucide_ []
[ S.path_ [ SP.d_ "M7 7h10v10" ]
, S.path_ [ SP.d_ "M7 17 17 7" ]
]-- | Props for 'empty_'. Icon, title and description nest other views.
data EmptyProps context model action
= EmptyProps
{ emptyIcon :: Maybe (View context model action)
-- ^ Icon shown in the header medallion
, emptyTitle :: Maybe (View context model action)
, emptyDescription :: Maybe (View context model action)
, emptyFooter :: [View context model action]
-- ^ Content under the actions (e.g. a \"learn more\" link)
, emptyClasses :: [MisoString]
, emptyAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor: bare empty state
defaultEmptyProps :: EmptyProps context model action
defaultEmptyProps
= EmptyProps
{ emptyIcon = Nothing
, emptyTitle = Nothing
, emptyDescription = Nothing
, emptyFooter = []
, emptyClasses = []
, emptyAttrs = []
}Building forms with labelled, described fields.
-----------------------------------------------------------------------------
module MyForm (formUsage) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import Miso.UI.Button
import Miso.UI.Checkbox
import Miso.UI.Input
import Miso.UI.Label
import Miso.UI.RadioGroup
import Miso.UI.Switch
import Miso.UI.Textarea
import Miso.UI.Form
-----------------------------------------------------------------------------
formUsage :: View context model action
formUsage =
form_ defaultFormProps
[ field_ defaultFieldProps
{ fieldId = Just "username"
, fieldLabel = Just "Username"
, fieldDescription = Just "This is your public display name."
}
[ input_ defaultInputProps
{ inputId = Just "username"
, inputPlaceholder = Just "dmjio"
}
]
, field_ defaultFieldProps
{ fieldId = Just "bio"
, fieldLabel = Just "Bio"
}
[ textarea_ defaultTextareaProps
{ textareaId = Just "bio"
, textareaRows = Just "3"
}
]
, button_ defaultButtonProps
{ buttonAttrs = [ P.type_ "submit" ] }
[ "Submit" ]
]-- | Props for 'form_'
data FormProps model action
= FormProps
{ formClasses :: [MisoString]
-- ^ Extra classes appended to @form.form@ (e.g. @grid gap-6@)
, formAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor: vertical form grid
defaultFormProps :: FormProps model action
defaultFormProps
= FormProps
{ formClasses = [ "grid", "gap-6" ]
, formAttrs = []
}
-----------------------------------------------------------------------------
-- | Props for 'field_': label + control + description stack
data FieldProps context model action
= FieldProps
{ fieldId :: Maybe MisoString
-- ^ id of the labelled control (@for@ on the label)
, fieldLabel :: Maybe (View context model action)
, fieldDescription :: Maybe (View context model action)
, fieldClasses :: [MisoString]
, fieldAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor
defaultFieldProps :: FieldProps context model action
defaultFieldProps
= FieldProps
{ fieldId = Nothing
, fieldLabel = Nothing
, fieldDescription = Nothing
, fieldClasses = []
, fieldAttrs = []
}Displays a form input field or a component that looks like an input field.
-----------------------------------------------------------------------------
module MyInput (inputSample) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import Miso.UI.Input
-----------------------------------------------------------------------------
inputSample :: View context model action
inputSample =
H.div_
[ P.class_ "flex flex-col gap-y-4" ]
$ [ input_ defaultInputProps { inputPlaceholder = Just "Text" }
, input_ defaultInputProps { inputPlaceholder = Just "Disabled", inputDisabled = True }
, input_ defaultInputProps { inputPlaceholder = Just "Error", inputInvalid = True }
, input_ defaultInputProps { inputType = "email", inputPlaceholder = Just "Email" }
, input_ defaultInputProps { inputType = "password", inputPlaceholder = Just "Password" }
, input_ defaultInputProps { inputType = "number", inputPlaceholder = Just "Number" }
, input_ defaultInputProps { inputType = "file" }
, input_ defaultInputProps { inputType = "tel", inputPlaceholder = Just "Tel" }
, input_ defaultInputProps { inputType = "url", inputPlaceholder = Just "URL" }
, input_ defaultInputProps { inputType = "search", inputPlaceholder = Just "Search" }
] ++
[ input_ defaultInputProps { inputType = t }
| t <- [ "date", "datetime-local", "month", "week", "time" ]
]-- | Props for 'input_'
data InputProps model action
= InputProps
{ inputType :: MisoString
-- ^ @type@ attribute (@text@, @email@, @password@, @date@, ...)
, inputId :: Maybe MisoString
, inputPlaceholder :: Maybe MisoString
, inputValue :: Maybe MisoString
, inputDisabled :: Bool
, inputInvalid :: Bool
-- ^ Renders with @aria-invalid@ (error styling)
, inputClasses :: [MisoString]
-- ^ Extra classes appended to @input@
, inputAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor: text input, enabled, no placeholder
defaultInputProps :: InputProps model action
defaultInputProps
= InputProps
{ inputType = "text"
, inputId = Nothing
, inputPlaceholder = Nothing
, inputValue = Nothing
, inputDisabled = False
, inputInvalid = False
, inputClasses = []
, inputAttrs = []
}A control with pinned header and footer rows.
-----------------------------------------------------------------------------
module MyInputGroup (inputGroupUsage) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import qualified Miso.Svg as S
import qualified Miso.Svg.Property as SP
import Miso.UI.Button
import Miso.UI.Icons
import Miso.UI.Textarea
import Miso.UI.Types
import Miso.UI.InputGroup
-----------------------------------------------------------------------------
inputGroupUsage :: View context model action
inputGroupUsage =
inputGroup_ defaultInputGroupProps
{ inputGroupHeader =
[ H.span_
[ P.class_ "font-mono text-sm text-muted-foreground mr-auto" ]
[ "script.js" ]
]
, inputGroupFooter =
[ H.span_
[ P.class_ "text-sm text-muted-foreground mr-auto" ]
[ "Line 1, Column 1" ]
, button_ defaultButtonProps { buttonSize = Small } [ "Run" ]
]
}
[ textarea_ defaultTextareaProps
{ textareaPlaceholder = Just "console.log('Hello, world!')."
, textareaClasses = [ "pt-15", "pb-17", "min-h-77" ]
}
]-- | Props for 'inputGroup_'. Header and footer overlay the wrapped control.
data InputGroupProps context model action
= InputGroupProps
{ inputGroupHeader :: [View context model action]
-- ^ Content pinned to the top of the group
, inputGroupFooter :: [View context model action]
-- ^ Content pinned to the bottom of the group
, inputGroupClasses :: [MisoString]
, inputGroupAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor
defaultInputGroupProps :: InputGroupProps context model action
defaultInputGroupProps
= InputGroupProps
{ inputGroupHeader = []
, inputGroupFooter = []
, inputGroupClasses = []
, inputGroupAttrs = []
}Displays keyboard input or shortcuts.
-----------------------------------------------------------------------------
module MyKbd (kbdSample) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import Miso.UI.Kbd
-----------------------------------------------------------------------------
kbdSample :: View context model action
kbdSample =
H.div_
[ P.class_ "flex flex-col items-center gap-4" ]
[ kbdGroup_ []
[ kbd_ defaultKbdProps [ k ] | k <- [ "⌘", "⇧", "⌥", "⌃" ] ]
, kbdGroup_ []
[ kbd_ defaultKbdProps [ "Ctrl" ]
, H.span_ [] [ "+" ]
, kbd_ defaultKbdProps [ "B" ]
]
]-- | Props for 'kbd_'
data KbdProps model action
= KbdProps
{ kbdClasses :: [MisoString]
-- ^ Extra classes appended to @kbd@
, kbdAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor
defaultKbdProps :: KbdProps model action
defaultKbdProps
= KbdProps
{ kbdClasses = []
, kbdAttrs = []
}Renders an accessible label associated with controls.
-----------------------------------------------------------------------------
module MyLabel (labelSample) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import Miso.UI.Label
-----------------------------------------------------------------------------
labelSample :: View context model action
labelSample =
H.div_
[ P.class_ "grid w-full max-w-sm gap-6" ]
[ H.div_
[ P.class_ "flex items-center gap-3" ]
[ H.input_
[ P.class_ "input"
, P.id_ "label-demo-terms"
, P.type_ "checkbox"
]
, label_ defaultLabelProps { labelFor = Just "label-demo-terms" }
[ "Accept terms and conditions" ]
]
, H.div_
[ P.class_ "grid gap-3" ]
[ label_ defaultLabelProps { labelFor = Just "label-demo-text" } [ "Username" ]
, H.input_
[ P.placeholder_ "Username"
, P.class_ "input"
, P.id_ "label-demo-text"
, P.type_ "text"
]
]
, H.div_
[ P.class_ "grid gap-3" ]
[ label_ defaultLabelProps { labelFor = Just "label-demo-disabled" } [ "Disabled" ]
, H.input_
[ P.disabled_
, P.placeholder_ "Disabled"
, P.class_ "peer input"
, P.id_ "label-demo-disabled"
, P.type_ "text"
]
]
]-- | Props for 'label_'
data LabelProps model action
= LabelProps
{ labelFor :: Maybe MisoString
-- ^ @for@ attribute (id of the labelled control)
, labelClasses :: [MisoString]
-- ^ Extra classes appended to @label@
, labelAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor
defaultLabelProps :: LabelProps model action
defaultLabelProps
= LabelProps
{ labelFor = Nothing
, labelClasses = []
, labelAttrs = []
}Pagination with page navigation, next and previous links.
-----------------------------------------------------------------------------
module MyPagination (paginationSample) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import Miso.UI.Icons
import Miso.UI.Pagination
-----------------------------------------------------------------------------
paginationSample :: View context model action
paginationSample =
H.div_
[ P.class_ "inline-flex" ]
[ pagination_ defaultPaginationProps
[ paginationPrevious_ "#"
, paginationLink_ False "#" [ "1" ]
, paginationLink_ True "#" [ "2" ]
, paginationLink_ False "#" [ "3" ]
, paginationEllipsis_ "#"
, paginationNext_ "#"
]
]-- | Props for 'pagination_'
data PaginationProps model action
= PaginationProps
{ paginationClasses :: [MisoString]
-- ^ Extra classes appended to the @nav@
, paginationAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor
defaultPaginationProps :: PaginationProps model action
defaultPaginationProps
= PaginationProps
{ paginationClasses = []
, paginationAttrs = []
}Displays rich content in a portal, triggered by a button.
-----------------------------------------------------------------------------
module MyPopover (popoverSample) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import Miso.UI.Input
import Miso.UI.Label
import Miso.UI.Types
import Miso.UI.Popover
-----------------------------------------------------------------------------
popoverSample :: View context model action
popoverSample =
popover_ defaultPopoverProps
{ popoverId = "demo-popover"
, popoverTrigger = [ "Open popover" ]
}
[ H.div_
[ P.class_ "grid gap-4" ]
[ H.header_
[ P.class_ "grid gap-1.5" ]
[ H.h4_ [ P.class_ "leading-none font-medium" ] [ "Dimensions" ]
, H.p_ [ P.class_ "text-muted-foreground text-sm" ]
[ "Set the dimensions for the layer." ]
]
, H.form_
[ P.class_ "form grid gap-2" ]
[ dimension "demo-popover-width" "Width" "100%"
, dimension "demo-popover-max-width" "Max. width" "300px"
, dimension "demo-popover-height" "Height" "25px"
, dimension "demo-popover-max-height" "Max. height" "none"
]
]
]
where
dimension fieldId labelText val =
H.div_
[ P.class_ "grid grid-cols-3 items-center gap-4" ]
[ label_ defaultLabelProps { labelFor = Just fieldId } [ text labelText ]
, input_ defaultInputProps
{ inputId = Just fieldId
, inputValue = Just val
, inputClasses = [ "col-span-2", "h-8" ]
}
]-- | Props for 'popover_'
data PopoverProps context model action
= PopoverProps
{ popoverId :: MisoString
-- ^ Base id; trigger\/popover ids are derived from it (required)
, popoverTrigger :: [View context model action]
-- ^ Content of the trigger button (nests other views)
, popoverTriggerClasses :: [MisoString]
-- ^ Classes of the trigger button (defaults to @btn-outline@)
, popoverClasses :: [MisoString]
-- ^ Extra classes for the popover (e.g. @w-80@)
, popoverSide :: Side
-- ^ Placement side (@data-side@)
, popoverAlign :: Align
-- ^ Placement alignment (@data-align@)
, popoverAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor: outline trigger, bottom placement
defaultPopoverProps :: PopoverProps context model action
defaultPopoverProps
= PopoverProps
{ popoverId = "popover"
, popoverTrigger = []
, popoverTriggerClasses = [ "btn-outline" ]
, popoverClasses = [ "w-80" ]
, popoverSide = BottomSide
, popoverAlign = CenterAlign
, popoverAttrs = []
}Displays an indicator showing the completion progress of a task.
-----------------------------------------------------------------------------
module MyProgress (progressSample) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.CSS as CSS
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import qualified Miso.String as MS
import Miso.UI.Progress
-----------------------------------------------------------------------------
progressSample :: View context model action
progressSample =
H.div_
[ P.class_ "flex flex-col gap-4 max-w-sm" ]
[ progress_ defaultProgressProps { progressValue = 13 }
, progress_ defaultProgressProps { progressValue = 66 }
]-- | Props for 'progress_'
data ProgressProps model action
= ProgressProps
{ progressValue :: Int
-- ^ Percentage complete (0-100)
, progressClasses :: [MisoString]
-- ^ Extra classes appended to the track
, progressAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor: empty bar
defaultProgressProps :: ProgressProps model action
defaultProgressProps
= ProgressProps
{ progressValue = 0
, progressClasses = []
, progressAttrs = []
}A set of checkable buttons where only one can be checked at a time.
-----------------------------------------------------------------------------
module MyRadioGroup (radioGroupUsage) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import Miso.UI.RadioGroup
-----------------------------------------------------------------------------
radioGroupUsage :: View context model action
radioGroupUsage =
radioGroup_ defaultRadioGroupProps
[ radio_ defaultRadioProps { radioName = "my-group", radioValue = "default" }
[ "Default" ]
, radio_ defaultRadioProps
{ radioName = "my-group"
, radioValue = "comfortable"
, radioChecked = True
}
[ "Comfortable" ]
, radio_ defaultRadioProps
{ radioName = "my-group"
, radioValue = "compact"
, radioDisabled = True
}
[ "Compact" ]
]-- | Props for 'radioGroup_'
data RadioGroupProps model action
= RadioGroupProps
{ radioGroupClasses :: [MisoString]
-- ^ Extra classes appended to the @fieldset@
, radioGroupAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor
defaultRadioGroupProps :: RadioGroupProps model action
defaultRadioGroupProps
= RadioGroupProps
{ radioGroupClasses = []
, radioGroupAttrs = []
}
-----------------------------------------------------------------------------
-- | Props for a single 'radio_' inside a group
data RadioProps model action
= RadioProps
{ radioName :: MisoString
-- ^ Groups radios together (required)
, radioValue :: MisoString
, radioChecked :: Bool
, radioDisabled :: Bool
, radioClasses :: [MisoString]
-- ^ Extra classes appended to the @input@
, radioLabelClasses :: [MisoString]
-- ^ Extra classes appended to the wrapping @label@
, radioAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor: unchecked, enabled
defaultRadioProps :: RadioProps model action
defaultRadioProps
= RadioProps
{ radioName = "radio-group"
, radioValue = ""
, radioChecked = False
, radioDisabled = False
, radioClasses = []
, radioLabelClasses = []
, radioAttrs = []
}Displays a list of options for the user to pick from.
-----------------------------------------------------------------------------
module MySelect (selectUsage) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import Miso.UI.Icons
import Miso.UI.Select
-----------------------------------------------------------------------------
selectUsage :: View context model action
selectUsage =
H.div_
[ P.class_ "flex flex-wrap items-center gap-2" ]
[ select_ defaultSelectProps
[ H.optgroup_
[ P.label_ "Fruits" ]
[ H.option_ [] [ "Apple" ]
, H.option_ [] [ "Banana" ]
]
]
, selectMenu_ defaultSelectMenuProps
{ selectMenuId = "my-select"
, selectMenuLabel = [ "Blueberry" ]
, selectMenuValue = "blueberry"
}
[ selectOption_ False "apple" [ "Apple" ]
, selectOption_ True "blueberry" [ "Blueberry" ]
]
]-- | Props for the native 'select_'
data SelectProps model action
= SelectProps
{ selectId :: Maybe MisoString
, selectDisabled :: Bool
, selectClasses :: [MisoString]
-- ^ Extra classes appended to @select@ (e.g. @w-[180px]@)
, selectAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor for the native select
defaultSelectProps :: SelectProps model action
defaultSelectProps
= SelectProps
{ selectId = Nothing
, selectDisabled = False
, selectClasses = [ "w-[180px]" ]
, selectAttrs = []
}
-----------------------------------------------------------------------------
-- | Props for the popover-based 'selectMenu_' (basecoat JS select)
data SelectMenuProps context model action
= SelectMenuProps
{ selectMenuId :: MisoString
-- ^ Base id; trigger\/popover\/listbox ids are derived from it (required)
, selectMenuLabel :: [View context model action]
-- ^ Content of the trigger button (current selection)
, selectMenuValue :: MisoString
-- ^ Currently selected value (kept in a hidden input)
, selectMenuDisabled :: Bool
, selectMenuScrollable :: Bool
-- ^ Constrain the listbox height and scroll (@max-h-64@)
, selectMenuTriggerClasses :: [MisoString]
-- ^ Extra classes for the trigger button
, selectMenuAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor for the JS select
defaultSelectMenuProps :: SelectMenuProps context model action
defaultSelectMenuProps
= SelectMenuProps
{ selectMenuId = "select-menu"
, selectMenuLabel = []
, selectMenuValue = ""
, selectMenuDisabled = False
, selectMenuScrollable = False
, selectMenuTriggerClasses = [ "w-[180px]" ]
, selectMenuAttrs = []
}Use to show a placeholder while content is loading.
-----------------------------------------------------------------------------
module MySkeleton (skeletonSample) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import Miso.UI.Skeleton
-----------------------------------------------------------------------------
skeletonSample :: View context model action
skeletonSample =
H.div_
[ P.class_ "flex flex-col gap-4" ]
[ H.div_
[ P.class_ "flex items-center gap-4" ]
[ skeleton_ defaultSkeletonProps
{ skeletonCircle = True
, skeletonClasses = [ "size-10", "shrink-0" ]
}
, H.div_
[ P.class_ "grid gap-2" ]
[ skeleton_ defaultSkeletonProps { skeletonClasses = [ "h-4", "w-[150px]" ] }
, skeleton_ defaultSkeletonProps { skeletonClasses = [ "h-4", "w-[100px]" ] }
]
]
, H.div_
[ P.class_ "flex max-sm:flex-col gap-4 w-full" ]
[ skeletonCard, skeletonCard ]
]
where
skeletonCard =
H.div_
[ P.class_ "card w-full @md:w-auto @md:min-w-sm" ]
[ H.header_ []
[ skeleton_ defaultSkeletonProps { skeletonClasses = [ "h-4", "w-2/3" ] }
, skeleton_ defaultSkeletonProps { skeletonClasses = [ "h-4", "w-1/2" ] }
]
, H.section_ []
[ skeleton_ defaultSkeletonProps { skeletonClasses = [ "aspect-square", "w-full" ] }
]
]-- | Props for 'skeleton_'
data SkeletonProps model action
= SkeletonProps
{ skeletonCircle :: Bool
-- ^ Round skeleton (e.g. avatar placeholder) instead of rounded rectangle
, skeletonClasses :: [MisoString]
-- ^ Size the skeleton with utility classes (e.g. @h-4 w-[150px]@)
, skeletonAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor: rounded rectangle
defaultSkeletonProps :: SkeletonProps model action
defaultSkeletonProps
= SkeletonProps
{ skeletonCircle = False
, skeletonClasses = []
, skeletonAttrs = []
}An input where the user selects a value from within a given range.
-----------------------------------------------------------------------------
module MySlider (sliderSample) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.CSS as CSS
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import Miso.UI.Slider
-----------------------------------------------------------------------------
sliderSample
:: (DOMRef -> action)
-> (DOMRef -> action)
-> View context model action
sliderSample initSlider destroySlider =
H.div_
[ P.class_ "max-w-sm" ]
[ slider_ defaultSliderProps
{ sliderMax = "200"
, sliderValue = "150"
, sliderPercent = "75%"
, sliderAttrs =
[ onCreatedWith initSlider
, onBeforeDestroyedWith destroySlider
]
}
]-- | Props for 'slider_'
data SliderProps model action
= SliderProps
{ sliderMin :: MisoString
, sliderMax :: MisoString
, sliderStep :: MisoString
, sliderValue :: MisoString
, sliderPercent :: MisoString
-- ^ Initial track fill, sets the @--slider-value@ CSS variable (e.g. @\"75%\"@)
, sliderClasses :: [MisoString]
-- ^ Extra classes appended to the @input@
, sliderAttrs :: [Attribute model action]
-- ^ Extra attributes; basecoat's slider JS needs
-- @onCreatedWith@ \/ @onBeforeDestroyedWith@ hooks passed here
}
-----------------------------------------------------------------------------
-- | Smart constructor: 0-100, starts at 50
defaultSliderProps :: SliderProps model action
defaultSliderProps
= SliderProps
{ sliderMin = "0"
, sliderMax = "100"
, sliderStep = "1"
, sliderValue = "50"
, sliderPercent = "50%"
, sliderClasses = [ "w-full" ]
, sliderAttrs = []
}An indicator that can be used to show a loading state.
129 MB / 1000 MB
-----------------------------------------------------------------------------
module MySpinner (spinnerUsage) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import qualified Miso.Svg as S
import qualified Miso.Svg.Property as SP
import Miso.UI.Button
import Miso.UI.Icons
import Miso.UI.Progress
import Miso.UI.Types
import Miso.UI.Spinner
-----------------------------------------------------------------------------
spinnerUsage :: View context model action
spinnerUsage =
H.div_
[ P.class_ "flex items-center gap-4" ]
[ spinner_ defaultSpinnerProps
, spinner_ defaultSpinnerProps { spinnerClasses = [ "size-6" ] }
, spinner_ defaultSpinnerProps
{ spinnerClasses = [ "size-8", "text-muted-foreground" ] }
]-- | Props for 'spinner_'
data SpinnerProps model action
= SpinnerProps
{ spinnerLabel :: MisoString
-- ^ @aria-label@ for screen readers
, spinnerClasses :: [MisoString]
-- ^ Extra classes (e.g. @size-4@)
, spinnerAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor
defaultSpinnerProps :: SpinnerProps model action
defaultSpinnerProps
= SpinnerProps
{ spinnerLabel = "Loading"
, spinnerClasses = [ "size-4" ]
, spinnerAttrs = []
}A control that allows the user to toggle between on and off.
-----------------------------------------------------------------------------
module MySwitch (switchSample) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import Miso.UI.Switch
-----------------------------------------------------------------------------
switchSample :: View context model action
switchSample =
H.div_
[ P.class_ "inline-flex flex-col gap-y-6" ]
[ switch_ defaultSwitchProps [ "Airplane Mode" ]
, switch_ defaultSwitchProps
{ switchChecked = True
, switchClasses = [ "checked:bg-blue-500", "dark:checked:bg-blue-600" ]
}
[ "Bluetooth" ]
, H.label_
[ P.class_ "label gap-6 leading-none border rounded-lg p-4 has-[input[type='checkbox']:checked]:border-blue-600" ]
[ H.div_
[ P.class_ "grid gap-1" ]
[ H.h2_ [ P.class_ "font-medium text-sm" ] [ "Share across devices" ]
, H.p_
[ P.class_ "text-muted-foreground text-sm" ]
[ "Focus is shared across devices, and turns off when you leave the app." ]
]
, switchInput_ defaultSwitchProps
{ switchClasses = [ "checked:bg-blue-500", "dark:checked:bg-blue-600" ]
}
]
]-- | Props for 'switch_'
data SwitchProps model action
= SwitchProps
{ switchId :: Maybe MisoString
, switchName :: MisoString
, switchChecked :: Bool
, switchDisabled :: Bool
, switchClasses :: [MisoString]
-- ^ Extra classes appended to the @input@ (e.g. @checked:bg-blue-500@)
, switchLabelClasses :: [MisoString]
-- ^ Extra classes appended to the wrapping @label@
, switchAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor: unchecked, enabled
defaultSwitchProps :: SwitchProps model action
defaultSwitchProps
= SwitchProps
{ switchId = Nothing
, switchName = "switch"
, switchChecked = False
, switchDisabled = False
, switchClasses = []
, switchLabelClasses = []
, switchAttrs = []
}A responsive table component.
| Invoice | Status | Method | Amount |
|---|---|---|---|
| INV001 | Paid | Credit Card | $250.00 |
| INV002 | Pending | PayPal | $150.00 |
| INV003 | Unpaid | Bank Transfer | $350.00 |
| INV004 | Paid | Paypal | $450.00 |
| INV005 | Paid | Credit Card | $550.00 |
| INV006 | Pending | Bank Transfer | $200.00 |
| INV007 | Unpaid | Credit Card | $300.00 |
| Total | $2,500.00 | ||
-----------------------------------------------------------------------------
module MyTable (tableUsage) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import Miso.UI.Table
-----------------------------------------------------------------------------
tableUsage :: View context model action
tableUsage =
table_ defaultTableProps
[ H.caption_ [] [ "A list of your recent invoices." ]
, H.thead_ []
[ H.tr_ []
[ H.th_ [] [ "Invoice" ]
, H.th_ [] [ "Status" ]
, H.th_ [] [ "Amount" ]
]
]
, H.tbody_ []
[ H.tr_ []
[ H.td_ [ P.class_ "font-medium" ] [ "INV001" ]
, H.td_ [] [ "Paid" ]
, H.td_ [ P.class_ "text-right" ] [ "$250.00" ]
]
]
]-- | Props for 'table_'
data TableProps model action
= TableProps
{ tableClasses :: [MisoString]
-- ^ Extra classes appended to the @table@
, tableWrapperClasses :: [MisoString]
-- ^ Extra classes appended to the scrollable wrapper
, tableAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor
defaultTableProps :: TableProps model action
defaultTableProps
= TableProps
{ tableClasses = []
, tableWrapperClasses = []
, tableAttrs = []
}A set of layered sections of content displayed one at a time.
Make changes to your account here. Click save when you're done.
Change your password here. After saving, you'll be logged out.
-----------------------------------------------------------------------------
module MyTabs (tabsUsage) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.Html as H
import qualified Miso.Html.Property as P
import Miso.UI.Tabs
-----------------------------------------------------------------------------
tabsUsage :: View context model action
tabsUsage =
tabs_ defaultTabsProps { tabsId = "my-tabs" }
[ tabList_ []
[ tabButton_ defaultTabButtonProps
{ tabButtonId = "my-tabs-tab-1"
, tabButtonControls = "my-tabs-panel-1"
, tabButtonSelected = True
}
[ "Account" ]
, tabButton_ defaultTabButtonProps
{ tabButtonId = "my-tabs-tab-2"
, tabButtonControls = "my-tabs-panel-2"
}
[ "Password" ]
]
, tab_ defaultTabPanelProps
{ tabPanelId = "my-tabs-panel-1"
, tabPanelLabelledBy = "my-tabs-tab-1"
, tabPanelSelected = True
}
[ "Account panel" ]
, tab_ defaultTabPanelProps
{ tabPanelId = "my-tabs-panel-2"
, tabPanelLabelledBy = "my-tabs-tab-2"
}
[ "Password panel" ]
]-- | Props for 'tabs_'
data TabsProps model action
= TabsProps
{ tabsId :: MisoString
-- ^ id of the tabs root (basecoat JS keys off it; required)
, tabsClasses :: [MisoString]
-- ^ Extra classes appended to @div.tabs@
, tabsAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor
defaultTabsProps :: TabsProps model action
defaultTabsProps
= TabsProps
{ tabsId = "tabs"
, tabsClasses = [ "w-full" ]
, tabsAttrs = []
}
-----------------------------------------------------------------------------
-- | Props for 'tabButton_'
data TabButtonProps model action
= TabButtonProps
{ tabButtonId :: MisoString
-- ^ id of this tab button (matched by the panel's @aria-labelledby@)
, tabButtonControls :: MisoString
-- ^ id of the controlled panel
, tabButtonSelected :: Bool
, tabButtonDisabled :: Bool
, tabButtonAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor: unselected tab
defaultTabButtonProps :: TabButtonProps model action
defaultTabButtonProps
= TabButtonProps
{ tabButtonId = ""
, tabButtonControls = ""
, tabButtonSelected = False
, tabButtonDisabled = False
, tabButtonAttrs = []
}
-----------------------------------------------------------------------------
-- | Props for 'tab_' (a tab panel)
data TabPanelProps model action
= TabPanelProps
{ tabPanelId :: MisoString
-- ^ id of the panel (matched by the button's @aria-controls@)
, tabPanelLabelledBy :: MisoString
-- ^ id of the button labelling this panel
, tabPanelSelected :: Bool
, tabPanelAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor: hidden panel
defaultTabPanelProps :: TabPanelProps model action
defaultTabPanelProps
= TabPanelProps
{ tabPanelId = ""
, tabPanelLabelledBy = ""
, tabPanelSelected = False
, tabPanelAttrs = []
}Displays a form textarea or a component that looks like a textarea.
Type your message and press enter to send.
-----------------------------------------------------------------------------
module MyTextarea (textareaUsage) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import Miso.UI.Label
import Miso.UI.Textarea
-----------------------------------------------------------------------------
textareaUsage :: View context model action
textareaUsage =
H.div_
[ P.class_ "flex flex-col gap-y-6" ]
[ textarea_ defaultTextareaProps { textareaPlaceholder = Just "Type your message here" }
, textarea_ defaultTextareaProps
{ textareaPlaceholder = Just "Type your message here"
, textareaInvalid = True
}
, H.div_
[ P.class_ "grid gap-3" ]
[ label_ defaultLabelProps { labelFor = Just "my-textarea" } [ "Label" ]
, textarea_ defaultTextareaProps
{ textareaPlaceholder = Just "Type your message here"
, textareaId = Just "my-textarea"
}
]
]-- | Props for 'textarea_'
data TextareaProps model action
= TextareaProps
{ textareaId :: Maybe MisoString
, textareaPlaceholder :: Maybe MisoString
, textareaRows :: Maybe MisoString
, textareaDisabled :: Bool
, textareaInvalid :: Bool
-- ^ Renders with @aria-invalid@ (error styling)
, textareaClasses :: [MisoString]
-- ^ Extra classes appended to @textarea@
, textareaAttrs :: [Attribute model action]
}
-----------------------------------------------------------------------------
-- | Smart constructor: enabled, no placeholder
defaultTextareaProps :: TextareaProps model action
defaultTextareaProps
= TextareaProps
{ textareaId = Nothing
, textareaPlaceholder = Nothing
, textareaRows = Nothing
, textareaDisabled = False
, textareaInvalid = False
, textareaClasses = []
, textareaAttrs = []
}A succinct message that is displayed temporarily.
-----------------------------------------------------------------------------
module MyToast (toastSample) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.Html.Event as E
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import Miso.UI.Button
import Miso.UI.Types
import Miso.UI.Toast
-----------------------------------------------------------------------------
toastSample :: (ToastProps -> action) -> View context model action
toastSample toAction =
H.div_
[ P.class_ "flex flex-wrap items-center gap-2" ]
[ toastTrigger_ toAction
defaultToastProps
{ toastCategory = "success"
, toastTitle = "Success"
, toastDescription = "A successful toast !"
}
[ "Success" ]
, toastTrigger_ toAction
defaultToastProps
{ toastCategory = "error"
, toastTitle = "Error"
, toastDescription = "An error toast :("
}
[ "Error" ]
, toastTrigger_ toAction
defaultToastProps
{ toastCategory = "info"
, toastTitle = "Info"
, toastDescription = "An informational toast =]"
}
[ "Info" ]
, toastTrigger_ toAction
defaultToastProps
{ toastCategory = "warning"
, toastTitle = "Warning"
, toastDescription = "A warning toast :/"
}
[ "Warning" ]
]-- | Props describing a basecoat toast. Dispatched to basecoat's toaster JS
-- (a @basecoat:toast@ custom event) by the application's update function.
data ToastProps
= ToastProps
{ toastCategory :: MisoString
-- ^ @success@, @error@, @info@ or @warning@
, toastTitle :: MisoString
, toastDescription :: MisoString
, toastLabel :: MisoString
-- ^ Label of the dismiss button
} deriving (Show, Eq)
-----------------------------------------------------------------------------
-- | Smart constructor: informational toast
defaultToastProps :: ToastProps
defaultToastProps
= ToastProps
{ toastCategory = "info"
, toastTitle = ""
, toastDescription = ""
, toastLabel = "Dismiss"
}A popup that displays information related to an element on hover or focus.
-----------------------------------------------------------------------------
module MyTooltip (tooltipSample) where
-----------------------------------------------------------------------------
import Miso
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import Miso.UI.Button
import Miso.UI.Types
import Miso.UI.Tooltip
-----------------------------------------------------------------------------
tooltipSample :: View context model action
tooltipSample =
H.div_
[ P.class_ "flex flex-wrap items-center gap-4" ]
[ tooltip_ defaultTooltipProps { tooltipText = "Top tooltip" } [ "Top" ]
, tooltip_ defaultTooltipProps { tooltipText = "Right tooltip", tooltipSide = RightSide } [ "Right" ]
, tooltip_ defaultTooltipProps { tooltipText = "Bottom tooltip", tooltipSide = BottomSide } [ "Bottom" ]
, tooltip_ defaultTooltipProps { tooltipText = "Left tooltip", tooltipSide = LeftSide } [ "Left" ]
]-- | Props for 'tooltip_'
data TooltipProps model action
= TooltipProps
{ tooltipText :: MisoString
-- ^ Tooltip content (@data-tooltip@)
, tooltipSide :: Side
-- ^ Placement (@data-side@); 'TopSide' by default
, tooltipButton :: ButtonProps model action
-- ^ Props for the trigger button rendered by 'tooltip_'
}
-----------------------------------------------------------------------------
-- | Smart constructor: tooltip on top of an outline button
defaultTooltipProps :: TooltipProps model action
defaultTooltipProps
= TooltipProps
{ tooltipText = ""
, tooltipSide = TopSide
, tooltipButton = defaultButtonProps { buttonVariant = Outline }
}