diff --git a/app/views/split_checkout/_details.html.haml b/app/views/split_checkout/_details.html.haml index a3927a0b3b..2a627b649c 100644 --- a/app/views/split_checkout/_details.html.haml +++ b/app/views/split_checkout/_details.html.haml @@ -6,14 +6,14 @@ = t("split_checkout.step1.contact_information.title") .two-columns-inputs - %div.checkout-input + %div.checkout-input.with-floating-label{ "data-controller": "floating-label" } = f.label :email, t("split_checkout.step1.contact_information.email.label") - = f.text_field :email, { placeholder: t("split_checkout.step1.contact_information.email.placeholder") } + = f.text_field :email, { placeholder: " " } = f.error_message_on :email - %div.checkout-input + %div.checkout-input.with-floating-label{ "data-controller": "floating-label" } = bill_address.label :phone, t("split_checkout.step1.contact_information.phone.label") - = bill_address.text_field :phone, { placeholder: t("split_checkout.step1.contact_information.phone.placeholder") } + = bill_address.text_field :phone, { placeholder: " " } = f.error_message_on "bill_address.phone" %div.checkout-substep @@ -22,34 +22,34 @@ = t("split_checkout.step1.billing_address.title") .two-columns-inputs - %div.checkout-input + %div.checkout-input.with-floating-label{ "data-controller": "floating-label" } = bill_address.label :firstname, t("split_checkout.step1.billing_address.first_name.label") - = bill_address.text_field :firstname, { placeholder: t("split_checkout.step1.billing_address.first_name.placeholder") } + = bill_address.text_field :firstname, { placeholder: " " } = f.error_message_on "bill_address.firstname" - %div.checkout-input + %div.checkout-input.with-floating-label{ "data-controller": "floating-label" } = bill_address.label :lastname, t("split_checkout.step1.billing_address.last_name.label") - = bill_address.text_field :lastname, { placeholder: t("split_checkout.step1.billing_address.last_name.placeholder") } + = bill_address.text_field :lastname, { placeholder: " " } = f.error_message_on "bill_address.lastname" - %div.checkout-input + %div.checkout-input.with-floating-label{ "data-controller": "floating-label"} = bill_address.label :address1, t("split_checkout.step1.address.address1.label") - = bill_address.text_field :address1, { placeholder: t("split_checkout.step1.address.address1.placeholder") } + = bill_address.text_field :address1, { placeholder: " " } = f.error_message_on "bill_address.address1" - %div.checkout-input + %div.checkout-input.with-floating-label{ "data-controller": "floating-label"} = bill_address.label :address2, t("split_checkout.step1.address.address2.label") - = bill_address.text_field :address2, { placeholder: t("split_checkout.step1.address.address2.placeholder") } + = bill_address.text_field :address2, { placeholder: " " } = f.error_message_on "bill_address.address2" - %div.checkout-input + %div.checkout-input.with-floating-label{ "data-controller": "floating-label"} = bill_address.label :city, t("split_checkout.step1.address.city.label") - = bill_address.text_field :city, { placeholder: t("split_checkout.step1.address.city.placeholder") } + = bill_address.text_field :city, { placeholder: " " } = f.error_message_on "bill_address.city" - %div.checkout-input + %div.checkout-input.with-floating-label{ "data-controller": "floating-label"} = bill_address.label :zipcode, t("split_checkout.step1.address.zipcode.label") - = bill_address.text_field :zipcode, { placeholder: t("split_checkout.step1.address.zipcode.placeholder") } + = bill_address.text_field :zipcode, { placeholder: " " } = f.error_message_on "bill_address.zipcode" %div{ "data-controller": "dependent-select", "data-dependent-select-options-value": countries_with_states } @@ -112,24 +112,24 @@ %div{"data-shippingmethod-target": "shippingMethodAddress", style: "display: #{!display_ship_address || shipping_and_billing_match?(@order) ? 'none' : 'block'}" } = f.fields :ship_address, model: @order.ship_address do |ship_address| - %div.checkout-input + %div.checkout-input.with-floating-label{ "data-controller": "floating-label"} = ship_address.label :address1, t("split_checkout.step1.address.address1.label") - = ship_address.text_field :address1, { placeholder: t("split_checkout.step1.address.address1.placeholder") } + = ship_address.text_field :address1, { placeholder: " " } = f.error_message_on "ship_address.address1" - %div.checkout-input + %div.checkout-input.with-floating-label{ "data-controller": "floating-label"} = ship_address.label :address2, t("split_checkout.step1.address.address2.label") - = ship_address.text_field :address2, { placeholder: t("split_checkout.step1.address.address2.placeholder") } + = ship_address.text_field :address2, { placeholder: " " } = f.error_message_on "ship_address.address2" - %div.checkout-input + %div.checkout-input.with-floating-label{ "data-controller": "floating-label"} = ship_address.label :city, t("split_checkout.step1.address.city.label") - = ship_address.text_field :city, { placeholder: t("split_checkout.step1.address.city.placeholder") } + = ship_address.text_field :city, { placeholder: " " } = f.error_message_on "ship_address.city" - %div.checkout-input + %div.checkout-input.with-floating-label{ "data-controller": "floating-label"} = ship_address.label :zipcode, t("split_checkout.step1.address.zipcode.label") - = ship_address.text_field :zipcode, { placeholder: t("split_checkout.step1.address.zipcode.placeholder") } + = ship_address.text_field :zipcode, { placeholder: " " } = f.error_message_on "ship_address.zipcode" %div{ "data-controller": "dependent-select", "data-dependent-select-options-value": countries_with_states } diff --git a/app/webpacker/controllers/floating_label_controller.js b/app/webpacker/controllers/floating_label_controller.js new file mode 100644 index 0000000000..7361ff3fd2 --- /dev/null +++ b/app/webpacker/controllers/floating_label_controller.js @@ -0,0 +1,30 @@ +import { Controller } from "stimulus"; + +export default class extends Controller { + connect() { + const input = this.element.querySelector("input"); + input.addEventListener("focus", this.focus.bind(this)); + input.addEventListener("blur", this.blur.bind(this)); + if (input.value.length > 0) { + this.focus(); + } + + const label = this.element.querySelector("label"); + // Add transition class to the label and display the label + // after a short delay to avoid flickering + setTimeout(() => { + label.classList.add("with-transition"); + label.style.display = "block"; + }, 100); + } + + focus() { + this.element.classList.add("active"); + } + + blur(e) { + if (e.target.value.length === 0) { + this.element.classList.remove("active"); + } + } +} diff --git a/app/webpacker/css/darkswarm/split-checkout.scss b/app/webpacker/css/darkswarm/split-checkout.scss index 5d0e682cae..6a9cc3a90c 100644 --- a/app/webpacker/css/darkswarm/split-checkout.scss +++ b/app/webpacker/css/darkswarm/split-checkout.scss @@ -331,3 +331,35 @@ } } } + +// Shows label as a placeholder, inside the input and when the input is focused shows the label above the input +.checkout-input.with-floating-label { + position: relative; + + label { + display: none; // Display none by default, and shown by floating_label_controller + position: absolute; + top: 0; + left: 0; + font-size: 0.875rem; + padding: 8px; + padding-left: 9px; + color: $min-accessible-grey; + pointer-events: none; + transform: translateY(0); + transform-origin: top left; + &.with-transition { + transition: all 0.2s ease-in-out; + } + } + &.active { + label { + transform: translateY(-9px) translateX(10px) scale(0.9); + background-color: white; + padding-left: 3px; + padding-right: 3px; + padding-top: 0; + padding-bottom: 0; + } + } +} diff --git a/config/locales/en.yml b/config/locales/en.yml index 488f01aab3..0c97da073e 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1919,33 +1919,25 @@ en: title: Contact information email: label: Email - placeholder: e.g. Janedoe@email.com phone: label: Phone number - placeholder: e.g. 07987654321 billing_address: title: Billing address first_name: label: First Name - placeholder: e.g. Jane last_name: label: Last Name - placeholder: e.g. Doe address: address1: label: Address (Street + House Number) - placeholder: e.g. Flat 1 Elm apartments address2: label: Additional address info (optional) - placeholder: e.g. Cavalier avenur city: label: City - placeholder: e.g. London state_id: label: State zipcode: label: Postcode - placeholder: e.g. SW11 3QN country_id: label: Country shipping_info: