From e8de76dc46dd9830035075fbe6dc2d3527cb5eb5 Mon Sep 17 00:00:00 2001 From: Gaetan Craig-Riou Date: Wed, 4 Sep 2024 15:24:29 +1000 Subject: [PATCH] Add style for Shop As before, move imported css to partials to avoid duplication. And use mixin and variable to handle tooltip styling --- .../product_preview.turbo_stream.haml | 42 ++-- .../css/admin_v3/pages/product_preview.scss | 75 ++++++- app/webpacker/css/darkswarm/_shop-inputs.scss | 76 +------ .../css/darkswarm/_shop-product-rows.scss | 196 +----------------- .../css/darkswarm/_shop-product-thumb.scss | 29 +-- .../darkswarm/shop_partials/_shop-inputs.scss | 76 +++++++ .../shop_partials/_shop-product-rows.scss | 195 +++++++++++++++++ .../shop_partials/_shop-product-thumb.scss | 28 +++ .../css/shared/question-mark-icon.scss | 20 +- 9 files changed, 409 insertions(+), 328 deletions(-) create mode 100644 app/webpacker/css/darkswarm/shop_partials/_shop-inputs.scss create mode 100644 app/webpacker/css/darkswarm/shop_partials/_shop-product-rows.scss create mode 100644 app/webpacker/css/darkswarm/shop_partials/_shop-product-thumb.scss diff --git a/app/views/admin/products_v3/product_preview.turbo_stream.haml b/app/views/admin/products_v3/product_preview.turbo_stream.haml index d1498775a3..ca4e62b535 100644 --- a/app/views/admin/products_v3/product_preview.turbo_stream.haml +++ b/app/views/admin/products_v3/product_preview.turbo_stream.haml @@ -35,22 +35,24 @@ .product-producer = t :products_from %span - = @product.variants.first.supplier.name - .filter-shopfront.property-selectors.inline-block - %ul - - @product.properties_including_inherited.each do |property| - %li - - if property[:value].present? - = render partial: "admin/shared/tooltip", locals: { tooltip_text: property[:value], link_text: property[:name], placement: "bottom" } - - else - %a - %span - = property[:name] + %a + = @product.variants.first.supplier.name + .product-properties.filter-shopfront.property-selectors + .filter-shopfront.property-selectors.inline-block + %ul + - @product.properties_including_inherited.each do |property| + %li + - if property[:value].present? + = render partial: "admin/shared/tooltip", locals: { tooltip_text: property[:value], link_text: property[:name], placement: "bottom" } + - else + %a + %span + = property[:name] .shop-variants - @product.variants.sort { |v1, v2| v1.name_to_display <=> v2.name_to_display }.sort { |v1, v2| v1.unit_value <=> v2.unit_value }.each do |variant| .variants.row .small-3.columns.variant-name - - if variant.display_name + - if variant.display_name.present? .inline = variant.display_name .variant-unit @@ -58,8 +60,7 @@ .small-4.medium-3.columns.variant-price = number_to_currency(variant.price) .unit-price.variant-unit-price - -# TODO tool tip - = render partial: "admin/shared/tooltip", locals: { tooltip_text: t("js.shopfront.unit_price_tooltip"), link_text: "?", link: "#", link_class: "question-mark-icon", placement: "top" } + = render partial: "admin/shared/tooltip", locals: { tooltip_text: t("js.shopfront.unit_price_tooltip"), link_text: "", link: "", link_class: "question-mark-icon", placement: "top" } - # TODO use an helper - unit_price = UnitPrice.new(variant) - price_per_unit = variant.price / (unit_price.denominator || 1) @@ -71,16 +72,13 @@ = number_to_currency(0.00) .small-5.medium-3.large-3.columns.variant-quantity-column.text-right .variant-quantity-inputs - %button.add-variant{ disabled: true} + %button.add-variant = t("js.shopfront.variant.add_to_cart") - - # TODO can't check the shop preferrence here, display by default ? - - if !variant.on_demand && variant.on_hand <= 3 - .variant-remaining-stock - = t("js.shopfront.variant.remaining_in_stock", quantity: variant.on_hand) - - .product-properties.filter-shopfront.property-selectors - %filter-selector{ 'selector-set' => "productPropertySelectors", objects: "[product] | propertiesWithValuesOf" } + - # TODO can't check the shop preferrence here, display by default ? + - if !variant.on_demand && variant.on_hand <= 3 + .variant-remaining-stock + = t("js.shopfront.variant.remaining_in_stock", quantity: variant.on_hand) %div{ data: { "tabs-target": "content" } } .row diff --git a/app/webpacker/css/admin_v3/pages/product_preview.scss b/app/webpacker/css/admin_v3/pages/product_preview.scss index 78250a8648..90fa84c80d 100644 --- a/app/webpacker/css/admin_v3/pages/product_preview.scss +++ b/app/webpacker/css/admin_v3/pages/product_preview.scss @@ -91,6 +91,35 @@ margin-bottom: 1.25rem; } + .text-right { + text-align: right !important; + } + + // from foundation-sites/scss/foundations/components/_buttons.scss + button, + .button { + -webkit-appearance: none; + -moz-appearance: none; + border-radius: 0; + border-style: solid; + border-width: 0; + cursor: pointer; + font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; + font-weight: normal; + line-height: normal; + margin: 0 0 1.25rem; + position: relative; + text-align: center; + text-decoration: none; + display: inline-block; + padding: 1rem 2rem 1.0625rem 2rem; + font-size: 1rem; + background-color: #008cba; + border-color: #007095; + color: #ffffff; + transition: background-color 300ms ease-out; + } + // from foundation-sites/scss/foundations/components/_grid.scss .column + .column:last-child, .column + .columns:last-child, @@ -99,6 +128,22 @@ float: right; } + .small-3 { + width: 25%; + } + + @media only screen and (min-width: 40.0625em) { + .medium-3 { + width: 20%; // original value 25% + } + } + + @media only screen and (min-width: 64.0625em) { + .large-3 { + width: 25%; + } + } + // from foundation-sites/scss/foundations/components/_global.scss img { display: inline-block; @@ -106,10 +151,11 @@ } // Import frontend partials + + // Product details @import "../../darkswarm/shop_partials/typography"; @import "../../darkswarm/overrides"; - // product preview override .row { margin: 0 auto; width: 100%; @@ -119,4 +165,31 @@ @import "../../darkswarm/shop_partials/shop-filters"; @import "../../darkswarm/shop-modals"; @import "../../darkswarm/shop_partials/images"; + + // Shop + @import "../../darkswarm/shop_partials/shop-product-thumb"; + @import "../../darkswarm/shop_partials/shop-product-rows"; + @import "../../darkswarm/shop_partials/shop-inputs"; + @import "../../shared/question-mark-icon"; + + button.add-variant { + opacity: 0.5; + } + + .variant-remaining-stock { + opacity: 0.5; + } + + .question-mark-icon { + display: block; + } + + .tooltip { + @include joyride-content; + width: $joyride-width; + } + + .arrow { + background-color: $dynamic-blue; + } } diff --git a/app/webpacker/css/darkswarm/_shop-inputs.scss b/app/webpacker/css/darkswarm/_shop-inputs.scss index 98f4f7fecf..26c28c2fa9 100644 --- a/app/webpacker/css/darkswarm/_shop-inputs.scss +++ b/app/webpacker/css/darkswarm/_shop-inputs.scss @@ -15,81 +15,7 @@ // // They are not nested so that they can be used in modals. -.variant-quantity-inputs { - height: 2.5rem; - white-space: nowrap; -} - -button.add-variant, button.variant-quantity { - height: 2.5rem; - border-radius: 0; - background-color: $orange-500; - color: white; - // Override foundation button styles: - font-size: 1rem; - margin: 0; - padding: 0; - transition: none; - - &:hover { - background-color: $orange-600; - } - - &[disabled] { - background-color: $grey-400; - - &:hover, &:focus { - background-color: $grey-400; - } - } - &:nth-of-type(1) { - border-bottom-left-radius: 0.25em; - border-top-left-radius: 0.25em; - } - &:nth-last-of-type(1) { - border-top-right-radius: 0.25em; - border-bottom-right-radius: 0.25em; - } -} - -button.add-variant { - min-width: 7rem; - padding: 0 1em; - - &[disabled] { - &:hover, &:focus { - background-color: $orange-500; - } - } -} - -button.variant-quantity { - width: 2.25rem; - - &:nth-of-type(1):not(.bulk-buy):not(.bulk-buy-add) { - border-right: .1em solid $orange-400; - } -} - -.variant-quantity-display, .variant-remaining-stock { - font-size: 0.875em; - margin-top: 0.25em; - text-align: center; - width: 7rem; - display: inline-block; -} - -.variant-quantity-display { - visibility: hidden; - - &.visible { - visibility: visible; - } -} - -.variant-remaining-stock { - color: $red-500; -} +@import "shop_partials/shop-inputs"; button.bulk-buy.variant-quantity { background-color: transparent; diff --git a/app/webpacker/css/darkswarm/_shop-product-rows.scss b/app/webpacker/css/darkswarm/_shop-product-rows.scss index 0ab0a8b1fd..ddf25d6d51 100644 --- a/app/webpacker/css/darkswarm/_shop-product-rows.scss +++ b/app/webpacker/css/darkswarm/_shop-product-rows.scss @@ -1,201 +1,7 @@ .darkswarm { products { product { - // GENERAL LAYOUT - .row { - .columns { - padding-top: 0em; - padding-bottom: 0em; - line-height: 1.1; - } - } - - .shop-variants { - // product-thumb width + 1rem - padding-left: calc(22.222% + 1rem); - - @include breakpoint(phablet) { - padding-left: 0; - clear: left; - } - } - - // ROW VARIANTS - .row.variants { - margin: 0 0 1em 0; - - &.out-of-stock { - opacity: 0.2; - } - - .variant-name, - .total-price { - padding-top: .74em; - } - .variant-price { - padding-top: .65em; - } - - // Variant name - .variant-name { - padding-left: 0; - padding-right: 0; - - @include breakpoint(phablet) { - padding-left: 0.5rem; - } - - & > *:nth-child(n + 2) { - color: $grey-550; - font-size: 0.875rem; - font-style: italic; - line-height: normal; - } - } - - // Variant price - .variant-price { - white-space: nowrap; - @include breakpoint(phablet) { - padding-left: 1rem; - } - } - - .variant-unit-price { - color: $grey-700; - font-size: 0.85rem; - margin-top: 15px; - position: relative; - left: -1px; - } - - // Total price - .total-price { - padding-left: 0rem; - color: $disabled-med; - - .filled { - color: $med-drk-grey; - } - - @include breakpoint(phablet) { - display: none; - } - } - } - - // ROW SUMMARY - .summary { - margin-left: 0; - margin-right: 0; - margin-bottom: 1.25em; - background: #fff; - - .columns { - padding-top: 1em; - padding-bottom: 1em; - line-height: 1; - - @include breakpoint(tablet) { - padding-top: 0.65rem; - padding-bottom: 0.65rem; - } - } - - .summary-header { - // product-thumb width + 1rem - padding-left: calc(22.222% + 1rem); - padding-right: 1rem; - - @include breakpoint(phablet) { - padding-left: calc(33.333% + 1rem); - } - - .product-producer { - color: $grey-550; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - font-style: italic; - - a { - color: $teal-500; - - &:hover, &:focus, &:active { - color: $teal-600; - text-decoration: underline; - } - } - } - - h3 { - font-size: 1.3rem; - margin-top: 0.75rem; - margin-bottom: 0.6rem; - } - - h3 a { - color: $orange-500; - - &:hover, &:focus, &:active { - color: $orange-600; - text-decoration: underline; - } - } - - .product-description { - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - margin-bottom: 0.75rem; - cursor: pointer; - // Force product description to be on one line - // and truncate with ellipsis - display: -webkit-box; - -webkit-line-clamp: 1; - -webkit-box-orient: vertical; - overflow: hidden; - // line-clamp is not supported in Safari - // Trick to get overflow: hidden to work in old Safari - line-height: 1rem; - height: 1.75rem; - - > div { - margin-bottom: 1.5rem; // Equivalent to p (trix doesn't use p as separator by default, so emulate div as p to be backward compatible) - } - - @include trix-styles; - } - - .product-properties { - margin: .5em 0; - - li { - margin: 0 0.25rem 0.25rem 0; - - a { - padding: 0.1em 0.625em; - - cursor: auto; - - &.has-tip { - cursor: pointer; - font-weight: normal; - } - &:hover, &:focus { - border-color: #ccc; - } - } - - // Foundation doesn't show the nub on mobile. - // Repeating the style to show it here. - .nub { - border-color: transparent transparent #333333 transparent; - } - } - } - } - } + @import "shop_partials/shop-product-rows"; } } } diff --git a/app/webpacker/css/darkswarm/_shop-product-thumb.scss b/app/webpacker/css/darkswarm/_shop-product-thumb.scss index 9b51d7f881..d218a9c1ad 100644 --- a/app/webpacker/css/darkswarm/_shop-product-thumb.scss +++ b/app/webpacker/css/darkswarm/_shop-product-thumb.scss @@ -1,34 +1,7 @@ .darkswarm { products { product { - .product-thumb { - // Desktop: the product summary is nine columns wide. Use two - // for the image. 100% / 9 * 2 = 22.222% <= 192px - width: calc(22.222%); - float: left; - - // Mobile: the summary has full twelve columns and the image - // should take four of them. 100% / 12 * 4 = 33.333% <= 227px - @include breakpoint(phablet) { - width: calc(33.333%); - } - - // Make this an anchor for the bulk label. - position: relative; - - .product-thumb__bulk-label { - background-color: $grey-700; - color: white; - position: absolute; - right: 0; - top: .8em; - padding: .25em .5em; - } - - &:hover { - filter: brightness(96%); - } - } + @import "shop_partials/shop-product-thumb"; } } } diff --git a/app/webpacker/css/darkswarm/shop_partials/_shop-inputs.scss b/app/webpacker/css/darkswarm/shop_partials/_shop-inputs.scss new file mode 100644 index 0000000000..65dbfaca77 --- /dev/null +++ b/app/webpacker/css/darkswarm/shop_partials/_shop-inputs.scss @@ -0,0 +1,76 @@ +.variant-quantity-inputs { + height: 2.5rem; + white-space: nowrap; +} + +button.add-variant, button.variant-quantity { + height: 2.5rem; + border-radius: 0; + background-color: $orange-500; + color: white; + // Override foundation button styles: + font-size: 1rem; + margin: 0; + padding: 0; + transition: none; + + &:hover { + background-color: $orange-600; + } + + &[disabled] { + background-color: $grey-400; + + &:hover, &:focus { + background-color: $grey-400; + } + } + &:nth-of-type(1) { + border-bottom-left-radius: 0.25em; + border-top-left-radius: 0.25em; + } + &:nth-last-of-type(1) { + border-top-right-radius: 0.25em; + border-bottom-right-radius: 0.25em; + } +} + +button.add-variant { + min-width: 7rem; + padding: 0 1em; + + &[disabled] { + &:hover, &:focus { + background-color: $orange-500; + } + } +} + +button.variant-quantity { + width: 2.25rem; + + &:nth-of-type(1):not(.bulk-buy):not(.bulk-buy-add) { + border-right: .1em solid $orange-400; + } +} + +.variant-quantity-display, .variant-remaining-stock { + font-size: 0.875em; + margin-top: 0.25em; + text-align: center; + width: 7rem; + display: inline-block; +} + +.variant-quantity-display { + visibility: hidden; + + &.visible { + visibility: visible; + } +} + +.variant-remaining-stock { + color: $red-500; +} + diff --git a/app/webpacker/css/darkswarm/shop_partials/_shop-product-rows.scss b/app/webpacker/css/darkswarm/shop_partials/_shop-product-rows.scss new file mode 100644 index 0000000000..1cf62b4263 --- /dev/null +++ b/app/webpacker/css/darkswarm/shop_partials/_shop-product-rows.scss @@ -0,0 +1,195 @@ +// GENERAL LAYOUT +.row { + .columns { + padding-top: 0em; + padding-bottom: 0em; + line-height: 1.1; + } +} + +.shop-variants { + // product-thumb width + 1rem + padding-left: calc(22.222% + 1rem); + + @include breakpoint(phablet) { + padding-left: 0; + clear: left; + } +} + +// ROW VARIANTS +.row.variants { + margin: 0 0 1em 0; + + &.out-of-stock { + opacity: 0.2; + } + + .variant-name, + .total-price { + padding-top: .74em; + } + .variant-price { + padding-top: .65em; + } + + // Variant name + .variant-name { + padding-left: 0; + padding-right: 0; + + @include breakpoint(phablet) { + padding-left: 0.5rem; + } + + & > *:nth-child(n + 2) { + color: $grey-550; + font-size: 0.875rem; + font-style: italic; + line-height: normal; + } + } + + // Variant price + .variant-price { + white-space: nowrap; + @include breakpoint(phablet) { + padding-left: 1rem; + } + } + + .variant-unit-price { + color: $grey-700; + font-size: 0.85rem; + margin-top: 15px; + position: relative; + left: -1px; + } + + // Total price + .total-price { + padding-left: 0rem; + color: $disabled-med; + + .filled { + color: $med-drk-grey; + } + + @include breakpoint(phablet) { + display: none; + } + } +} + +// ROW SUMMARY +.summary { + margin-left: 0; + margin-right: 0; + margin-bottom: 1.25em; + background: #fff; + + .columns { + padding-top: 1em; + padding-bottom: 1em; + line-height: 1; + + @include breakpoint(tablet) { + padding-top: 0.65rem; + padding-bottom: 0.65rem; + } + } + + .summary-header { + // product-thumb width + 1rem + padding-left: calc(22.222% + 1rem); + padding-right: 1rem; + + @include breakpoint(phablet) { + padding-left: calc(33.333% + 1rem); + } + + .product-producer { + color: $grey-550; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + font-style: italic; + + a { + color: $teal-500; + + &:hover, &:focus, &:active { + color: $teal-600; + text-decoration: underline; + } + } + } + + h3 { + font-size: 1.3rem; + margin-top: 0.75rem; + margin-bottom: 0.6rem; + } + + h3 a { + color: $orange-500; + + &:hover, &:focus, &:active { + color: $orange-600; + text-decoration: underline; + } + } + + .product-description { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + margin-bottom: 0.75rem; + cursor: pointer; + // Force product description to be on one line + // and truncate with ellipsis + display: -webkit-box; + -webkit-line-clamp: 1; + -webkit-box-orient: vertical; + overflow: hidden; + // line-clamp is not supported in Safari + // Trick to get overflow: hidden to work in old Safari + line-height: 1rem; + height: 1.75rem; + + > div { + margin-bottom: 1.5rem; // Equivalent to p (trix doesn't use p as separator by default, so emulate div as p to be backward compatible) + } + + @include trix-styles; + } + + .product-properties { + margin: .5em 0; + + li { + margin: 0 0.25rem 0.25rem 0; + + a { + padding: 0.1em 0.625em; + + cursor: auto; + + &.has-tip { + cursor: pointer; + font-weight: normal; + } + &:hover, &:focus { + border-color: #ccc; + } + } + + // Foundation doesn't show the nub on mobile. + // Repeating the style to show it here. + .nub { + border-color: transparent transparent #333333 transparent; + } + } + } + } +} diff --git a/app/webpacker/css/darkswarm/shop_partials/_shop-product-thumb.scss b/app/webpacker/css/darkswarm/shop_partials/_shop-product-thumb.scss new file mode 100644 index 0000000000..eb88dd7405 --- /dev/null +++ b/app/webpacker/css/darkswarm/shop_partials/_shop-product-thumb.scss @@ -0,0 +1,28 @@ +.product-thumb { + // Desktop: the product summary is nine columns wide. Use two + // for the image. 100% / 9 * 2 = 22.222% <= 192px + width: calc(22.222%); + float: left; + + // Mobile: the summary has full twelve columns and the image + // should take four of them. 100% / 12 * 4 = 33.333% <= 227px + @include breakpoint(phablet) { + width: calc(33.333%); + } + + // Make this an anchor for the bulk label. + position: relative; + + .product-thumb__bulk-label { + background-color: $grey-700; + color: white; + position: absolute; + right: 0; + top: .8em; + padding: .25em .5em; + } + + &:hover { + filter: brightness(96%); + } +} diff --git a/app/webpacker/css/shared/question-mark-icon.scss b/app/webpacker/css/shared/question-mark-icon.scss index e8720d207c..932c897844 100644 --- a/app/webpacker/css/shared/question-mark-icon.scss +++ b/app/webpacker/css/shared/question-mark-icon.scss @@ -50,8 +50,19 @@ margin-left: 2px; } +@mixin joyride-content { + background-color: $dynamic-blue; + padding: $padding-small; + border-radius: $radius-small; + color: $white; + width: 100%; + font-size: 0.8rem; +} + +$joyride-width: 16rem; + .joyride-tip-guide.question-mark-tooltip { - width: 16rem; + width: $joyride-width; max-width: 65%; // JS needs to be tweaked to adjust for left alignment - this is dynamic can't rewrite in CSS margin-left: -7.4rem; @@ -70,12 +81,7 @@ } .joyride-content-wrapper { - background-color: $dynamic-blue; - padding: $padding-small; - border-radius: $radius-small; - color: $white; - width: 100%; - font-size: 0.8rem; + @include joyride-content; } .joyride-nub.bottom {