diff --git a/.changeset/green-shoes-press.md b/.changeset/green-shoes-press.md new file mode 100644 index 000000000..22fcb538a --- /dev/null +++ b/.changeset/green-shoes-press.md @@ -0,0 +1,5 @@ +--- +'@cloudfour/patterns': minor +--- + +Add support for Jetpack Form Block diff --git a/src/components/checkbox/checkbox.scss b/src/components/checkbox/checkbox.scss index 2a0e8a402..8481407df 100644 --- a/src/components/checkbox/checkbox.scss +++ b/src/components/checkbox/checkbox.scss @@ -1,175 +1,5 @@ -@use '../../compiled/tokens/scss/color'; -@use '../../compiled/tokens/scss/ease'; -@use '../../compiled/tokens/scss/size'; -@use '../../compiled/tokens/scss/transition'; -@use '../../mixins/focus'; -@use '../../mixins/theme'; - -/** - * Themed properties - */ - -@include theme.props { - --theme-color-text-checkbox-checked-hover: var( - --theme-color-text-checkbox-hover - ); - --theme-color-text-checkbox-disabled: #{color.$base-gray-dark}; - --theme-color-text-checkbox-hover: #{color.$brand-primary}; -} - -@include theme.props(dark) { - --theme-color-text-checkbox-checked-hover: #{color.$brand-primary-darker}; - --theme-color-text-checkbox-disabled: #{color.$text-light}; - --theme-color-text-checkbox-hover: #{color.$text-dark}; -} - -/** - * 1. This `@supports` query prevents IE11 (and older browsers) from applying - * these styles, falling back to the native checkbox appearance. - * 2. Modern browsers let us apply wholly custom styles to certain elements, - * but only when `appearance` is set to `none`. Because this property is not - * a finalized standard, vendor prefixes are still required. - * 3. Some browsers will squish the checkbox in flex containers, which we never, - * ever want. - * 4. Without this, checkboxes appear too small unless hard-pixel sizes are - * used (ew). - */ +@use '../../mixins/toggle-input'; .c-checkbox { - @supports (-moz-appearance: none) or (-webkit-appearance: none) or - (appearance: none) { - /* 1 */ - -moz-appearance: none; /* stylelint-disable-line property-no-vendor-prefix */ - -webkit-appearance: none; /* stylelint-disable-line property-no-vendor-prefix */ - appearance: none; /* 2 */ - background-color: color.$text-light; - block-size: size.$square-toggle-medium; - border: size.$edge-control solid currentColor; - border-radius: size.$border-radius-medium; - color: color.$text-dark; - cursor: pointer; - flex: none; /* 3 */ - font: inherit; /* 4 */ - inline-size: size.$square-toggle-medium; - padding: 0; - position: relative; - transition-duration: transition.$quick; - transition-property: background-color, border-color, color; - transition-timing-function: ease.$out; - vertical-align: middle; - - /** - * State: Focused - * - * We use `focus-visible` here because checkboxes do not inherently require - * keyboard interactions. - */ - - @include focus.focus-visible { - box-shadow: 0 0 0 size.$edge-large color.$brand-primary-lighter; - } - - /** - * We add the check mark via a pseudo element so we can easily apply - * transitions to it without requiring separate elements. - * - * 1. The icon looks kind of claustrophobic if it runs right up to the - * element edge, so we re-use the border size as an inset value. This - * appears much more balanced! - * 2. Starting state of animation. - */ - - &::after { - background-image: svg-load( - 'icons/check.svg', - stroke=color.$text-light-emphasis - ); - background-position: center; - background-repeat: no-repeat; - background-size: contain; - content: ''; - inset: size.$edge-control; /* 1 */ - opacity: 0; /* 2 */ - position: absolute; - transform: scale(0); /* 2 */ - transition-duration: transition.$quick; - transition-property: opacity, transform; - transition-timing-function: ease.$out; - } - - /** - * State: Hover - */ - - &:hover { - background-color: color.$text-light-emphasis; - color: var(--theme-color-text-checkbox-hover); - } - - /** - * State: Checked - */ - - &:checked { - background-color: currentColor; - - /** - * End state of animation - */ - - &::after { - opacity: 1; - transform: scale(1); - } - - &:hover { - color: var(--theme-color-text-checkbox-checked-hover); - } - } - - /** - * State: Disabled - * - * 1. We want the checkbox to appear "read-only." A transparent background - * and dashed line help symbolize a lack of interactivity. - * 2. Same color used for disabled `c-input` borders. - */ - - &:disabled { - background-color: transparent; /* 1 */ - border-style: dashed; /* 1 */ - color: var(--theme-color-text-checkbox-disabled); /* 2 */ - cursor: not-allowed; - - &::after { - /** - * Inline SVGs aren't aware of custom properties, so we have to do a bit - * of theming trickery here - */ - - @include theme.styles { - background-image: svg-load( - 'icons/check.svg', - stroke=color.$base-gray-dark - ); - } - - @include theme.styles(dark) { - background-image: svg-load( - 'icons/check.svg', - stroke=color.$text-light - ); - } - } - - /** - * We can forego the border entirely for a disabled checkmark, as the hit - * area is unimportant. - */ - - &:checked { - border-color: transparent; - } - } - } + @include toggle-input.checkbox; } diff --git a/src/components/input/input.scss b/src/components/input/input.scss index 35a2d4187..8a26bd40f 100644 --- a/src/components/input/input.scss +++ b/src/components/input/input.scss @@ -1,164 +1,5 @@ -@use 'sass:math'; -@use '../../compiled/tokens/scss/color'; -@use '../../compiled/tokens/scss/ease'; -@use '../../compiled/tokens/scss/size'; -@use '../../compiled/tokens/scss/transition'; -@use '../../mixins/theme'; - -/** - * Themed properties - */ - -@include theme.props { - --theme-color-background-input-disabled: #{color.$base-gray-light}; - --theme-color-border-input-disabled: #{color.$base-gray}; - --theme-color-border-input-hover: #{color.$brand-primary}; -} - -@include theme.props(dark) { - --theme-color-background-input-disabled: #{color.$brand-primary-lighter}; - --theme-color-border-input-disabled: #{color.$brand-primary-dark}; - --theme-color-border-input-hover: currentColor; -} - -/** - * 1. Browsers apply certain default styles unless appearance is set to `none`. - * Unfortunately Chrome, Safari and Mozilla all still rely on the - * vendor-prefixed version of this property at the time of this writing. - * 2. Input heights vary between different types in certain browsers unless a - * height is explicitly set. - * 3. Non-normal line heights break placeholder text alignment in Safari. - * 4. Safari will not style disabled inputs with readable text unless we set - * this property in addition to `color`. Unfortunately this also resets the - * appearance of `::placeholder`, which we'll style later on. - */ +@use '../../mixins/input'; .c-input { - -moz-appearance: none; /* stylelint-disable-line property-no-vendor-prefix */ - -webkit-appearance: none; /* stylelint-disable-line property-no-vendor-prefix */ - appearance: none; /* 1 */ - background-color: color.$text-light; - block-size: size.$height-control-default; /* 2 */ - border: size.$edge-control solid currentColor; - border-radius: size.$border-radius-medium; - color: color.$text-dark; - display: block; - font: inherit; - font-style: normal; - inline-size: 100%; - line-height: normal; /* 3 */ - outline: none; - padding: size.$padding-control-vertical size.$spacing-control-text-inset; - -webkit-text-fill-color: color.$text-dark; /* 4 */ - transition-duration: transition.$quick; - transition-property: background-color, border-color; - transition-timing-function: ease.$out; - vertical-align: middle; - - /** - * For certain single-line input types, using `text-indent` instead of - * `padding-left` gives a more natural and intuitive appearance when text - * content overflows. - * - * We do not apply this for search inputs because Safari gets weird about - * search input padding. - */ - - &[type='email'], - &[type='text'] { - padding-inline-start: 0; - text-indent: size.$spacing-control-text-inset; - } - - /** - * For textareas with rows, overrides static default height - */ - - &[rows] { - block-size: auto; - } - - /** - * Progressively-enhanced styles; `is-elastic` is added by JavaScript - */ - - &.is-elastic { - resize: none; - } - - /** - * Multi-line types should be taller - */ - - @at-root textarea#{&} { - block-size: size.$height-control-multiline; - } - - /** - * Types that disclose additional options should have an icon - * - * 1. Setting the background size to `100%` avoids a strange background shift - * bug on hover in Chrome but has no visible effect in other browsers as - * long as the image is an SVG that does not preserve its aspect ratio. - * 2. Firefox misaligns inner options when padding is applied, but all modern - * browsers seem to align selects predictably even when there is no - * vertical padding. We still keep a small amount of padding because - * Firefox's inner dotted outline looks gross when it runs into the outer - * border, and existing hacks around this visibly degrade text rendering. - * 3. Prevents option text from overlapping icon. - */ - - @at-root select#{&} { - background-image: svg-load('icons/caret-down.svg', fill=color.$text-dark); - background-position: right size.$spacing-control-icon-inset center; - background-repeat: no-repeat; - background-size: size.$square-control-icon 100%; /* 1 */ - padding-block: math.div(size.$padding-control-vertical, 2); /* 2 */ - padding-inline-end: size.$spacing-control-icon-inset + - size.$square-control-icon; /* 3 */ - } - - &:hover:not(:disabled):not([readonly]) { - background-color: color.$text-light-emphasis; - border-color: var(--theme-color-border-input-hover); - } - - /** - * We use plain ol' `focus` rather than `focus-visible` because text inputs - * are almost always in a state of keyboard interaction, making the difference - * (if any) minimal. - */ - - &:focus { - background-color: #fff; - box-shadow: 0 0 0 size.$edge-large color.$brand-primary-lighter; - } - - &[readonly]:not(:disabled) { - background-color: transparent; - border-color: transparent; - color: inherit; - } - - &:disabled { - background-color: var(--theme-color-background-input-disabled); - border-color: var(--theme-color-border-input-disabled); - cursor: not-allowed; - } - - /** - * 1. We set `-webkit-text-fill-color` on the root element so that Safari - * would respect our disabled text color. But that also resets the - * `::placeholder` color, so we have to specify our own so it will be - * distinct from a normal value while maintaining reasonable high color - * contrast. - * 2. Firefox uses `opacity` instead of a lightened text color, appearing - * lighter than other browsers unless we reset it here. - */ - - &::placeholder { - color: color.$text-dark-muted; /* 1 */ - opacity: 1; /* 2 */ - -webkit-text-fill-color: color.$text-dark-muted; /* 1 */ - } + @include input.default; } diff --git a/src/mixins/_input.scss b/src/mixins/_input.scss new file mode 100644 index 000000000..3b4f1f134 --- /dev/null +++ b/src/mixins/_input.scss @@ -0,0 +1,171 @@ +@use 'sass:math'; +@use '../compiled/tokens/scss/color'; +@use '../compiled/tokens/scss/ease'; +@use '../compiled/tokens/scss/size'; +@use '../compiled/tokens/scss/transition'; +@use './theme'; + +/// Required themed properties (Default) +@include theme.props { + --theme-color-background-input-disabled: #{color.$base-gray-light}; + --theme-color-border-input-disabled: #{color.$base-gray}; + --theme-color-border-input-hover: #{color.$brand-primary}; +} + +/// Required themed properties (Dark) +@include theme.props(dark) { + --theme-color-background-input-disabled: #{color.$brand-primary-lighter}; + --theme-color-border-input-disabled: #{color.$brand-primary-dark}; + --theme-color-border-input-hover: currentColor; +} + +/// Base input styles +/// +/// 1. Browsers apply certain default styles unless appearance is set to `none`. +/// Unfortunately Chrome, Safari and Mozilla all still rely on the +/// vendor-prefixed version of this property at the time of this writing. +/// 2. Input heights vary between different types in certain browsers unless a +/// height is explicitly set. +/// 3. Non-normal line heights break placeholder text alignment in Safari. +/// 4. Safari will not style disabled inputs with readable text unless we set +/// this property in addition to `color`. Unfortunately this also resets the +/// appearance of `::placeholder`, which we'll style later on. +@mixin base { + // stylelint-disable-next-line property-no-vendor-prefix + -moz-appearance: none; + // stylelint-disable-next-line property-no-vendor-prefix + -webkit-appearance: none; + appearance: none; // 1 + background-color: color.$text-light; + block-size: size.$height-control-default; // 2 + border: size.$edge-control solid currentColor; + border-radius: size.$border-radius-medium; + color: color.$text-dark; + display: block; + font: inherit; + font-style: normal; + inline-size: 100%; + line-height: normal; // 3 + outline: none; + padding: size.$padding-control-vertical size.$spacing-control-text-inset; + -webkit-text-fill-color: color.$text-dark; // 4 + transition-duration: transition.$quick; + transition-property: background-color, border-color; + transition-timing-function: ease.$out; + vertical-align: middle; +} + +/// Single-line input styles (text, email, etc.) +/// +/// For certain single-line input types, using `text-indent` instead of +/// `padding-left` gives a more natural and intuitive appearance when text +/// content overflows. +/// +/// It is not recommended to use this for search inputs because Safari gets +/// weird about search input padding. +@mixin single-line { + padding-inline-start: 0; + text-indent: size.$spacing-control-text-inset; +} + +/// Multi-line input styles (textarea) +@mixin multi-line { + block-size: size.$height-control-multiline; + + // Let the browser determine the height of the textarea based on its content + // when it is not explicitly set. + &[rows] { + block-size: auto; + } + + // Prevent resizing if elastic JavaScript behavior is applied + &.is-elastic { + resize: none; + } +} + +/// Types that disclose additional options should have an icon +/// +/// 1. Setting the background size to `100%` avoids a strange background shift +/// bug on hover in Chrome but has no visible effect in other browsers as +/// long as the image is an SVG that does not preserve its aspect ratio. +/// 2. Firefox misaligns inner options when padding is applied, but all modern +/// browsers seem to align selects predictably even when there is no +/// vertical padding. We still keep a small amount of padding because +/// Firefox's inner dotted outline looks gross when it runs into the outer +/// border, and existing hacks around this visibly degrade text rendering. +/// 3. Prevents option text from overlapping icon. +@mixin icon-affordance( + $icon-url: svg-load('icons/caret-down.svg', fill=color.$text-dark) +) { + @if $icon-url { + background-image: $icon-url; + } + + background-position: right size.$spacing-control-icon-inset center; + background-repeat: no-repeat; + background-size: size.$square-control-icon 100%; // 1 + padding-block: math.div(size.$padding-control-vertical, 2); // 2 + padding-inline-end: size.$spacing-control-icon-inset size.$square-control-icon; // 3 +} + +/// Various input and interaction states +@mixin states { + &:hover:not(:disabled):not([readonly]) { + background-color: color.$text-light-emphasis; + border-color: var(--theme-color-border-input-hover); + } + + /// We use plain ol' `focus` rather than `focus-visible` because text inputs + /// are almost always in a state of keyboard interaction, making the difference + /// (if any) minimal. + &:focus { + background-color: #fff; + box-shadow: 0 0 0 size.$edge-large color.$brand-primary-lighter; + } + + &[readonly]:not(:disabled) { + background-color: transparent; + border-color: transparent; + color: inherit; + } + + &:disabled { + background-color: var(--theme-color-background-input-disabled); + border-color: var(--theme-color-border-input-disabled); + cursor: not-allowed; + } + + /// 1. We set `-webkit-text-fill-color` on the root element so that Safari + /// would respect our disabled text color. But that also resets the + /// `::placeholder` color, so we have to specify our own so it will be + /// distinct from a normal value while maintaining reasonable high color + /// contrast. + /// 2. Firefox uses `opacity` instead of a lightened text color, appearing + /// lighter than other browsers unless we reset it here. + &::placeholder { + color: color.$text-dark-muted; // 1 + opacity: 1; // 2 + -webkit-text-fill-color: color.$text-dark-muted; // 1 + } +} + +/// All default input styles in one convenient mixin! +@mixin default { + @include base; + + @include states; + + &[type='email'], + &[type='text'] { + @include single-line; + } + + @at-root textarea#{&} { + @include multi-line; + } + + @at-root select#{&} { + @include icon-affordance; + } +} diff --git a/src/mixins/_toggle-input.scss b/src/mixins/_toggle-input.scss new file mode 100644 index 000000000..04c6302b2 --- /dev/null +++ b/src/mixins/_toggle-input.scss @@ -0,0 +1,149 @@ +@use '../compiled/tokens/scss/color'; +@use '../compiled/tokens/scss/ease'; +@use '../compiled/tokens/scss/size'; +@use '../compiled/tokens/scss/transition'; +@use './focus'; +@use './theme'; + +@include theme.props { + --theme-color-text-checkbox-checked-hover: var( + --theme-color-text-checkbox-hover + ); + --theme-color-text-checkbox-disabled: #{color.$base-gray-dark}; + --theme-color-text-checkbox-hover: #{color.$brand-primary}; +} + +@include theme.props(dark) { + --theme-color-text-checkbox-checked-hover: #{color.$brand-primary-darker}; + --theme-color-text-checkbox-disabled: #{color.$text-light}; + --theme-color-text-checkbox-hover: #{color.$text-dark}; +} + +/// Checkbox styles +/// +/// 1. This `@supports` query prevents IE11 (and older browsers) from applying +/// these styles, falling back to the native checkbox appearance. +/// 2. Modern browsers let us apply wholly custom styles to certain elements, +/// but only when `appearance` is set to `none`. Because this property is not +/// a finalized standard, vendor prefixes are still required. +/// 3. Some browsers will squish the checkbox in flex containers, which we +/// never, ever want. +/// 4. Without this, checkboxes appear too small unless hard-pixel sizes are +/// used (ew). +@mixin checkbox { + @supports (-moz-appearance: none) or (-webkit-appearance: none) or + (appearance: none) { + // 1 + // stylelint-disable-next-line property-no-vendor-prefix + -moz-appearance: none; + // stylelint-disable-next-line property-no-vendor-prefix + -webkit-appearance: none; + appearance: none; // 2 + background-color: color.$text-light; + block-size: size.$square-toggle-medium; + border: size.$edge-control solid currentColor; + border-radius: size.$border-radius-medium; + color: color.$text-dark; + cursor: pointer; + flex: none; // 3 + font: inherit; // 4 + inline-size: size.$square-toggle-medium; + padding: 0; + position: relative; + transition-duration: transition.$quick; + transition-property: background-color, border-color, color; + transition-timing-function: ease.$out; + vertical-align: middle; + + /// State: Focused + /// + /// We use `focus-visible` here because checkboxes do not inherently require + /// keyboard interactions. + @include focus.focus-visible { + box-shadow: 0 0 0 size.$edge-large color.$brand-primary-lighter; + } + + /// We add the check mark via a pseudo element so we can easily apply + /// transitions to it without requiring separate elements. + /// + /// 1. The icon looks kind of claustrophobic if it runs right up to the + /// element edge, so we re-use the border size as an inset value. This + /// appears much more balanced! + /// 2. Starting state of animation. + &::after { + background-image: svg-load( + 'icons/check.svg', + stroke=color.$text-light-emphasis + ); + background-position: center; + background-repeat: no-repeat; + background-size: contain; + content: ''; + inset: size.$edge-control; // 1 + opacity: 0; // 2 + position: absolute; + transform: scale(0); // 2 + transition-duration: transition.$quick; + transition-property: opacity, transform; + transition-timing-function: ease.$out; + } + + /// State: Hover + &:hover { + background-color: color.$text-light-emphasis; + color: var(--theme-color-text-checkbox-hover); + } + + /// State: Checked + &:checked { + background-color: currentColor; + + /// End state of animation + &::after { + opacity: 1; + transform: scale(1); + } + + &:hover { + color: var(--theme-color-text-checkbox-checked-hover); + } + } + + /// State: Disabled + /// + /// 1. We want the checkbox to appear "read-only." A transparent background + /// and dashed line help symbolize a lack of interactivity. + /// 2. Same color used for disabled `c-input` borders. + + &:disabled { + background-color: transparent; // 1 + border-style: dashed; // 1 + color: var(--theme-color-text-checkbox-disabled); // 2 + cursor: not-allowed; + + &::after { + /// Inline SVGs aren't aware of custom properties, so we have to do a + /// bit of theming trickery here + @include theme.styles { + background-image: svg-load( + 'icons/check.svg', + stroke=color.$base-gray-dark + ); + } + + @include theme.styles(dark) { + background-image: svg-load( + 'icons/check.svg', + stroke=color.$text-light + ); + } + } + + /// We can forego the border entirely for a disabled checkmark, as the hit + /// area is unimportant. + &:checked { + border-color: transparent; + } + } + } +} diff --git a/src/vendor/wordpress/demo/contact-form/form.twig b/src/vendor/wordpress/demo/contact-form/form.twig new file mode 100644 index 000000000..2ab7b82e3 --- /dev/null +++ b/src/vendor/wordpress/demo/contact-form/form.twig @@ -0,0 +1,117 @@ +{% embed '@cloudfour/objects/container/container.twig' with { + class: 'o-container--prose o-container--pad', +} only %} + {% block content %} + {# Markup generated in a local WordPress instance with Jetpack 1.19 on March 14, 2023 #} +
+
+
+
+ + +
+ + + +
+ + +
+ + + +
+ +
+ + + +
+
+ + + +
+ +
+ + +
+
+ + + +
+ + +
+ + + +
+ + +
+ + + + + + + +
+ + +
+ + + +
+ + +
+ + + +
+ + +
+ + + +
+ +
+
+ + + + + + +
+
+ + + + +
+
+ {% endblock %} +{% endembed %} diff --git a/src/vendor/wordpress/demo/contact-form/success.twig b/src/vendor/wordpress/demo/contact-form/success.twig new file mode 100644 index 000000000..8e5ba4be8 --- /dev/null +++ b/src/vendor/wordpress/demo/contact-form/success.twig @@ -0,0 +1,62 @@ +{% embed '@cloudfour/objects/container/container.twig' with { + class: 'o-container--prose o-container--pad', +} only %} + {% block content %} + {# Markup generated in a local WordPress instance with Jetpack 1.19 on March 14, 2023 #} +
+
+

Go back

+

Your message has been sent

+ +

+
Name:
+
Test McTest
+

+

+
Email:
+
tyler@cloudfour.com
+

+

+
Who is your favorite manager?:
+
Some other guy, I can’t quite remember
+

+

+
Which are you hungry for?:
+
Pizza, Sandwiches, Chocolate
+

+

+
Why are you writing today?:
+
Sorry, my cat sat on my keyboard
+

+

+
Text:
+
This is text
+

+

+
Date:
+
Today
+

+

+
Phone:
+
5555555555
+

+

+
Website:
+
https://tylersticka.com
+

+

+
Message:
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse condimentum ultricies mi at iaculis. Aenean quis accumsan est. Duis auctor luctus dolor quis imperdiet. Duis efficitur molestie purus, a ullamcorper nulla egestas sed. Proin ut tortor ex. Nam consequat lectus feugiat, feugiat erat at, fringilla tortor.
+

+

+
Example of a checkbox:
+
Yes
+

+

+
Consent:
+
Yes
+

+
+
+ {% endblock %} +{% endembed %} diff --git a/src/vendor/wordpress/jetpack-blocks.stories.mdx b/src/vendor/wordpress/jetpack-blocks.stories.mdx index eeaf8cba8..fd05ca0f8 100644 --- a/src/vendor/wordpress/jetpack-blocks.stories.mdx +++ b/src/vendor/wordpress/jetpack-blocks.stories.mdx @@ -1,4 +1,6 @@ import { Canvas, Meta, Story } from '@storybook/addon-docs'; +import contactFormDemo from './demo/contact-form/form.twig'; +import contactFormSuccessDemo from './demo/contact-form/success.twig'; @@ -27,3 +29,27 @@ See also: [Markdown Block documentation](https://jetpack.com/support/markdown/) `} + +## Form Blocks + +Jetpack includes [a Form Block](https://jetpack.com/support/jetpack-blocks/contact-form/) which may be used to construct contact forms from various form field blocks. + +Our styles include customizations for some of these form elements, with some exceptions: + +- We do not have a custom radio input style yet. For now, the default browser styles are used. +- We do not support Jetpack's style customizations. These would make forms feel inconsistent with the rest of our experience. +- We do not optimize our styles for Jetpack's jQuery UI enhancements, which we recommend [dequeuing](http://developer.wordpress.org/reference/functions/wp_dequeue_script/) and/or [deregistering](http://developer.wordpress.org/reference/functions/wp_deregister_script/) where possible for performance. + + + + {contactFormDemo} + + + +The success messaging markup generated by these blocks is pretty quirky, but we do our best to style it. + + + + {contactFormSuccessDemo} + + diff --git a/src/vendor/wordpress/styles/_jetpack-blocks.scss b/src/vendor/wordpress/styles/_jetpack-blocks.scss index c3eacfcf0..96b423ba4 100644 --- a/src/vendor/wordpress/styles/_jetpack-blocks.scss +++ b/src/vendor/wordpress/styles/_jetpack-blocks.scss @@ -1,5 +1,172 @@ +@use '../../../mixins/border-radius'; +@use '../../../mixins/headings'; +@use '../../../mixins/input'; @use '../../../mixins/spacing'; +@use '../../../mixins/theme'; +@use '../../../mixins/toggle-input'; +@use '../../../mixins/unit'; +@use '../../../compiled/tokens/scss/color'; +@use '../../../compiled/tokens/scss/size'; +@use '../../../compiled/tokens/scss/font-weight'; +/// Apply consistent vertical rhythm to Jetpack blocks. +.wp-block-jetpack-contact-form, .wp-block-jetpack-markdown { @include spacing.vertical-rhythm; } + +/// For some reason the Jetpack contact form adds `16px` of padding as an inline +/// style with no mechanism for customization. This is a hack to remove it. +.wp-block-jetpack-contact-form { + padding: 0 !important; +} + +/// Apply our existing form component styles to Jetpack form fields. +.grunion-field { + /// Test-based inputs + &:not([type='checkbox']):not([type='radio']) { + @include input.default; + } + + /// Checkboxes + &[type='checkbox'] { + @include toggle-input.checkbox; + } +} + +/// Apply the same spacing to fields and labels as in our Form Group object. +.grunion-field-wrap, +.grunion-checkbox-multiple-options, +.grunion-radio-options { + display: grid; + gap: #{size.$spacing-gap-form-group-default}; +} + +/// Style the "(required)" text that follows required field labels. +.grunion-field-label > span { + color: var(--theme-color-text-muted); + margin-inline-start: 1ch; +} + +/// Arrange the label and input for checkboxes and radio buttons side-by-side. +.grunion-field-label.checkbox, +.grunion-checkbox-multiple-label, +.grunion-radio-label { + display: grid; + gap: 1ch; + grid-template-columns: auto 1fr; +} + +/// Style consent messaging fields in a visually distinct way, similar to a card +/// or contained WordPress block with a background. +.grunion-field-consent-wrap { + @include border-radius.conditional; + @include spacing.fluid-margin-inline-negative; + @include spacing.fluid-padding-inline; + background-color: var(--theme-color-background-secondary); + display: block; + padding-block: size.$rhythm-default; +} + +/// The submission message markup seems _ancient_. It appears to be using +/// empty paragraphs to create spacing between elements. Luckily we're able to +/// style things adequately in spite of this. +/// +/// 1. Prevent floats from breaking the layout. +.wp-block-jetpack-contact-form-container .contact-form-submission { + contain: layout; // 1 + + /// The back link should appear a bit like our tertiary buttons, though we + /// don't use those component styles directly to keep the styles manageable. + /// + /// We include a left arrow icon via a pseudo element. + .go-back-message .link { + align-items: center; + display: inline-flex; + font-weight: font-weight.$semibold; + gap: 1ch; + position: relative; + text-decoration: none; + + &::before { + background-position: center; + background-repeat: no-repeat; + background-size: 100%; + block-size: 1em; + content: ''; + inline-size: 1em; + + @include theme.styles { + background-image: svg-load( + 'icons/arrow-left.svg', + stroke=color.$text-action + ); + } + + @include theme.styles(dark) { + background-image: svg-load( + 'icons/arrow-left.svg', + stroke=color.$text-light + ); + } + } + } + + /// Success message heading. There's no means of customizing its heading level + /// so we take our best guess at the appropriate visual hierarchy. + /// + /// 1. Use existing vertical rhythm to create spacing between the heading and + /// "back" link. + /// 2. Add space afterwards. We need to use bottom margin because the field + /// names and values float. We swap the default rhythm for `rem` so it will + /// not be unexpectedly large. + h4 { + @include headings.level(2); + margin-block-start: var(--rhythm, #{size.$rhythm-default}); // 1 + + &:not(:last-child) { + margin-block-end: unit.swap(size.$rhythm-default, rem); // 2 + } + } + + /// Remove empty paragraphs to streamline traversal of the document using + /// accessibility tools. + p:empty { + display: none; + } + + /// Allow shorter name/value combinations to align themselves side-by-side as + /// space allows, breaking onto new lines when necessary. We can't use flexbox + /// or inline-block because there aren't mechanisms for breaking onto a new + /// line, and we can't use grid because the names and values vary in length + /// too much to enforce consistent columns. + .field-name, + .field-value { + float: left; + } + + /// 1. Break onto a new line with each field name. + /// 2. Field names are a slightly heavier weight. This is more necessary here + /// than in the form itself since there aren't any outlines or other + /// affordances to make the values distinct. + /// 3. Add a bit of space between names and values. + .field-name { + clear: left; // 1 + font-weight: font-weight.$medium; // 2 + margin-inline-end: 1ch; // 3 + } + + /// 1. Field values appear slightly muted. + /// 2. Because values may break onto new lines, we need to use bottom margin + /// to continue vertical rhythm. We only apply this when the field value is + /// the last of its type: We can't use `:last-child` because it is often + /// followed by an empty paragraph. (This can be simplified once + /// `margin-trim` is widely supported!) + .field-value { + color: var(--theme-color-text-muted); // 1 + + &:not(:last-of-type) { + margin-block-end: var(--rhythm, #{size.$rhythm-default}); // 2 + } + } +}