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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Horizontal list section component #5437

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open

Conversation

jmuzina
Copy link
Member

@jmuzina jmuzina commented Dec 16, 2024

Done

Implements the horizontal list section component per figma

Fixes #5433

QA

Check if PR is ready for release

If this PR contains Vanilla SCSS or macro code changes, it should contain the following changes to make sure it's ready for the release:

  • PR should have one of the following labels to automatically categorise it in release notes:
    • Feature 🎁, Breaking Change 💣, Bug 🐛, Documentation 📝, Maintenance 🔨.
  • Vanilla version in package.json should be updated relative to the most recent release, following semver convention
    • if existing APIs (CSS classes & macro APIs) are not changed it can be a bugfix release (x.x.X)
    • if existing APIs (CSS classes & macro APIs) are changed/added/removed it should be a minor version (x.X.0)
    • see the wiki for more details
  • Any changes to component class names (new patterns, variants, removed or added features) or macros should be listed on the what's new page.

Screenshots

Screenshots enclosed

Default

Large

Default Large

Medium

Default Medium

Small

Default Small

25/75

Large

25/75 Large

Medium

25/75 Medium

Small

25/75 Small

@webteam-app
Copy link

@jmuzina jmuzina force-pushed the ft-horizontal-list branch 3 times, most recently from 0192add to 78dae55 Compare December 16, 2024 19:48
scss/_patterns_lists.scss Outdated Show resolved Hide resolved
scss/_patterns_lists.scss Outdated Show resolved Hide resolved
@lyubomir-popov
Copy link
Contributor

quick chat-gpt based snippet to avoid partitioning into 3 without using the current grid at all /* Base styles for .row and its children /
.row {
display: grid;
grid-template-columns: repeat(1, 1fr); /
Default to 1 column /
gap: 1rem; /
Adjust the gap between items as needed */
}

.row > * {
grid-column: span 1; /* Default to span 1 column */
}

/* Container query for widths < 33ch */
@container (max-width: 32.99ch) {
.row {
grid-template-columns: repeat(1, 1fr);
}

.row > * {
grid-column: span 1;
}
}

/* Container query for widths >= 33ch and < 2*33ch (66ch) */
@container (min-width: 33ch) and (max-width: 65.99ch) {
.row {
grid-template-columns: repeat(2, 1fr);
}

.row > * {
grid-column: span 2;
}
}

/* Container query for widths >= 233ch (66ch) and < 433ch (132ch) */
@container (min-width: 66ch) and (max-width: 131.99ch) {
.row {
grid-template-columns: repeat(4, 1fr);
}

.row > * {
grid-column: span 2;
}
}

/* Container query for widths >= 4*33ch (132ch) */
@container (min-width: 132ch) {
.row {
grid-template-columns: repeat(4, 1fr);

@lyubomir-popov
Copy link
Contributor

(for easier copy-pasting: https://chatgpt.com/share/67618c6b-0668-8000-b0c6-079803ff13b7)

@jmuzina
Copy link
Member Author

jmuzina commented Dec 17, 2024

Highlighting an issue with that chatgpt output: it seems it is suggesting an illegal use of container queries to change grid column template.

.p-list--horizontal {
  container-type: inline-size;
  display: grid;
  grid-template-columns: repeat(1, 1fr);
  gap: 1rem;
  .p-list__item {
    grid-column: span 4;
  }
  @container (min-width: 33ch) {
     // targeting the container itself within a container query is illegal
     .p-list--horizontal {  
         grid-template-columns: repeat(4, 1fr);
         .p-list__item {
            grid-column: span 2;
         }
      }
  } 
  @container (min-width: 66ch) {
     .p-list--horizontal {  
         grid-template-columns: repeat(8, 1fr);
      }
  } 
}

Something that could work is wrapping the lists in some wrapper element:

Intrinsic example with wrapper
<div class="p-list--horizontal-wrapper">
  <ul class="p-list--horizontal">
    <li class="p-list__item is-ticked ">
      <p>10 year security maintenance and CVE Patching</p>
    </li>
    <li class="p-list__item is-ticked">
      <p>
        <a href="#">Kernel Livepatch</a> for 24/7 patching with no downtime
      </p>
    </li>
    <li class="p-list__item is-ticked">
      <p>
        <a href="#">Expanded security</a> for infrastructure and applications
      </p>
    </li>
    <li class="p-list__item is-ticked">
      <p>
        <a href="#">FIPS 140-2</a> cryptographic modules certified by NIST
      </p>
    </li>
    <li class="p-list__item is-ticked">
      <p>
        <a href="#">Common Criteria EAL2</a>: ISO/IEC IS 15408 validated by CSEC
      </p>
    </li>
    <li class="p-list__item is-ticked">
      <p>
        <a href="#">DISA/STIG</a> hardening for <abbr title="Department of Defence, USA">DoD</abbr>
        compliance
      </p>
    </li>
    <li class="p-list__item is-ticked">
      <p>
        <a href="#">CIS profiles</a> for cyber defence and malware prevention
      </p>
    </li>
  </ul>
</div>
 .p-list--horizontal-wrapper {
    @extend %fixed-width-container;

    container-type: inline-size;
    .p-list--horizontal {
      @extend %vf-list-with-state-icons;
      display: grid;
      column-gap: 1rem;

      .p-list__item {
        @extend %vf-list-item;
        border-top: $border;
      }
    }

    @container (width < 50ch) {
      .p-list--horizontal {
        grid-template-columns: repeat(1, 1fr);
      }
    }

    @container (50ch <= width < 90ch) {
      .p-list--horizontal {
        grid-template-columns: repeat(2, 1fr);
      }
    }

    @container (width >= 90ch) {
      .p-list--horizontal {
        grid-template-columns: repeat(4, 1fr);

        // Skip the first column on large
        &.is-3-cols-on-large {
          .p-list__item {
            &:nth-child(3n + 1) {
              grid-column-start: 2;
            }
            &:nth-child(3n + 2) {
              grid-column-start: 3;
            }
            &:nth-child(3n + 3) {
              grid-column-start: 4;
            }
          }
        }
      }
    }
  }

@jmuzina jmuzina added Review: Design needed Review: Code needed Review: Percy needed This PR needs a review of Percy for visual regressions Feature 🎁 New feature or request labels Dec 17, 2024
@jmuzina jmuzina changed the title wip: feat: Horizontal List component wip: feat: Horizontal list section component Dec 17, 2024
@jmuzina jmuzina marked this pull request as ready for review December 17, 2024 21:12
@jmuzina jmuzina changed the title wip: feat: Horizontal list section component feat: Horizontal list section component Dec 17, 2024

### 25/75 Horizontal section

You can also add the `.is-25-75` modifier to reserve 25% space at the start of the list and place the remaining items in the remaining 75% space.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jmuzina Could it work without a modifier class name but nested inside row--25-75-on-large or similar?

Copy link
Member Author

@jmuzina jmuzina Dec 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could do this. However, it would require the user to create an empty column, and wrap the list in a .col as well, which I was trying to avoid to keep the markup very minimal.

Here's how that might look

<div class="row--25-75-on-large">
  <div class="col"></div>
  <!-- or omit the empty column above and use a col-start-large-3 here -->
  <div class="col">
    <ul class="p-list--horizontal-section">
      <!--list items....-->
    </ul>
  </div>
</div>

Instead, I have gone for this:

<ul class="p-list--horizontal-section is-25-75">
  <!--list items....-->
</ul>

@@ -199,6 +216,49 @@ $list-step-bullet-margin: $sph--x-large;
}
}

@mixin vf-p-list-horizontal-section {
.p-list--horizontal-section {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because of how different it is from standard "lists", I wonder if making it a "variant" of p-list is justified, or should it be more like it's own component (like p-horizontal-list-section or something).

On the other hand, keeping it as p-list-- we can reuse existing p-list__item and bullet/ticked options, so I guess there is a value in that consistency.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this component behaves a bit like an HOC in that it is a rather featured combination of grid and list. However, it requires its own styling. So, I've implemented it as a list variant to be able to take advantage of other list classes and internal placeholders like you have mentioned.

@lyubomir-popov
Copy link
Contributor

lyubomir-popov commented Dec 19, 2024

Thanks Julie mostly looks good, save for the things below:

  • looking at the combined example, a few things don't respect the baseline grid. For example:
    image
    the padding-top / margin-bottom here should match whatever heading text element (p, h*) is used.

  • If you turn on the baseline grid, can you tell whether these are freom new additions/changes, or older ones? I can see thesplit lists for example throw things off.

  • Separately, on the dividers. Here's what I had in mind. The last rule ensures it doesn't overshoot when the screen is less wide than the fixed width. the extra 2rem are for the demo page border, which is 1rem on all sides. In terms of variables, we just need to subtract the grid margin variable * 2.

.p-list--horizontal-section>.p-list__item:nth-child(4n+1)::after {
    content: "";
    position: absolute;
    top: 0;
    height: 1px;
    width: calc(80rem - 3rem);
    background: red;
    left: 0;
    max-width: calc(100vw - 5rem);
}

Preview:
image

@jmuzina jmuzina force-pushed the ft-horizontal-list branch from 17617eb to 6492063 Compare January 6, 2025 17:17
@jmuzina
Copy link
Member Author

jmuzina commented Jan 6, 2025

@lyubomir-popov Addressing your points:

looking at the combined example, a few things don't respect the baseline grid... If you turn on the baseline grid, can you tell whether these are from new additions/changes, or older ones? I can see the split lists for example throw things off.

This appears to be already occurring in production. Our visual testing is reporting that the only visual changes introduced here are the new list variant examples. Possibly we have some other issue to resolve related to split list baseline alignment, and we can create a separate issue for it. Let me know if that works for you.

Separately, on the dividers. Here's what I had in mind. The last rule ensures it doesn't overshoot when the screen is less wide than the fixed width. the extra 2rem are for the demo page border, which is 1rem on all sides. In terms of variables, we just need to subtract the grid margin variable * 2.

.p-list--horizontal-section>.p-list__item:nth-child(4n+1)::after {
    content: "";
    position: absolute;
    top: 0;
    height: 1px;
    width: calc(80rem - 3rem);
    background: red;
    left: 0;
    max-width: calc(100vw - 5rem);
}

I have synthesized our work from the pre-break pairing session with some polish of my own to make this even more robust (and avoid issues with page margin that we were seeing before).

I set the border pseudoelement widths to 100% * columns, making the borders span the full grid width without relying on more complex calculations, meaning we can set the width in one simple rule and avoid needing to set max-width using vw.

If you're curious, the code is below:

// Sets horizontal list section grid column count and makes list item borders span the full grid width.
// $columns: Number of columns that the list items should be divided into.
// $skip-cols: Number of columns at the start of each row to skip
@mixin list-horizontal-section-row-width($columns, $skip-cols: 0) {
--columns: #{$columns + $skip-cols};
// List item borders span full grid width, not list item width.
// Multiply 100% width by the number of columns to create a border that spans the full grid width.
.p-list__item:nth-child(#{$columns}n + 1)::after {
background: $colors--theme--border-default;
content: '';
height: 1px;
left: 0;
position: absolute;
top: 0;
width: calc(100% * (#{$columns}));
}
@if $skip-cols > 0 {
@for $i from 1 through $skip-cols {
.p-list__item:nth-child(#{$columns}n + #{$i}) {
grid-column-start: #{($i + 1)};
}
}
}
}
@mixin vf-p-list-horizontal-section {
$horizontal-list-section-medium-content-width: 66ch;
$horizontal-list-section-large-content-width: 100ch;
.p-list--horizontal-section-wrapper {
container-type: inline-size;
.p-list--horizontal-section {
@extend %vf-list;
@extend %fixed-width-container;
display: grid;
@container (width < #{$horizontal-list-section-medium-content-width}) {
@include list-horizontal-section-row-width($columns: 1);
}
@container (#{$horizontal-list-section-medium-content-width} <= width < #{$horizontal-list-section-large-content-width}) {
@include list-horizontal-section-row-width($columns: 2);
}
&:not(.is-25-75) {
@container (width >= #{$horizontal-list-section-large-content-width}) {
@include list-horizontal-section-row-width($columns: 4);
}
}
// --columns is set in the container queries above
grid-template-columns: repeat(var(--columns), 1fr);
.p-list__item {
@extend %vf-list-item;
@include vf-list-item-icon-divisor-offset;
@include vf-list-item-horizontal-section;
}
}
.p-list--horizontal-section.is-25-75 {
// skip first column on large
@container (width >= #{$horizontal-list-section-large-content-width}) {
@include list-horizontal-section-row-width($columns: 3, $skip-cols: 1);
}
}
}
}

@jmuzina jmuzina requested a review from bartaz January 6, 2025 17:38
@lyubomir-popov
Copy link
Contributor

can someone pls restart the demo? cc @bartaz

@bartaz
Copy link
Member

bartaz commented Jan 7, 2025

can someone pls restart the demo? cc @bartaz

There are some docker issues on the demos right now, will restart when its fixed

@jmuzina
Copy link
Member Author

jmuzina commented Jan 7, 2025

I just noticed that the grid column gap is not properly set, will fix that shortly
image

@lyubomir-popov
Copy link
Contributor

@jmuzina looks great overall! A few nit picks:

  • can we please make these lines muted, as per the logic (muted everywhere except above h2 titles at the beginning of a section):

image

  • seems to be missing the grid-gutter between columns - see how the text is able to touch:

image
should look like so using the grid gutter variable:
image

  • small typo (missing "to"):

image

  • maybe add an "experimental" label, due to using not the grid but container queries?

@jmuzina jmuzina force-pushed the ft-horizontal-list branch from 53fd205 to ab73aec Compare January 7, 2025 14:40
@jmuzina jmuzina force-pushed the ft-horizontal-list branch from ab73aec to fa34b4b Compare January 7, 2025 14:44
@jmuzina
Copy link
Member Author

jmuzina commented Jan 7, 2025

@lyubomir-popov addressing your comments:

can we please make these lines muted, as per the logic (muted everywhere except above h2 titles at the beginning of a section):

Fixed
image

seems to be missing the grid-gutter between columns - see how the text is able to touch:

Fixed, using $grid-gutter-widths (2rem when width >= 66ch). No gap needed when width < 66ch, as there is only one column in that case.

image
image

small typo (missing "to"):

Fixed, thanks.

maybe add an "experimental" label, due to using not the grid but container queries?

Added
image

@jmuzina

This comment was marked as outdated.

@lyubomir-popov
Copy link
Contributor

Last comment - can we please remove the line break avter the word "variants"?
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature 🎁 New feature or request Review: Code needed Review: Design +1 Review: Percy needed This PR needs a review of Percy for visual regressions
Projects
None yet
Development

Successfully merging this pull request may close these issues.

New component: Horizontal List
4 participants