diff --git a/website/app/styles/pages/components/advanced-table.scss b/website/app/styles/pages/components/advanced-table.scss index 59341f28df9..460fa7b86a0 100644 --- a/website/app/styles/pages/components/advanced-table.scss +++ b/website/app/styles/pages/components/advanced-table.scss @@ -6,14 +6,6 @@ // COMPONENTS > TABLE > ADVANCEDTABLE #show-content-components-table-advanced-table { - .doc-advanced-table-scrollable-wrapper { - overflow-x: auto; - } - - .doc-advanced-table-vertical-scrollable-wrapper { - height: 500px; - } - .doc-advanced-table-multiselect-with-pagination-demo { .hds-advanced-table + .hds-pagination { margin-top: 16px; diff --git a/website/docs/components/app-header/partials/code/component-api.md b/website/docs/components/app-header/partials/code/component-api.md index 49079bb8e98..79434f2913e 100644 --- a/website/docs/components/app-header/partials/code/component-api.md +++ b/website/docs/components/app-header/partials/code/component-api.md @@ -13,7 +13,7 @@ A named block where the utility actions will be rendered. Typically, `Dropdown` or `Button` components should be added here, such as a help menu, user menu, or search button. - Set a custom breakpoint to control the page width at which the UI switches from displaying the mobile/small view vs. the desktop/view. + Set a custom breakpoint to control the page width at which the UI switches from displaying the mobile/small view vs. the desktop/large view. Controls whether a "navigator narrator" and a "skip link" are added to the navigation (provided by the [`ember-a11y-refocus` Ember addon](https://github.com/ember-a11y/ember-a11y-refocus)). It can be programmatically turned off by passing `false`. Warning: if it is set to false, then it will fail Bypass Blocks, [Success Criteria 2.4.1](https://www.w3.org/WAI/WCAG22/Understanding/bypass-blocks.html). Since this component appears on every page, the application will not be considered conformant. diff --git a/website/docs/components/app-side-nav/partials/code/component-api.md b/website/docs/components/app-side-nav/partials/code/component-api.md index b8135a7fc6e..1dc403da56a 100644 --- a/website/docs/components/app-side-nav/partials/code/component-api.md +++ b/website/docs/components/app-side-nav/partials/code/component-api.md @@ -21,6 +21,9 @@ This is the full-fledged component (responsive and animated). Controls if the App Side Nav is rendered collapsed or expanded when initialized. This allows an application to preserve the collapsed/expanded state across sessions. After the initial render, this argument is altered based on user interactions (collapse/expand the App Side Nav or resize the window) and it is not a suitable way of controlling the App Side Nav state from outside after render (it’s an internal state). + + Set a custom breakpoint to control the page width at which the UI switches from displaying the mobile/small view vs. the desktop/large view. + Callback function invoked when the `AppSideNav` is collapsed or expanded. The function receives a boolean argument stating if the `AppSideNav` is minimized or not. diff --git a/website/docs/components/app-side-nav/partials/code/how-to-use.md b/website/docs/components/app-side-nav/partials/code/how-to-use.md index 7ac99d2ebad..aea7870444c 100644 --- a/website/docs/components/app-side-nav/partials/code/how-to-use.md +++ b/website/docs/components/app-side-nav/partials/code/how-to-use.md @@ -118,7 +118,7 @@ Below is an example (inspired by the Cloud UI navigation) of how the two kinds o ```handlebars {{!-- -for demo purposes we set `@isResponsive` to `false` but in your app it will probably need to be set to `true` +for demo purposes we set `@isResponsive` to `false` but in your app it will probably need to be set to `true` (or omitted to rely on defaults) --}}
@@ -175,7 +175,7 @@ When the App Side Nav is used in conjunction with portals, the nesting of naviga As mentioned above, the full-fledged `Hds::AppSideNav` component is “responsive” by default: - when the **viewport is `desktop`**, the sidebar navigation is static and has a fixed width - - the width at which the viewport is considered “desktop” is controlled by a dedicated CSS variable `--hds-app-desktop-breakpoint`; if needed it can be overwritten (at `:root` level) to define a custom “desktop” breakpoint + - the width at which the viewport is considered “desktop” can be overwritten using the `@breakpoint` argument - when the **viewport is `mobile`**, the sidebar navigation is responsive and the user can minimize or maximize its width via a toggle button (the component will take care automatically of the transitions between these two states) - in this case the App Side Nav occupies only a minimum width in terms of page layout, even when expanded (it partially covers the main content) - a toggle button is added to the App Side Nav, used to expand/minimize its width diff --git a/website/docs/components/code-block/partials/code/how-to-use.md b/website/docs/components/code-block/partials/code/how-to-use.md index 28214b85448..0623003c068 100644 --- a/website/docs/components/code-block/partials/code/how-to-use.md +++ b/website/docs/components/code-block/partials/code/how-to-use.md @@ -149,12 +149,12 @@ loadInitializers(App, config.modulePrefix);" ### Limit height -Code content uses `auto` height by default but you can opt to set a `maxHeight` value to save space. Vertical scrolling is enabled as part of this feature allowing users to scroll vertically to view the overflowing content. +Code content uses `auto` height by default but you can opt to set a `maxHeight` value to save space. If the content height exceeds the set max height, vertical scrolling is enabled to view the overflowing content and a toggle button is displayed to expand the height and show the Code Block content in its entirety. ```handlebars - Determines if the Advanced Table has a sticky header. + + Sets the maximum height of the Advanced Table. If the `@maxHeight` is set, there will automatically be a sticky header. To turn off the sticky header and still have a max height, set `@hasStickyHeader` to false. + + + Determines if the Advanced Table has a sticky header. If set to `true`, must be used with the `@maxHeight` argument. If `@maxHeight` is set and `@hasStickyHeader` is `false`, there will not be a sticky header. Determines if the Advanced Table has a sticky first column. diff --git a/website/docs/components/table/advanced-table/partials/code/how-to-use.md b/website/docs/components/table/advanced-table/partials/code/how-to-use.md index b4f1ef596d6..a2b91cc9aa0 100644 --- a/website/docs/components/table/advanced-table/partials/code/how-to-use.md +++ b/website/docs/components/table/advanced-table/partials/code/how-to-use.md @@ -382,31 +382,30 @@ We recommend using functionalities like [pagination](/components/pagination), [s #### Vertical scrolling -For situations where the default number of rows visible may be high, it can be difficult for users to track which column is which once they scroll. In this case, the `hasStickyHeader` argument can be used to make the column headers persist as the user scrolls. +For situations where the default number of rows visible may be high, it can be difficult for users to track which column is which once they scroll. In this case, the `maxHeight` argument can be used to set the maximum height of the Advanced Table which will also add a sticky header. This will make the column headers persist as the user scrolls. + +If you want to set the `maxHeight` but not have a sticky header, set `hasStickyHeader` to false. ```handlebars - -
- - <:body as |B|> - - {{B.data.id}} - {{B.data.name}} - {{B.data.email}} - {{B.data.role}} - - - -
+ + <:body as |B|> + + {{B.data.id}} + {{B.data.name}} + {{B.data.email}} + {{B.data.role}} + + + ``` #### Horizontal scrolling @@ -418,36 +417,33 @@ The component adds the sticky styles to the `[B].Th` component in each row. If t Note: Using `@hasStickyFirstColumn` with nested rows is not supported. ```handlebars - -
- - <:body as |B|> - - {{B.data.first_name}} - {{B.data.last_name}} - {{B.data.age}} - {{B.data.email}} - {{B.data.phone}} - {{B.data.bio}} - {{B.data.education}} - {{B.data.occupation}} - - - -
+ + <:body as |B|> + + {{B.data.first_name}} + {{B.data.last_name}} + {{B.data.age}} + {{B.data.email}} + {{B.data.phone}} + {{B.data.bio}} + {{B.data.education}} + {{B.data.occupation}} + + + ``` ### Multi-select Advanced Table diff --git a/website/docs/foundations/breakpoints/index.md b/website/docs/foundations/breakpoints/index.md new file mode 100644 index 00000000000..f457c21ce99 --- /dev/null +++ b/website/docs/foundations/breakpoints/index.md @@ -0,0 +1,16 @@ +--- +title: Breakpoints +caption: Standardized breakpoints for different device widths. +description: Breakpoints are width values that standardize responsive experiences across the HashiCorp product suite. +links: + figma: https://www.figma.com/design/uX4OEaJQdWfzULADchjAeN/HDS-Foundations-v2.0?node-id=13020-244&t=0N1UWbTuY6sSq3Od-1 +previewImage: assets/illustrations/foundations/breakpoints.jpg +--- + +
+ @include "partials/guidelines/guidelines.md" +
+ +
+ @include "partials/code/how-to-use.md" +
\ No newline at end of file diff --git a/website/docs/foundations/breakpoints/partials/code/how-to-use.md b/website/docs/foundations/breakpoints/partials/code/how-to-use.md new file mode 100644 index 00000000000..15daf92f062 --- /dev/null +++ b/website/docs/foundations/breakpoints/partials/code/how-to-use.md @@ -0,0 +1,119 @@ +## How to use the breakpoints + +In [responsive design](https://developer.mozilla.org/en-US/docs/Learn_web_development/Core/CSS_layout/Responsive_Design) it's common practice to define specific media queries in CSS that can be used to control not only the layout of the entire page and its parts, but also other aspects of a UI like typography, spacing, the rendering of decorative elements, the resolution of media assets, and much more. These media queries are built using CSS `@media` declarations in combination with a set of standard breakpoints. + +Our design system defines [breakpoint values](/foundations/breakpoints#the-ranges) based on browser viewport widths. The intervals between these breakpoints create distinct ranges, which can be used with the [Sass](/foundations/breakpoints?tab=code#sass) and [JavaScript](/foundations/breakpoints?tab=code#javascript) helpers to implement responsive designs for our applications. + +### Sass + +To use the Sass helpers provided by the design system, you must import the corresponding Sass file (via `@use`, [as recommended](https://sass-lang.com/documentation/at-rules/use/#differences-from-import)) from the `@hashicorp/design-system-components` package: + + +```scss +// from @hashicorp/design-system-components package +@use "mixins/breakpoints" as *; +``` + +!!! info + +If you are not able to import the file using the declaration above, [contact the Design Systems Team](/about/support) for support. + +!!! + +Once the file is imported, you will have access to the Sass helpers described below. + +#### Mixins + +Sass mixins offer the simplest, most efficient way to implement responsive layouts using the standard breakpoints defined in our system. We provide three different mixins: + +- `hds-breakpoint-above($name)` - for media queries that apply to a viewport range **above** a certain breakpoint (useful for a mobile-first approach) +- `hds-breakpoint-below($name)` - for media queries that apply to a viewport range **below** a certain breakpoint (useful for a desktop-first approach) +- `hds-breakpoint-between($lower, $upper)` - for media queries that apply to a viewport range **between** two breakpoints + +Here is an example of how the mixins could be used in a mobile-first responsive layout: + +```scss +// from @hashicorp/design-system-components package +@use "mixins/breakpoints" as *; + +.my-responsive-layout { + // this is the default behavior, that covers the range 0px–767px + display: flex; + direction: column; + gap: 1rem; + + // at 768px the layout changes, from a vertical stack to an horizontal one + @include hds-breakpoint-above('md') { + direction: row; + } + + // at larger viewports we increase the spacing between the items + @include hds-breakpoint-above('xl') { + gap: 2rem; + } +} +``` + +The same layout could be achieved using a desktop-first approach in a similar way: + +```scss +// from @hashicorp/design-system-components package +@use "mixins/breakpoints" as *; + +.my-responsive-layout { + // this is the default behavior + display: flex; + direction: row; + gap: 2rem; + + // at smaller viewports we decrease the spacing between the items + @include hds-breakpoint-below('xl') { + gap: 1rem; + } + + // at 768px the layout changes, from an horizontal stack to a vertical one + @include hds-breakpoint-below('md') { + direction: column; + } +} +``` + +Of course, these are oversimplified examples. In your implementation, you will have to choose which mixin is best suited to achieve the desired responsive layout. This will depend on the design specifications, the context of the layout within the page, and how it relates with other UI elements. + +#### Key/Value Map + +For special use cases, we also provide a Sass map–`$hds-breakpoints`–which is a lower level helper than the mixins. Here's an example of how this map could be used: + +```scss +// explicit import of `map` module (required by Sass) +@use "sass:map"; +// from @hashicorp/design-system-components package +@use "mixins/breakpoints" as *; + +@each $name, $size in $hds-breakpoints { + .my-custom-breakpoint-class--#{$name} { + // here you have access to the breakpoint name and its value (width in px) + } +} +``` + +### JavaScript + +We also provide helpers in case you need to access the breakpoints names/values in JavaScript code. + +You have access to the list of breakpoint names and values using the `hdsBreakpoints` map: + +```javascript{data-execute=false} +import { hdsBreakpoints } from '@hashicorp/design-system-components/utils/hds-breakpoints'; + +// do something with a specific breakpoint value +const myBreakpoint1 = hdsBreakpoints['xl'].value; // numeric (eg. 1440) +const myBreakpoint2 = hdsBreakpoints['lg'].px; // size in px (eg. 1088px) +const myBreakpoint3 = hdsBreakpoints['sm'].rem; // size in rem (eg. 30rem) + +// loop over all the breakpoints +Object.entries(hdsBreakpoints).forEach(([name, sizes]) => { + // do something with a specific breakpoint value in px + const myBreakpointSizePx = sizes.px; +}); +``` diff --git a/website/docs/foundations/breakpoints/partials/guidelines/guidelines.md b/website/docs/foundations/breakpoints/partials/guidelines/guidelines.md new file mode 100644 index 00000000000..7574c9d55c2 --- /dev/null +++ b/website/docs/foundations/breakpoints/partials/guidelines/guidelines.md @@ -0,0 +1,46 @@ +Breakpoints are viewport widths where layouts adjust to support responsive experiences on varied screen sizes and devices. These values are used to create utilities and helper components that standardize changes in UI at these widths. + +## The ranges + +There are five HDS breakpoint values: `sm`, `md`, `lg`, `xl`, and `xxl`. + +| Name | Value | Application | +| ------ | ------------ | ----------------------------- | +| sm | 480px | 480 → 767 | +| md | 768px | 768 → 1087 | +| lg | 1088px | 1088 → 1439 | +| xl | 1440px | 1440 → 1919 | +| xxl | 1920px | 1920 and up | + +The breakpoint name refers to a range of pixel values, not just the starting value. For example, the `sm` breakpoint refers to widths between 480px and 767px. This helps simplify the language around what these ranges mean when designing and increases the flexibility in implementation. + +_Note: the range 0-479px is intentionally left without a name. We don't anticipate designers needing to produce mockups for screen sizes below this width and from the audits conducted, Cloud UI has set a standard of 480px for the most narrow design. From a development perspective, in a mobile-first approach the range below 480px can be covered using default styles (overwritten via media queries for subsequent ranges)._ + +### Custom values + +The provided breakpoints serve as a cohesive _starting_ point for design, which is why templates have been provided in our [Patterns library](https://www.figma.com/design/5Pv32j4QiOOD8lkFTD1dxC/HDS-Patterns-v2.0?m=auto&node-id=71-11371&t=OvSfKLEJhHntQQZA-1) for this purpose. However, custom values may be necessary for specific use cases that these breakpoints do not cover. For example, if a team discovers that users with 2500px viewports are using a product, a nuanced approach to the UI at that screen size may be required. In such cases, a custom width value may be used to enhance the user experience. + +!!! insight + +If a custom value already exists that is relatively close to an established breakpoint, we recommend migrating it to the nearest standard breakpoint. This creates a consistent and predictable experience for the user as they work within (and across) the HashiCorp product suite. + +!!! + +## Designing with purpose + +Not all designs require redesigning at each breakpoint. Only when designs are considered complicated and/or constrained by UI elements should a designer take the time to show how they change as the viewport changes in size. + +For example, a UI featuring a table layout may not require changes for each breakpoint because the expected behavior is for the table to maintain its full width regardless of the breakpoint value. A design isn't necessary to elaborate this standard behavior. + +![](/assets/foundations/breakpoints/breakpoints-table-example.png) + +Redesigning across multiple breakpoints is often necessary for complex UIs, such as a landing page with cards arranged in a grid. As the viewport size decreases, both the position and content of the cards change, requiring nuanced designs across breakpoints. In such scenarios, designers should specify how the layout adjusts at the `sm`, `md`, and `lg` views. + +![Diagram depicting "large", "medium", and "small" screen sizes displaying a varying number of columns in rows of content blocks.](/assets/foundations/breakpoints/breakpoints-card-designs-shfting.png) + +## Responsiveness in Helios + +Responsive behavior is already built into some Helios components. These components include, but are not limited to: +* [App Side Nav](/components/app-side-nav) (width collapses below lg breakpoint) +* [Stepper Nav](/components/stepper/nav) (layout shifts below sm breakpoint) +* [Pagination](/components/pagination) (layout stacks below lg breakpoint) diff --git a/website/public/assets/components/code-block/code-block-collapsed.png b/website/public/assets/components/code-block/code-block-collapsed.png new file mode 100644 index 00000000000..bc6ff77c9c3 Binary files /dev/null and b/website/public/assets/components/code-block/code-block-collapsed.png differ diff --git a/website/public/assets/components/code-block/code-block-expanded.png b/website/public/assets/components/code-block/code-block-expanded.png new file mode 100644 index 00000000000..2c3436f6e21 Binary files /dev/null and b/website/public/assets/components/code-block/code-block-expanded.png differ diff --git a/website/public/assets/foundations/breakpoints/breakpoints-card-designs-shfting.png b/website/public/assets/foundations/breakpoints/breakpoints-card-designs-shfting.png new file mode 100644 index 00000000000..725b90c20e6 Binary files /dev/null and b/website/public/assets/foundations/breakpoints/breakpoints-card-designs-shfting.png differ diff --git a/website/public/assets/foundations/breakpoints/breakpoints-table-example.png b/website/public/assets/foundations/breakpoints/breakpoints-table-example.png new file mode 100644 index 00000000000..ec5a14156ce Binary files /dev/null and b/website/public/assets/foundations/breakpoints/breakpoints-table-example.png differ diff --git a/website/public/assets/illustrations/foundations/breakpoints.jpg b/website/public/assets/illustrations/foundations/breakpoints.jpg new file mode 100644 index 00000000000..582b4520127 Binary files /dev/null and b/website/public/assets/illustrations/foundations/breakpoints.jpg differ