Copy over starting point from Evan's TodoMVC app.

This commit is contained in:
Dillon Kearns 2022-08-12 07:56:01 -07:00
parent bb1239fbba
commit 5634b8788b
2 changed files with 509 additions and 439 deletions

View File

@ -1,13 +1,20 @@
module Route.Index exposing (ActionData, Data, Model, Msg, route)
import Api.Scalar exposing (Uuid(..))
import Browser
import Browser.Dom as Dom
import DataSource exposing (DataSource)
import Effect exposing (Effect)
import ErrorPage exposing (ErrorPage)
import Form
import Form.Validation as Validation
import Head
import Html exposing (Html)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (..)
import Html.Keyed as Keyed
import Html.Lazy exposing (lazy, lazy2)
import Json.Decode as Json
import Pages.Msg
import Pages.PageUrl exposing (PageUrl)
import Path exposing (Path)
@ -16,15 +23,18 @@ import Seo.Common
import Server.Request as Request
import Server.Response as Response exposing (Response)
import Shared
import Task
import View exposing (View)
type alias Model =
{}
{ visibility : String
}
type Msg
= NoOp
| ChangeVisibility String
type alias RouteParams =
@ -32,7 +42,8 @@ type alias RouteParams =
type alias Data =
{}
{ entries : List Entry
}
type alias ActionData =
@ -60,7 +71,10 @@ init :
-> StaticPayload Data ActionData RouteParams
-> ( Model, Effect Msg )
init maybePageUrl sharedModel static =
( {}, Effect.none )
( { visibility = "All"
}
, Effect.none
)
update :
@ -75,6 +89,11 @@ update pageUrl sharedModel static msg model =
NoOp ->
( model, Effect.none )
ChangeVisibility visibility ->
( { model | visibility = visibility }
, Effect.none
)
subscriptions : Maybe PageUrl -> RouteParams -> Path -> Shared.Model -> Model -> Sub Msg
subscriptions maybePageUrl routeParams path sharedModel model =
@ -90,24 +109,24 @@ head static =
data : RouteParams -> Request.Parser (DataSource (Response Data ErrorPage))
data routeParams =
Request.succeed (DataSource.succeed (Response.render {}))
type Action
= Signout
| SetQuantity Uuid Int
signoutForm : Form.HtmlForm String Action input Msg
signoutForm =
Form.init
{ combine = Validation.succeed Signout
, view =
\formState ->
[ Html.button [] [ Html.text "Sign out" ]
]
}
|> Form.hiddenKind ( "kind", "signout" ) "Expected signout"
Request.succeed
(DataSource.succeed
(Response.render
{ entries =
[ { description = "Test"
, completed = False
, editing = False
, id = 1
}
, { description = "Test 2"
, completed = False
, editing = False
, id = 2
}
]
}
)
)
action : RouteParams -> Request.Parser (DataSource (Response ActionData ErrorPage))
@ -122,7 +141,237 @@ view :
-> StaticPayload Data ActionData RouteParams
-> View (Pages.Msg.Msg Msg)
view maybeUrl sharedModel model app =
{ title = "Ctrl-R Smoothies"
{ title = "Elm TodoMVC"
, body =
[]
[ div
[ class "todomvc-wrapper"
, style "visibility" "hidden"
]
[ section
[ class "todoapp" ]
[ --lazy viewInput model.field
lazy2 viewEntries model.visibility app.data.entries
, lazy2 viewControls model.visibility app.data.entries
]
, infoFooter
]
]
}
type alias Entry =
{ description : String
, completed : Bool
, editing : Bool
, id : Int
}
-- VIEW
viewInput : String -> Html Msg
viewInput task =
header
[ class "header" ]
[ h1 [] [ text "todos" ]
, input
[ class "new-todo"
, placeholder "What needs to be done?"
, autofocus True
, value task
, name "newTodo"
]
[]
]
-- VIEW ALL ENTRIES
viewEntries : String -> List Entry -> Html (Pages.Msg.Msg Msg)
viewEntries visibility entries =
let
isVisible todo =
case visibility of
"Completed" ->
todo.completed
"Active" ->
not todo.completed
_ ->
True
allCompleted =
List.all .completed entries
cssVisibility =
if List.isEmpty entries then
"hidden"
else
"visible"
in
section
[ class "main"
, style "visibility" cssVisibility
]
[ input
[ class "toggle-all"
, type_ "checkbox"
, name "toggle"
, checked allCompleted
--, onClick (CheckAll (not allCompleted))
]
[]
, label
[ for "toggle-all" ]
[ text "Mark all as complete" ]
, Keyed.ul [ class "todo-list" ] <|
List.map viewKeyedEntry (List.filter isVisible entries)
]
-- VIEW INDIVIDUAL ENTRIES
viewKeyedEntry : Entry -> ( String, Html (Pages.Msg.Msg Msg) )
viewKeyedEntry todo =
( String.fromInt todo.id, lazy viewEntry todo )
viewEntry : Entry -> Html (Pages.Msg.Msg Msg)
viewEntry todo =
li
[ classList [ ( "completed", todo.completed ), ( "editing", todo.editing ) ] ]
[ div
[ class "view" ]
[ input
[ class "toggle"
, type_ "checkbox"
, checked todo.completed
--, onClick (Check todo.id (not todo.completed))
]
[]
, label
[--onDoubleClick (EditingEntry todo.id True)
]
[ text todo.description ]
, button
[ class "destroy"
--, onClick (Delete todo.id)
]
[]
]
, input
[ class "edit"
, value todo.description
, name "title"
, id ("todo-" ++ String.fromInt todo.id)
--, onInput (UpdateEntry todo.id)
--, onBlur (EditingEntry todo.id False)
--, onEnter (EditingEntry todo.id False)
]
[]
]
-- VIEW CONTROLS AND FOOTER
viewControls : String -> List Entry -> Html (Pages.Msg.Msg Msg)
viewControls visibility entries =
let
entriesCompleted =
List.length (List.filter .completed entries)
entriesLeft =
List.length entries - entriesCompleted
in
footer
[ class "footer"
, hidden (List.isEmpty entries)
]
[ lazy viewControlsCount entriesLeft
, lazy viewControlsFilters visibility
, lazy viewControlsClear entriesCompleted
]
viewControlsCount : Int -> Html (Pages.Msg.Msg Msg)
viewControlsCount entriesLeft =
let
item_ =
if entriesLeft == 1 then
" item"
else
" items"
in
span
[ class "todo-count" ]
[ strong [] [ text (String.fromInt entriesLeft) ]
, text (item_ ++ " left")
]
viewControlsFilters : String -> Html (Pages.Msg.Msg Msg)
viewControlsFilters visibility =
ul
[ class "filters" ]
[ visibilitySwap "#/" "All" visibility
, text " "
, visibilitySwap "#/active" "Active" visibility
, text " "
, visibilitySwap "#/completed" "Completed" visibility
]
visibilitySwap : String -> String -> String -> Html (Pages.Msg.Msg Msg)
visibilitySwap uri visibility actualVisibility =
li
[--onClick (ChangeVisibility visibility)
]
[ a [ href uri, classList [ ( "selected", visibility == actualVisibility ) ] ]
[ text visibility ]
]
viewControlsClear : Int -> Html (Pages.Msg.Msg Msg)
viewControlsClear entriesCompleted =
button
[ class "clear-completed"
, hidden (entriesCompleted == 0)
--, onClick DeleteComplete
]
[ text ("Clear completed (" ++ String.fromInt entriesCompleted ++ ")")
]
infoFooter : Html msg
infoFooter =
footer [ class "info" ]
[ p [] [ text "Double-click to edit a todo" ]
, p []
[ text "Written by "
, a [ href "https://github.com/dillonkearns" ] [ text "Dillon Kearns" ]
]
, p []
[ text "Forked from Evan Czaplicki's vanilla Elm implementation "
, a [ href "https://github.com/evancz/elm-todomvc/blob/f236e7e56941c7705aba6e42cb020ff515fe3290/src/Main.elm" ] [ text "github.com/evancz/elm-todomvc" ]
]
, p []
[ text "Part of "
, a [ href "http://todomvc.com" ] [ text "TodoMVC" ]
]
]

View File

@ -1,561 +1,382 @@
nav {
padding: 20px;
font-weight: bold;
font-size: 26px;
html,
body {
margin: 0;
padding: 0;
}
.checkout {
display: flex;
align-items: center;
border:rgba(47, 47, 47, 0.304) solid 1px;
border-radius: 5px;
padding: 5px;
.todomvc-wrapper {
visibility: visible !important;
}
button {
display: flex;
align-items: center;
/* border:rgba(80, 80, 80, 0.704) solid 1px; */
/* border-radius: 5px; */
padding: 5px;
margin: 0;
padding: 0;
border: 0;
background: none;
font-size: 100%;
vertical-align: baseline;
font-family: inherit;
font-weight: inherit;
color: inherit;
-webkit-appearance: none;
appearance: none;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
font-smoothing: antialiased;
}
kbd {
background-color: #eee;
border-radius: 3px;
border: 1px solid #b4b4b4;
box-shadow: 0 1px 1px rgba(0, 0, 0, .2), 0 2px 0 0 rgba(255, 255, 255, .7) inset;
color: #333;
display: inline-block;
font-size: .85em;
font-weight: 700;
line-height: 1;
padding: 2px 4px;
white-space: nowrap;
}
.item {
border: #929292 1px solid;
padding: 10px;
display: flex;
justify-content: space-between;
}
.item form {
padding: 20px;
}
.item img {
width: 150px;
}
.icon svg {
width: 20px !important;
}
hr {
margin: 20px 0;
border: 0;
border-top: 1px dashed #c5c5c5;
border-bottom: 1px dashed #f7f7f7;
}
.learn a {
font-weight: normal;
text-decoration: none;
color: #b83f45;
}
.learn a:hover {
text-decoration: underline;
color: #787e7e;
}
.learn h3,
.learn h4,
.learn h5 {
margin: 10px 0;
font-weight: 500;
line-height: 1.2;
color: #000;
}
.learn h3 {
font-size: 24px;
}
.learn h4 {
font-size: 18px;
}
.learn h5 {
margin-bottom: 0;
font-size: 14px;
}
.learn ul {
padding: 0;
margin: 0 0 30px 25px;
}
.learn li {
line-height: 20px;
}
.learn p {
font-size: 15px;
font-weight: 300;
line-height: 1.3;
margin-top: 0;
margin-bottom: 0;
}
#issue-count {
display: none;
}
.quote {
border: none;
margin: 20px 0 60px 0;
}
.quote p {
font-style: italic;
}
.quote p:before {
content: '“';
font-size: 50px;
opacity: .15;
position: absolute;
top: -20px;
left: 3px;
}
.quote p:after {
content: '”';
font-size: 50px;
opacity: .15;
position: absolute;
bottom: -42px;
right: 3px;
}
.quote footer {
position: absolute;
bottom: -40px;
right: 0;
}
.quote footer img {
border-radius: 3px;
}
.quote footer a {
margin-left: 5px;
vertical-align: middle;
}
.speech-bubble {
position: relative;
padding: 10px;
background: rgba(0, 0, 0, .04);
border-radius: 5px;
}
.speech-bubble:after {
content: '';
position: absolute;
top: 100%;
right: 30px;
border: 13px solid transparent;
border-top-color: rgba(0, 0, 0, .04);
}
.learn-bar > .learn {
position: absolute;
width: 272px;
top: 8px;
left: -300px;
padding: 10px;
border-radius: 5px;
background-color: rgba(255, 255, 255, .6);
transition-property: left;
transition-duration: 500ms;
}
@media (min-width: 899px) {
.learn-bar {
width: auto;
padding-left: 300px;
}
.learn-bar > .learn {
left: 8px;
}
}
html,
body {
margin: 0;
padding: 0;
}
body {
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #f5f5f5;
color: #4d4d4d;
min-width: 230px;
max-width: 550px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-weight: 300;
width: auto;
font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1.4em;
background: #f5f5f5;
color: #4d4d4d;
min-width: 230px;
max-width: 550px;
margin: 0 auto;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
font-smoothing: antialiased;
font-weight: 300;
}
:focus {
outline: 0;
button,
input[type="checkbox"] {
outline: none;
}
.hidden {
display: none;
display: none;
}
.todoapp {
background: #fff;
margin: 130px 0 40px 0;
position: relative;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.1);
background: #fff;
margin: 130px 0 40px 0;
position: relative;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.1);
}
/* .todoapp input::-webkit-input-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
} */
.todoapp input::-webkit-input-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
/* .todoapp input::-moz-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
.todoapp input::-moz-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
.todoapp input::input-placeholder {
font-style: italic;
font-weight: 300;
color: #e6e6e6;
} */
font-style: italic;
font-weight: 300;
color: #e6e6e6;
}
.todoapp h1 {
position: absolute;
top: -155px;
width: 100%;
font-size: 100px;
font-weight: 100;
text-align: center;
color: rgba(175, 47, 47, 0.15);
-webkit-text-rendering: optimizeLegibility;
-moz-text-rendering: optimizeLegibility;
text-rendering: optimizeLegibility;
position: absolute;
top: -155px;
width: 100%;
font-size: 100px;
font-weight: 100;
text-align: center;
color: rgba(175, 47, 47, 0.15);
-webkit-text-rendering: optimizeLegibility;
-moz-text-rendering: optimizeLegibility;
text-rendering: optimizeLegibility;
}
.new-todo,
.edit {
position: relative;
margin: 0;
width: 100%;
font-size: 24px;
font-family: inherit;
font-weight: inherit;
line-height: 1.4em;
border: 0;
color: inherit;
padding: 6px;
border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
position: relative;
margin: 0;
width: 100%;
font-size: 24px;
font-family: inherit;
font-weight: inherit;
line-height: 1.4em;
border: 0;
outline: none;
color: inherit;
padding: 6px;
border: 1px solid #999;
box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-font-smoothing: antialiased;
font-smoothing: antialiased;
}
.new-todo {
padding: 16px 16px 16px 60px;
border: none;
background: rgba(0, 0, 0, 0.003);
box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03);
padding: 16px 16px 16px 60px;
border: none;
background: rgba(0, 0, 0, 0.003);
box-shadow: inset 0 -2px 1px rgba(0,0,0,0.03);
}
.main {
position: relative;
z-index: 2;
border-top: 1px solid #e6e6e6;
position: relative;
z-index: 2;
border-top: 1px solid #e6e6e6;
}
label[for='toggle-all'] {
display: none;
}
.toggle-all {
text-align: center;
border: none; /* Mobile Safari */
opacity: 0;
position: absolute;
position: absolute;
top: -55px;
left: -12px;
width: 60px;
height: 34px;
text-align: center;
border: none; /* Mobile Safari */
}
.toggle-all + label {
width: 60px;
height: 34px;
font-size: 0;
position: absolute;
top: -52px;
left: -13px;
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
.toggle-all:before {
content: '';
font-size: 22px;
color: #e6e6e6;
padding: 10px 27px 10px 27px;
}
.toggle-all + label:before {
content: '';
font-size: 22px;
color: #e6e6e6;
padding: 10px 27px 10px 27px;
}
.toggle-all:checked + label:before {
color: #737373;
.toggle-all:checked:before {
color: #737373;
}
.todo-list {
margin: 0;
padding: 0;
list-style: none;
margin: 0;
padding: 0;
list-style: none;
}
.todo-list li {
position: relative;
font-size: 24px;
border-bottom: 1px solid #ededed;
position: relative;
font-size: 24px;
border-bottom: 1px solid #ededed;
}
.todo-list li:last-child {
border-bottom: none;
border-bottom: none;
}
.todo-list li.editing {
border-bottom: none;
padding: 0;
border-bottom: none;
padding: 0;
}
.todo-list li.editing .edit {
display: block;
width: 506px;
padding: 12px 16px;
margin: 0 0 0 43px;
display: block;
width: 506px;
padding: 13px 17px 12px 17px;
margin: 0 0 0 43px;
}
.todo-list li.editing .view {
display: none;
display: none;
}
.todo-list li .toggle {
text-align: center;
width: 40px;
/* auto, since non-WebKit browsers doesn't support input styling */
height: auto;
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
border: none; /* Mobile Safari */
-webkit-appearance: none;
appearance: none;
text-align: center;
width: 40px;
/* auto, since non-WebKit browsers doesn't support input styling */
height: auto;
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
border: none; /* Mobile Safari */
-webkit-appearance: none;
appearance: none;
}
.todo-list li .toggle {
opacity: 0;
.todo-list li .toggle:after {
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#ededed" stroke-width="3"/></svg>');
}
.todo-list li .toggle + label {
/*
Firefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433
IE and Edge requires *everything* to be escaped to render, so we do that instead of just the `#` - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/
*/
background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E');
background-repeat: no-repeat;
background-position: center left;
}
.todo-list li .toggle:checked + label {
background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E');
.todo-list li .toggle:checked:after {
content: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="-10 -18 100 135"><circle cx="50" cy="50" r="50" fill="none" stroke="#bddad5" stroke-width="3"/><path fill="#5dc2af" d="M72 25L42 71 27 56l-4 4 20 20 34-52z"/></svg>');
}
.todo-list li label {
word-break: break-all;
padding: 15px 15px 15px 60px;
display: block;
line-height: 1.2;
transition: color 0.4s;
white-space: pre-line;
word-break: break-all;
padding: 15px 60px 15px 15px;
margin-left: 45px;
display: block;
line-height: 1.2;
transition: color 0.4s;
}
.todo-list li.completed label {
color: #d9d9d9;
text-decoration: line-through;
color: #d9d9d9;
text-decoration: line-through;
}
.todo-list li .destroy {
display: none;
position: absolute;
top: 0;
right: 10px;
bottom: 0;
width: 40px;
height: 40px;
margin: auto 0;
font-size: 30px;
color: #cc9a9a;
margin-bottom: 11px;
transition: color 0.2s ease-out;
display: none;
position: absolute;
top: 0;
right: 10px;
bottom: 0;
width: 40px;
height: 40px;
margin: auto 0;
font-size: 30px;
color: #cc9a9a;
margin-bottom: 11px;
transition: color 0.2s ease-out;
}
.todo-list li .destroy:hover {
color: #af5b5e;
color: #af5b5e;
}
.todo-list li .destroy:after {
content: '×';
content: '×';
}
.todo-list li:hover .destroy {
display: block;
display: block;
}
.todo-list li .edit {
display: none;
display: none;
}
.todo-list li.editing:last-child {
margin-bottom: -1px;
margin-bottom: -1px;
}
.footer {
color: #777;
padding: 10px 15px;
height: 20px;
text-align: center;
border-top: 1px solid #e6e6e6;
color: #777;
padding: 10px 15px;
height: 20px;
text-align: center;
border-top: 1px solid #e6e6e6;
}
.footer:before {
content: '';
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 50px;
overflow: hidden;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2),
0 8px 0 -3px #f6f6f6,
0 9px 1px -3px rgba(0, 0, 0, 0.2),
0 16px 0 -6px #f6f6f6,
0 17px 2px -6px rgba(0, 0, 0, 0.2);
content: '';
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 50px;
overflow: hidden;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2),
0 8px 0 -3px #f6f6f6,
0 9px 1px -3px rgba(0, 0, 0, 0.2),
0 16px 0 -6px #f6f6f6,
0 17px 2px -6px rgba(0, 0, 0, 0.2);
}
.todo-count {
float: left;
text-align: left;
float: left;
text-align: left;
}
.todo-count strong {
font-weight: 300;
font-weight: 300;
}
.filters {
margin: 0;
padding: 0;
list-style: none;
position: absolute;
right: 0;
left: 0;
margin: 0;
padding: 0;
list-style: none;
position: absolute;
right: 0;
left: 0;
}
.filters li {
display: inline;
display: inline;
}
.filters li a {
color: inherit;
margin: 3px;
padding: 3px 7px;
text-decoration: none;
border: 1px solid transparent;
border-radius: 3px;
color: inherit;
margin: 3px;
padding: 3px 7px;
text-decoration: none;
border: 1px solid transparent;
border-radius: 3px;
}
.filters li a.selected,
.filters li a:hover {
border-color: rgba(175, 47, 47, 0.1);
border-color: rgba(175, 47, 47, 0.1);
}
.filters li a.selected {
border-color: rgba(175, 47, 47, 0.2);
border-color: rgba(175, 47, 47, 0.2);
}
.clear-completed,
html .clear-completed:active {
float: right;
position: relative;
line-height: 20px;
text-decoration: none;
cursor: pointer;
float: right;
position: relative;
line-height: 20px;
text-decoration: none;
cursor: pointer;
position: relative;
}
.clear-completed:hover {
text-decoration: underline;
text-decoration: underline;
}
.info {
margin: 65px auto 0;
color: #bfbfbf;
font-size: 10px;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
text-align: center;
margin: 65px auto 0;
color: #bfbfbf;
font-size: 10px;
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
text-align: center;
}
.info p {
line-height: 1;
line-height: 1;
}
.info a {
color: inherit;
text-decoration: none;
font-weight: 400;
color: inherit;
text-decoration: none;
font-weight: 400;
}
.info a:hover {
text-decoration: underline;
text-decoration: underline;
}
/*
Hack to remove background from Mobile Safari.
Can't use it globally since it destroys checkboxes in Firefox
Hack to remove background from Mobile Safari.
Can't use it globally since it destroys checkboxes in Firefox
*/
@media screen and (-webkit-min-device-pixel-ratio:0) {
.toggle-all,
.todo-list li .toggle {
background: none;
}
.toggle-all,
.todo-list li .toggle {
background: none;
}
.todo-list li .toggle {
height: 40px;
}
.todo-list li .toggle {
height: 40px;
}
.toggle-all {
-webkit-transform: rotate(90deg);
transform: rotate(90deg);
-webkit-appearance: none;
appearance: none;
}
}
@media (max-width: 430px) {
.footer {
height: 50px;
}
.footer {
height: 50px;
}
.filters {
bottom: 10px;
}
.filters {
bottom: 10px;
}
}