Skip to content

Commit

Permalink
Merge remote-tracking branch 'shopify/main' into next
Browse files Browse the repository at this point in the history
* shopify/main:
  Gift cards/add recipient (Shopify#2412)
  Update 1 translation file (Shopify#2453)
  [Slideshow] Add ambient movement to background (Shopify#2383)
  Wrap calls to search results ind collection counts in paginate to reduce additional requests (Shopify#2421)
  [Header] Add app block in the header section (Shopify#2238)
  [Image with Text] Add ambient movement to image (Shopify#2385)
  Update 1 translation file (Shopify#2450)
  [Blog post section] Fix slides size on mobile  (Shopify#2368)
  Duplicated scrollbar in drawer menu (Shopify#2400)
  [Header locales] Support gradients (Shopify#2386)
  [Image banner] Add ambient movement to background (Shopify#2342)
  • Loading branch information
pangloss committed Mar 23, 2023
2 parents f07ba31 + e808393 commit adbc0c7
Show file tree
Hide file tree
Showing 74 changed files with 2,093 additions and 709 deletions.
26 changes: 26 additions & 0 deletions assets/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -2310,6 +2310,12 @@ product-info .loading-overlay:not(.hidden) ~ *,
align-items: center;
}

@media screen and (max-width: 749px) {
.header--has-app {
grid-template-columns: auto 1fr auto;
}
}

@media screen and (min-width: 990px) {
.header {
grid-template-columns: 1fr auto 1fr;
Expand Down Expand Up @@ -2458,6 +2464,12 @@ product-info .loading-overlay:not(.hidden) ~ *,
justify-self: end;
}

.header__icons .shopify-app-block {
max-width: 4.4rem;
max-height: 4.4rem;
overflow: hidden;
}

.header__icon:not(.header__icon--summary),
.header__icon span {
display: flex;
Expand Down Expand Up @@ -3121,3 +3133,17 @@ details-disclosure > details {
.rte blockquote > * {
margin: -0.5rem 0 -0.5rem 0;
}

/* Ambient animation */

@media (prefers-reduced-motion: no-preference) {
.animate--ambient > img,
.animate--ambient > svg {
animation: animateAmbient 30s linear infinite;
}

@keyframes animateAmbient {
0% { transform: rotate(0deg) translateX(1em) rotate(0deg) scale(1.2); }
100% { transform: rotate(360deg) translateX(1em) rotate(-360deg) scale(1.2); }
}
}
2 changes: 1 addition & 1 deletion assets/component-cart-items.css
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@

.product-option {
font-size: 1.4rem;
word-break: break-all;
word-break: break-word;
line-height: calc(1 + 0.5 / var(--font-body-scale));
}

Expand Down
1 change: 1 addition & 0 deletions assets/component-localization-form.css
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ noscript .localization-selector.link {
font-size: 1.4rem;
letter-spacing: 0.06rem;
height: auto;
background: transparent;
}

.header__localization .disclosure .localization-form__select:hover {
Expand Down
1 change: 1 addition & 0 deletions assets/component-menu-drawer.css
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ details[open].menu-opening > .menu-drawer__submenu {
.menu-drawer__utility-links {
padding: 2rem;
background-color: rgba(var(--color-foreground), 0.03);
position: relative;
}

.menu-drawer__account {
Expand Down
3 changes: 2 additions & 1 deletion assets/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ const ON_CHANGE_DEBOUNCE_TIMER = 300;
const PUB_SUB_EVENTS = {
cartUpdate: 'cart-update',
quantityUpdate: 'quantity-update',
variantChange: 'variant-change'
variantChange: 'variant-change',
cartError: 'cart-error'
};
7 changes: 6 additions & 1 deletion assets/product-form.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ if (!customElements.get('product-form')) {
this.cart = document.querySelector('cart-notification') || document.querySelector('cart-drawer');
this.submitButton = this.querySelector('[type="submit"]');
if (document.querySelector('cart-drawer')) this.submitButton.setAttribute('aria-haspopup', 'dialog');

this.hideErrors = this.dataset.hideErrors === 'true';
}

onSubmitHandler(evt) {
Expand Down Expand Up @@ -37,6 +39,7 @@ if (!customElements.get('product-form')) {
.then((response) => response.json())
.then((response) => {
if (response.status) {
publish(PUB_SUB_EVENTS.cartError, {source: 'product-form', productVariantId: formData.get('id'), errors: response.description, message: response.message});
this.handleErrorMessage(response.description);

const soldOutMessage = this.submitButton.querySelector('.sold-out-message');
Expand All @@ -51,7 +54,7 @@ if (!customElements.get('product-form')) {
return;
}

if (!this.error) publish(PUB_SUB_EVENTS.cartUpdate, {source: 'product-form'});
if (!this.error) publish(PUB_SUB_EVENTS.cartUpdate, {source: 'product-form', productVariantId: formData.get('id')});
this.error = false;
const quickAddModal = this.closest('quick-add-modal');
if (quickAddModal) {
Expand All @@ -75,6 +78,8 @@ if (!customElements.get('product-form')) {
}

handleErrorMessage(errorMessage = false) {
if (this.hideErrors) return;

this.errorMessageWrapper = this.errorMessageWrapper || this.querySelector('.product-form__error-message-wrapper');
if (!this.errorMessageWrapper) return;
this.errorMessage = this.errorMessage || this.errorMessageWrapper.querySelector('.product-form__error-message');
Expand Down
139 changes: 139 additions & 0 deletions assets/recipient-form.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
if (!customElements.get('recipient-form')) {
customElements.define('recipient-form', class RecipientForm extends HTMLElement {
constructor() {
super();
this.checkboxInput = this.querySelector(`#Recipient-Checkbox-${ this.dataset.sectionId }`);
this.checkboxInput.disabled = false;
this.hiddenControlField = this.querySelector(`#Recipient-Control-${ this.dataset.sectionId }`);
this.hiddenControlField.disabled = true;
this.emailInput = this.querySelector(`#Recipient-email-${ this.dataset.sectionId }`);
this.nameInput = this.querySelector(`#Recipient-name-${ this.dataset.sectionId }`);
this.messageInput = this.querySelector(`#Recipient-message-${ this.dataset.sectionId }`);
this.errorMessageWrapper = this.querySelector('.product-form__recipient-error-message-wrapper');
this.errorMessageList = this.errorMessageWrapper?.querySelector('ul');
this.errorMessage = this.errorMessageWrapper?.querySelector('.error-message');
this.defaultErrorHeader = this.errorMessage?.innerText;
this.currentProductVariantId = this.dataset.productVariantId;
this.addEventListener('change', this.onChange.bind(this));
}

cartUpdateUnsubscriber = undefined;
variantChangeUnsubscriber = undefined;
cartErrorUnsubscriber = undefined;

connectedCallback() {
this.cartUpdateUnsubscriber = subscribe(PUB_SUB_EVENTS.cartUpdate, (event) => {
if (event.source === 'product-form' && event.productVariantId.toString() === this.currentProductVariantId) {
this.resetRecipientForm();
}
});

this.variantChangeUnsubscriber = subscribe(PUB_SUB_EVENTS.variantChange, (event) => {
if (event.data.sectionId === this.dataset.sectionId) {
this.currentProductVariantId = event.data.variant.id.toString();
}
});

this.cartUpdateUnsubscriber = subscribe(PUB_SUB_EVENTS.cartError, (event) => {
if (event.source === 'product-form' && event.productVariantId.toString() === this.currentProductVariantId) {
this.displayErrorMessage(event.message, event.errors);
}
});
}

disconnectedCallback() {
if (this.cartUpdateUnsubscriber) {
this.cartUpdateUnsubscriber();
}

if (this.variantChangeUnsubscriber) {
this.variantChangeUnsubscriber();
}

if (this.cartErrorUnsubscriber) {
this.cartErrorUnsubscriber();
}
}

onChange() {
if (!this.checkboxInput.checked) {
this.clearInputFields();
this.clearErrorMessage();
}
}

clearInputFields() {
this.emailInput.value = '';
this.nameInput.value = '';
this.messageInput.value = '';
}

displayErrorMessage(title, body) {
this.clearErrorMessage();
this.errorMessageWrapper.hidden = false;
if (typeof body === 'object') {
this.errorMessage.innerText = this.defaultErrorHeader;
return Object.entries(body).forEach(([key, value]) => {
const errorMessageId = `RecipientForm-${ key }-error-${ this.dataset.sectionId }`
const fieldSelector = `#Recipient-${ key }-${ this.dataset.sectionId }`;
const placeholderElement = this.querySelector(`${fieldSelector}`);
const label = placeholderElement?.getAttribute('placeholder') || key;
const message = `${label} ${value}`;
const errorMessageElement = this.querySelector(`#${errorMessageId}`);
const errorTextElement = errorMessageElement?.querySelector('.error-message')
if (!errorTextElement) return;

if (this.errorMessageList) {
this.errorMessageList.appendChild(this.createErrorListItem(fieldSelector, message));
}

errorTextElement.innerText = `${message}.`;
errorMessageElement.classList.remove('hidden');

const inputElement = this[`${key}Input`];
if (!inputElement) return;

inputElement.setAttribute('aria-invalid', true);
inputElement.setAttribute('aria-describedby', errorMessageId);
});
}

this.errorMessage.innerText = body;
}

createErrorListItem(target, message) {
const li = document.createElement('li');
const a = document.createElement('a');
a.setAttribute('href', target);
a.innerText = message;
li.appendChild(a);
li.className = "error-message";
return li;
}

clearErrorMessage() {
this.errorMessageWrapper.hidden = true;

if (this.errorMessageList) this.errorMessageList.innerHTML = '';

this.querySelectorAll('.recipient-fields .form__message').forEach(field => {
field.classList.add('hidden');
const textField = field.querySelector('.error-message');
if (textField) textField.innerText = '';
});

[this.emailInput, this.messageInput, this.nameInput].forEach(inputElement => {
inputElement.setAttribute('aria-invalid', false);
inputElement.removeAttribute('aria-describedby');
});
}

resetRecipientForm() {
if (this.checkboxInput.checked) {
this.checkboxInput.checked = false;
this.clearInputFields();
this.clearErrorMessage();
}
}
});
}
2 changes: 1 addition & 1 deletion assets/section-featured-blog.css
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@

@media screen and (max-width: 749px) {
.blog__post.article {
width: calc(100% - 3rem);
width: calc(100% - 3rem - var(--grid-mobile-horizontal-spacing));
}
}

Expand Down
128 changes: 127 additions & 1 deletion assets/section-main-product.css
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@
flex: 0 0 100%;
padding: 0;
margin: 0 0 1.2rem 0;
max-width: 37rem;
max-width: 44rem;
min-width: fit-content;
border: none;
}
Expand Down Expand Up @@ -1473,3 +1473,129 @@ a.product__text {
display: none;
}
}

/* Recipient form */
.recipient-form {
/* (2.88[line-height] - 1.6rem) / 2 */
--recipient-checkbox-margin-top: 0.64rem;

display: block;
position: relative;
max-width: 44rem;
margin-bottom: 2.5rem;
}

.recipient-form-field-label {
margin: 0.6rem 0;
}

.recipient-form-field-label--space-between {
display: flex;
justify-content: space-between;
}

.recipient-checkbox {
flex-grow: 1;
font-size: 1.6rem;
display: flex;
word-break: break-word;
align-items: flex-start;
max-width: inherit;
position: relative;
}

.no-js .recipient-checkbox {
display: none;
}

.recipient-form > input[type='checkbox'] {
position: absolute;
width: 1.6rem;
height: 1.6rem;
margin: var(--recipient-checkbox-margin-top) 0;
top: 0;
left: 0;
z-index: -1;
appearance: none;
-webkit-appearance: none;
}

.recipient-fields__field {
margin: 0 0 2rem 0;
}

.recipient-fields .field__label {
white-space: nowrap;
text-overflow: ellipsis;
max-width: calc(100% - 3.5rem);
overflow: hidden;
}

.recipient-checkbox > svg {
margin-top: var(--recipient-checkbox-margin-top);
margin-right: 1.2rem;
flex-shrink: 0;
}

.recipient-form .icon-checkmark {
visibility: hidden;
position: absolute;
left: 0.28rem;
z-index: 5;
top: 0.4rem;
}

.recipient-form > input[type='checkbox']:checked + label .icon-checkmark {
visibility: visible;
}

.js .recipient-fields {
display: none;
}

.recipient-fields hr {
margin: 1.6rem auto;
}

.recipient-form > input[type='checkbox']:checked ~ .recipient-fields {
display: block;
animation: animateMenuOpen var(--duration-default) ease;
}
.recipient-form > input[type='checkbox']:not(:checked, :disabled) ~ .recipient-fields ,
.recipient-email-label {
display: none;
}

.js .recipient-email-label.required,
.no-js .recipient-email-label.optional {
display: inline;
}

.recipient-form ul {
line-height: calc(1 + 0.6 / var(--font-body-scale));
padding-left: 4.4rem;
text-align: left;
}

.recipient-form ul a {
display: inline;
}

.recipient-form .error-message::first-letter {
text-transform: capitalize;
}

@media screen and (forced-colors: active) {
.recipient-fields > hr {
border-top: 0.1rem solid rgb(var(--color-background));
}

.recipient-checkbox > svg {
background-color: inherit;
border: 0.1rem solid rgb(var(--color-background));
}

.recipient-form > input[type='checkbox']:checked + label .icon-checkmark {
border: none;
}
}

0 comments on commit adbc0c7

Please sign in to comment.