Last active
April 5, 2025 19:57
-
-
Save dmjio/0851afa4898253cfa9d67fe323bd0f3a to your computer and use it in GitHub Desktop.
Tailwind Components DaisyUI Library and Miso integration, thanks to DeepSeek R1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE OverloadedStrings #-} | |
module DaisyUI where | |
import Miso | |
import Miso.String (MisoString, ms) | |
-- Action type for all component interactions | |
data Action | |
= ButtonClicked MisoString | |
| AccordionToggled Int | |
| AlertDismissed | |
| DropdownToggled | |
| ModalToggled Bool | |
| TabSelected Int | |
| NoOp | |
deriving (Show, Eq) | |
-- Model to track component states | |
data Model = Model | |
{ activeAccordionItem :: Maybe Int | |
, isDropdownOpen :: Bool | |
, isModalOpen :: Bool | |
, activeTab :: Int | |
} deriving (Show, Eq) | |
initialModel :: Model | |
initialModel = Model | |
{ activeAccordionItem = Nothing | |
, isDropdownOpen = False | |
, isModalOpen = False | |
, activeTab = 0 | |
} | |
-- Update function | |
update :: Action -> Model -> Effect Action Model | |
update action model = case action of | |
ButtonClicked btnId -> | |
noEff $ model { activeAccordionItem = Nothing } -- Example: reset accordion on button click | |
AccordionToggled idx -> | |
noEff $ model { activeAccordionItem = | |
if Just idx == activeAccordionItem model | |
then Nothing | |
else Just idx | |
} | |
AlertDismissed -> | |
noEff model -- Could add alert visibility to model | |
DropdownToggled -> | |
noEff $ model { isDropdownOpen = not (isDropdownOpen model) } | |
ModalToggled state -> | |
noEff $ model { isModalOpen = state } | |
TabSelected idx -> | |
noEff $ model { activeTab = idx } | |
NoOp -> | |
noEff model | |
-- Enhanced Button Component with click handler | |
button :: ButtonType -> ButtonSize -> ButtonShape -> Maybe ButtonState -> MisoString -> Action -> View Action | |
button btnType size shape state content onClick = | |
button_ | |
[ class_ $ ms $ "btn " <> buttonTypeClass btnType <> " " <> sizeClass size <> " " <> shapeClass shape <> " " <> stateClass state | |
, onClick onClick | |
] | |
[ text content ] | |
where | |
buttonTypeClass BtnPrimary = "btn-primary" | |
-- ... rest of buttonTypeClass as before | |
sizeClass BtnXs = "btn-xs" | |
-- ... rest of sizeClass as before | |
shapeClass BtnSquare = "btn-square" | |
-- ... rest of shapeClass as before | |
stateClass (Just BtnActive) = "btn-active" | |
-- ... rest of stateClass as before | |
-- Enhanced Accordion with toggling | |
accordion :: Model -> [AccordionItem] -> View Action | |
accordion model items = | |
div_ [ class_ "join join-vertical w-full" ] $ | |
map (\(i, item) -> | |
let isActive = activeAccordionItem model == Just i | |
in div_ [ class_ "collapse collapse-arrow join-item border border-base-300" ] [ | |
input_ | |
[ type_ "radio" | |
, name_ "my-accordion" | |
, checked_ isActive | |
, onClick (AccordionToggled i) | |
], | |
div_ [ class_ "collapse-title text-xl font-medium" ] [ | |
text (accordionTitle item) | |
], | |
div_ [ class_ "collapse-content" ] [ | |
accordionContent item | |
] | |
] | |
) (zip [0..] items) | |
-- Alert with dismiss button | |
alert :: AlertType -> View Action -> View Action | |
alert alertType content = | |
div_ [ class_ $ "alert " <> alertTypeClass alertType ] [ | |
content, | |
button_ | |
[ class_ "btn btn-sm" | |
, onClick AlertDismissed | |
] | |
[ text "×" ] | |
] | |
where | |
alertTypeClass AlertInfo = "alert-info" | |
-- ... rest of alertTypeClass as before | |
-- Dropdown with toggle action | |
dropdown :: Model -> MisoString -> [View Action] -> View Action | |
dropdown model title items = | |
div_ [ class_ "dropdown" ] [ | |
div_ | |
[ tabIndex_ "0" | |
, role_ "button" | |
, class_ "btn m-1" | |
, onClick DropdownToggled | |
] | |
[ text title ], | |
if isDropdownOpen model | |
then ul_ | |
[ tabIndex_ "0" | |
, class_ "dropdown-content z-[1] menu p-2 shadow bg-base-100 rounded-box w-52" | |
] | |
items | |
else noHtml | |
] | |
-- Modal with open/close controls | |
modal :: Model -> View Action -> View Action -> View Action | |
modal model title content = | |
div_ [ class_ $ if isModalOpen model then "modal modal-open" else "modal" ] [ | |
div_ [ class_ "modal-box" ] [ | |
h3_ [ class_ "font-bold text-lg" ] [ title ], | |
p_ [ class_ "py-4" ] [ content ], | |
div_ [ class_ "modal-action" ] [ | |
button BtnPrimary BtnMd BtnSquare Nothing "Close" (ModalToggled False) | |
] | |
] | |
] | |
-- Tabs with selection action | |
tabs :: Model -> [Tab] -> View Action | |
tabs model tabItems = | |
div_ [] [ | |
div_ [ class_ "tabs" ] $ | |
map (\(i, tab) -> | |
a_ | |
[ class_ $ "tab " <> if i == activeTab model then "tab-active" else "" | |
, onClick (TabSelected i) | |
] | |
[ text (tabName tab) ] | |
) (zip [0..] tabItems), | |
div_ [ class_ "tab-content" ] [ | |
tabContent (tabItems !! activeTab model) | |
] | |
] | |
-- Example view using all components | |
exampleView :: Model -> View Action | |
exampleView model = | |
div_ [ class_ "p-4" ] [ | |
h1_ [ class_ "text-2xl font-bold mb-4" ] [ text "DaisyUI Components in Miso" ], | |
-- Button example | |
div_ [ class_ "mb-8" ] [ | |
h2_ [ class_ "text-xl mb-2" ] [ text "Buttons" ], | |
button BtnPrimary BtnMd BtnSquare Nothing "Primary Button" (ButtonClicked "primary"), | |
button BtnSecondary BtnSm BtnCircle Nothing "Secondary" (ButtonClicked "secondary") | |
], | |
-- Accordion example | |
div_ [ class_ "mb-8" ] [ | |
h2_ [ class_ "text-xl mb-2" ] [ text "Accordion" ], | |
accordion model [ | |
AccordionItem "First Item" (text "Content for first item"), | |
AccordionItem "Second Item" (text "Content for second item") | |
] | |
], | |
-- Alert example | |
div_ [ class_ "mb-8" ] [ | |
h2_ [ class_ "text-xl mb-2" ] [ text "Alert" ], | |
alert AlertInfo (text "This is an info alert with dismiss button") | |
], | |
-- Dropdown example | |
div_ [ class_ "mb-8" ] [ | |
h2_ [ class_ "text-xl mb-2" ] [ text "Dropdown" ], | |
dropdown model "Dropdown Menu" [ | |
li_ [] [ a_ [] [ text "Item 1" ] ], | |
li_ [] [ a_ [] [ text "Item 2" ] ] | |
] | |
], | |
-- Modal example | |
div_ [ class_ "mb-8" ] [ | |
h2_ [ class_ "text-xl mb-2" ] [ text "Modal" ], | |
button BtnPrimary BtnMd BtnSquare Nothing "Open Modal" (ModalToggled True), | |
modal model (text "Modal Title") (text "Modal content goes here") | |
], | |
-- Tabs example | |
div_ [ class_ "mb-8" ] [ | |
h2_ [ class_ "text-xl mb-2" ] [ text "Tabs" ], | |
tabs model [ | |
Tab "Tab 1" (text "Content for Tab 1") True, | |
Tab "Tab 2" (text "Content for Tab 2") False | |
] | |
] | |
] | |
-- App setup | |
app :: App Model Action | |
app = App | |
{ initialAction = NoOp | |
, model = initialModel | |
, update = update | |
, view = exampleView | |
, subs = [] | |
, events = defaultEvents | |
, mountPoint = Nothing | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment