Signed by hanna SSH key fingerprint: SHA256:4g9cWhkAAw8gwqhJUcVbSnGEvdGwklW+1Aa/fMUu59k
assets/base.css +8 −0 assets/fabrica.js +33 −0 crates/web/src/pages.rs +7 −4 assets/base.css +8 −0 275 input [ type = "password" ] , 275 input [ type = "password" ] , 276 input [ type = "email" ] , 276 input [ type = "email" ] , 277 input [ type = "search" ] , 277 input [ type = "search" ] , 278 input [ type = "url" ] , 278 textarea , 279 textarea , 279 select { 280 select { 280 width : 100% ; 281 width : 100% ; 303 . link-slot { 304 . link-slot { 304 margin-bottom : 0.5rem ; 305 margin-bottom : 0.5rem ; 305 } 306 } 307 . link-add { 308 margin-top : 0.25rem ; 309 } 310 311 [ hidden ] { 312 display : none !important ; 313 } 306 314 307 315 308 . auth-wrap { 316 . auth-wrap {
assets/fabrica.js +33 −0 56 } ) ; 56 } ) ; 57 } ) ; 57 } ) ; 58 58 59 60 61 62 document . querySelectorAll ( "[data-link-fields]" ) . forEach ( function ( wrap ) { 63 var slots = Array . prototype. slice. call ( wrap . querySelectorAll ( ".link-slot" ) ) ; 64 var addBtn = wrap . querySelector ( "[data-link-add]" ) ; 65 var firstEmptyShown ; 66 slots . forEach ( function ( s ) { 67 if ( s . value. trim ( ) ) { 68 s . hidden = false ; 69 } else if ( ! firstEmptyShown ) { 70 s . hidden = false ; 71 firstEmptyShown = true ; 72 } else { 73 s . hidden = true ; 74 } 75 } ) ; 76 function anyHidden ( ) { 77 return slots . some ( function ( s ) { return s . hidden; } ) ; 78 } 79 if ( addBtn ) { 80 addBtn . hidden = ! anyHidden ( ) ; 81 addBtn . addEventListener ( "click" , function ( ) { 82 var next = slots . filter ( function ( s ) { return s . hidden; } ) [ 0] ; 83 if ( next ) { 84 next . hidden = false ; 85 next . focus ( ) ; 86 } 87 addBtn . hidden = ! anyHidden ( ) ; 88 } ) ; 89 } 90 } ) ; 91 59 92 60 document . addEventListener ( "click" , function ( e ) { 93 document . addEventListener ( "click" , function ( e ) { 61 var btn = e . target. closest ( "[data-clipboard]" ) ; 94 var btn = e . target. closest ( "[data-clipboard]" ) ;
crates/web/src/pages.rs +7 −4 631 input type ="text" id="location" name="location" value=( val ( & user. location) ) ; 631 input type ="text" id="location" name="location" value=( val ( & user. location) ) ; 632 label for ="link1" { "Links" } 632 label for ="link1" { "Links" } 633 p class="muted field-hint" { "Up to five links (website, GitHub, Mastodon, …); icons are chosen from the address." } 633 p class="muted field-hint" { "Up to five links (website, GitHub, Mastodon, …); icons are chosen from the address." } 634 @for i in 0 ..LINK_SLOTS { 634 div class="link-fields" data-link-fields { 635 input type ="url" id=( format ! ( "link{}" , i + 1 ) ) name=( format ! ( "link{}" , i + 1 ) ) 635 @for i in 0 ..LINK_SLOTS { 636 class="link-slot" value=( user. links. get ( i) . map_or ( "" , String :: as_str) ) 636 input type ="url" id=( format ! ( "link{}" , i + 1 ) ) name=( format ! ( "link{}" , i + 1 ) ) 637 placeholder="https://example.com" ; 637 class="link-slot" value=( user. links. get ( i) . map_or ( "" , String :: as_str) ) 638 placeholder="https://example.com" ; 639 } 640 button class="btn link-add" type ="button" data-link-add { "Add link" } 638 } 641 } 639 button class="btn btn-primary" type ="submit" { "Save profile" } 642 button class="btn btn-primary" type ="submit" { "Save profile" } 640 } 643 }