fix: update to correct NeoBrutalismCSS CDN and class names

- Switch CDN to jsdelivr (matches design spec)
- Use nb-card, nb-card-title, nb-button default, nb-checkbox, nb-navbar-link
- Add Google Fonts import for Lexend Mega
- Style all route links as nb-button default buttons
- Fix navbar to use nb-navbar-brand and nb-navbar-nav
- Update style.css for new NB version compatibility
This commit is contained in:
2026-07-16 07:34:45 -04:00
parent e8036bab11
commit 95ac550191
9 changed files with 98 additions and 85 deletions
+16 -13
View File
@@ -16,42 +16,45 @@ body {
padding: 0; padding: 0;
} }
/* Override NB navbar to have drop shadow like our design */
.nb-navbar { .nb-navbar {
background: #fff;
border-bottom: 3px solid #000;
padding: 0.75rem 1.5rem;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: 4px 4px 0 #000; box-shadow: 4px 4px 0 #000;
margin-bottom: 2rem; margin-bottom: 2rem;
} }
.nb-navbar-start, .nb-navbar-end { /* List items with subtle dividers */
display: flex;
align-items: center;
gap: 0.5rem;
}
.nb-list-item { .nb-list-item {
border-bottom: 1px solid rgba(0,0,0,0.1); border-bottom: 1px solid rgba(0,0,0,0.1);
padding: 0.5rem;
} }
.nb-list-item:last-child { .nb-list-item:last-child {
border-bottom: none; border-bottom: none;
} }
/* Stat tiles */
.stat-tile {
text-align: center;
padding: 1rem;
}
/* Container padding */
.nb-container {
padding: 0 1rem;
}
@keyframes fadeIn { @keyframes fadeIn {
from { opacity: 0; } from { opacity: 0; }
to { opacity: 1; } to { opacity: 1; }
} }
/* Responsive */
@media (max-width: 768px) { @media (max-width: 768px) {
.nb-navbar { .nb-navbar {
flex-direction: column; flex-direction: column;
gap: 0.5rem; gap: 0.5rem;
padding: 0.5rem; padding: 0.5rem;
} }
.nb-navbar-end { .nb-navbar-nav {
flex-wrap: wrap; flex-wrap: wrap;
justify-content: center; justify-content: center;
} }
+4 -4
View File
@@ -17,7 +17,7 @@ import Effectful
import Sis.Database import Sis.Database
import Sis.Route import Sis.Route
import Sis.Style import Sis.Style (nbBoxClass, nbButtonDefaultClass, nbInputClass, nbLabelClass, nbBadgeClass, nbHeadingClass, nbContainerClass, nbListItemClass, colorRed, colorYellow, colorGreen)
import Sis.Types import Sis.Types
import Sis.View.Layout import Sis.View.Layout
import Web.Hyperbole import Web.Hyperbole
@@ -52,7 +52,7 @@ instance (DB :> es, IOE :> es) => HyperView ActivityPage es where
activityView :: ActivityLogPage -> View ActivityPage () activityView :: ActivityLogPage -> View ActivityPage ()
activityView log = do activityView log = do
el @ att "class" nbContainerClass @ att "style" "max-width:960px;margin:0 auto" $ do el @ att "class" nbContainerClass @ att "style" "max-width:960px;margin:0 auto" $ do
el @ att "class" nbFontHeading1Class $ text "Activity Log" el @ att "class" nbHeadingClass $ text "Activity Log"
if null (alpEntries log) if null (alpEntries log)
then el @ att "style" "opacity:0.5" $ text "No activity recorded yet." then el @ att "style" "opacity:0.5" $ text "No activity recorded yet."
else el @ att "class" nbBoxClass $ mapM_ entryRow (alpEntries log) else el @ att "class" nbBoxClass $ mapM_ entryRow (alpEntries log)
@@ -60,12 +60,12 @@ activityView log = do
then el @ att "style" "margin-top:1rem;display:flex;gap:0.5rem;justify-content:center" $ do then el @ att "style" "margin-top:1rem;display:flex;gap:0.5rem;justify-content:center" $ do
let totalPages = (alpTotal log + alpPerPage log - 1) `div` alpPerPage log let totalPages = (alpTotal log + alpPerPage log - 1) `div` alpPerPage log
if alpPage log > 1 if alpPage log > 1
then button (GoToPage (alpPage log - 1)) @ att "class" nbButtonClass $ text "Previous" then button (GoToPage (alpPage log - 1)) @ att "class" nbButtonDefaultClass $ text "Previous"
else none else none
el @ att "style" "align-self:center" $ el @ att "style" "align-self:center" $
text ("Page " <> T.pack (show (alpPage log)) <> " of " <> T.pack (show totalPages)) text ("Page " <> T.pack (show (alpPage log)) <> " of " <> T.pack (show totalPages))
if alpPage log < totalPages if alpPage log < totalPages
then button (GoToPage (alpPage log + 1)) @ att "class" nbButtonClass $ text "Next" then button (GoToPage (alpPage log + 1)) @ att "class" nbButtonDefaultClass $ text "Next"
else none else none
else none else none
+5 -5
View File
@@ -18,7 +18,7 @@ import Effectful
import Sis.Database import Sis.Database
import Sis.Route import Sis.Route
import Sis.Style import Sis.Style (nbBoxClass, nbButtonDefaultClass, nbInputClass, nbLabelClass, nbBadgeClass, nbHeadingClass, nbContainerClass, nbListItemClass, colorRed, colorYellow, colorGreen)
import Sis.Types import Sis.Types
import Sis.View.Layout import Sis.View.Layout
import Web.Hyperbole import Web.Hyperbole
@@ -59,8 +59,8 @@ choresView :: [Chore] -> View ChoresPage ()
choresView chores' = do choresView chores' = do
el @ att "class" nbContainerClass @ att "style" "max-width:960px;margin:0 auto" $ do el @ att "class" nbContainerClass @ att "style" "max-width:960px;margin:0 auto" $ do
el @ att "style" "display:flex;justify-content:space-between;align-items:center;margin-bottom:1rem" $ do el @ att "style" "display:flex;justify-content:space-between;align-items:center;margin-bottom:1rem" $ do
el @ att "class" nbFontHeading1Class $ text "Chores" el @ att "class" nbHeadingClass $ text "Chores"
button CNewChore @ att "class" nbButtonClass $ text "+ New Chore" button CNewChore @ att "class" nbButtonDefaultClass $ text "+ New Chore"
if null chores' if null chores'
then el @ att "style" "opacity:0.5" $ text "No chores yet. Create one to get started!" then el @ att "style" "opacity:0.5" $ text "No chores yet. Create one to get started!"
else el @ att "class" nbBoxClass $ mapM_ choreRow chores' else el @ att "class" nbBoxClass $ mapM_ choreRow chores'
@@ -73,8 +73,8 @@ choreRow c = do
el @ att "style" "font-weight:500" $ text (choreName c) el @ att "style" "font-weight:500" $ text (choreName c)
el @ att "style" "opacity:0.5;font-size:0.85rem" $ text (scheduleLabel (choreSchedule c)) el @ att "style" "opacity:0.5;font-size:0.85rem" $ text (scheduleLabel (choreSchedule c))
el @ att "style" "display:flex;gap:0.25rem" $ do el @ att "style" "display:flex;gap:0.25rem" $ do
button CNewChore @ att "class" nbButtonClass @ att "style" "font-size:0.8rem;padding:0.25rem 0.5rem" $ text "Edit" button CNewChore @ att "class" nbButtonDefaultClass @ att "style" "font-size:0.8rem;padding:0.25rem 0.5rem" $ text "Edit"
button (CDeleteChore (choreId c)) @ att "class" nbButtonClass @ att "style" "font-size:0.8rem;padding:0.25rem 0.5rem;background:var(--nb-red)" $ text "Delete" button (CDeleteChore (choreId c)) @ att "class" nbButtonDefaultClass @ att "style" "font-size:0.8rem;padding:0.25rem 0.5rem;background:var(--nb-red)" $ text "Delete"
scheduleBadge :: Schedule -> Text scheduleBadge :: Schedule -> Text
scheduleBadge ScheduleSometime{} = "sometime" scheduleBadge ScheduleSometime{} = "sometime"
+7 -7
View File
@@ -19,7 +19,7 @@ import Effectful
import Sis.Database import Sis.Database
import Sis.Route import Sis.Route
import Sis.Style import Sis.Style (nbBoxClass, nbButtonDefaultClass, nbInputClass, nbLabelClass, nbBadgeClass, nbHeadingClass, nbContainerClass, nbListItemClass, colorRed, colorYellow, colorGreen)
import Sis.Types import Sis.Types
import Sis.View.Layout import Sis.View.Layout
import Web.Hyperbole import Web.Hyperbole
@@ -56,27 +56,27 @@ instance (DB :> es, IOE :> es) => HyperView DashboardPage es where
dashboardView :: Dashboard -> View DashboardPage () dashboardView :: Dashboard -> View DashboardPage ()
dashboardView dash = do dashboardView dash = do
el @ att "class" nbContainerClass @ att "style" "max-width:960px;margin:0 auto" $ do el @ att "class" nbContainerClass @ att "style" "max-width:960px;margin:0 auto" $ do
el @ att "class" nbFontHeading1Class $ text "Dashboard" el @ att "class" nbHeadingClass $ text "Dashboard"
el @ att "style" "display:flex;gap:1rem;margin-bottom:1.5rem" $ do el @ att "style" "display:flex;gap:1rem;margin-bottom:1.5rem" $ do
let stats = dashStats dash let stats = dashStats dash
statTile "Overdue" (T.pack (show (dsOverdue stats))) colorRed statTile "Overdue" (T.pack (show (dsOverdue stats))) colorRed
statTile "Due Today" (T.pack (show (dsDueToday stats))) colorYellow statTile "Due Today" (T.pack (show (dsDueToday stats))) colorYellow
statTile "Done This Week" (T.pack (show (dsDoneThisWeek stats))) colorGreen statTile "Done This Week" (T.pack (show (dsDoneThisWeek stats))) colorGreen
el @ att "class" nbFontHeading2Class $ text "Overdue & Due Today" el @ att "class" nbHeadingClass $ text "Overdue & Due Today"
if null (dashDueItems dash) if null (dashDueItems dash)
then el @ att "style" "opacity:0.5" $ text "Nothing due! Great job." then el @ att "style" "opacity:0.5" $ text "Nothing due! Great job."
else el @ att "class" nbBoxClass $ do else el @ att "class" nbBoxClass $ do
mapM_ dueItemRow (dashDueItems dash) mapM_ dueItemRow (dashDueItems dash)
el @ att "class" nbFontHeading2Class $ text "Completed Today" el @ att "class" nbHeadingClass $ text "Completed Today"
if null (dashCompletedItems dash) if null (dashCompletedItems dash)
then el @ att "style" "opacity:0.5" $ text "No activity recorded today." then el @ att "style" "opacity:0.5" $ text "No activity recorded today."
else el @ att "class" nbBoxClass $ mapM_ completedItemRow (dashCompletedItems dash) else el @ att "class" nbBoxClass $ mapM_ completedItemRow (dashCompletedItems dash)
route RActivity $ text "View Full Activity Log" route RActivity @ att "class" nbButtonDefaultClass $ text "View Full Activity Log"
statTile :: Text -> Text -> Text -> View ctx () statTile :: Text -> Text -> Text -> View ctx ()
statTile label count color = do statTile label count color = do
el @ att "class" nbBoxClass @ att "style" ("flex:1;text-align:center;padding:1rem;border-color:" <> color) $ do el @ att "class" nbBoxClass @ att "style" ("flex:1;text-align:center;padding:1rem;border-color:" <> color) $ do
el @ att "class" nbFontHeading1Class $ text count el @ att "class" nbHeadingClass $ text count
text label text label
dueItemRow :: DueItem -> View DashboardPage () dueItemRow :: DueItem -> View DashboardPage ()
@@ -90,7 +90,7 @@ dueItemRow di = do
case diAssigneeName di of case diAssigneeName di of
Just name -> el @ att "style" "opacity:0.5" $ text ("(" <> name <> ")") Just name -> el @ att "style" "opacity:0.5" $ text ("(" <> name <> ")")
Nothing -> none Nothing -> none
button (CheckOff (occurrenceId (diOccurrence di))) @ att "class" nbButtonClass @ att "style" "font-size:0.85rem" $ text "Check Off" button (CheckOff (occurrenceId (diOccurrence di))) @ att "class" nbButtonDefaultClass @ att "style" "font-size:0.85rem" $ text "Check Off"
completedItemRow :: CompletedItem -> View DashboardPage () completedItemRow :: CompletedItem -> View DashboardPage ()
completedItemRow ci = do completedItemRow ci = do
+8 -8
View File
@@ -17,7 +17,7 @@ import Effectful
import Sis.Database import Sis.Database
import Sis.Route import Sis.Route
import Sis.Style import Sis.Style (nbBoxClass, nbButtonDefaultClass, nbInputClass, nbLabelClass, nbBadgeClass, nbHeadingClass, nbContainerClass, nbListItemClass, colorRed, colorYellow, colorGreen)
import Sis.Types import Sis.Types
import Sis.View.Layout import Sis.View.Layout
import Web.Hyperbole import Web.Hyperbole
@@ -69,7 +69,7 @@ noHouseholdView :: View HouseholdPage ()
noHouseholdView = do noHouseholdView = do
el @ att "class" nbContainerClass @ att "style" "max-width:480px;margin:4rem auto" $ do el @ att "class" nbContainerClass @ att "style" "max-width:480px;margin:4rem auto" $ do
el @ att "class" nbBoxClass @ att "style" "padding:2rem;text-align:center" $ do el @ att "class" nbBoxClass @ att "style" "padding:2rem;text-align:center" $ do
el @ att "class" nbFontHeading1Class $ text "Create Your Household" el @ att "class" nbHeadingClass $ text "Create Your Household"
el @ att "style" "margin-bottom:1rem" $ text "You need a household to get started." el @ att "style" "margin-bottom:1rem" $ text "You need a household to get started."
-- Form for household creation would go here -- Form for household creation would go here
el $ text "Household creation form coming soon" el $ text "Household creation form coming soon"
@@ -77,18 +77,18 @@ noHouseholdView = do
householdView :: Household -> [Membership] -> [Invite] -> View HouseholdPage () householdView :: Household -> [Membership] -> [Invite] -> View HouseholdPage ()
householdView h mems invs = do householdView h mems invs = do
el @ att "class" nbContainerClass @ att "style" "max-width:960px;margin:0 auto" $ do el @ att "class" nbContainerClass @ att "style" "max-width:960px;margin:0 auto" $ do
el @ att "class" nbFontHeading1Class $ text (householdName h) el @ att "class" nbHeadingClass $ text (householdName h)
el @ att "style" "opacity:0.7" $ text (T.pack (show (length mems)) <> " members") el @ att "style" "opacity:0.7" $ text (T.pack (show (length mems)) <> " members")
el @ att "class" nbFontHeading2Class $ text "Members" el @ att "class" nbHeadingClass $ text "Members"
el @ att "class" nbBoxClass @ att "style" "margin-bottom:1.5rem" $ mapM_ memberRow mems el @ att "class" nbBoxClass @ att "style" "margin-bottom:1.5rem" $ mapM_ memberRow mems
el @ att "class" nbFontHeading2Class $ text "Invite Members" el @ att "class" nbHeadingClass $ text "Invite Members"
el @ att "class" nbBoxClass $ do el @ att "class" nbBoxClass $ do
el @ att "style" "margin-bottom:0.5rem" $ text "Create an invite link to share:" el @ att "style" "margin-bottom:0.5rem" $ text "Create an invite link to share:"
button CreateInviteAction @ att "class" nbButtonClass $ text "+ Create Invite Link" button CreateInviteAction @ att "class" nbButtonDefaultClass $ text "+ Create Invite Link"
if null invs if null invs
then none then none
else el @ att "style" "margin-top:1rem" $ do else el @ att "style" "margin-top:1rem" $ do
el @ att "class" nbFontHeading2Class $ text "Pending Invites" el @ att "class" nbHeadingClass $ text "Pending Invites"
mapM_ inviteRow (filter ((== InvitePending) . inviteStatus) invs) mapM_ inviteRow (filter ((== InvitePending) . inviteStatus) invs)
memberRow :: Membership -> View HouseholdPage () memberRow :: Membership -> View HouseholdPage ()
@@ -106,7 +106,7 @@ inviteRow :: Invite -> View HouseholdPage ()
inviteRow i = do inviteRow i = do
el @ att "class" nbListItemClass @ att "style" "display:flex;justify-content:space-between;padding:0.5rem" $ do el @ att "class" nbListItemClass @ att "style" "display:flex;justify-content:space-between;padding:0.5rem" $ do
el @ att "style" "font-size:0.85rem" $ text ("/invite/" <> inviteCode i) el @ att "style" "font-size:0.85rem" $ text ("/invite/" <> inviteCode i)
button (RevokeInviteAction (inviteId i)) @ att "class" nbButtonClass @ att "style" "font-size:0.8rem;background:var(--nb-red)" $ button (RevokeInviteAction (inviteId i)) @ att "class" nbButtonDefaultClass @ att "style" "font-size:0.8rem;background:var(--nb-red)" $
text "Revoke" text "Revoke"
initials :: Text -> Text initials :: Text -> Text
+9 -8
View File
@@ -17,7 +17,7 @@ import Effectful
import Sis.Auth (generateToken, hashPassword, verifyPassword) import Sis.Auth (generateToken, hashPassword, verifyPassword)
import Sis.Database import Sis.Database
import Sis.Route import Sis.Route
import Sis.Style import Sis.Style (nbBoxClass, nbButtonDefaultClass, nbInputClass, nbLabelClass, nbBadgeClass, nbHeadingClass, nbContainerClass, nbListItemClass, colorRed, colorYellow, colorGreen)
import Sis.Types import Sis.Types
import Sis.View.Layout import Sis.View.Layout
import Web.Hyperbole import Web.Hyperbole
@@ -49,15 +49,15 @@ loginSuccessView :: View LoginPage ()
loginSuccessView = do loginSuccessView = do
el @ att "class" nbContainerClass @ att "style" "max-width:480px;margin:4rem auto;text-align:center" $ do el @ att "class" nbContainerClass @ att "style" "max-width:480px;margin:4rem auto;text-align:center" $ do
el @ att "class" nbBoxClass @ att "style" "padding:2rem" $ do el @ att "class" nbBoxClass @ att "style" "padding:2rem" $ do
el @ att "class" nbFontHeading1Class $ text "Logged In!" el @ att "class" nbHeadingClass $ text "Logged In!"
el @ att "style" "margin-top:1rem;margin-bottom:1rem" $ text "You are now logged in." el @ att "style" "margin-top:1rem;margin-bottom:1rem" $ text "You are now logged in."
route RDashboard $ text "Go to Dashboard" route RDashboard @ att "class" nbButtonDefaultClass $ text "Go to Dashboard"
loginView :: Maybe Text -> View LoginPage () loginView :: Maybe Text -> View LoginPage ()
loginView mError = do loginView mError = do
el @ att "class" nbContainerClass @ att "style" "max-width:480px;margin:4rem auto" $ do el @ att "class" nbContainerClass @ att "style" "max-width:480px;margin:4rem auto" $ do
el @ att "class" nbBoxClass @ att "style" "padding:2rem" $ do el @ att "class" nbBoxClass @ att "style" "padding:2rem" $ do
el @ att "class" nbFontHeading1Class $ text "Welcome Back" el @ att "class" nbHeadingClass $ text "Welcome Back"
el @ att "style" "opacity:0.7;margin-bottom:1.5rem" $ text "Log in to manage your household chores." el @ att "style" "opacity:0.7;margin-bottom:1.5rem" $ text "Log in to manage your household chores."
case mError of case mError of
Just err -> Just err ->
@@ -69,10 +69,11 @@ loginView mError = do
el @ att "class" nbLabelClass $ text "Password" el @ att "class" nbLabelClass $ text "Password"
tag "input" @ att "type" "password" . att "name" "lfPassword" . att "class" nbInputClass @ att "style" "width:100%" $ none tag "input" @ att "type" "password" . att "name" "lfPassword" . att "class" nbInputClass @ att "style" "width:100%" $ none
el @ att "style" "display:flex;align-items:center;gap:0.5rem;margin-bottom:1rem" $ do el @ att "style" "display:flex;align-items:center;gap:0.5rem;margin-bottom:1rem" $ do
tag "input" @ att "type" "checkbox" . att "name" "lfRemember" $ none tag "input" @ att "type" "checkbox" . att "name" "lfRemember" . att "class" "nb-checkbox" $ none
text "Remember me" el @ att "class" nbLabelClass $ text "Remember me"
submit (text "Log In") @ att "class" nbButtonClass @ att "style" "width:100%" submit (text "Log In") @ att "class" nbButtonDefaultClass @ att "style" "width:100%"
route RSignup $ text "Don't have an account? Sign Up" el @ att "style" "margin-top:1rem;text-align:center" $ do
route RSignup @ att "class" nbButtonDefaultClass $ text "Sign Up"
page :: (Hyperbole :> es, DB :> es, IOE :> es) => Page es '[LoginPage] page :: (Hyperbole :> es, DB :> es, IOE :> es) => Page es '[LoginPage]
page = do page = do
mSession <- lookupSession @UserSession mSession <- lookupSession @UserSession
+8 -8
View File
@@ -18,7 +18,7 @@ import Effectful
import Sis.Auth (generateToken, hashPassword, verifyPassword) import Sis.Auth (generateToken, hashPassword, verifyPassword)
import Sis.Database import Sis.Database
import Sis.Route import Sis.Route
import Sis.Style import Sis.Style (nbBoxClass, nbButtonDefaultClass, nbInputClass, nbLabelClass, nbBadgeClass, nbHeadingClass, nbContainerClass, nbListItemClass, colorRed, colorYellow, colorGreen)
import Sis.Types import Sis.Types
import Sis.View.Layout import Sis.View.Layout
import Web.Hyperbole import Web.Hyperbole
@@ -55,15 +55,15 @@ signupSuccessView :: View SignupPage ()
signupSuccessView = do signupSuccessView = do
el @ att "class" nbContainerClass @ att "style" "max-width:480px;margin:4rem auto;text-align:center" $ do el @ att "class" nbContainerClass @ att "style" "max-width:480px;margin:4rem auto;text-align:center" $ do
el @ att "class" nbBoxClass @ att "style" "padding:2rem" $ do el @ att "class" nbBoxClass @ att "style" "padding:2rem" $ do
el @ att "class" nbFontHeading1Class $ text "Account Created!" el @ att "class" nbHeadingClass $ text "Account Created!"
el @ att "style" "margin-top:1rem;margin-bottom:1rem" $ text "Your account has been created." el @ att "style" "margin-top:1rem;margin-bottom:1rem" $ text "Your account has been created."
route RDashboard $ text "Go to Dashboard" route RDashboard @ att "class" nbButtonDefaultClass $ text "Go to Dashboard"
signupView :: Maybe Text -> View SignupPage () signupView :: Maybe Text -> View SignupPage ()
signupView mError = do signupView mError = do
el @ att "class" nbContainerClass @ att "style" "max-width:480px;margin:4rem auto" $ do el @ att "class" nbContainerClass @ att "style" "max-width:480px;margin:4rem auto" $ do
el @ att "class" nbBoxClass @ att "style" "padding:2rem" $ do el @ att "class" nbBoxClass @ att "style" "padding:2rem" $ do
el @ att "class" nbFontHeading1Class $ text "Create Account" el @ att "class" nbHeadingClass $ text "Create Account"
el @ att "style" "opacity:0.7;margin-bottom:1.5rem" $ text "Join your household chore tracker." el @ att "style" "opacity:0.7;margin-bottom:1.5rem" $ text "Join your household chore tracker."
case mError of case mError of
Just err -> Just err ->
@@ -79,10 +79,10 @@ signupView mError = do
el @ att "class" nbLabelClass $ text "Confirm Password" el @ att "class" nbLabelClass $ text "Confirm Password"
tag "input" @ att "type" "password" . att "name" "sfConfirm" . att "class" nbInputClass @ att "style" "width:100%" $ none tag "input" @ att "type" "password" . att "name" "sfConfirm" . att "class" nbInputClass @ att "style" "width:100%" $ none
el @ att "style" "display:flex;align-items:center;gap:0.5rem;margin-bottom:1rem" $ do el @ att "style" "display:flex;align-items:center;gap:0.5rem;margin-bottom:1rem" $ do
tag "input" @ att "type" "checkbox" . att "name" "sfAgree" $ none tag "input" @ att "type" "checkbox" . att "name" "sfAgree" . att "class" "nb-checkbox" $ none
text "I agree to the terms of service" el @ att "class" nbLabelClass $ text "I agree to the terms of service"
submit (text "Sign Up") @ att "class" nbButtonClass @ att "style" "width:100%" submit (text "Sign Up") @ att "class" nbButtonDefaultClass @ att "style" "width:100%"
route RLogin $ text "Already have an account? Log In" route RLogin @ att "class" nbButtonDefaultClass $ text "Log In"
page :: (Hyperbole :> es, DB :> es, IOE :> es) => Page es '[SignupPage] page :: (Hyperbole :> es, DB :> es, IOE :> es) => Page es '[SignupPage]
page = do page = do
mSession <- lookupSession @UserSession mSession <- lookupSession @UserSession
+32 -26
View File
@@ -1,42 +1,48 @@
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
{- | Neo Brutalism CSS class name constants for Hyperbole views. -- | Neo Brutalism CSS class name constants for Hyperbole views.
Use with: \@ att \"class\" nbBoxClass -- Based on https://github.com/matifandy8/NeoBrutalismCSS
-} module Sis.Style
module Sis.Style ( ( nbBoxClass, nbButtonDefaultClass, nbInputClass, nbLabelClass
nbBoxClass, , nbBadgeClass, nbHeadingClass
nbButtonClass, , nbNavbarClass, nbNavbarLinkClass, nbContainerClass, nbListItemClass
nbInputClass, , colorRed, colorYellow, colorGreen
nbLabelClass, ) where
nbBadgeClass,
nbFontHeading1Class,
nbFontHeading2Class,
nbNavbarClass,
nbContainerClass,
nbListItemClass,
colorRed,
colorYellow,
colorGreen,
) where
import Data.Text (Text) import Data.Text (Text)
nbBoxClass, nbButtonClass, nbInputClass, nbLabelClass, nbBadgeClass :: Text -- Box/panel
nbBoxClass = "nb-box" nbBoxClass :: Text
nbButtonClass = "nb-button" nbBoxClass = "nb-card"
-- Button (default variant: black border, white bg)
nbButtonDefaultClass :: Text
nbButtonDefaultClass = "nb-button default"
-- Form elements
nbInputClass, nbLabelClass :: Text
nbInputClass = "nb-input" nbInputClass = "nb-input"
nbLabelClass = "nb-label" nbLabelClass = "nb-label"
nbBadgeClass = "nb-badge"
nbFontHeading1Class, nbFontHeading2Class :: Text -- Badge/pill (inline label)
nbFontHeading1Class = "nb-font-heading1" nbBadgeClass :: Text
nbFontHeading2Class = "nb-font-heading2" nbBadgeClass = "nb-button default"
nbNavbarClass, nbContainerClass, nbListItemClass :: Text -- Heading
nbHeadingClass :: Text
nbHeadingClass = "nb-card-title"
-- Navbar
nbNavbarClass, nbNavbarLinkClass :: Text
nbNavbarClass = "nb-navbar" nbNavbarClass = "nb-navbar"
nbNavbarLinkClass = "nb-navbar-link"
-- Layout
nbContainerClass, nbListItemClass :: Text
nbContainerClass = "nb-container" nbContainerClass = "nb-container"
nbListItemClass = "nb-list-item" nbListItemClass = "nb-list-item"
-- CSS color variables
colorRed, colorYellow, colorGreen :: Text colorRed, colorYellow, colorGreen :: Text
colorRed = "var(--nb-red)" colorRed = "var(--nb-red)"
colorYellow = "var(--nb-yellow)" colorYellow = "var(--nb-yellow)"
+9 -6
View File
@@ -15,7 +15,7 @@ import Data.Text (Text)
import GHC.Generics (Generic) import GHC.Generics (Generic)
import Sis.Route import Sis.Route
import Sis.Style import Sis.Style (nbNavbarClass, nbNavbarLinkClass, nbHeadingClass, nbButtonDefaultClass)
import Web.Hyperbole import Web.Hyperbole
import Web.Hyperbole.Effect.Session import Web.Hyperbole.Effect.Session
@@ -44,8 +44,12 @@ documentHead = do
title "Sis — Household Chore Tracker" title "Sis — Household Chore Tracker"
mobileFriendly mobileFriendly
meta @ att "charset" "UTF-8" meta @ att "charset" "UTF-8"
stylesheet "https://unpkg.com/neobrutalismcss@latest" stylesheet "https://cdn.jsdelivr.net/gh/matifandy8/NeoBrutalismCSS/dist/index.min.css"
stylesheet "/static/style.css" stylesheet "/static/style.css"
-- Lexend Mega font for headings/buttons (used by NeoBrutalismCSS)
tag "link" @ att "rel" "preconnect" . att "href" "https://fonts.googleapis.com" $ none
tag "link" @ att "rel" "preconnect" . att "href" "https://fonts.gstatic.com" @ att "crossorigin" "" $ none
tag "link" @ att "href" "https://fonts.googleapis.com/css2?family=Lexend+Mega:wght@900&family=Public+Sans:wght@400;600;700&display=swap" . att "rel" "stylesheet" $ none
tag "link" @ att "rel" "manifest" . att "href" "/static/manifest.json" $ none tag "link" @ att "rel" "manifest" . att "href" "/static/manifest.json" $ none
script' scriptEmbed script' scriptEmbed
@@ -56,9 +60,8 @@ documentHead = do
navbar :: View ctx () navbar :: View ctx ()
navbar = do navbar = do
el @ att "class" nbNavbarClass $ do el @ att "class" nbNavbarClass $ do
el @ att "class" "nb-navbar-start" $ do el @ att "class" "nb-navbar-brand" @ att "style" "font-weight:700" $ text "Sis"
el @ att "class" nbFontHeading2Class @ att "style" "font-weight:700" $ text "Sis" el @ att "class" "nb-navbar-nav" $ do
el @ att "class" "nb-navbar-end" $ do
routeLink RDashboard "Dashboard" routeLink RDashboard "Dashboard"
routeLink RChores "Chores" routeLink RChores "Chores"
routeLink RHousehold "Household" routeLink RHousehold "Household"
@@ -67,4 +70,4 @@ navbar = do
routeLink :: (Route r) => r -> Text -> View ctx () routeLink :: (Route r) => r -> Text -> View ctx ()
routeLink rt lbl = do routeLink rt lbl = do
el @ att "class" nbButtonClass $ route rt $ text lbl el @ att "class" nbNavbarLinkClass $ route rt $ text lbl