widget-restructuring and new colors
This commit is contained in:
parent
56d949d57f
commit
ca582f8e8a
@ -330,18 +330,20 @@ defaultMenuLayout menu widget = do
|
||||
-- value passed to hamletToRepHtml cannot be a widget, this allows
|
||||
-- you to use normal widget features in default-layout.
|
||||
|
||||
pc <- widgetToPageContent $ do
|
||||
-- addStylesheet $ StaticR css_globals_lucius
|
||||
$(widgetFile "default-layout")
|
||||
withUrlRenderer $(hamletFile "templates/default-layout-wrapper.hamlet")
|
||||
where
|
||||
navbar :: [MenuTypes] -> Maybe (Route UniWorX) -> Widget
|
||||
navbar menuTypes mcurrentRoute = $(widgetFile "widgets/navbar")
|
||||
asidenav :: [MenuTypes] -> Maybe (Route UniWorX) -> Widget
|
||||
asidenav menuTypes mcurrentRoute = $(widgetFile "widgets/asidenav")
|
||||
breadcrumbsList :: [(Route UniWorX, Text)] -> Text -> Widget
|
||||
breadcrumbsList parents title = $(widgetFile "widgets/breadcrumbs")
|
||||
let
|
||||
navbar :: Widget
|
||||
navbar = $(widgetFile "widgets/navbar")
|
||||
asidenav :: Widget
|
||||
asidenav = $(widgetFile "widgets/asidenav")
|
||||
breadcrumbs :: Widget
|
||||
breadcrumbs = $(widgetFile "widgets/breadcrumbs")
|
||||
|
||||
pc <- widgetToPageContent $ do
|
||||
addStylesheetRemote "https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,800,900"
|
||||
$(widgetFile "default-layout")
|
||||
$(widgetFile "standalone/showHide")
|
||||
$(widgetFile "standalone/sortable")
|
||||
withUrlRenderer $(hamletFile "templates/default-layout-wrapper.hamlet")
|
||||
|
||||
-- How to run database actions.
|
||||
instance YesodPersist UniWorX where
|
||||
|
||||
@ -43,12 +43,6 @@ getHomeR :: Handler Html
|
||||
getHomeR = do
|
||||
(btnWdgt, btnEnctype) <- generateFormPost (buttonForm :: Form CreateButton)
|
||||
defaultLayout $ do
|
||||
addStylesheet $ StaticR css_show_hide_css
|
||||
addStylesheet $ StaticR css_sortable_css
|
||||
addStylesheet $ StaticR css_reactive_input_css
|
||||
addScript $ StaticR js_show_hide_js
|
||||
addScript $ StaticR js_sortable_js
|
||||
addScript $ StaticR js_reactive_input_js
|
||||
setTitle "Willkommen zum ReWorX Test!"
|
||||
$(widgetFile "home")
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
{-# LANGUAGE FlexibleContexts #-}
|
||||
{-# LANGUAGE ViewPatterns #-}
|
||||
|
||||
module Handler.Utils.Form where
|
||||
module Handler.Utils.Form where
|
||||
|
||||
import Import
|
||||
import qualified Data.Char as Char
|
||||
@ -21,7 +21,7 @@ import qualified Data.Foldable as Foldable
|
||||
import qualified Data.Text as T
|
||||
-- import Yesod.Form.Types
|
||||
import Yesod.Form.Functions (parseHelper)
|
||||
import Yesod.Form.Bootstrap3
|
||||
import Yesod.Form.Bootstrap3
|
||||
|
||||
import qualified Text.Blaze.Internal as Blaze (null)
|
||||
|
||||
@ -35,7 +35,7 @@ data FormIdentifier = FIDcourse | FIDsheet
|
||||
deriving (Enum, Eq, Ord, Bounded, Read, Show)
|
||||
|
||||
|
||||
identForm :: FormIdentifier -> Form a -> Form a
|
||||
identForm :: FormIdentifier -> Form a -> Form a
|
||||
identForm fid = identifyForm (T.pack $ show fid)
|
||||
|
||||
-------------------
|
||||
@ -48,7 +48,7 @@ data FormLayout = FormStandard
|
||||
renderAForm :: Monad m => FormLayout -> FormRender m a
|
||||
renderAForm formLayout aform fragment = do
|
||||
(res, (($ []) -> views)) <- aFormToForm aform
|
||||
let widget = $(widgetFile "form")
|
||||
let widget = $(widgetFile "widgets/form")
|
||||
return (res, widget)
|
||||
|
||||
----------------------------
|
||||
@ -67,12 +67,12 @@ class (Enum a, Bounded a, Ord a, PathPiece a) => Button a where
|
||||
|
||||
cssClass :: a -> ButtonCssClass
|
||||
cssClass _ = BCDefault
|
||||
|
||||
|
||||
--Some standard Buttons useful throughout
|
||||
|
||||
|
||||
--Some standard Buttons useful throughout
|
||||
data StandardButton = BtnDelete | BtnAbort | BtnSave
|
||||
deriving (Enum, Eq, Ord, Bounded, Read, Show)
|
||||
|
||||
|
||||
instance PathPiece StandardButton where -- for displaying the button only, not really for paths
|
||||
toPathPiece = showToPathPiece
|
||||
fromPathPiece = readFromPathPiece
|
||||
@ -81,7 +81,7 @@ instance Button StandardButton where
|
||||
label BtnDelete = "Löschen"
|
||||
label BtnAbort = "Abbrechen"
|
||||
label BtnSave = "Speichern"
|
||||
|
||||
|
||||
cssClass BtnDelete = BCWarning
|
||||
cssClass BtnAbort = BCDefault
|
||||
cssClass BtnSave = BCPrimary
|
||||
@ -97,45 +97,45 @@ instance Button SubmitButton where
|
||||
label BtnSubmit = "Submit"
|
||||
|
||||
cssClass BtnSubmit = BCPrimary
|
||||
|
||||
-- -- Looks like a button, but is just a link (e.g. for create course, etc.)
|
||||
|
||||
-- -- Looks like a button, but is just a link (e.g. for create course, etc.)
|
||||
-- data LinkButton = LinkButton (Route UniWorX)
|
||||
-- deriving (Enum, Eq, Ord, Bounded, Read, Show)
|
||||
--
|
||||
--
|
||||
-- instance PathPiece LinkButton where
|
||||
-- LinkButton route = ???
|
||||
|
||||
|
||||
linkButton :: Widget -> ButtonCssClass -> Route UniWorX -> Widget
|
||||
linkButton lbl cls url = [whamlet| <a href=@{url} .btn .#{bcc2txt cls} role=button>^{lbl} |]
|
||||
-- [whamlet|
|
||||
-- <form method=post action=@{url}>
|
||||
-- <form method=post action=@{url}>
|
||||
-- <input type="hidden" name="_formid" value="identify-linkButton">
|
||||
-- <button .btn .#{bcc2txt cls} type=submit value="Link to @{url}">^{lbl}
|
||||
-- |]
|
||||
-- <input .btn .#{bcc2txt cls} type="submit" value=^{lbl}>
|
||||
|
||||
|
||||
-- |]
|
||||
-- <input .btn .#{bcc2txt cls} type="submit" value=^{lbl}>
|
||||
|
||||
|
||||
buttonField :: Button a => a -> Field Handler a
|
||||
buttonField btn = Field {fieldParse, fieldView, fieldEnctype}
|
||||
where
|
||||
where
|
||||
fieldEnctype = UrlEncoded
|
||||
|
||||
fieldView fid name attrs _val _ =
|
||||
|
||||
fieldView fid name attrs _val _ =
|
||||
[whamlet|
|
||||
<button .btn .#{bcc2txt $ cssClass btn} type=submit name=#{name} value=#{toPathPiece btn} *{attrs} ##{fid}>^{label btn}
|
||||
<button .button .#{bcc2txt $ cssClass btn} type=submit name=#{name} value=#{toPathPiece btn} *{attrs} ##{fid}>^{label btn}
|
||||
|]
|
||||
|
||||
|
||||
fieldParse [] _ = return $ Right Nothing
|
||||
fieldParse [str] _
|
||||
fieldParse [str] _
|
||||
| str == toPathPiece btn = return $ Right $ Just btn
|
||||
| otherwise = return $ Left "Wrong button value"
|
||||
fieldParse _ _ = return $ Left "Multiple button values"
|
||||
|
||||
|
||||
|
||||
|
||||
combinedButtonField1 :: Button a => [a] -> AForm Handler [Maybe a]
|
||||
combinedButtonField1 btns = traverse b2f btns
|
||||
where
|
||||
b2f b = aopt (buttonField b) "" Nothing
|
||||
b2f b = aopt (buttonField b) "" Nothing
|
||||
|
||||
submitButton :: AForm Handler ()
|
||||
submitButton = void $ combinedButtonField1 [BtnSubmit]
|
||||
@ -144,10 +144,10 @@ submitButton = void $ combinedButtonField1 [BtnSubmit]
|
||||
combinedButtonField :: Button a => [a] -> Form m -> Form (a,m)
|
||||
combinedButtonField btns inner csrf = do
|
||||
buttonIdent <- newFormIdent
|
||||
let button b = mopt (buttonField b) ("n/a"{ fsName = Just buttonIdent }) Nothing
|
||||
let button b = mopt (buttonField b) ("n/a"{ fsName = Just buttonIdent }) Nothing
|
||||
(results, btnViews) <- unzip <$> mapM button [minBound..maxBound]
|
||||
(innerRes,innerWdgt) <- inner
|
||||
let widget = do
|
||||
let widget = do
|
||||
[whamlet|
|
||||
#{csrf}
|
||||
^{innerWdgt}
|
||||
@ -169,14 +169,14 @@ combinedButtonField btns inner csrf = do
|
||||
accResult' _ x@(FormSuccess _) = x --SJ: Is this safe? Shouldn't Failure override Success?
|
||||
accResult' (FormSuccess Nothing) x = x
|
||||
accResult' FormMissing _ = FormMissing
|
||||
accResult' (FormFailure errs) _ = FormFailure errs
|
||||
accResult' (FormFailure errs) _ = FormFailure errs
|
||||
-}
|
||||
|
||||
-- buttonForm :: Button a => Markup -> MForm (HandlerT UniWorX IO) (FormResult a, (WidgetT UniWorX IO ()))
|
||||
buttonForm :: (Button a) => Form a
|
||||
buttonForm csrf = do
|
||||
buttonIdent <- newFormIdent
|
||||
let button b = mopt (buttonField b) ("n/a"{ fsName = Just buttonIdent }) Nothing
|
||||
let button b = mopt (buttonField b) ("n/a"{ fsName = Just buttonIdent }) Nothing
|
||||
(results, btnViews) <- unzip <$> mapM button [minBound..maxBound]
|
||||
let widget = do
|
||||
[whamlet|
|
||||
@ -197,7 +197,7 @@ buttonForm csrf = do
|
||||
accResult' FormMissing _ = FormMissing
|
||||
accResult' (FormFailure errs) _ = FormFailure errs
|
||||
|
||||
|
||||
|
||||
---------------------------------------
|
||||
-- Buttons (old version, deprecated) --
|
||||
---------------------------------------
|
||||
@ -233,8 +233,8 @@ postButtonForm lblId = identifyForm lblId buttonF
|
||||
buttonF = renderAForm FormStandard $ pure () <* bootstrapSubmit bProps
|
||||
bProps :: BootstrapSubmit Text
|
||||
bProps = fromString $ unpack lblId
|
||||
|
||||
|
||||
|
||||
|
||||
------------
|
||||
-- Fields --
|
||||
------------
|
||||
@ -271,7 +271,7 @@ sheetTypeAFormReq d (Just (Normal p)) =
|
||||
|
||||
utcTimeField :: (Monad m, RenderMessage (HandlerSite m) FormMessage) => Field m UTCTime
|
||||
-- StackOverflow: dayToUTC <$> (areq (jqueryDayField def {...}) settings Nothing)
|
||||
utcTimeField = Field
|
||||
utcTimeField = Field
|
||||
{ fieldParse = parseHelper $ readTime
|
||||
, fieldView = \theId name attrs val isReq ->
|
||||
[whamlet|
|
||||
@ -280,42 +280,42 @@ utcTimeField = Field
|
||||
|]
|
||||
, fieldEnctype = UrlEncoded
|
||||
}
|
||||
where
|
||||
where
|
||||
fieldTimeFormat :: String
|
||||
--fieldTimeFormat = "%e.%m.%y %k:%M"
|
||||
fieldTimeFormat = "%Y-%m-%eT%H:%M"
|
||||
|
||||
|
||||
readTime :: Text -> Either FormMessage UTCTime
|
||||
readTime t =
|
||||
readTime t =
|
||||
case parseTimeM True germanTimeLocale fieldTimeFormat (T.unpack t) of
|
||||
(Just time) -> Right time
|
||||
Nothing -> Left $ MsgInvalidEntry $ "Datum/Zeit Format: tt.mm.yy hh:mm " ++ t
|
||||
|
||||
showTime :: UTCTime -> Text
|
||||
|
||||
showTime :: UTCTime -> Text
|
||||
showTime = fromString . (formatTime germanTimeLocale fieldTimeFormat)
|
||||
|
||||
|
||||
fsb :: Text -> FieldSettings site
|
||||
fsb = bfs -- Just to avoid annoying Ambiguous Type Errors
|
||||
|
||||
|
||||
fsb :: Text -> FieldSettings site
|
||||
fsb = bfs -- Just to avoid annoying Ambiguous Type Errors
|
||||
|
||||
addAttr :: Text -> Text -> FieldSettings site -> FieldSettings site
|
||||
addAttr attr valu fs = fs { fsAttrs=newAttrs (fsAttrs fs) }
|
||||
where
|
||||
where
|
||||
newAttrs :: [(Text,Text)] -> [(Text,Text)]
|
||||
newAttrs [] = [(attr,valu)]
|
||||
newAttrs (p@(a,v):t)
|
||||
newAttrs (p@(a,v):t)
|
||||
| attr==a = (a,T.append valu $ cons ' ' v):t
|
||||
| otherwise = p:(newAttrs t)
|
||||
| otherwise = p:(newAttrs t)
|
||||
|
||||
addAttrs :: Text -> [Text] -> FieldSettings site -> FieldSettings site
|
||||
addAttrs attr valus fs = fs { fsAttrs=newAttrs (fsAttrs fs) }
|
||||
where
|
||||
where
|
||||
newAttrs :: [(Text,Text)] -> [(Text,Text)]
|
||||
newAttrs [] = [(attr,T.intercalate " " valus)]
|
||||
newAttrs (p@(a,v):t)
|
||||
newAttrs (p@(a,v):t)
|
||||
| attr==a = (a,T.intercalate " " (v:valus)):t
|
||||
| otherwise = p:(newAttrs t)
|
||||
|
||||
| otherwise = p:(newAttrs t)
|
||||
|
||||
addClass :: Text -> FieldSettings site -> FieldSettings site
|
||||
addClass = addAttr "class"
|
||||
|
||||
@ -332,7 +332,7 @@ addIdClass :: Text -> Text -> FieldSettings site -> FieldSettings site
|
||||
addIdClass gId gClass fs = fs { fsId= Just gId, fsAttrs=("class",gClass):(fsAttrs fs) }
|
||||
|
||||
|
||||
setClass :: FieldSettings site -> Text -> FieldSettings site -- deprecated
|
||||
setClass :: FieldSettings site -> Text -> FieldSettings site -- deprecated
|
||||
setClass fs c = fs { fsAttrs=("class",c):(fsAttrs fs) }
|
||||
|
||||
setNameClass :: FieldSettings site -> Text -> Text -> FieldSettings site -- deprecated
|
||||
@ -342,4 +342,3 @@ setTooltip :: String -> FieldSettings site -> FieldSettings site
|
||||
setTooltip tt fs
|
||||
| null tt = fs { fsTooltip = Nothing }
|
||||
| otherwise = fs { fsTooltip = Just $ fromString tt }
|
||||
|
||||
|
||||
@ -4,5 +4,5 @@ module Handler.Utils.Templates where
|
||||
|
||||
import Import.NoFoundation
|
||||
|
||||
lipsum :: WidgetT site IO ()
|
||||
lipsum = $(widgetFile "widgets/lipsum")
|
||||
-- lipsum :: WidgetT site IO ()
|
||||
-- lipsum = $(widgetFile "widgets/lipsum")
|
||||
|
||||
@ -16,3 +16,6 @@ import Data.Fixed as Import
|
||||
|
||||
import CryptoID as Import
|
||||
import Data.UUID as Import (UUID)
|
||||
|
||||
|
||||
import Text.Lucius as Import
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
.reactive-label {
|
||||
cursor: text;
|
||||
color: #333;
|
||||
transform: translate(0, 0);
|
||||
transition: all .1s;
|
||||
}
|
||||
.reactive-label.small {
|
||||
cursor: default;
|
||||
color: #888;
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
.reactive-label {
|
||||
position: absolute;
|
||||
left: 4px;
|
||||
top: 8px;
|
||||
}
|
||||
.reactive-label.small {
|
||||
transform: translate(0, -120%);
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
@ -1,15 +1,16 @@
|
||||
<!-- navigation -->
|
||||
^{navbar menuTypes mcurrentRoute}
|
||||
<div .navbar-container>
|
||||
^{navbar}
|
||||
|
||||
<div .main>
|
||||
|
||||
<aside .main__aside>
|
||||
^{asidenav menuTypes mcurrentRoute}
|
||||
^{asidenav}
|
||||
|
||||
<div .main__content>
|
||||
<!-- breadcrumbs -->
|
||||
$if not $ Just HomeR == mcurrentRoute
|
||||
^{breadcrumbsList parents title}
|
||||
^{breadcrumbs}
|
||||
|
||||
<!-- alerts -->
|
||||
$forall (status, msg) <- mmsgs
|
||||
@ -19,9 +20,6 @@
|
||||
<!-- actual content -->
|
||||
^{widget}
|
||||
|
||||
<!-- a little lorem ipsum for waste of vertical space -->
|
||||
^{lipsum}
|
||||
|
||||
<!-- footer -->
|
||||
<footer>
|
||||
#{appCopyright $ appSettings master}
|
||||
|
||||
@ -12,7 +12,24 @@
|
||||
--sec-font-color: #eaf2ff;
|
||||
--box-bg-color: #dddddd;
|
||||
/* THEME 3 */
|
||||
--base00: rebeccapurple;
|
||||
--darkbase: #364B60;
|
||||
--lightbase: #2490E8;
|
||||
--lighterbase: #60C2FF;
|
||||
--whitebase: #FCFFFA;
|
||||
--greybase: #B1B5C0;
|
||||
--fontbase: #34303a;
|
||||
|
||||
|
||||
/* THEME INDEPENDENT COLORS */
|
||||
--errorbase: red;
|
||||
|
||||
|
||||
/* FONTS */
|
||||
--fontfamilybase: "Source Sans Pro", Helvetica, sans-serif;
|
||||
|
||||
/* DIMENSIONS */
|
||||
--header-height: 60px;
|
||||
--header-height-collapsed: 50px;
|
||||
}
|
||||
|
||||
|
||||
@ -26,8 +43,8 @@
|
||||
|
||||
body {
|
||||
background-color: white;
|
||||
color: #333;
|
||||
font-family: "Source Sans Pro", Helvetica, sans-serif;
|
||||
color: var(--fontbase);
|
||||
font-family: var(--fontfamilybase);
|
||||
font-weight: 400;
|
||||
font-size: 16px;
|
||||
overflow-y: scroll;
|
||||
@ -35,13 +52,13 @@ body {
|
||||
|
||||
a,
|
||||
a:visited {
|
||||
color: rebeccapurple;
|
||||
color: var(--darkbase);
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
transition: color .2s ease, background-color .2s ease;
|
||||
}
|
||||
a:hover {
|
||||
color: #422063;
|
||||
color: var(--lightbase);
|
||||
}
|
||||
|
||||
ul {
|
||||
@ -80,19 +97,29 @@ th, td {
|
||||
/* LAYOUT */
|
||||
.main {
|
||||
display: flex;
|
||||
padding: 0 10vw;
|
||||
padding-right: 5vw;
|
||||
min-height: calc(100vh - var(--header-height));
|
||||
}
|
||||
|
||||
.main__aside {
|
||||
flex: 0 0 200px;
|
||||
margin-right: 40px;
|
||||
width: 300px;
|
||||
padding-right: 20px;
|
||||
padding-left: 4vw;
|
||||
background-color: var(--darkbase);
|
||||
/*background: -moz-linear-gradient(right, var(--darkbase) 0%, #395069 100%); /* FF3.6-15 */*/
|
||||
/*background: -webkit-linear-gradient(right, var(--darkbase) 0%, #395069 100%); /* Chrome10-25,Safari5.1-6 */*/
|
||||
/*background: linear-gradient(to left, var(--darkbase) 0%, #395069 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */*/
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.main__content {
|
||||
/*padding: 0 10vw;*/
|
||||
background-color: white;
|
||||
padding: 20px 40px;
|
||||
flex: 1;
|
||||
z-index: 0;
|
||||
|
||||
div {
|
||||
> div {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
@ -100,126 +127,3 @@ th, td {
|
||||
margin: 10px 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* FORMS */
|
||||
input[type="text"],
|
||||
input[type="password"],
|
||||
input[type="url"],
|
||||
input[type="number"],
|
||||
input[type="email"] {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
padding: 7px 3px 7px;
|
||||
border: none;
|
||||
outline: 0;
|
||||
border-bottom: 2px solid rebeccapurple;
|
||||
color: var(--base-font-color);
|
||||
transition: all .1s;
|
||||
font-size: 16px;
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
input[type="text"]:focus,
|
||||
input[type="password"]:focus,
|
||||
input[type="url"]:focus,
|
||||
input[type="number"]:focus,
|
||||
input[type="email"]:focus {
|
||||
border-bottom-color: red;
|
||||
background-color: rgba(0, 0, 0, 0.02);
|
||||
}
|
||||
|
||||
input[type="submit"],
|
||||
input[type="button"],
|
||||
button {
|
||||
outline: 0;
|
||||
border: 0;
|
||||
box-shadow: 0;
|
||||
background-color: var(--base00);
|
||||
color: white;
|
||||
padding: 7px 13px;
|
||||
border: 1px solid rebeccapurple;
|
||||
transition: all .1s;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input[type="submit"][disabled],
|
||||
input[type="button"][disabled],
|
||||
button[disabled] {
|
||||
opacity: 0.3;
|
||||
border: 1px solid transparent;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
input[type="submit"]:not([disabled]):hover,
|
||||
input[type="button"]:not([disabled]):hover,
|
||||
button:not([disabled]):hover {
|
||||
background-color: var(--base-bg-color);
|
||||
color: var(--base-font-color);
|
||||
}
|
||||
|
||||
.form-group {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(100px, max-content));
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/*CUSTOM CHECKBOXES AND RADIO BOXES*/
|
||||
.checkbox,
|
||||
.radio {
|
||||
position: relative;
|
||||
}
|
||||
.checkbox > [type="checkbox"],
|
||||
.radio > [type="radio"] {
|
||||
display: none;
|
||||
}
|
||||
.checkbox > label,
|
||||
.radio > label {
|
||||
padding: 7px 13px 7px 30px;
|
||||
background-color: rebeccapurple;
|
||||
border-radius: 4px;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
}
|
||||
.checkbox > label::before,
|
||||
.radio > label::before,
|
||||
.checkbox > label::after,
|
||||
.radio > label::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 7px;
|
||||
left: 4px;
|
||||
display: block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: white;
|
||||
transform: scale(0.2, 0.2);
|
||||
transition: all .2s;
|
||||
}
|
||||
.radio > label::before,
|
||||
.radio > label::after {
|
||||
transform: scale(0.01, 0.01);
|
||||
}
|
||||
.checkbox > label::before,
|
||||
.radio > label::before {
|
||||
width: 20px;
|
||||
height: 2px;
|
||||
}
|
||||
.checkbox > label::after,
|
||||
.radio > label::after {
|
||||
width: 20px;
|
||||
height: 2px;
|
||||
}
|
||||
.checkbox > :checked + label,
|
||||
.radio > :checked + label {
|
||||
background-color: #451477;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.checkbox > :checked + label::before,
|
||||
.radio > :checked + label::before {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
.checkbox > :checked + label::after,
|
||||
.radio > :checked + label::after {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
$newline never
|
||||
#{fragment}
|
||||
$case formLayout
|
||||
$of FormStandard
|
||||
$forall view <- views
|
||||
<div :fvRequired view:.required :not $ fvRequired view:.optional :isJust $ fvErrors view:.has-error>
|
||||
$if not (Blaze.null $ fvLabel view)
|
||||
<label for=#{fvId view}>#{fvLabel view}
|
||||
^{fvInput view}
|
||||
@ -8,7 +8,6 @@
|
||||
|
||||
<p .alert .alert-danger>Das System ist noch nicht produktiv einsetzbar
|
||||
|
||||
<!-- SHOW-HIDE-TEST -->
|
||||
<hr>
|
||||
<div .js-show-hide>
|
||||
<h2 .js-show-hide__toggle>Teilweise funktionierende Abschnitte
|
||||
@ -58,69 +57,6 @@
|
||||
<td>T2C2
|
||||
<td>35
|
||||
|
||||
<hr>
|
||||
<div .js-show-hide.js-show-hide--collapsed>
|
||||
<h2 .js-show-hide__toggle>Formulare
|
||||
<p>(Senden-Button wird aktiviert, sobald alle benötigten Felder ausgefüllt sind.)
|
||||
<form method=post action=@{HomeR}>
|
||||
<div .form-group>
|
||||
<label .reactive-label for=text>Vorname*
|
||||
<input type=text id=text required=true>
|
||||
<div .form-group>
|
||||
<label .reactive-label for=password>Passwort*
|
||||
<input type=password id=password required=true>
|
||||
<div .form-group>
|
||||
<label .reactive-label for=email>Email*
|
||||
<input type=email id=email required=true>
|
||||
<div .form-group>
|
||||
<label for=date>Geburtsdatum:
|
||||
<input type=date id=date>
|
||||
|
||||
<div .form-group>
|
||||
<div>
|
||||
<input type=submit value="Senden" id=submit-btn>
|
||||
|
||||
<div .form-group>
|
||||
<textarea>No content yet
|
||||
|
||||
<p>Bitte wähle aus (auch mehrere):
|
||||
<div .form-group>
|
||||
<div .checkbox>
|
||||
<input type=checkbox id=chkbox1>
|
||||
<label for=chkbox1>Opt A
|
||||
<div .checkbox>
|
||||
<input type=checkbox id=chkbox2>
|
||||
<label for=chkbox2>Opt B
|
||||
<div .checkbox>
|
||||
<input type=checkbox id=chkbox3>
|
||||
<label for=chkbox3>Opt C
|
||||
<div .checkbox>
|
||||
<input type=checkbox id=chkbox4>
|
||||
<label for=chkbox4>Opt D
|
||||
|
||||
<p>Wähle aus diesen Optionen eines aus:
|
||||
<div .form-group>
|
||||
<div .radio>
|
||||
<input type=radio name=group1[] id=rdbtn1>
|
||||
<label for=rdbtn1>Opt A
|
||||
<div .radio>
|
||||
<input type=radio name=group1[] id=rdbtn2>
|
||||
<label for=rdbtn2>Opt B
|
||||
<div .radio>
|
||||
<input type=radio name=group1[] id=rdbtn3>
|
||||
<label for=rdbtn3>Opt C
|
||||
|
||||
<p>Wähle eines aus der Liste aus:
|
||||
<div .form-group>
|
||||
<select required=true>
|
||||
<option>Option 1
|
||||
<option>Option 2
|
||||
<option>Option 3
|
||||
|
||||
<div .form-group>
|
||||
<h3>Test-Button. Does nothing.
|
||||
<input type=button value="Test">
|
||||
|
||||
<hr>
|
||||
<div>
|
||||
<h2>Funktionen zum Testen
|
||||
|
||||
1
templates/standalone/showHide.hamlet
Normal file
1
templates/standalone/showHide.hamlet
Normal file
@ -0,0 +1 @@
|
||||
<!-- only here to be able to include showHide using `toWidget` -->
|
||||
@ -24,12 +24,12 @@
|
||||
left: -28px;
|
||||
top: 10px;
|
||||
border-left: 8px solid transparent;
|
||||
border-top: 8px solid rebeccapurple;
|
||||
border-top: 8px solid var(--lightbase);
|
||||
}
|
||||
|
||||
.js-show-hide__toggle:hover::before,
|
||||
.js-show-hide--collapsed .js-show-hide__toggle::before {
|
||||
border-left: 8px solid rebeccapurple;
|
||||
border-left: 8px solid var(--lightbase);
|
||||
border-top: 8px solid transparent;
|
||||
top: 5px;
|
||||
left: -22px;
|
||||
1
templates/standalone/sortable.hamlet
Normal file
1
templates/standalone/sortable.hamlet
Normal file
@ -0,0 +1 @@
|
||||
<!-- only here to be able to include sortable using `toWidget` -->
|
||||
@ -6,25 +6,26 @@ table.js-sortable th {
|
||||
|
||||
table.js-sortable th.sorted-asc,
|
||||
table.js-sortable th.sorted-desc {
|
||||
color: rebeccapurple;
|
||||
color: var(--darkbase);
|
||||
}
|
||||
|
||||
table.js-sortable th.sorted-asc::after,
|
||||
table.js-sortable th.sorted-desc::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 0;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
top: 3px;
|
||||
transform: translateY(-100%);
|
||||
border-left: 8px solid transparent;
|
||||
border-right: 8px solid transparent;
|
||||
}
|
||||
|
||||
table.js-sortable th.sorted-asc::after {
|
||||
border-top: 8px solid rebeccapurple;
|
||||
border-bottom: 8px solid var(--lightbase);
|
||||
}
|
||||
|
||||
table.js-sortable th.sorted-desc::after {
|
||||
border-bottom: 8px solid rebeccapurple;
|
||||
border-top: 8px solid var(--lightbase);
|
||||
}
|
||||
@ -1,20 +1,26 @@
|
||||
.asidenav {
|
||||
margin-top: 20px;
|
||||
color: white;
|
||||
}
|
||||
.asidenav__box {
|
||||
margin: 10px 0;
|
||||
padding: 10px;
|
||||
border-bottom: 4px solid rebeccapurple;
|
||||
border-bottom: 4px solid var(--darkbase);
|
||||
}
|
||||
.asidenav__box-title {
|
||||
margin-left: -10px;
|
||||
}
|
||||
.asidenav__link {
|
||||
padding: 4px 7px;
|
||||
|
||||
.asidenav .asidenav__link {
|
||||
display: block;
|
||||
padding: 4px 7px;
|
||||
border-radius: 2px;
|
||||
margin: 4px 0;
|
||||
color: var(--darkbase);
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
.asidenav__link:hover {
|
||||
.asidenav .asidenav__link:hover {
|
||||
color: white;
|
||||
background-color: rebeccapurple;
|
||||
background-color: var(--darkbase);
|
||||
}
|
||||
|
||||
9
templates/widgets/form.hamlet
Normal file
9
templates/widgets/form.hamlet
Normal file
@ -0,0 +1,9 @@
|
||||
$newline never
|
||||
#{fragment}
|
||||
$case formLayout
|
||||
$of FormStandard
|
||||
$forall view <- views
|
||||
<div .form-group :fvRequired view:.form-group--required :not $ fvRequired view:.form-group--optional :isJust $ fvErrors view:.form-group--has-error>
|
||||
$if not (Blaze.null $ fvLabel view)
|
||||
<label form-group__label .reactive-label for=#{fvId view}>#{fvLabel view}
|
||||
^{fvInput view}
|
||||
@ -6,16 +6,19 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
|
||||
// makes <label> smaller if <input> is focussed
|
||||
window.utils.reactiveInputLabel = function(input, label) {
|
||||
if (input.value.length > 0) {
|
||||
label.classList.add('reactive-label--small');
|
||||
}
|
||||
input.addEventListener('focus', function() {
|
||||
label.classList.add('small');
|
||||
label.classList.add('reactive-label--small');
|
||||
});
|
||||
label.addEventListener('click', function() {
|
||||
label.classList.add('small');
|
||||
label.classList.add('reactive-label--small');
|
||||
input.focus();
|
||||
});
|
||||
input.addEventListener('blur', function() {
|
||||
if (input.value.length < 1) {
|
||||
label.classList.remove('small');
|
||||
label.classList.remove('reactive-label--small');
|
||||
}
|
||||
});
|
||||
};
|
||||
238
templates/widgets/form.lucius
Normal file
238
templates/widgets/form.lucius
Normal file
@ -0,0 +1,238 @@
|
||||
/* GENERAL STYLES FOR FORMS */
|
||||
|
||||
/* FORMS */
|
||||
input[type="text"],
|
||||
input[type="password"],
|
||||
input[type="url"],
|
||||
input[type="number"],
|
||||
input[type="email"] {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
padding: 7px 3px 7px;
|
||||
outline: 0;
|
||||
border: 0;
|
||||
border-bottom: 2px solid var(--darkbase);
|
||||
box-shadow: 0 2px 13px rgba(0, 0, 0, 0.05);
|
||||
color: var(--fontbase);
|
||||
transition: all .1s;
|
||||
font-size: 16px;
|
||||
min-width: 300px;
|
||||
}
|
||||
|
||||
input[type="text"]:focus,
|
||||
input[type="password"]:focus,
|
||||
input[type="url"]:focus,
|
||||
input[type="number"]:focus,
|
||||
input[type="email"]:focus {
|
||||
border-bottom-color: var(--lightbase);
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
input[type="submit"],
|
||||
input[type="button"],
|
||||
button {
|
||||
outline: 0;
|
||||
border: 0;
|
||||
box-shadow: 0;
|
||||
background-color: var(--lightbase);
|
||||
color: white;
|
||||
padding: 10px 17px;
|
||||
min-width: 100px;
|
||||
transition: all .1s;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
input[type="submit"][disabled],
|
||||
input[type="button"][disabled],
|
||||
button[disabled] {
|
||||
opacity: 0.3;
|
||||
border: 1px solid transparent;
|
||||
background-color: var(--greybase);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
input[type="submit"]:not([disabled]):hover,
|
||||
input[type="button"]:not([disabled]):hover,
|
||||
button:not([disabled]):hover {
|
||||
background-color: var(--lighterbase);
|
||||
}
|
||||
|
||||
textarea {
|
||||
outline: 0;
|
||||
border: 0;
|
||||
padding: 7px 4px;
|
||||
min-width: 300px;
|
||||
min-height: 100px;
|
||||
font-family: var(--fontfamilybase);
|
||||
font-size: 16px;
|
||||
color: var(--fontbase);
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
box-shadow: 0 2px 13px rgba(0, 0, 0, 0.05);
|
||||
border-bottom: 2px solid var(--darkbase);
|
||||
}
|
||||
|
||||
textarea:focus {
|
||||
background-color: transparent;
|
||||
border-bottom-color: var(--lightbase);
|
||||
}
|
||||
|
||||
.form-group {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(150px, max-content));
|
||||
align-items: center;
|
||||
margin: 10px 0;
|
||||
margin-left: -20px;
|
||||
padding-left: 10px;
|
||||
border-left: 8px solid transparent;
|
||||
}
|
||||
|
||||
.form-group--required {
|
||||
border-left: 8px solid var(--lightbase);
|
||||
}
|
||||
|
||||
.form-group--optional {
|
||||
border-left: 8px solid var(--greybase);
|
||||
}
|
||||
|
||||
.form-group--has-error {
|
||||
border-left: 8px solid var(--errorbase) !important;
|
||||
}
|
||||
|
||||
/* CUSTOM LEGACY CHECKBOX AND RADIO BOXES */
|
||||
input[type="checkbox"] {
|
||||
position: relative;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
-webkit-appearance: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
input[type="checkbox"]::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: var(--lighterbase);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 2px;
|
||||
}
|
||||
input[type="checkbox"]:checked::before {
|
||||
background-color: var(--lightbase);
|
||||
}
|
||||
input[type="checkbox"]:checked::after {
|
||||
content: '✓';
|
||||
position: absolute;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
/* CUSTOM CHECKBOXES AND RADIO BOXES */
|
||||
/* Completely replaces legacy checkbox and radiobox */
|
||||
.checkbox,
|
||||
.radio {
|
||||
position: relative;
|
||||
margin: 3px;
|
||||
|
||||
> [type="checkbox"],
|
||||
> [type="radio"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
> label {
|
||||
display: block;
|
||||
padding: 7px 13px 7px 30px;
|
||||
background-color: var(--darkbase);
|
||||
border-radius: 4px;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
> label::before,
|
||||
> label::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
left: 4px;
|
||||
display: block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: white;
|
||||
transition: all .2s;
|
||||
}
|
||||
|
||||
> label::before {
|
||||
width: 20px;
|
||||
height: 2px;
|
||||
transform: scale(0.8, 0.1);
|
||||
}
|
||||
|
||||
> label::after {
|
||||
width: 20px;
|
||||
height: 2px;
|
||||
transform: scale(0.8, 0.1);
|
||||
}
|
||||
|
||||
> :checked + label {
|
||||
background-color: var(--lightbase);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
&:hover > label::before,
|
||||
> :checked + label::before {
|
||||
transform: scale(1, 1) rotate(45deg);
|
||||
}
|
||||
|
||||
&:hover > label::after,
|
||||
> :checked + label::after {
|
||||
transform: scale(1, 1) rotate(-45deg);
|
||||
}
|
||||
}
|
||||
.radio > label::before {
|
||||
transform: scale(0.01, 0.01) rotate(45deg);
|
||||
}
|
||||
.radio > label::after {
|
||||
transform: scale(0.01, 0.01) rotate(-45deg);
|
||||
}
|
||||
|
||||
.radio::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
right: 2px;
|
||||
bottom: 2px;
|
||||
border-radius: 4px;
|
||||
border: 2px solid white;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
/* REACTIVE LABELS */
|
||||
.reactive-label {
|
||||
cursor: text;
|
||||
color: #888;
|
||||
transform: translate(0, 0);
|
||||
transition: all .1s;
|
||||
}
|
||||
.reactive-label--small {
|
||||
cursor: default;
|
||||
color: var(--fontbase);
|
||||
}
|
||||
@media (max-width: 768px) {
|
||||
.reactive-label {
|
||||
position: absolute;
|
||||
left: 4px;
|
||||
top: 8px;
|
||||
}
|
||||
.reactive-label--small {
|
||||
transform: translate(0, -120%);
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
@ -4,10 +4,10 @@
|
||||
$forall menuType <- menuTypes
|
||||
$case menuType
|
||||
$of NavbarLeft (MenuItem label route _)
|
||||
<li :Just route == mcurrentRoute:.navbar__list-item--active>
|
||||
<li .navbar__list-item :Just route == mcurrentRoute:.navbar__list-item--active>
|
||||
<a .navbar__link href=@{route}>#{label}
|
||||
$of NavbarRight (MenuItem label route _)
|
||||
<li :Just route == mcurrentRoute:.navbar__list-item--active>
|
||||
<li .navbar__list-item :Just route == mcurrentRoute:.navbar__list-item--active>
|
||||
<a .navbar__link href=@{route}>#{label}
|
||||
$of _
|
||||
|
||||
|
||||
@ -1,8 +1,3 @@
|
||||
:root {
|
||||
--header-height: 60px;
|
||||
--header-height-collapsed: 50px;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
position: relative;
|
||||
display: flex;
|
||||
@ -12,13 +7,14 @@
|
||||
width: 100%;
|
||||
height: var(--header-height);
|
||||
line-height: var(--header-height);
|
||||
padding: 0 10vw;
|
||||
background: #663399; /* Old browsers */
|
||||
background: -moz-linear-gradient(bottom, #663399 0%, #734e99 100%); /* FF3.6-15 */
|
||||
background: -webkit-linear-gradient(bottom, #663399 0%,#734e99 100%); /* Chrome10-25,Safari5.1-6 */
|
||||
background: linear-gradient(to top, #663399 0%,#734e99 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
|
||||
padding: 0 5vw;
|
||||
background: var(--darkbase); /* Old browsers */
|
||||
background: -moz-linear-gradient(bottom, var(--darkbase) 0%, #425d79 100%); /* FF3.6-15 */
|
||||
background: -webkit-linear-gradient(bottom, var(--darkbase) 0%,#425d79 100%); /* Chrome10-25,Safari5.1-6 */
|
||||
background: linear-gradient(to top, var(--darkbase) 0%,#425d79 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */
|
||||
color: white;
|
||||
box-shadow: 0 1px 10px rgba(0, 0, 0, 0.3);
|
||||
box-shadow: 0 1px 10px rgba(0, 0, 0, 0.1);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.navbar .navbar__link {
|
||||
@ -26,15 +22,16 @@
|
||||
height: 100%;
|
||||
padding: 0 13px;
|
||||
color: white;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.navbar .navbar__link:hover {
|
||||
.navbar__list-item--active > .navbar__link {
|
||||
background-color: white;
|
||||
color: rebeccapurple;
|
||||
color: var(--darkbase);
|
||||
}
|
||||
|
||||
.navbar__list-item--active {
|
||||
background-color: #422063;
|
||||
.navbar .navbar__list-item > .navbar__link:hover {
|
||||
background-color: var(--darkbase);
|
||||
}
|
||||
|
||||
.navbar--sticky {
|
||||
@ -48,6 +45,7 @@
|
||||
}
|
||||
.navbar__pushdown {
|
||||
display: none;
|
||||
background-color: var(--darkbase);
|
||||
height: var(--header-height);
|
||||
}
|
||||
.navbar--sticky + .navbar__pushdown {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user