Begin styling efforts
Start styling the Chord Drill Sergeant for mobile devices because that is that device on which I will primarily use CDS. I'm also deleting the debugger related code. I would like to support a debugger, but I'm not currently using this one, so I am going to remove it to keep things slender. - Introduce TailwindCSS, which also introduced elm-live, index.html, index.css - Add mobile-first styling for the preferences modal - Remove unused code
This commit is contained in:
		
							parent
							
								
									a64601cc05
								
							
						
					
					
						commit
						1d427c4921
					
				
					 8 changed files with 264 additions and 126 deletions
				
			
		| 
						 | 
					@ -1 +1,3 @@
 | 
				
			||||||
/elm-stuff
 | 
					/elm-stuff
 | 
				
			||||||
 | 
					/elm.js
 | 
				
			||||||
 | 
					/output.css
 | 
				
			||||||
| 
						 | 
					@ -53,5 +53,5 @@ in which you can develop:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```shell
 | 
					```shell
 | 
				
			||||||
$ nix-shell
 | 
					$ nix-shell
 | 
				
			||||||
$ elm reactor
 | 
					$ elm-live -- src/Main.elm --output=elm.js
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										3
									
								
								website/sandbox/chord-drill-sergeant/index.css
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								website/sandbox/chord-drill-sergeant/index.css
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,3 @@
 | 
				
			||||||
 | 
					@tailwind base;
 | 
				
			||||||
 | 
					@tailwind components;
 | 
				
			||||||
 | 
					@tailwind utilities;
 | 
				
			||||||
							
								
								
									
										15
									
								
								website/sandbox/chord-drill-sergeant/index.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								website/sandbox/chord-drill-sergeant/index.html
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,15 @@
 | 
				
			||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html lang="en">
 | 
				
			||||||
 | 
					  <head>
 | 
				
			||||||
 | 
					    <meta charset="UTF-8" />
 | 
				
			||||||
 | 
					    <title>Chord Drill Sergeant</title>
 | 
				
			||||||
 | 
					    <link rel="stylesheet" href="./output.css" />
 | 
				
			||||||
 | 
					    <script src="./elm.js"></script>
 | 
				
			||||||
 | 
					  </head>
 | 
				
			||||||
 | 
					  <body class="font-serif">
 | 
				
			||||||
 | 
					    <div id="mount"></div>
 | 
				
			||||||
 | 
					    <script>
 | 
				
			||||||
 | 
					     Elm.Main.init({node: document.getElementById("mount")});
 | 
				
			||||||
 | 
					    </script>
 | 
				
			||||||
 | 
					  </body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
| 
						 | 
					@ -4,5 +4,6 @@ in pkgs.mkShell {
 | 
				
			||||||
  buildInputs = with pkgs; [
 | 
					  buildInputs = with pkgs; [
 | 
				
			||||||
    elmPackages.elm
 | 
					    elmPackages.elm
 | 
				
			||||||
    elmPackages.elm-format
 | 
					    elmPackages.elm-format
 | 
				
			||||||
 | 
					    elmPackages.elm-live
 | 
				
			||||||
  ];
 | 
					  ];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,17 +1,16 @@
 | 
				
			||||||
module Main exposing (main)
 | 
					module Main exposing (main)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Browser
 | 
					import Browser
 | 
				
			||||||
import ChordInspector
 | 
					 | 
				
			||||||
import Html exposing (..)
 | 
					import Html exposing (..)
 | 
				
			||||||
import Html.Attributes exposing (..)
 | 
					import Html.Attributes exposing (..)
 | 
				
			||||||
import Html.Events exposing (..)
 | 
					import Html.Events exposing (..)
 | 
				
			||||||
import NoteInspector
 | 
					 | 
				
			||||||
import Piano
 | 
					import Piano
 | 
				
			||||||
import Random
 | 
					import Random
 | 
				
			||||||
import Random.List
 | 
					import Random.List
 | 
				
			||||||
import Tempo
 | 
					import Tempo
 | 
				
			||||||
import Theory
 | 
					import Theory
 | 
				
			||||||
import Time exposing (..)
 | 
					import Time exposing (..)
 | 
				
			||||||
 | 
					import UI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type alias Model =
 | 
					type alias Model =
 | 
				
			||||||
| 
						 | 
					@ -26,13 +25,15 @@ type alias Model =
 | 
				
			||||||
    , firstNote : Theory.Note
 | 
					    , firstNote : Theory.Note
 | 
				
			||||||
    , lastNote : Theory.Note
 | 
					    , lastNote : Theory.Note
 | 
				
			||||||
    , practiceMode : PracticeMode
 | 
					    , practiceMode : PracticeMode
 | 
				
			||||||
    , debug :
 | 
					    , view : View
 | 
				
			||||||
        { enable : Bool
 | 
					 | 
				
			||||||
        , inspectChord : Bool
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type View
 | 
				
			||||||
 | 
					    = Preferences
 | 
				
			||||||
 | 
					    | Practice
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{-| Control the type of practice you'd like.
 | 
					{-| Control the type of practice you'd like.
 | 
				
			||||||
-}
 | 
					-}
 | 
				
			||||||
type PracticeMode
 | 
					type PracticeMode
 | 
				
			||||||
| 
						 | 
					@ -48,7 +49,6 @@ type Msg
 | 
				
			||||||
    | IncreaseTempo
 | 
					    | IncreaseTempo
 | 
				
			||||||
    | DecreaseTempo
 | 
					    | DecreaseTempo
 | 
				
			||||||
    | SetTempo String
 | 
					    | SetTempo String
 | 
				
			||||||
    | ToggleInspectChord
 | 
					 | 
				
			||||||
    | ToggleInversion Theory.ChordInversion
 | 
					    | ToggleInversion Theory.ChordInversion
 | 
				
			||||||
    | ToggleChordType Theory.ChordType
 | 
					    | ToggleChordType Theory.ChordType
 | 
				
			||||||
    | TogglePitchClass Theory.PitchClass
 | 
					    | TogglePitchClass Theory.PitchClass
 | 
				
			||||||
| 
						 | 
					@ -84,7 +84,7 @@ init : Model
 | 
				
			||||||
init =
 | 
					init =
 | 
				
			||||||
    let
 | 
					    let
 | 
				
			||||||
        ( firstNote, lastNote ) =
 | 
					        ( firstNote, lastNote ) =
 | 
				
			||||||
            ( Theory.C3, Theory.C5 )
 | 
					            ( Theory.A1, Theory.C8 )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        inversions =
 | 
					        inversions =
 | 
				
			||||||
            Theory.allInversions
 | 
					            Theory.allInversions
 | 
				
			||||||
| 
						 | 
					@ -96,7 +96,7 @@ init =
 | 
				
			||||||
            Theory.allPitchClasses
 | 
					            Theory.allPitchClasses
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        keys =
 | 
					        keys =
 | 
				
			||||||
            Theory.allKeys
 | 
					            []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        practiceMode =
 | 
					        practiceMode =
 | 
				
			||||||
            KeyMode
 | 
					            KeyMode
 | 
				
			||||||
| 
						 | 
					@ -121,13 +121,10 @@ init =
 | 
				
			||||||
    , whitelistedKeys = keys
 | 
					    , whitelistedKeys = keys
 | 
				
			||||||
    , selectedChord = Nothing
 | 
					    , selectedChord = Nothing
 | 
				
			||||||
    , isPaused = True
 | 
					    , isPaused = True
 | 
				
			||||||
    , tempo = 60
 | 
					    , tempo = 30
 | 
				
			||||||
    , firstNote = firstNote
 | 
					    , firstNote = firstNote
 | 
				
			||||||
    , lastNote = lastNote
 | 
					    , lastNote = lastNote
 | 
				
			||||||
    , debug =
 | 
					    , view = Preferences
 | 
				
			||||||
        { enable = False
 | 
					 | 
				
			||||||
        , inspectChord = True
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -212,16 +209,6 @@ update msg model =
 | 
				
			||||||
            , Cmd.none
 | 
					            , Cmd.none
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ToggleInspectChord ->
 | 
					 | 
				
			||||||
            ( { model
 | 
					 | 
				
			||||||
                | debug =
 | 
					 | 
				
			||||||
                    { inspectChord = not model.debug.inspectChord
 | 
					 | 
				
			||||||
                    , enable = model.debug.enable
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
              }
 | 
					 | 
				
			||||||
            , Cmd.none
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        ToggleChordType chordType ->
 | 
					        ToggleChordType chordType ->
 | 
				
			||||||
            let
 | 
					            let
 | 
				
			||||||
                chordTypes =
 | 
					                chordTypes =
 | 
				
			||||||
| 
						 | 
					@ -331,33 +318,6 @@ playPause { isPaused } =
 | 
				
			||||||
        button [ onClick Pause ] [ text "Pause" ]
 | 
					        button [ onClick Pause ] [ text "Pause" ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
debugger : Html Msg
 | 
					 | 
				
			||||||
debugger =
 | 
					 | 
				
			||||||
    fieldset []
 | 
					 | 
				
			||||||
        [ label [] [ text "Inspect Chord" ]
 | 
					 | 
				
			||||||
        , input [ type_ "checkbox", onClick ToggleInspectChord, checked init.debug.inspectChord ] []
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pitchClassCheckboxes : List Theory.PitchClass -> Html Msg
 | 
					 | 
				
			||||||
pitchClassCheckboxes pitchClasses =
 | 
					 | 
				
			||||||
    ul []
 | 
					 | 
				
			||||||
        (Theory.allPitchClasses
 | 
					 | 
				
			||||||
            |> List.map
 | 
					 | 
				
			||||||
                (\pitchClass ->
 | 
					 | 
				
			||||||
                    li []
 | 
					 | 
				
			||||||
                        [ label [] [ text (Theory.viewPitchClass pitchClass) ]
 | 
					 | 
				
			||||||
                        , input
 | 
					 | 
				
			||||||
                            [ type_ "checkbox"
 | 
					 | 
				
			||||||
                            , onClick (TogglePitchClass pitchClass)
 | 
					 | 
				
			||||||
                            , checked (List.member pitchClass pitchClasses)
 | 
					 | 
				
			||||||
                            ]
 | 
					 | 
				
			||||||
                            []
 | 
					 | 
				
			||||||
                        ]
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
chordTypeCheckboxes : List Theory.ChordType -> Html Msg
 | 
					chordTypeCheckboxes : List Theory.ChordType -> Html Msg
 | 
				
			||||||
chordTypeCheckboxes chordTypes =
 | 
					chordTypeCheckboxes chordTypes =
 | 
				
			||||||
    ul []
 | 
					    ul []
 | 
				
			||||||
| 
						 | 
					@ -396,45 +356,71 @@ inversionCheckboxes inversions =
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
keyCheckboxes : List Theory.Key -> Html Msg
 | 
					selectKey :
 | 
				
			||||||
keyCheckboxes keys =
 | 
					    Model
 | 
				
			||||||
 | 
					    ->
 | 
				
			||||||
 | 
					        { pitchClass : Theory.PitchClass
 | 
				
			||||||
 | 
					        , majorKey : Theory.Key
 | 
				
			||||||
 | 
					        , minorKey : Theory.Key
 | 
				
			||||||
 | 
					        , bluesKey : Theory.Key
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    -> Html Msg
 | 
				
			||||||
 | 
					selectKey model { pitchClass, majorKey, minorKey, bluesKey } =
 | 
				
			||||||
 | 
					    let
 | 
				
			||||||
 | 
					        active key =
 | 
				
			||||||
 | 
					            List.member key model.whitelistedKeys
 | 
				
			||||||
 | 
					    in
 | 
				
			||||||
 | 
					    div [ class "flex pt-0" ]
 | 
				
			||||||
 | 
					        [ p [ class "text-gray-500 text-center text-5xl flex-1 py-10" ] [ text (Theory.viewPitchClass pitchClass) ]
 | 
				
			||||||
 | 
					        , UI.textToggleButton
 | 
				
			||||||
 | 
					            { label = "major"
 | 
				
			||||||
 | 
					            , handleClick = ToggleKey majorKey
 | 
				
			||||||
 | 
					            , classes = [ "flex-1" ]
 | 
				
			||||||
 | 
					            , toggled = active majorKey
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        , UI.textToggleButton
 | 
				
			||||||
 | 
					            { label = "minor"
 | 
				
			||||||
 | 
					            , handleClick = ToggleKey minorKey
 | 
				
			||||||
 | 
					            , classes = [ "flex-1" ]
 | 
				
			||||||
 | 
					            , toggled = active minorKey
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        , UI.textToggleButton
 | 
				
			||||||
 | 
					            { label = "blues"
 | 
				
			||||||
 | 
					            , handleClick = ToggleKey bluesKey
 | 
				
			||||||
 | 
					            , classes = [ "flex-1" ]
 | 
				
			||||||
 | 
					            , toggled = active bluesKey
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					keyCheckboxes : Model -> Html Msg
 | 
				
			||||||
 | 
					keyCheckboxes model =
 | 
				
			||||||
    div []
 | 
					    div []
 | 
				
			||||||
        [ h2 [] [ text "Choose Key" ]
 | 
					        [ h2 [ class "text-center py-10 text-5xl" ] [ text "Select Keys" ]
 | 
				
			||||||
        , button [ onClick SelectAllKeys ] [ text "Select all" ]
 | 
					 | 
				
			||||||
        , button [ onClick DeselectAllKeys ] [ text "Deselect all" ]
 | 
					 | 
				
			||||||
        , ul []
 | 
					        , ul []
 | 
				
			||||||
            (Theory.allKeys
 | 
					            (Theory.allPitchClasses
 | 
				
			||||||
                |> List.map
 | 
					                |> List.map
 | 
				
			||||||
                    (\key ->
 | 
					                    (\pitchClass ->
 | 
				
			||||||
                        li []
 | 
					                        selectKey model
 | 
				
			||||||
                            [ label [] [ text (Theory.viewKey key) ]
 | 
					                            { pitchClass = pitchClass
 | 
				
			||||||
                            , input
 | 
					                            , majorKey = { pitchClass = pitchClass, mode = Theory.MajorMode }
 | 
				
			||||||
                                [ type_ "checkbox"
 | 
					                            , minorKey = { pitchClass = pitchClass, mode = Theory.MinorMode }
 | 
				
			||||||
                                , onClick (ToggleKey key)
 | 
					                            , bluesKey = { pitchClass = pitchClass, mode = Theory.BluesMode }
 | 
				
			||||||
                                , checked (List.member key keys)
 | 
					                            }
 | 
				
			||||||
                                ]
 | 
					 | 
				
			||||||
                                []
 | 
					 | 
				
			||||||
                            ]
 | 
					 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
displayChord :
 | 
					displayChord :
 | 
				
			||||||
    { debug : Bool
 | 
					    { chord : Theory.Chord
 | 
				
			||||||
    , chord : Theory.Chord
 | 
					 | 
				
			||||||
    , firstNote : Theory.Note
 | 
					    , firstNote : Theory.Note
 | 
				
			||||||
    , lastNote : Theory.Note
 | 
					    , lastNote : Theory.Note
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    -> Html Msg
 | 
					    -> Html Msg
 | 
				
			||||||
displayChord { debug, chord, firstNote, lastNote } =
 | 
					displayChord { chord, firstNote, lastNote } =
 | 
				
			||||||
    div []
 | 
					    div []
 | 
				
			||||||
        [ if debug then
 | 
					        [ p [] [ text (Theory.viewChord chord) ]
 | 
				
			||||||
            ChordInspector.render chord
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          else
 | 
					 | 
				
			||||||
            span [] []
 | 
					 | 
				
			||||||
        , p [] [ text (Theory.viewChord chord) ]
 | 
					 | 
				
			||||||
        , case Theory.notesForChord chord of
 | 
					        , case Theory.notesForChord chord of
 | 
				
			||||||
            Just x ->
 | 
					            Just x ->
 | 
				
			||||||
                Piano.render
 | 
					                Piano.render
 | 
				
			||||||
| 
						 | 
					@ -448,57 +434,65 @@ displayChord { debug, chord, firstNote, lastNote } =
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
view : Model -> Html Msg
 | 
					practiceModeButtons : Model -> Html Msg
 | 
				
			||||||
view model =
 | 
					practiceModeButtons model =
 | 
				
			||||||
    div []
 | 
					    div [ class "text-center" ]
 | 
				
			||||||
 | 
					        [ h2 [ class "py-10 text-5xl" ] [ text "Practice Mode" ]
 | 
				
			||||||
 | 
					        , div [ class "flex pb-6" ]
 | 
				
			||||||
 | 
					            [ UI.simpleButton
 | 
				
			||||||
 | 
					                { label = "Key"
 | 
				
			||||||
 | 
					                , classes = [ "flex-1", "rounded-r-none" ]
 | 
				
			||||||
 | 
					                , handleClick = SetPracticeMode KeyMode
 | 
				
			||||||
 | 
					                , color =
 | 
				
			||||||
 | 
					                    if model.practiceMode == KeyMode then
 | 
				
			||||||
 | 
					                        UI.Primary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    else
 | 
				
			||||||
 | 
					                        UI.Secondary
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            , UI.simpleButton
 | 
				
			||||||
 | 
					                { label = "Fine Tune"
 | 
				
			||||||
 | 
					                , handleClick = SetPracticeMode FineTuneMode
 | 
				
			||||||
 | 
					                , classes = [ "flex-1", "rounded-l-none" ]
 | 
				
			||||||
 | 
					                , color =
 | 
				
			||||||
 | 
					                    if model.practiceMode == FineTuneMode then
 | 
				
			||||||
 | 
					                        UI.Primary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    else
 | 
				
			||||||
 | 
					                        UI.Secondary
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					preferences : Model -> Html Msg
 | 
				
			||||||
 | 
					preferences model =
 | 
				
			||||||
 | 
					    div [ class "pt-10 pb-20 px-10" ]
 | 
				
			||||||
        [ Tempo.render
 | 
					        [ Tempo.render
 | 
				
			||||||
            { tempo = model.tempo
 | 
					            { tempo = model.tempo
 | 
				
			||||||
            , handleIncrease = IncreaseTempo
 | 
					 | 
				
			||||||
            , handleDecrease = DecreaseTempo
 | 
					 | 
				
			||||||
            , handleInput = SetTempo
 | 
					            , handleInput = SetTempo
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        , div []
 | 
					        , practiceModeButtons model
 | 
				
			||||||
            [ h2 [] [ text "Practice Mode" ]
 | 
					 | 
				
			||||||
            , input
 | 
					 | 
				
			||||||
                [ type_ "radio"
 | 
					 | 
				
			||||||
                , id "key-mode"
 | 
					 | 
				
			||||||
                , name "key-mode"
 | 
					 | 
				
			||||||
                , checked (model.practiceMode == KeyMode)
 | 
					 | 
				
			||||||
                , onClick (SetPracticeMode KeyMode)
 | 
					 | 
				
			||||||
                ]
 | 
					 | 
				
			||||||
                []
 | 
					 | 
				
			||||||
            , label [ for "key-mode" ] [ text "Key Mode" ]
 | 
					 | 
				
			||||||
            , input
 | 
					 | 
				
			||||||
                [ type_ "radio"
 | 
					 | 
				
			||||||
                , id "fine-tune-mode"
 | 
					 | 
				
			||||||
                , name "fine-tune-mode"
 | 
					 | 
				
			||||||
                , checked (model.practiceMode == FineTuneMode)
 | 
					 | 
				
			||||||
                , onClick (SetPracticeMode FineTuneMode)
 | 
					 | 
				
			||||||
                ]
 | 
					 | 
				
			||||||
                []
 | 
					 | 
				
			||||||
            , label [ for "fine-tune-mode" ] [ text "Fine-tuning Mode" ]
 | 
					 | 
				
			||||||
            ]
 | 
					 | 
				
			||||||
        , case model.practiceMode of
 | 
					        , case model.practiceMode of
 | 
				
			||||||
            KeyMode ->
 | 
					            KeyMode ->
 | 
				
			||||||
                keyCheckboxes model.whitelistedKeys
 | 
					                keyCheckboxes model
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            FineTuneMode ->
 | 
					            FineTuneMode ->
 | 
				
			||||||
                div []
 | 
					                div []
 | 
				
			||||||
                    [ pitchClassCheckboxes model.whitelistedPitchClasses
 | 
					                    [ inversionCheckboxes model.whitelistedInversions
 | 
				
			||||||
                    , inversionCheckboxes model.whitelistedInversions
 | 
					 | 
				
			||||||
                    , chordTypeCheckboxes model.whitelistedChordTypes
 | 
					                    , chordTypeCheckboxes model.whitelistedChordTypes
 | 
				
			||||||
                    ]
 | 
					                    ]
 | 
				
			||||||
        , playPause model
 | 
					        ]
 | 
				
			||||||
        , if model.debug.enable then
 | 
					 | 
				
			||||||
            debugger
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
          else
 | 
					
 | 
				
			||||||
            span [] []
 | 
					practice : Model -> Html Msg
 | 
				
			||||||
 | 
					practice model =
 | 
				
			||||||
 | 
					    div []
 | 
				
			||||||
 | 
					        [ playPause model
 | 
				
			||||||
        , case model.selectedChord of
 | 
					        , case model.selectedChord of
 | 
				
			||||||
            Just chord ->
 | 
					            Just chord ->
 | 
				
			||||||
                displayChord
 | 
					                displayChord
 | 
				
			||||||
                    { debug = model.debug.inspectChord
 | 
					                    { chord = chord
 | 
				
			||||||
                    , chord = chord
 | 
					 | 
				
			||||||
                    , firstNote = model.firstNote
 | 
					                    , firstNote = model.firstNote
 | 
				
			||||||
                    , lastNote = model.lastNote
 | 
					                    , lastNote = model.lastNote
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
| 
						 | 
					@ -508,6 +502,16 @@ view model =
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					view : Model -> Html Msg
 | 
				
			||||||
 | 
					view model =
 | 
				
			||||||
 | 
					    case model.view of
 | 
				
			||||||
 | 
					        Preferences ->
 | 
				
			||||||
 | 
					            preferences model
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Practice ->
 | 
				
			||||||
 | 
					            practice model
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
{-| For now, I'm just dumping things onto the page to sketch ideas.
 | 
					{-| For now, I'm just dumping things onto the page to sketch ideas.
 | 
				
			||||||
-}
 | 
					-}
 | 
				
			||||||
main =
 | 
					main =
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,25 +3,22 @@ module Tempo exposing (render)
 | 
				
			||||||
import Html exposing (..)
 | 
					import Html exposing (..)
 | 
				
			||||||
import Html.Attributes exposing (..)
 | 
					import Html.Attributes exposing (..)
 | 
				
			||||||
import Html.Events exposing (..)
 | 
					import Html.Events exposing (..)
 | 
				
			||||||
 | 
					import UI
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type alias Props msg =
 | 
					type alias Props msg =
 | 
				
			||||||
    { tempo : Int
 | 
					    { tempo : Int
 | 
				
			||||||
    , handleIncrease : msg
 | 
					 | 
				
			||||||
    , handleDecrease : msg
 | 
					 | 
				
			||||||
    , handleInput : String -> msg
 | 
					    , handleInput : String -> msg
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
render : Props msg -> Html msg
 | 
					render : Props msg -> Html msg
 | 
				
			||||||
render { tempo, handleIncrease, handleDecrease, handleInput } =
 | 
					render { tempo, handleInput } =
 | 
				
			||||||
    div []
 | 
					    div [ class "text-center" ]
 | 
				
			||||||
        [ p [] [ text (String.fromInt tempo ++ " BPM") ]
 | 
					        [ p [ class "text-5xl py-10" ] [ text (String.fromInt tempo ++ " BPM") ]
 | 
				
			||||||
        , button [ onClick handleDecrease ] [ text "Slower" ]
 | 
					        , UI.textField
 | 
				
			||||||
        , input
 | 
					            { placeholderText = "Set tempo..."
 | 
				
			||||||
            [ onInput handleInput
 | 
					            , handleInput = handleInput
 | 
				
			||||||
            , placeholder "Set tempo..."
 | 
					            , classes = []
 | 
				
			||||||
            ]
 | 
					            }
 | 
				
			||||||
            []
 | 
					 | 
				
			||||||
        , button [ onClick handleIncrease ] [ text "Faster" ]
 | 
					 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										116
									
								
								website/sandbox/chord-drill-sergeant/src/UI.elm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								website/sandbox/chord-drill-sergeant/src/UI.elm
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,116 @@
 | 
				
			||||||
 | 
					module UI exposing (..)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import Html exposing (..)
 | 
				
			||||||
 | 
					import Html.Attributes exposing (..)
 | 
				
			||||||
 | 
					import Html.Events exposing (..)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Color
 | 
				
			||||||
 | 
					    = Primary
 | 
				
			||||||
 | 
					    | Secondary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bgForColor : Color -> String
 | 
				
			||||||
 | 
					bgForColor color =
 | 
				
			||||||
 | 
					    case color of
 | 
				
			||||||
 | 
					        Primary ->
 | 
				
			||||||
 | 
					            "bg-gray-600"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Secondary ->
 | 
				
			||||||
 | 
					            "bg-gray-300"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					textForColor : Color -> String
 | 
				
			||||||
 | 
					textForColor color =
 | 
				
			||||||
 | 
					    case color of
 | 
				
			||||||
 | 
					        Primary ->
 | 
				
			||||||
 | 
					            "text-white"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Secondary ->
 | 
				
			||||||
 | 
					            "text-black"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tw : List String -> String
 | 
				
			||||||
 | 
					tw styles =
 | 
				
			||||||
 | 
					    String.join " " styles
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					simpleButton :
 | 
				
			||||||
 | 
					    { label : String
 | 
				
			||||||
 | 
					    , handleClick : msg
 | 
				
			||||||
 | 
					    , color : Color
 | 
				
			||||||
 | 
					    , classes : List String
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    -> Html msg
 | 
				
			||||||
 | 
					simpleButton { label, handleClick, color, classes } =
 | 
				
			||||||
 | 
					    let
 | 
				
			||||||
 | 
					        buttonClasses =
 | 
				
			||||||
 | 
					            [ bgForColor color
 | 
				
			||||||
 | 
					            , textForColor color
 | 
				
			||||||
 | 
					            , "py-10"
 | 
				
			||||||
 | 
					            , "px-20"
 | 
				
			||||||
 | 
					            , "text-5xl"
 | 
				
			||||||
 | 
					            , "rounded-lg"
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					    in
 | 
				
			||||||
 | 
					    button
 | 
				
			||||||
 | 
					        [ class (tw <| List.concat [ buttonClasses, classes ])
 | 
				
			||||||
 | 
					        , onClick handleClick
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					        [ text label ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					textToggleButton :
 | 
				
			||||||
 | 
					    { label : String
 | 
				
			||||||
 | 
					    , handleClick : msg
 | 
				
			||||||
 | 
					    , classes : List String
 | 
				
			||||||
 | 
					    , toggled : Bool
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    -> Html msg
 | 
				
			||||||
 | 
					textToggleButton { label, toggled, handleClick, classes } =
 | 
				
			||||||
 | 
					    let
 | 
				
			||||||
 | 
					        ( textColor, textTreatment ) =
 | 
				
			||||||
 | 
					            if toggled then
 | 
				
			||||||
 | 
					                ( "text-red-600", "underline" )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					                ( "text-black", "no-underline" )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        buttonClasses =
 | 
				
			||||||
 | 
					            [ textColor
 | 
				
			||||||
 | 
					            , textTreatment
 | 
				
			||||||
 | 
					            , "py-10"
 | 
				
			||||||
 | 
					            , "px-10"
 | 
				
			||||||
 | 
					            , "text-5xl"
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					    in
 | 
				
			||||||
 | 
					    button
 | 
				
			||||||
 | 
					        [ class (tw <| List.concat [ buttonClasses, classes ])
 | 
				
			||||||
 | 
					        , onClick handleClick
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					        [ text label ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					textField :
 | 
				
			||||||
 | 
					    { placeholderText : String
 | 
				
			||||||
 | 
					    , handleInput : String -> msg
 | 
				
			||||||
 | 
					    , classes : List String
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    -> Html msg
 | 
				
			||||||
 | 
					textField { placeholderText, handleInput, classes } =
 | 
				
			||||||
 | 
					    let
 | 
				
			||||||
 | 
					        inputClasses =
 | 
				
			||||||
 | 
					            [ "text-5xl"
 | 
				
			||||||
 | 
					            , "w-full"
 | 
				
			||||||
 | 
					            , "py-10"
 | 
				
			||||||
 | 
					            , "px-16"
 | 
				
			||||||
 | 
					            , "border"
 | 
				
			||||||
 | 
					            , "rounded-lg"
 | 
				
			||||||
 | 
					            ]
 | 
				
			||||||
 | 
					    in
 | 
				
			||||||
 | 
					    input
 | 
				
			||||||
 | 
					        [ class (tw <| List.concat [ inputClasses, classes ])
 | 
				
			||||||
 | 
					        , onInput handleInput
 | 
				
			||||||
 | 
					        , placeholder placeholderText
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					        []
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue