diff --git a/src/assets/sass/demos/block-demo.scss b/src/assets/sass/demos/block-demo.scss new file mode 100644 index 000000000..5361ea824 --- /dev/null +++ b/src/assets/sass/demos/block-demo.scss @@ -0,0 +1,87 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +/* -------------------------------------------------------------------------- */ +// Block demo + +@import '../protocol/includes/lib'; +@import '../docs/protocol'; +@import '../docs/protocol-extra'; + +#config { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + grid-column-gap: $layout-md; + grid-row-gap: $layout-md; + + fieldset fieldset { + margin-bottom: $layout-sm; + } + + legend { + @include font-size(16px); + } +} + +#config-preset { + grid-column-start: 1; + grid-column-end: 4; +} + +.demo { + .mzp-c-block, + .mzp-c-block-container, + .mzp-c-block-media, + .mzp-c-block-body { + + &:before { + content: attr(class); + background-color: #fff; + color: #000; + display: block; + font-family: monospace; + font-size: 12px; + left: 0; + padding: 0 2px; + position: absolute; + top: 0; + z-index: 1; + } + } + + .mzp-c-block-container { + &:before { + top: 1em; + } + } + + .mzp-c-block { + outline: 1px solid red; + } + + .mzp-c-block-container { + background-color: rgba(0, 0, 255, 0.1); + } + + .mzp-c-block-media { + background-color: rgba(0, 255, 0, 0.1); + } + + .mzp-c-block-body { + background-color: rgba(255, 0, 0, 0.1); + } +} + +.spacer { + align-items: center; + background-color: rgba(0, 0, 0, 0.2); + display: flex; + justify-content: center; + height: 200px; + margin: 20px; +} + +#demo-block .mzp-has-bg .mzp-c-block-container { + background-color: $color-yellow-20; +} diff --git a/src/assets/sass/demos/block.scss b/src/assets/sass/demos/block.scss new file mode 100644 index 000000000..526454acd --- /dev/null +++ b/src/assets/sass/demos/block.scss @@ -0,0 +1,10 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +/* -------------------------------------------------------------------------- */ +// Block demo + +@import '../protocol/includes/lib'; +@import '../docs/protocol'; +@import '../docs/protocol-extra'; diff --git a/src/assets/sass/protocol/components/_block.scss b/src/assets/sass/protocol/components/_block.scss new file mode 100644 index 000000000..d015daa0e --- /dev/null +++ b/src/assets/sass/protocol/components/_block.scss @@ -0,0 +1,433 @@ +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +@import '../includes/lib'; + +// horizontal spacing should match mzp-l-content's horizontal spacing + +// xs +$v-grid-xs: $layout-xs; +$h-grid-xs: $layout-lg; + +//md +$v-grid-md: $layout-md; +$h-grid-md: $layout-lg; + +//lg +$v-grid-lg: $layout-lg; +$h-grid-lg: $layout-xl; + + +/* -------------------------------------------------------------------------- */ +// Basic vertical alignment + +.mzp-c-block { + overflow-x: hidden; + padding: $v-grid-xs 0; + position: relative; + + @media #{$mq-md} { + padding: $v-grid-md 0; + } + + @media #{$mq-lg} { + padding: $v-grid-lg 0; + } +} + +.mzp-c-block-container { + @include clearfix(); + @include border-box; + margin: 0 auto; + max-width: $content-max; + min-width: $content-xs; + padding: 0 $layout-xs; + + @media #{$mq-md} { + padding: 0 $h-grid-md; + } + + @media #{$mq-lg} { + padding: 0 $h-grid-lg; + } + + .mzp-t-dark &, + .mzp-has-bg { + @include light-links; + background-color: #000; + color: #fff; + } +} + +.mzp-c-block-media-img { + display: block; +} + +.mzp-c-block-body { + position: relative; + + // vertical spacing between body and media before side by side display kicks in + @media all and (max-width: #{$screen-lg - 1}) { + &:first-child { + margin-bottom: $v-grid-xs; + + @media all and (min-width: #{$screen-md}) { + margin-bottom: $v-grid-md; + } + } + + &:last-child { + margin-top: $v-grid-xs; + + @media all and (min-width: #{$screen-md}) { + margin-top: $v-grid-md; + } + } + + .mzp-has-media-hide & { + margin-top: 0; + margin-bottom: 0; + + @media all and (min-width: #{$screen-md}) { + margin-top: 0; + margin-bottom: 0; + } + } + } +} + +.mzp-c-block-media { + position: relative; + + @media all and (max-width:#{$screen-lg - 1}) { + .mzp-has-media-hide & { + display: none; + } + } +} + +/* -------------------------------------------------------------------------- */ +// side by side layout, float based fall back + +@media #{$mq-lg} { + .mzp-c-block-body { + @include border-box; + @include bidi(((float, left, right),)); + width: 50%; + padding: 0 ($h-grid-lg / 2); + + > *:first-child { + margin-top: 0; + } + + > *:last-child { + margin-bottom: 0; + } + + .mzp-l-block-body-33 & { + width: 33.33%; + } + + .mzp-l-block-body-66 & { + width: 66.66%; + } + + .mzp-l-reversed & { + @include bidi(((float, right, left),)); + } + } + + .mzp-c-block-media { + @include border-box; + @include bidi(((float, right, left),)); + width: 50%; + padding: 0 ($h-grid-lg / 2); + + + .mzp-l-block-body-33 & { + width: 66.66%; + } + + .mzp-l-block-body-66 & { + width: 33.33%; + } + + .mzp-l-reversed & { + @include bidi(((float, left, right),)); + } + } + +} + +/* -------------------------------------------------------------------------- */ +// side by side layout, grid based + +@media #{$mq-lg} { + @supports( display:grid) { + .mzp-c-block-container { + // grid is all start/end based we don't need bidi declarations for RTL support \o/ + display: grid; + grid-template-columns: 1fr 1fr; + grid-template-areas: "body media"; + grid-column-gap: $h-grid-lg; + + .mzp-l-block-body-33 > & { + grid-template-columns: 2fr 3fr; + } + + .mzp-l-block-body-66 > & { + grid-template-columns: 3fr 2fr; + } + + .mzp-l-reversed > & { + grid-template-areas: "media body"; + } + + .mzp-l-block-body-33.mzp-l-reversed > & { + grid-template-columns: 3fr 2fr; + } + + .mzp-l-block-body-66.mzp-l-reversed > & { + grid-template-columns: 2fr 3fr; + } + } + + .mzp-c-block-body, + .mzp-c-block-media { + .mzp-c-block-container & { // extra specificitly to over-ride the styles that make the float fall-back work + float: none; + min-width: 0; //because of https://stackoverflow.com/questions/43311943/prevent-content-from-expanding-grid-items + padding: 0; + width: auto; + } + } + + .mzp-c-block-body { + grid-area: body; + } + + .mzp-c-block-media { + align-self: stretch; + grid-area: media; + + .mzp-c-block-media-img { + display: block; + max-width: none; + } + } + } +} + +/* -------------------------------------------------------------------------- */ +// constraints on height or width of media + +.mzp-c-block-media { + @media all and (max-width: #{$screen-lg - 1}) { + // center image & constrain width + &.mzp-l-media-constrain-mobile { + text-align: center; + + .mzp-c-block-media-img { + margin: 0 auto; + max-width: $content-sm; + } + } + } + + @media #{$mq-lg} { + @supports ( display:grid ) { + &.mzp-l-media-constrain-width { + .mzp-c-block-media-img { + max-width: 100%; + } + } + + &.mzp-l-media-constrain-height { + height: 100%; + justify-self: auto !important; /* stylelint-disable-line declaration-no-important */ + + .mzp-c-block-media-img { + bottom: 0; + left: 0; + max-height: 100%; + max-width: auto; + position: absolute; + top: 0; + width: auto; + + [dir='rtl'] &, + .mzp-l-reversed & { + left: auto; + right: 0; + } + } + } + } + } +} + +/* --------------------------------------------------------------------------- */ +// vertical spacing for body or media + + +.mzp-t-dark, +.mzp-has-bg { + .mzp-c-block-body { + // vertical spacing between text and edges when there's a bg-color + @media all and (max-width: #{$screen-lg - 1}) { + &:first-child { + padding-top: $v-grid-xs; + + @media all and (min-width: #{$screen-md}) { + padding-top: $v-grid-md; + } + } + + &:last-child { + padding-bottom: $v-grid-xs; + + @media all and (min-width: #{$screen-md}) { + padding-bottom: $v-grid-md; + } + } + + @at-root #{selector-append(".mzp-has-media-hide", &)} { + padding-top: $v-grid-xs; + padding-bottom: $v-grid-xs; + + @media all and (min-width: #{$screen-md}) { + padding-top: $v-grid-md; + padding-bottom: $v-grid-md; + } + } + } + } +} + +@media #{$mq-lg} { + @supports(display:grid) { + .mzp-t-dark, + .mzp-has-bg { + .mzp-c-block-body { + padding: $v-grid-lg 0; + } + } + + .mzp-l-v-pad { + &.mzp-c-block-body, + &.mzp-c-block-media { + padding: $v-grid-lg 0; + } + } + + .mzp-l-pop-top, + .mzp-l-pop { + &.mzp-c-block { + padding-top: $v-grid-lg * 2; + } + .mzp-c-block-media { + margin-top: $v-grid-lg * -1; + } + } + .mzp-l-pop-bottom, + .mzp-l-pop { + &.mzp-c-block { + padding-bottom: $v-grid-lg * 2; + } + .mzp-c-block-media { + margin-bottom: $v-grid-lg * -1; + } + } + } +} + +/* --------------------------------------------------------------------------- */ +// vertical and horizontal aligment for body or media +// text align works for float fallback +// justify positioning works for no constraint or width constraint +// absolute positioning works on constrain-height + +.mzp-c-block-container { + .mzp-l-h-start { + @include bidi(((text-align, left, right),)); + justify-self: start; + + .mzp-c-block-media-img { + @include bidi(( + (margin-right, auto, margin-left, 0), + (margin-left, 0, margin-right, 0), + )); + } + } + + .mzp-l-h-center { + justify-self: center; + text-align: center; + + .mzp-c-block-media-img { + margin: 0 auto; + } + + @media #{$mq-lg} { + @supports(display:grid) { + &.mzp-l-media-constrain-height .mzp-c-block-media-img { + left: 50%; + transform: translateX(-50%); + } + } + } + } + + .mzp-l-h-end { + @include bidi(((text-align, right, left),)); + justify-self: end; + + .mzp-c-block-media-img { + @include bidi(( + (margin-left, auto, margin-right, 0), + (margin-right, 0, margin-left, 0), + )); + } + + @media #{$mq-lg} { + @supports(display:grid) { + &.mzp-l-media-constrain-height .mzp-c-block-media-img { + right: 0; + left: auto; + } + } + } + } + + // vertical alignment only after grid starts + @media #{$mq-lg} { + @supports(display:grid) { + + .mzp-l-v-start { + align-self: start; + } + + .mzp-l-v-center { + align-self: center; + + &.mzp-l-media-constrain-height .mzp-c-block-media-img { + top: 50%; + transform: translateY(-50%); + } + + &.mzp-l-h-center.mzp-l-media-constrain-height .mzp-c-block-media-img { + transform: translateY(-50%) translateX(-50%); + } + } + + .mzp-l-v-end { + align-self: end; + + &.mzp-l-media-constrain-height .mzp-c-block-media-img { + top: auto; + } + } + } + } +} diff --git a/src/assets/sass/protocol/protocol-extra.scss b/src/assets/sass/protocol/protocol-extra.scss index 7b25f944e..bc6fabdd5 100644 --- a/src/assets/sass/protocol/protocol-extra.scss +++ b/src/assets/sass/protocol/protocol-extra.scss @@ -9,6 +9,7 @@ $image-path: '../img' !default; @import '../protocol/components/article'; @import '../protocol/components/billboard'; +@import '../protocol/components/block'; @import '../protocol/components/button'; @import '../protocol/components/call-out'; @import '../protocol/components/emphasis-box'; diff --git a/src/pages/demos/block-demo.hbs b/src/pages/demos/block-demo.hbs new file mode 100644 index 000000000..9cdd85f0e --- /dev/null +++ b/src/pages/demos/block-demo.hbs @@ -0,0 +1,479 @@ +--- +title: Block Examples +layout: blank +styles: + - block-demo +--- + +Interactive widget: +- toggle outlines +-> output what classes to add to what elements + +
+ + +Block body description. Add logos, buttons, more paragraphs, etc. Whatever the design calls for.
+ {{/content}} + {{/embed}} +set the horizontal alignment when using reversed because the default stays left
+in some cases pop-bottom will need you to set a bottom vertical aligment
+cant pop both top and bottom with constrain-height, you can probably get the effect you want with constrain width
+body and media pad are top and bottom right now, top OR buttom can be added if needed
+ +test on small screens. You might want to set an aligment on a small screen even if it doensn't look like it needs it at large
+ +bug on blue accounts banner with "mzp-c-block-media mzp-l-pop-top mzp-l-v-end mzp-l-media-constrain-height" when text content excees height of image.
+can't use mzp-l-media-constrain-height with v-?
need to add mzp-l-h-end to is-reversed in some cases
3 uttility classes, each controls something different, layout, green box, image in green box
+ +The image will be it's natural height, pushing the container larger.
+In some cases this means the image will overflow the container.
+ {{/content}} + {{/embed}} + + {{#embed "patterns.organisms.block.block" body_classes="" media_classes="mzp-l-media-constrain-height" }} + {{#content "content"}} +The image will be constrained by the height of the media container, to the maximum of the image height.
+ {{/content}} + {{/embed}} + + {{#embed "patterns.organisms.block.block" body_classes="" media_classes="mzp-l-media-constrain-height" }} + {{#content "content"}} +In some cases this means the image will overflow the container.
+By the image will be constrained by the width of the media container.
+ {{/content}} + {{/embed}} + +By default the body is 50% of the available space.
+ {{/content}} + {{/embed}} + + {{#embed "patterns.organisms.block.block" block_classes="mzp-l-block-body-33" body_classes="" }} + {{#content "content"}} +The body can be 33%
+ {{/content}} + {{/embed}} + + {{#embed "patterns.organisms.block.block" block_classes="mzp-l-block-body-66" body_classes="" }} + {{#content "content"}} +The body can be 66%
+ {{/content}} + {{/embed}} + + + {{#embed "patterns.organisms.block.block" block_classes="mzp-l-reversed" body_classes="" media_classes="" }} + {{#content "content"}} +An inversed block will have the media on the left.
+If you do not contrtain the width or height of the image be sure to set a horizontal aligment for it or it will overlap the text (like this!).
+ {{/content}} + {{/embed}} + +Both the body and media will be inside the block container with no padding between them and the edges.
+ {{/content}} + {{/embed}} + + {{#embed "patterns.organisms.block.block" block_classes="mzp-l-pop-top" }} + {{#content "content"}} +Chaning the fit to "pop" will make the media pop out of the block container. It can be set on all sides with mzp-l-pop or on individual sides with mzp-l-pop-top, mzp-l-pop-bottom, or mzp-l-pop-side. The image can only pop out of the container on the top, bottom, and side away from the body text.
In the examples above the image overflows the container. If you want it to stay inside the container one of the contstraint classes will need to be added.
+ {{/content}} + {{/embed}} + +The body is top and left aligned by default.
+ {{/content}} + {{/embed}} + + {{#embed "patterns.organisms.block.block" body_classes="mzp-l-v-end" }} + {{#content "content"}} +The text can be aligned to the bottom.
+ {{/content}} + {{/embed}} + + {{#embed "patterns.organisms.block.block" body_classes="mzp-l-v-center" }} + {{#content "content"}} +Or vertically centered.
+ {{/content}} + {{/embed}} + + {{#embed "patterns.organisms.block.block" body_classes="mzp-l-h-center" }} + {{#content "content"}} +Or horizontally centered.
+ {{/content}} + {{/embed}} + + {{#embed "patterns.organisms.block.block" body_classes="mzp-l-h-end" }} + {{#content "content"}} +Or horizontally aligned to the other side of the body container.
+ {{/content}} + {{/embed}} + + {{#embed "patterns.organisms.block.block" body_classes="mzp-l-v-end mzp-l-h-end" }} + {{#content "content"}} +Here is mzp-l-v-end and mzp-l-h-end.
+ {{/content}} + {{/embed}} + +The media is top aligned by default, on desktop. And center aligned by default on mobile.
+The media can be aligned to the bottom.
+Or vertically centered.
+Or horizontally centered.
+ {{/content}} + {{/embed}} + + {{#embed "patterns.organisms.block.block" media_classes="mzp-l-h-end" img_src="add-ons.png" }} + {{#content "content"}} +Or horizontally aligned to the other side of the body container.
+ {{/content}} + {{/embed}} + + {{#embed "patterns.organisms.block.block" media_classes="mzp-l-v-end mzp-l-h-end" img_src="add-ons.png" }} + {{#content "content"}} +Here is mzp-l-v-end and mzp-l-h-end.
+
+ It will restrict the size of the media and center it on mobile.
+
+ (See above)
+(See below)
+
+
+ Test
+A description with approximately 140 characters. That means we usually only have room for one or two sentences. This is what that looks like.
++ Call to action +
+ {{/content}} +{{/embed}} + +{{#embed "patterns.organisms.block.block" block_classes="mzp-l-block-body-66" body_classes="mzp-l-v-center" media_classes="mzp-l-media-constrain-width" }} + {{#content "content"}} +A longer description for more detailed copy. Here we have room for several sentences, but try not to make a paragraph too long as this will take up more space on smaller screens. Copy will also be on average 1/3 longer than English when translated to different languages, so try to keep sentences short and concise.
+ {{/content}} +{{/embed}} + +{{#embed "patterns.organisms.block.block" block_classes="mzp-l-block-body-33 mzp-l-reversed" body_classes="mzp-l-v-start" media_classes="mzp-l-v-center mzp-l-media-constrain-width" }} + {{#content "content"}} +A short description with a maximum of about 60 characters.
+A short description with a maximum of about 60 characters.
+A short description with a maximum of about 60 characters.
+A description with a maximum of 100 characters. That usually means only one or two sentences.
+ Learn more about us + {{/content}} +{{/embed}} + +A description with a maximum of 100 characters. That usually means only one or two sentences.
+ Learn more about us +
+ Firefox fights for you.
+ +
+
+ No more getting locked out of apps and websites. Lockbox secures all the passwords you’ve saved in Firefox and gives you easy access across all your iOS devices.
+ +
+
+ A description with a maximum of 140 characters and a link. That means we usually only have room for one or two sentences. Like this.
++ Call to action +
+ {{/block}} +
+ {{/if}}
+