Material Design
This sample uses C1 MVC's pseudo-classes to implement a form with dynamic labels, validation, and focus indicators similar to those in Google's Material Design spec.
- C1Input/MaterialDesign.js
- C1Input/MaterialDesign.css
- MaterialDesignController.cs
- MaterialDesign.cshtml
1 2 3 4 5 | // This file locates: "Scripts/Lesson/C1Input/MaterialDesign.js". c1.documentReady(function () { var time = wijmo.Control.getControl( '#time' ); time.value = null ; }); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | // This file locates: "Content/css/Lesson/C1Input/MaterialDesign.css". form { background-color: white; box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16), 0 3px 6px rgba(0, 0, 0, 0.23); max-width: 900px; } .wj-dialog-body { display: flex; flex-wrap: wrap; } .wj-dialog-body > .wj-labeled-input { width: 160px; margin: 0 .15in; } /* wj-labeled-input: adapted from MDL styles */ /* underline access keys */ .wj-labeled-input .accesskey { text-decoration: underline; } /* label input container */ .wj-labeled-input { position: relative; font-size: 16px; display: inline-block; box-sizing: border-box; width: 300px; max-width: 100%; margin: 0 20px; padding: 20px 0; } /* Wijmo control in the container */ .wj-labeled-input .wj-control.wj-content { margin: 0; width: 100%; background-color: transparent; border: none; border-bottom: 1px solid rgba(0,0,0,.1); } .wj-labeled-input .wj-control.wj-content button { opacity: 0.75; border-color: rgba(0,0,0,.1); } /* label in the container (must come after the control) */ .wj-labeled-input label { font-size: 16px; top: 24px; bottom: 0; margin: 0; pointer-events: none; position: absolute; display: block; width: 100%; overflow: hidden; white-space: nowrap; text-align: left; color: rgba(0, 0, 0, 0.258824); transition-duration: .2s; transition-timing-function: cubic-bezier(.4,0,.2,1); } /* move label out of the way when control is focused or not empty */ .wj- static -labels .wj-labeled-input :not(.wj-state-focused) + label, .wj-labeled-input .wj-state-focused + label, .wj-labeled-input :not(.wj-state-empty) + label { font-size: 12px; top: 4px; color: rgb(63,81,181); visibility: visible; } .wj-labeled-input .wj-state-invalid + label { color: #d50000; } /* underline label */ .wj-labeled-input label:after { background-color: rgb(63,81,181); bottom: 20px; content: '' ; height: 2px; left: 45%; position: absolute; transition-duration: .2s; transition-timing-function: cubic-bezier(.4,0,.2,1); visibility: hidden; width: 10px; } /* show underline when focused */ .wj-labeled-input .wj-state-focused + label:after { left: 0; visibility: visible; width: 100%; } .wj-labeled-input .wj-state-invalid + label:after { background-color: #d50000; } /* validation message */ .wj-labeled-input .wj-error { color: #d50000; position: absolute; font-size: 12px; margin-top: 3px; visibility: hidden; display: block; } .wj-labeled-input .wj-control.wj-state-invalid ~ .wj-error { visibility: visible; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 | using System.Web.Mvc; namespace LearnMvcClient.Controllers { public partial class C1InputController : Controller { // GET: MaterialDesign public ActionResult MaterialDesign() { return View(); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | @ { var countries = new [] { "US" , "UK" , "Japan" , "Germany" , "France" , "Italy" , "Russia" , "China" , "India" , "Korea" , "Spain" , "Canada" , "Denmark" , "Sweden" , "Holland" , "Norway" , "Portugal" }; var colors = new [] { "Black" , "White" , "Grey" , "Red" , "Green" , "Blue" , "Yellow" , "Pink" , "Purple" , "Orange" }; } < h1 > @Html .Raw(Resources.C1Input.MaterialDesign_Title) </ h1 > < p > @Html .Raw(Resources.C1Input.MaterialDesign_Text1) </ p > < form > < div class = "wj-dialog-header" tabindex = "-1" > @Html .Raw(Resources.C1Input.MaterialDesign_Text2) </ div > < div class = "wj-dialog-body" > <!-- personal information --> < div class = "wj-labeled-input" > < div id = "name" autocomplete = "name" required accesskey = "n" > </ div > < label for = "name" > @Html .Raw(Resources.C1Input.MaterialDesign_Text3)</ label > < div class = "wj-error" tabindex = "-1" > @Html .Raw(Resources.C1Input.MaterialDesign_Text4)</ div > @Html .C1().ComboBox( "#name" ).IsEditable( true ).IsRequired( true ).ShowDropDownButton( false ) </ div > < div class = "wj-labeled-input" > < div id = "email" autocomplete = "email" required pattern = "\S+@Html.Raw(" @")\S+\.\S+" accesskey = "e" > </ div > < label for = "email" > @Html .Raw(Resources.C1Input.MaterialDesign_Text5)</ label > < div class = "wj-error" tabindex = "-1" > @Html .Raw(Resources.C1Input.MaterialDesign_Text6)</ div > @Html .C1().ComboBox( "#email" ).IsEditable( true ).IsRequired( true ).ShowDropDownButton( false ) </ div > < div class = "wj-labeled-input" > < div id = "country" items-source = "countries" accesskey = "c" > </ div > < label for = "country" > @Html .Raw(Resources.C1Input.MaterialDesign_Text7)</ label > @Html .C1().ComboBox( "#country" ).Bind(countries).IsRequired( false ).IsEditable( true ).Text( "" ) </ div > < div class = "wj-labeled-input" > < div id = "card" autocomplete = "ccnumber" pattern = "[0-9]{4} [0-9]{4} [0-9]{4} [0-9]{4}" accesskey = "r" > </ div > < label for = "card" > @Html .Raw(Resources.C1Input.MaterialDesign_Text8)</ label > < div class = "wj-error" tabindex = "-1" > @Html .Raw(Resources.C1Input.MaterialDesign_Text9)</ div > @Html .C1().InputMask( "#card" ).IsRequired( false ).Value( "" ).Mask( "9999 9999 9999 9999" ) </ div > <!-- transaction information --> < div class = "wj-labeled-input" > < div id = "date" accesskey = "d" > </ div > < label for = "date" > @Html .Raw(Resources.C1Input.MaterialDesign_Text10)</ label > @Html .C1().InputDate( "#date" ).IsRequired( false ).Value( null ) </ div > < div class = "wj-labeled-input" > < div id = "time" accesskey = "t" > </ div > < label for = "time" > @Html .Raw(Resources.C1Input.MaterialDesign_Text11)></ label > @Html .C1().InputTime( "#time" ).IsRequired( false ).Min( new DateTime(1, 1, 1, 8, 0, 0)).Max( new DateTime(1, 1, 1, 18, 0, 0)).Value( null ) </ div > < div class = "wj-labeled-input" > < div id = "qty" accesskey = "q" > </ div > < label for = "quantity" > @Html .Raw(Resources.C1Input.MaterialDesign_Text12)</ label > @Html .C1().InputNumber( "#qty" ).IsRequired( false ).Format( "n0" ).Step(1).Value( null ) </ div > < div class = "wj-labeled-input" > < div id = "discount" accesskey = "i" > </ div > < label for = "discount" > @Html .Raw(Resources.C1Input.MaterialDesign_Text13)</ label > @Html .C1().InputNumber( "#discount" ).IsRequired( false ).Format( "p0" ).Step(0.05).Min(0).Max(0.2).Value( null ) </ div > < div class = "wj-labeled-input" > < div id = "colors" accesskey = "f" > </ div > < label for = "colors" > @Html .Raw(Resources.C1Input.MaterialDesign_Text14)</ label > @Html .C1().MultiSelect( "#colors" ).Bind(colors).HeaderFormat(Resources.C1Input.MaterialDesign_Text15) </ div > </ div > < div class = "wj-dialog-footer" > < button class = "btn btn-primary" type = "submit" > @Resources .Resource.Btn_Ok</ button > < button class = "btn btn-default wj-hide-cancel" > @Resources .Resource.Btn_Cancel</ button > </ div > </ form > |