Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add equal height row component #5039

Merged
merged 1 commit into from
Apr 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions releases.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
url: /docs/patterns/navigation
status: Updated
notes: We've updated the navigation to support new theming.
- component: Equal height row
url: /docs/patterns/equal-height-row
status: New
notes: We've introduced new equal height row component (<code>.p-equal-height-row</code>) to better align content across columns.
- version: 4.9.0
features:
- component: Images
Expand Down
214 changes: 214 additions & 0 deletions scss/_patterns_equal-height-row.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
@import 'settings';

// wrapper mixin that provides relevant class selectors for 1st, 2nd and 3rd dividers
@mixin position-divider-by-order-in-grid($divider-order, $large-screen: false) {
// for large screens, dividers are positioned as pseudo elements at row level
@if $large-screen {
@if $divider-order == 1 {
&.has-1st-divider::before {
@content;
}
}

@if $divider-order == 2 {
&.has-2nd-divider::after {
@content;
}
}

@if $divider-order == 3 {
// when 3rd-divider is present and 1st-divider is not present
&.has-3rd-divider:not(.has-1st-divider)::before,
// when 3rd-divider is present and 2nd-divider is not present
&.has-3rd-divider:not(.has-2nd-divider)::after {
@content;
}

// when only 3rd-divider is present
&.has-3rd-divider:not(.has-1st-divider):not(.has-2nd-divider)::before {
@content;
}

&.has-3rd-divider:not(.has-1st-divider):not(.has-2nd-divider)::after {
display: none;
}
}
} @else {
// for smaller screens, dividers are positioned as pseudo elements at column level
@if $divider-order == 1 {
&.has-1st-divider .p-equal-height-row__col::before {
@content;
}
}

@if $divider-order == 2 {
&.has-2nd-divider .p-equal-height-row__col::after {
@content;
}
}

@if $divider-order == 3 {
&.has-3rd-divider:not(.has-1st-divider) .p-equal-height-row__col::before,
&.has-3rd-divider:not(.has-2nd-divider) .p-equal-height-row__col::after {
@content;
}

&.has-3rd-divider:not(.has-1st-divider):not(.has-2nd-divider) .p-equal-height-row__col::before {
@content;
}

&.has-3rd-divider:not(.has-1st-divider):not(.has-2nd-divider) .p-equal-height-row__col::after {
display: none;
}
}
}
}

@mixin divider-styles($large-screen: false) {
// For each row or column grid we only have access to two pseudo elements
// if 1st-divider (::before) is present, assume 2nd-divider (::after) isn't, then 3rd-divider must be (::after)
// if 2nd-divider (::after) is present, assume 1st-divider (::before) isn't, then 3rd-divider must be (::before)
@if $large-screen {
&.has-1st-divider::before,
&.has-2nd-divider::after,
&.has-3rd-divider:not(.has-1st-divider)::before,
&.has-3rd-divider:not(.has-2nd-divider)::after {
@content;
}
} @else {
// For smaller screens, the divider pseudo elements are inserted at the column level
&.has-1st-divider .p-equal-height-row__col::before,
&.has-2nd-divider .p-equal-height-row__col::after,
&.has-3rd-divider:not(.has-1st-divider) .p-equal-height-row__col::before,
&.has-3rd-divider:not(.has-2nd-divider) .p-equal-height-row__col::after {
@content;
}
}
}

@mixin vf-p-equal-height-row {
.p-equal-height-row {
@extend %vf-row;
padding-bottom: $spv--strip-regular * 0.5;
position: relative;

.p-equal-height-row__col {
// smaller screens each column will have border top by default
border-top-color: $colors--theme--border-default;
border-top-style: solid;
border-top-width: 1px;
display: grid;
grid-column: span $grid-columns-small;
grid-row: span 4;
grid-template-rows: subgrid;
margin-top: -1px;
padding-bottom: $spv--small;
position: relative;

@media screen and ($breakpoint-small <= width < $breakpoint-large) {
grid-column: span $grid-columns-medium;
grid-template-columns: subgrid;

// for medium screen, each column item will take half of the available cols from the parent grid
.p-equal-height-row__item {
grid-column: span calc($grid-columns-medium / 2);
}

// for medium screen, position the first column item on the left of the grid
.p-equal-height-row__item:first-child {
grid-row: span 100; // this needs to be sufficiently large so remaining column items won't get stretched
}
}

@media screen and (width >= $breakpoint-large) {
border: none;
grid-column: span calc($grid-columns / 4);
padding-bottom: 0;
}
}

// divider styles
@include divider-styles($large-screen: false) {
@extend %vf-pseudo-border;
}

// remove row level dividers for smaller screen sizes
@include divider-styles($large-screen: true) {
@extend %vf-pseudo-border;
display: none;
}

@include position-divider-by-order-in-grid(1) {
grid-row: 2;
}

@include position-divider-by-order-in-grid(2) {
grid-row: 3;
}

@include position-divider-by-order-in-grid(3) {
grid-row: 4;
}

@media screen and ($breakpoint-small <= width < $breakpoint-large) {
// We don't need to insert divider below item-1 for medium screen size since item-1 gets positioned on the left
@include position-divider-by-order-in-grid(1) {
display: none;
}

@include position-divider-by-order-in-grid(2) {
grid-column: 4 / 7;
grid-row: 2;
}

@include position-divider-by-order-in-grid(3) {
grid-column: 4 / 7;
grid-row: 3;
}
}

@media screen and (width >= $breakpoint-large) {
padding-bottom: $spv--strip-regular;

// remove column level dividers for large screen sizes
@include divider-styles($large-screen: false) {
display: none;
}

@include divider-styles($large-screen: true) {
display: block;
grid-column-end: span 12;
grid-column-start: 1;
margin: auto;
}

@include position-divider-by-order-in-grid(1, $large-screen: true) {
grid-row: 2;
}

@include position-divider-by-order-in-grid(2, $large-screen: true) {
grid-row: 3;
}

@include position-divider-by-order-in-grid(3, $large-screen: true) {
grid-row: 4;
}
}
}

// support for 25-75 split on large screen size for this pattern
.row--25-75-on-large > .col,
.row > .col-9 {
& .p-equal-height-row {
grid-template-columns: repeat($grid-columns-small, minmax(0, 1fr));

@media screen and ($breakpoint-small <= width < $breakpoint-large) {
grid-template-columns: repeat($grid-columns-medium, minmax(0, 1fr));
}

@media screen and (width >= $breakpoint-large) {
grid-template-columns: repeat(9, minmax(0, 1fr));
}
}
}
}
5 changes: 5 additions & 0 deletions scss/_patterns_media-container.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
@mixin vf-p-media-container {
// stylelint-disable selector-max-type -- media container can use selector type
.p-media-container {
margin-top: $spv--small;
img {
display: block;
}
}
// stylelint-enable selector-max-type
}
24 changes: 13 additions & 11 deletions scss/_vanilla.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@

@import 'patterns_accordion';
@import 'patterns_article-pagination';
@import 'patterns_badge';
@import 'patterns_breadcrumbs';
@import 'patterns_buttons';
@import 'patterns_card';
@import 'patterns_chip';
@import 'patterns_badge';
@import 'patterns_code-snippet';
@import 'patterns_contextual-menu';
@import 'patterns_divider';
@import 'patterns_equal-height-row';
@import 'patterns_form-help-text';
@import 'patterns_form-validation';
@import 'patterns_form-tick-elements';
@import 'patterns_form-password-toggle';
@import 'patterns_form-tick-elements';
@import 'patterns_form-validation';
@import 'patterns_forms';
@import 'patterns_grid';
@import 'patterns_heading-icon';
Expand All @@ -39,22 +40,22 @@
@import 'patterns_search-and-filter';
@import 'patterns_search-box';
@import 'patterns_section';
@import 'patterns_segmented-control';
@import 'patterns_separator';
@import 'patterns_side-navigation';
@import 'patterns_side-navigation-expandable';
@import 'patterns_side-navigation';
@import 'patterns_slider';
@import 'patterns_status-label';
@import 'patterns_strip';
@import 'patterns_suru';
@import 'patterns_switch';
@import 'patterns_segmented-control';
@import 'patterns_table-icons';
@import 'patterns_table-expanding';
@import 'patterns_table-of-contents';
@import 'patterns_table-icons';
@import 'patterns_table-mobile-card';
@import 'patterns_table-of-contents';
@import 'patterns_table-sortable';
@import 'patterns_tabs';
@import 'patterns_tooltips';
@import 'patterns_suru';

// Layouts
@import 'layouts_application';
Expand Down Expand Up @@ -96,22 +97,23 @@
// Patterns
@include vf-p-accordion;
@include vf-p-article-pagination;
@include vf-p-badge;
@include vf-p-breadcrumbs;
@include vf-p-buttons;
@include vf-p-card;
@include vf-p-chip;
@include vf-p-section;
@include vf-p-badge;
@include vf-p-code-snippet;
@include vf-p-contextual-menu;
@include vf-p-divider;
@include vf-p-equal-height-row;
@include vf-p-form-help-text;
@include vf-p-form-validation;
@include vf-p-form-tick-elements;
@include vf-p-form-validation;
@include vf-p-forms;
@include vf-p-grid;
@include vf-p-heading-icon;
@include vf-p-headings;
@include vf-p-section;

@include vf-p-form-password-toggle;
@include vf-p-icons;
Expand Down
11 changes: 11 additions & 0 deletions scss/standalone/patterns_equal-height-row.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@import '../vanilla';
@include vf-base;

// dependencies needed for examples
@include vf-p-buttons;
@include vf-p-media-container;
@include vf-p-headings;

// vf-p-grid is needed for this pattern to work
@include vf-p-grid;
@include vf-p-equal-height-row;
2 changes: 2 additions & 0 deletions side-navigation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
subheadings:
- title: Accordion
url: /docs/patterns/accordion
- title: Equal height row
url: /docs/patterns/equal-height-row
- title: Badge
url: /docs/patterns/badge
- title: Breadcrumbs
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
{% extends "_layouts/examples.html" %}
{% block title %}Equal height row / Three column row{% endblock %}

{% block standalone_css %}patterns_equal-height-row{% endblock %}

{% block content %}

<div class="row--25-75-on-large">
<div class="col">
<a href="#">
<p class="p-muted-heading">Latest from our blog</p>
</a>
</div>
<div class="col">
<div class="p-equal-height-row">
<div class="p-equal-height-row__col">
<a href="#" class="p-equal-height-row__item">
<p>Unleash the power of GPU: Ubuntu WorkSpaces now support Graphics G4dn bundles</p>
</a>
<p class="p-equal-height-row__item">A few months ago, the OpenSSL Project announced the end of life of OpenSSL
1.1.1. It is used by thousands of software components included in Ubuntu 18.04 LTS and Ubuntu 20.04 LTS, with
many organisations relying on version 1.1.1....</p>
<div class="p-equal-height-row__item">
<hr class="p-rule" />
<a href="#">
<p>Learn more</p>
</a>
</div>
</div>
<div class="p-equal-height-row__col">
<a href="#" class="p-equal-height-row__item">
<p>Canonical joins SOAFEE SIG Ubuntu Desktop 23.10:Mantic Minotaur deep dive</p>
</a>
<p class="p-equal-height-row__item">If you&apos;ve been following my previous blog posts, you already know that
the automotive industry is changing faster than ever. Updating software and firmware in vehicles is one area
that&apos;s particularly challenging and in flux....</p>
<div class="p-equal-height-row__item">
<hr class="p-rule" />
<a href="#">
<p>Learn more</p>
</a>
</div>
</div>
<div class="p-equal-height-row__col">
<a href="#" class="p-equal-height-row__item">
<p>Canonical joins SOAFEE SIG Ubuntu Desktop 23.10:Mantic Minotaur deep dive</p>
</a>
<p class="p-equal-height-row__item">Today, around 96% of software projects utilize open source in some way. The
web team here at Canonical is passionate about Open source. We lead with an open-by-default approach and so
almost everything we do and work on can be found publicly on the Canonical Github org.</p>
<div class="p-equal-height-row__item">
<hr class="p-rule" />
<a href="#">
<p>Learn more</p>
</a>
</div>
</div>
</div>
</div>
</div>

{% endblock %}