From 89d9bc0cce020ada664654f18bdfe32b8f5452bb Mon Sep 17 00:00:00 2001 From: Adam Piontek <adam@73k.us> Date: Sun, 7 Mar 2021 17:17:16 -0500 Subject: [PATCH] implemented floating labels on inputs & selects, with icons --- assets/js/app.js | 3 +- .../live/user/registration.html.leex | 64 +++++++------- .../live/user/reset_password.html.leex | 58 ++++++------- .../live/user/settings/email.html.leex | 57 +++++++------ .../live/user/settings/password.html.leex | 84 +++++++++---------- .../user_management/form_component.html.leex | 76 +++++++++-------- .../live/user_management/index.html.leex | 10 +-- .../templates/user_confirmation/new.html.eex | 10 +-- .../user_reset_password/new.html.eex | 15 ++-- .../templates/user_session/new.html.eex | 24 +++--- 10 files changed, 199 insertions(+), 202 deletions(-) diff --git a/assets/js/app.js b/assets/js/app.js index 66c975dd..b5943bc8 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -17,9 +17,8 @@ import "../node_modules/bootstrap-icons/icons/at.svg"; // email field import "../node_modules/bootstrap-icons/icons/key.svg"; // new password field import "../node_modules/bootstrap-icons/icons/key-fill.svg"; // pw confirm field import "../node_modules/bootstrap-icons/icons/lock.svg"; // current pw field -import "../node_modules/bootstrap-icons/icons/shield-shaded.svg"; // role +import "../node_modules/bootstrap-icons/icons/shield.svg"; // role // live tables -import "../node_modules/bootstrap-icons/icons/filter.svg"; import "../node_modules/bootstrap-icons/icons/backspace.svg"; // clear filter import "../node_modules/bootstrap-icons/icons/sort-down-alt.svg"; import "../node_modules/bootstrap-icons/icons/sort-up-alt.svg"; diff --git a/lib/shift73k_web/live/user/registration.html.leex b/lib/shift73k_web/live/user/registration.html.leex index f64e057e..511a9666 100644 --- a/lib/shift73k_web/live/user/registration.html.leex +++ b/lib/shift73k_web/live/user/registration.html.leex @@ -9,42 +9,42 @@ <%= form_for @changeset, "#", [phx_change: :validate, phx_submit: :save, novalidate: true, id: "reg_form"], fn f -> %> - <div class="mb-3" phx-feedback-for="<%= input_id(f, :email) %>"> - <%= label f, :email, class: "form-label" %> - <div class="input-group has-validation"> - <span class="input-group-text"> - <%= icon_div @socket, "bi-at", [class: "icon"] %> - </span> - <%= email_input f, :email, - value: input_value(f, :email), - class: input_class(f, :email, "form-control"), - placeholder: "e.g., babka@73k.us", - maxlength: User.max_email, - autofocus: true, - phx_debounce: "blur", - aria_describedby: error_ids(f, :email) - %> - <%= error_tag f, :email %> - </div> + + <div class="form-floating mb-3" phx-feedback-for="<%= input_id(f, :email) %>"> + <%= email_input f, :email, + value: input_value(f, :email), + class: input_class(f, :email, "form-control"), + placeholder: "e.g., babka@73k.us", + maxlength: User.max_email, + autofocus: true, + phx_debounce: "blur", + aria_describedby: error_ids(f, :email) + %> + <%= label f, :email do %> + <%= icon_div @socket, "bi-at", [class: "icon baseline text-muted"] %> + Email + <% end %> + <%= error_tag f, :email %> </div> - <div class="mb-3" phx-feedback-for="<%= input_id(f, :password) %>"> - <%= label f, :password, class: "form-label" %> - <div class="input-group has-validation"> - <span class="input-group-text"> - <%= icon_div @socket, "bi-key", [class: "icon"] %> - </span> - <%= password_input f, :password, - value: input_value(f, :password), - class: input_class(f, :password, "form-control"), - maxlength: User.max_password, - phx_debounce: "250", - aria_describedby: error_ids(f, :password) - %> - <%= error_tag f, :password %> - </div> + + <div class="form-floating mb-3" phx-feedback-for="<%= input_id(f, :password) %>"> + <%= password_input f, :password, + value: input_value(f, :password), + class: input_class(f, :password, "form-control"), + placeholder: "Password", + maxlength: User.max_password, + phx_debounce: "250", + aria_describedby: error_ids(f, :password) + %> + <%= label f, :password do %> + <%= icon_div @socket, "bi-key", [class: "icon baseline text-muted"] %> + Password + <% end %> + <%= error_tag f, :password %> </div> + <div class="mb-3"> <%= submit (@trigger_submit && "Saving..." || "Register"), class: "btn btn-primary", diff --git a/lib/shift73k_web/live/user/reset_password.html.leex b/lib/shift73k_web/live/user/reset_password.html.leex index baae9beb..b29ae36c 100644 --- a/lib/shift73k_web/live/user/reset_password.html.leex +++ b/lib/shift73k_web/live/user/reset_password.html.leex @@ -9,39 +9,39 @@ <%= form_for @changeset, "#", [phx_change: :validate, phx_submit: :save, novalidate: true, id: "pw_reset_form"], fn f -> %> - <div class="mb-3" phx-feedback-for="<%= input_id(f, :password) %>"> - <%= label f, :password, "New password", class: "form-label" %> - <div class="input-group has-validation"> - <span class="input-group-text"> - <%= icon_div @socket, "bi-key", [class: "icon"] %> - </span> - <%= password_input f, :password, - value: input_value(f, :password), - class: input_class(f, :password, "form-control"), - maxlength: User.max_password, - autofocus: true, - aria_describedby: error_ids(f, :password) - %> - <%= error_tag f, :password %> - </div> + <div class="form-floating mb-3" phx-feedback-for="<%= input_id(f, :password) %>"> + <%= password_input f, :password, + value: input_value(f, :password), + class: input_class(f, :password, "form-control"), + placeholder: "New Password", + maxlength: User.max_password, + autofocus: true, + aria_describedby: error_ids(f, :password) + %> + <%= label f, :password do %> + <%= icon_div @socket, "bi-key", [class: "icon baseline text-muted"] %> + New password + <% end %> + <%= error_tag f, :password %> </div> - <div class="mb-3" phx-feedback-for="<%= input_id(f, :password_confirmation) %>"> - <%= label f, :password_confirmation, "Confirm new password", class: "form-label" %> - <div class="input-group has-validation"> - <span class="input-group-text"> - <%= icon_div @socket, "bi-key-fill", [class: "icon"] %> - </span> - <%= password_input f, :password_confirmation, - value: input_value(f, :password_confirmation), - class: input_class(f, :password_confirmation, "form-control"), - maxlength: User.max_password, - aria_describedby: error_ids(f, :password_confirmation) - %> - <%= error_tag f, :password_confirmation %> - </div> + + <div class="form-floating mb-3" phx-feedback-for="<%= input_id(f, :password_confirmation) %>"> + <%= password_input f, :password_confirmation, + value: input_value(f, :password_confirmation), + class: input_class(f, :password_confirmation, "form-control"), + placeholder: "Confirm new password", + maxlength: User.max_password, + aria_describedby: error_ids(f, :password_confirmation) + %> + <%= label f, :password do %> + <%= icon_div @socket, "bi-key-fill", [class: "icon baseline text-muted"] %> + Confirm new password + <% end %> + <%= error_tag f, :password_confirmation %> </div> + <div class="mb-3"> <%= submit "Reset password", class: "btn btn-primary", diff --git a/lib/shift73k_web/live/user/settings/email.html.leex b/lib/shift73k_web/live/user/settings/email.html.leex index 8016cd85..2d1b6e47 100644 --- a/lib/shift73k_web/live/user/settings/email.html.leex +++ b/lib/shift73k_web/live/user/settings/email.html.leex @@ -4,40 +4,39 @@ <%= form_for @changeset, "#", [phx_change: :validate, phx_submit: :save, phx_target: @myself], fn f -> %> - <div class="mb-3" phx-feedback-for="<%= input_id(f, :email) %>"> - <%= label f, :email, class: "form-label" %> - <div class="input-group has-validation"> - <span class="input-group-text"> - <%= icon_div @socket, "bi-at", [class: "icon"] %> - </span> - <%= email_input f, :email, - value: input_value(f, :email), - class: input_class(f, :email, "form-control"), - placeholder: "e.g., babka@73k.us", - maxlength: User.max_email, - phx_debounce: "500", - aria_describedby: error_ids(f, :email) - %> - <%= error_tag f, :email %> - </div> + + <div class="form-floating mb-3" phx-feedback-for="<%= input_id(f, :email) %>"> + <%= email_input f, :email, + value: input_value(f, :email), + class: input_class(f, :email, "form-control"), + placeholder: "e.g., babka@73k.us", + maxlength: User.max_email, + phx_debounce: "500", + aria_describedby: error_ids(f, :email) + %> + <%= label f, :email do %> + <%= icon_div @socket, "bi-at", [class: "icon baseline text-muted"] %> + Email + <% end %> + <%= error_tag f, :email %> </div> - <div class="mb-3" phx-feedback-for="<%= input_id(f, :current_password) %>"> - <%= label f, :current_password, class: "form-label" %> - <div class="input-group"> - <span class="input-group-text"> - <%= icon_div @socket, "bi-lock", [class: "icon"] %> - </span> - <%= password_input f, :current_password, - value: input_value(f, :current_password), - class: "form-control", - aria_describedby: error_ids(f, :current_password) - %> - <%= error_tag f, :current_password %> - </div> + <div class="form-floating mb-3" phx-feedback-for="<%= input_id(f, :current_password) %>"> + <%= password_input f, :current_password, + value: input_value(f, :current_password), + class: "form-control", + placeholder: "Current Password", + aria_describedby: error_ids(f, :current_password) + %> + <%= label f, :current_password do %> + <%= icon_div @socket, "bi-lock", [class: "icon baseline text-muted"] %> + Current password + <% end %> + <%= error_tag f, :current_password %> </div> + <div class="mb-3"> <%= submit "Change email", class: "btn btn-primary", diff --git a/lib/shift73k_web/live/user/settings/password.html.leex b/lib/shift73k_web/live/user/settings/password.html.leex index b216f15c..6d781dfd 100644 --- a/lib/shift73k_web/live/user/settings/password.html.leex +++ b/lib/shift73k_web/live/user/settings/password.html.leex @@ -4,52 +4,52 @@ <%= form_for @changeset, "#", [phx_change: :validate, phx_submit: :save, phx_target: @myself], fn f -> %> - <div class="mb-3" phx-feedback-for="<%= input_id(f, :password) %>"> - <%= label f, :password, "New password", class: "form-label" %> - <div class="input-group has-validation"> - <span class="input-group-text"> - <%= icon_div @socket, "bi-key", [class: "icon"] %> - </span> - <%= password_input f, :password, - value: input_value(f, :password), - class: input_class(f, :password, "form-control"), - maxlength: User.max_password, - phx_debounce: "500", - aria_describedby: error_ids(f, :password) - %> - <%= error_tag f, :password %> - </div> + + <div class="form-floating mb-3" phx-feedback-for="<%= input_id(f, :password) %>"> + <%= password_input f, :password, + value: input_value(f, :password), + class: input_class(f, :password, "form-control"), + placeholder: "New Password", + maxlength: User.max_password, + phx_debounce: "500", + aria_describedby: error_ids(f, :password) + %> + <%= label f, :password do %> + <%= icon_div @socket, "bi-key", [class: "icon baseline text-muted"] %> + New password + <% end %> + <%= error_tag f, :password %> </div> - <div class="mb-3" phx-feedback-for="<%= input_id(f, :password_confirmation) %>"> - <%= label f, :password_confirmation, "Confirm new password", class: "form-label" %> - <div class="input-group has-validation"> - <span class="input-group-text"> - <%= icon_div @socket, "bi-key-fill", [class: "icon"] %> - </span> - <%= password_input f, :password_confirmation, - value: input_value(f, :password_confirmation), - class: input_class(f, :password_confirmation, "form-control"), - maxlength: User.max_password, - aria_describedby: error_ids(f, :password_confirmation) - %> - <%= error_tag f, :password_confirmation %> - </div> + + <div class="form-floating mb-3" phx-feedback-for="<%= input_id(f, :password_confirmation) %>"> + <%= password_input f, :password_confirmation, + value: input_value(f, :password_confirmation), + class: input_class(f, :password_confirmation, "form-control"), + placeholder: "Confirm new password", + maxlength: User.max_password, + aria_describedby: error_ids(f, :password_confirmation) + %> + <%= label f, :password_confirmation do %> + <%= icon_div @socket, "bi-key-fill", [class: "icon baseline text-muted"] %> + Confirm new password + <% end %> + <%= error_tag f, :password_confirmation %> </div> - <div class="mb-3" phx-feedback-for="<%= input_id(f, :current_password) %>"> - <%= label f, :current_password, class: "form-label" %> - <div class="input-group"> - <span class="input-group-text"> - <%= icon_div @socket, "bi-lock", [class: "icon"] %> - </span> - <%= password_input f, :current_password, - value: input_value(f, :current_password), - class: "form-control", - aria_describedby: error_ids(f, :current_password) - %> - <%= error_tag f, :current_password %> - </div> + + <div class="form-floating mb-3" phx-feedback-for="<%= input_id(f, :current_password) %>"> + <%= password_input f, :current_password, + value: input_value(f, :current_password), + class: "form-control", + placeholder: "Current Password", + aria_describedby: error_ids(f, :current_password) + %> + <%= label f, :current_password do %> + <%= icon_div @socket, "bi-lock", [class: "icon baseline text-muted"] %> + Current password + <% end %> + <%= error_tag f, :current_password %> </div> <div class="mb-3"> diff --git a/lib/shift73k_web/live/user_management/form_component.html.leex b/lib/shift73k_web/live/user_management/form_component.html.leex index 92a10f7e..65607c0c 100644 --- a/lib/shift73k_web/live/user_management/form_component.html.leex +++ b/lib/shift73k_web/live/user_management/form_component.html.leex @@ -6,32 +6,49 @@ <div class="modal-body"> - <div class="mb-3" phx-feedback-for="<%= input_id(f, :email)%>"> - <%= label f, :email, class: "form-label" %> - <div class="input-group has-validation"> - <span class="input-group-text"> - <%= icon_div @socket, "bi-at", [class: "icon"] %> - </span> - <%= email_input f, :email, - value: input_value(f, :email), - class: input_class(f, :email, "form-control"), - placeholder: "e.g., babka@73k.us", - maxlength: User.max_email, - autofocus: true, - phx_debounce: "250", - aria_describedby: error_ids(f, :email) - %> - <%= error_tag f, :email %> - </div> + <div class="form-floating mb-3" phx-feedback-for="<%= input_id(f, :email) %>"> + <%= email_input f, :email, + value: input_value(f, :email), + class: input_class(f, :email, "form-control"), + placeholder: "e.g., babka@73k.us", + maxlength: User.max_email, + autofocus: true, + phx_debounce: "250", + aria_describedby: error_ids(f, :email) + %> + <%= label f, :email do %> + <%= icon_div @socket, "bi-at", [class: "icon baseline text-muted"] %> + Email + <% end %> + <%= error_tag f, :email %> </div> + + <div class="form-floating mb-3" phx-feedback-for="<%= input_id(f, :password) %>"> + <%= password_input f, :password, + value: input_value(f, :password), + class: input_class(f, :password, "form-control"), + placeholder: "Password", + maxlength: User.max_password, + aria_describedby: error_ids(f, :password) + %> + <%= label f, :password do %> + <%= icon_div @socket, "bi-key", [class: "icon baseline text-muted"] %> + Password + <% end %> + <%= error_tag f, :password %> + </div> + + + + <%= if Roles.can?(@current_user, %User{}, :edit_role) do %> - <%= label f, :role, class: "form-label" %> - <div class="input-group mb-3"> - <span class="input-group-text"> - <%= icon_div @socket, "bi-shield-shaded", [class: "icon"] %> - </span> + <div class="form-floating"> <%= select f, :role, Enum.map(User.roles(), fn {k, _v} -> {String.capitalize(Atom.to_string(k)), k} end), class: "form-select" %> + <%= label f, :role do %> + <%= icon_div @socket, "bi-shield", [class: "icon baseline text-muted"] %> + User role + <% end %> <span class="valid-feedback text-primary" style="display: block;"> <%= role_description(input_value(f, :role)) %> </span> @@ -40,21 +57,6 @@ <%= hidden_input f, :role, value: input_value(f, :role) %> <% end %> - <div phx-feedback-for="<%= input_id(f, :password) %>"> - <%= label f, :password, class: "form-label" %> - <div class="input-group has-validation"> - <span class="input-group-text"> - <%= icon_div @socket, "bi-key", [class: "icon"] %> - </span> - <%= password_input f, :password, - value: input_value(f, :password), - class: input_class(f, :password, "form-control"), - maxlength: User.max_password, - aria_describedby: error_ids(f, :password) - %> - <%= error_tag f, :password %> - </div> - </div> </div> <div class="modal-footer"> diff --git a/lib/shift73k_web/live/user_management/index.html.leex b/lib/shift73k_web/live/user_management/index.html.leex index ef589c5e..d36fb7ab 100644 --- a/lib/shift73k_web/live/user_management/index.html.leex +++ b/lib/shift73k_web/live/user_management/index.html.leex @@ -33,18 +33,12 @@ <%= form_for :filter, "#", [phx_change: "filter-change"], fn flt -> %> <div class="input-group"> - <span class="input-group-text"> - <%= icon_div @socket, "bi-filter", [class: "icon"] %> - </span> - <%= text_input flt, :filter, name: "filter", class: "form-control", placeholder: "Filter users...", value: @query.filter %> - </button> - <%= if @query.filter == "" do %> - <button class="btn btn-outline-secondary" type="button" aria-label="Clear filter" aria-disabled="true" disabled> + <button class="btn btn-outline-primary" type="button" aria-label="Clear filter" aria-disabled="true" disabled> <% else %> - <button class="btn btn-outline-secondary" type="button" aria-label="Clear filter" phx-click="filter-clear"> + <button class="btn btn-primary" type="button" aria-label="Clear filter" phx-click="filter-clear"> <% end %> <%= icon_div @socket, "bi-backspace", [class: "icon baseline"], [role: "img", aria_hidden: false] %> </button> diff --git a/lib/shift73k_web/templates/user_confirmation/new.html.eex b/lib/shift73k_web/templates/user_confirmation/new.html.eex index d2356fa1..5053dad7 100644 --- a/lib/shift73k_web/templates/user_confirmation/new.html.eex +++ b/lib/shift73k_web/templates/user_confirmation/new.html.eex @@ -9,11 +9,7 @@ <%= form_for :user, Routes.user_confirmation_path(@conn, :create), [class: "needs-validation", novalidate: true], fn f -> %> - <%= label f, :email, class: "form-label" %> - <div class="input-group has-validation mb-3"> - <span class="input-group-text"> - <%= icon_div @conn, "bi-at", [class: "icon fs-5"] %> - </span> + <div class="form-floating mb-3"> <%= email_input f, :email, value: @current_user && @current_user.email || "", placeholder: "e.g., babka@73k.us", @@ -22,6 +18,10 @@ required: true, autofocus: !@current_user %> + <%= label f, :email do %> + <%= icon_div @conn, "bi-at", [class: "icon baseline text-muted"] %> + Email + <% end %> <span class="invalid-feedback">must be a valid email address</span> </div> diff --git a/lib/shift73k_web/templates/user_reset_password/new.html.eex b/lib/shift73k_web/templates/user_reset_password/new.html.eex index f5a4aa5b..aa2f5476 100644 --- a/lib/shift73k_web/templates/user_reset_password/new.html.eex +++ b/lib/shift73k_web/templates/user_reset_password/new.html.eex @@ -9,18 +9,17 @@ <%= form_for :user, Routes.user_reset_password_path(@conn, :create), [class: "needs-validation", novalidate: true], fn f -> %> - <%= label f, :email, class: "form-label" %> - <div class="input-group has-validation mb-3"> - <span class="input-group-text"> - <%= icon_div @conn, "bi-at", [class: "icon"] %> - </span> + <div class="form-floating mb-3"> <%= email_input f, :email, - placeholder: "e.g., babka@73k.us", class: "form-control", + placeholder: "e.g., babka@73k.us", maxlength: User.max_email, - required: true, - autofocus: true + required: true %> + <%= label f, :email do %> + <%= icon_div @conn, "bi-at", [class: "icon baseline text-muted"] %> + Email + <% end %> <span class="invalid-feedback">must be a valid email address</span> </div> diff --git a/lib/shift73k_web/templates/user_session/new.html.eex b/lib/shift73k_web/templates/user_session/new.html.eex index ad58e38e..7b62f589 100644 --- a/lib/shift73k_web/templates/user_session/new.html.eex +++ b/lib/shift73k_web/templates/user_session/new.html.eex @@ -15,32 +15,36 @@ </div> <% end %> - <%= label f, :email, class: "form-label" %> - <div class="input-group has-validation mb-3"> - <span class="input-group-text"> - <%= icon_div @conn, "bi-at", [class: "icon"] %> - </span> + + <div class="form-floating mb-3"> <%= email_input f, :email, class: "form-control", placeholder: "e.g., babka@73k.us", maxlength: User.max_email, required: true %> + <%= label f, :email do %> + <%= icon_div @conn, "bi-at", [class: "icon baseline text-muted"] %> + Email + <% end %> <span class="invalid-feedback">must be a valid email address</span> </div> - <%= label f, :password, class: "form-label" %> - <div class="input-group has-validation mb-3"> - <span class="input-group-text"> - <%= icon_div @conn, "bi-lock", [class: "icon"] %> - </span> + + <div class="form-floating mb-3"> <%= password_input f, :password, class: "form-control", + placeholder: "Password", required: true %> + <%= label f, :password do %> + <%= icon_div @conn, "bi-lock", [class: "icon baseline text-muted"] %> + Password + <% end %> <span class="invalid-feedback">password is required</span> </div> + <div class="form-check mb-3 no-valid-style"> <%= checkbox f, :remember_me, class: "form-check-input" %> <%= label f, :remember_me, "Keep me logged in for 60 days", class: "form-check-label" %>