Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
---
id: Compass
section: AI
source: guide
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
source: guide
source: Development-guide

just aligning with the motion docs - not sure if the hyphen is needed or not

subsection: Generative UIs
---

When building a layout for generative UIs using the Compass components, there are several common patterns that may be implemented using Patternfly components and component variants.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
When building a layout for generative UIs using the Compass components, there are several common patterns that may be implemented using Patternfly components and component variants.
When building generative UI layouts using the Compass components, there are several common patterns to considering during your development.


### Compass structure
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
### Compass structure
## Structural patterns

unless you've specifically chosen these heading levels on purpose, just moving everything up a level


#### Containers & glass theme
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
#### Containers & glass theme
### Transparent containers

The glass look and feel is an opt-in global styling applied when `pf-v6-theme-glass` is present on the `html` element class list, similar to dark theme. For compass layouts, content that has the glass background and rounded borders should be wrapped in a `CompassPanel` (and some compass components will do this automatically). This component has various options to customize its own padding and behavior to fit the context of its usage, and so is present in nearly every area of a compass page. `CompassPanels` should not be directly nested if the glass theme is applied to prevent styling issues.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
The glass look and feel is an opt-in global styling applied when `pf-v6-theme-glass` is present on the `html` element class list, similar to dark theme. For compass layouts, content that has the glass background and rounded borders should be wrapped in a `CompassPanel` (and some compass components will do this automatically). This component has various options to customize its own padding and behavior to fit the context of its usage, and so is present in nearly every area of a compass page. `CompassPanels` should not be directly nested if the glass theme is applied to prevent styling issues.
Transparent containers create a modern glass look and feel. To enable transparency on a container, apply `pf-v6-theme-glass` to the `html` element class list, similar to the approach for enabling the dark mode theme.
Within Compass layouts, elements with a transparent glass background and rounded borders should be wrapped in a `<CompassPanel>` (some Compass components do this automatically). You can adjust various options of the `<CompassPanel>` to adapt its padding and behavior to fit the context of your use case.
To prevent styling issues, do not nest`<CompassPanel>` components while using the glass effects.

wasn't sure what was meant by "and so is present in nearly every area of a compass page", so I just removed mention of it, but we can reintegrate it. What does this mean? That CompassPanels will be used a bunch on a page?


#### Header
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
#### Header
### Header

A compass layout header will typically be constructed using a `CompassHeader` component, which constructs three sections: logo, nav, and profile. These sections may be passed any content, but here are some recommendations when building a compass layout:
- The logo should contain a `Brand` or other logo image or svg.
- The profile should contain a `Dropdown` with a user `Avatar` within the `MenuToggle`.
- The nav should contain a `CompassNavContent` component, which usually contains `CompassNavHome`, `CompassNavMain`, and `CompassNavSearch` components as shown below in a snippet. `CompassNavHome` and `CompassNavSearch` are opinionated components that will automatically provide a home and search button, and are optional. `CompassNavMain` will usually contain a `Tabs` component with the `isNav` flag to enable a top-level navigation type of styling.
Comment on lines +16 to +19
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
A compass layout header will typically be constructed using a `CompassHeader` component, which constructs three sections: logo, nav, and profile. These sections may be passed any content, but here are some recommendations when building a compass layout:
- The logo should contain a `Brand` or other logo image or svg.
- The profile should contain a `Dropdown` with a user `Avatar` within the `MenuToggle`.
- The nav should contain a `CompassNavContent` component, which usually contains `CompassNavHome`, `CompassNavMain`, and `CompassNavSearch` components as shown below in a snippet. `CompassNavHome` and `CompassNavSearch` are opinionated components that will automatically provide a home and search button, and are optional. `CompassNavMain` will usually contain a `Tabs` component with the `isNav` flag to enable a top-level navigation type of styling.
You can add a header to a Compass layout via the `<CompassHeader>` component. `<CompassHeader>` constructs 3 sections, which can contain any custom content, but will typically include the following:
- **Logo:** Contains a [`<Brand>`](/components/brand) or other image or SVG to represent a product logo.
- **Profile:** Contains a [`<Dropdown>`](/components/menus/dropdown) with a user [`<Avatar>`](/components/avatar) displayed in the `<MenuToggle>`.
- **Nav:** Contains a `<CompassNavContent>` component, which usually contains `<CompassNavHome>`, `<CompassNavMain>`, and `<CompassNavSearch>` components as shown in the following code example.
- `<CompassNavHome>` and `<CompassNavSearch>` are optional, but are opinionated components that will automatically provide a home and search button.
- `<CompassNavMain>` will usually contain a [`<Tabs>`](/components/tabs) component that uses the `isNav` flag to enable a top-level navigation styles.

Do we need to say "will typically be constructed" unless we also hint at other likely methods?


Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
#### Code example

```
<CompassNavContent>
<CompassNavHome onClick={() => console.log('Home')} />
<CompassNavMain>
<Tabs isNav />
</CompassNavMain>
<CompassNavSearch onClick={() => console.log('Search')} />
</CompassNavContent>
```

#### Sidebars
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
#### Sidebars
### Sidebars

There are two sidebars in a compass layout at the start and end of the page. There is no specific `Compass` helper component for these sections, and so usually a `CompassPanel` containing an `ActionList` with the `isVertical` flag will be passed to represent the side navigations.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
There are two sidebars in a compass layout at the start and end of the page. There is no specific `Compass` helper component for these sections, and so usually a `CompassPanel` containing an `ActionList` with the `isVertical` flag will be passed to represent the side navigations.
There are 2 vertical sidebars in a Compass layout: 1 at the start of the page and another at the end. There are no specific helper components for these sections, so they're usually created by passing the `isVertical` flag to a `<CompassPanel>` that contains an [`<ActionList>`](/components/action-list).


#### Footer
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
#### Footer
### Footer

There are two methods of adding a footer to a compass layout. In either case, a footer's content will remain the same and will usually consist of a `@patternfly/chatbot` `MessageBar`, wrapped by a `CompassPanel` and `CompassMessageBar` component, as shown below:

Comment on lines +35 to +36
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
There are two methods of adding a footer to a compass layout. In either case, a footer's content will remain the same and will usually consist of a `@patternfly/chatbot` `MessageBar`, wrapped by a `CompassPanel` and `CompassMessageBar` component, as shown below:
There are 2 methods of adding a footer to a compass layout.
In both methods, the footer content will remain the same, typically containing a [ChatBot `<MessageBar>`](/extensions/chatbot/messages/), wrapped in a `<CompassPanel>` and `<CompassMessageBar>` component:

```
<CompassMessageBar>
<CompassPanel isPill hasNoPadding hasNoBorder>
<MessageBar />
<div aria-live="polite" className="pf-v6-screen-reader">
// aria anouncments for message bar's state updates
</div>
</CompassPanel>
</CompassMessageBar>
```

In the first method of adding a footer, pass this content to the `footer` prop of the `Compass` component. This type of footer will extend the entire width of the viewport. However, if the footer content is expected to change in height (such as when MessageBar content expands), the sidebars will adjust their positioning. If this behavior is not desired, please use the second method and forego passing the `footer` prop.

For the second method of adding a footer, wrap the content in `CompassMainFooter` and pass it as part of the `main` content of the `Compass`. This will allow the sidebars to extend through to the bottom of the viewport and prevents them from resizing based on changing footer content height.
Comment on lines +48 to +50
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
In the first method of adding a footer, pass this content to the `footer` prop of the `Compass` component. This type of footer will extend the entire width of the viewport. However, if the footer content is expected to change in height (such as when MessageBar content expands), the sidebars will adjust their positioning. If this behavior is not desired, please use the second method and forego passing the `footer` prop.
For the second method of adding a footer, wrap the content in `CompassMainFooter` and pass it as part of the `main` content of the `Compass`. This will allow the sidebars to extend through to the bottom of the viewport and prevents them from resizing based on changing footer content height.
1. Via the `footer` prop.
To create a footer that will span the entire viewport width, pass content to the `footer` prop of the `<Compass>` component. If your footer content is expected to change in height (like `<MessageBar>` content that expands), the sidebars will adjust their positioning to align. If this behavior is not desired, don't use the `footer` prop and follow the second method.
2. Via the `<CompassMainFooter>` components.
To allow the sidebars to extend through the bottom of the viewport, preventing them from resizing based on changes to the footer container height, wrap footer content in `<CompassMainFooter>` and pass it to the `<Compass>` component as part of the `main` content.

the sub-content needs to be indented, which may need tweaking beyond what I can leave as a suggestion here


#### Main content
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
#### Main content
### Main content

The main content, taking up the center of viewport, will typically consist of a `Hero` or `CompassMainHeader`, a `CompassContent`, and an optional `CompassMainFooter`.

A typical compass page will consist of a `CompassMainHeader` and `CompassContent` with a `CompassPanel` child, and content of the page should go inside of this `CompassPanel`.

When making a dashboard view, use a `Hero` instead of a `CompassMainHeader`. And instead of having a single `CompassPanel` within a `CompassContent`, each individual dashbaord item should be wrapped in a `CompassPanel`. For example, in a dashboard that has many content cards, each `Card` (with `isPlain` flag) is wrapped by a `CompassPanel` inside of a `Grid`.
Comment on lines +53 to +57
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
The main content, taking up the center of viewport, will typically consist of a `Hero` or `CompassMainHeader`, a `CompassContent`, and an optional `CompassMainFooter`.
A typical compass page will consist of a `CompassMainHeader` and `CompassContent` with a `CompassPanel` child, and content of the page should go inside of this `CompassPanel`.
When making a dashboard view, use a `Hero` instead of a `CompassMainHeader`. And instead of having a single `CompassPanel` within a `CompassContent`, each individual dashbaord item should be wrapped in a `CompassPanel`. For example, in a dashboard that has many content cards, each `Card` (with `isPlain` flag) is wrapped by a `CompassPanel` inside of a `Grid`.
The main content in a Compass layout includes the generated information displays. Main content fills the center of the viewport and typically consists of a `<Hero>` or `<CompassMainHeader>`, a `<CompassContent>`, and an optional `<CompassMainFooter>`.
Often, the main section will contain a `<CompassMainHeader>` and `<CompassContent>` with a `<CompassPanel>` child containing the primary page content.
When making [a dashboard view](/patterns/dashboard), use a `<Hero>` instead of a `<CompassMainHeader>`. Instead of having a single `<CompassPanel>` within a `<CompassContent>`, each individual dashboard item should be wrapped in a `<CompassPanel>`. For example, in a dashboard with many content cards, each `<Card>` (with `isPlain` flag) should be wrapped by a `<CompassPanel>` inside of a [`<Grid>`](/foundations-and-styles/layouts/grid).


### CSS

PatternFly's token system allows additional customization of the look and feel of a compass layout.
For example, the following css mixin utilizes several global token overrides to better match the Red Hat Design System look and feel.
Comment on lines +59 to +62
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
### CSS
PatternFly's token system allows additional customization of the look and feel of a compass layout.
For example, the following css mixin utilizes several global token overrides to better match the Red Hat Design System look and feel.
## CSS customization
Our [design token system](/foundations-and-styles/design-tokens/overview) allows you to further customize the look and feel of a Compass layout.
For example, the following CSS mixin utilizes several global token overrides to better match the Red Hat Design System look and feel.


```
@mixin pf-v6-tokens {
// brand tokens
--pf-t--global--color--brand--100: var(--pf-t--color--red--40);
--pf-t--global--color--brand--200: var(--pf-t--color--red--50);
--pf-t--global--color--brand--300: var(--pf-t--color--red--60);
--pf-t--global--color--brand--400: var(--pf-t--color--red--70);
--pf-t--global--color--brand--500: var(--pf-t--color--red--80);

// dark brand tokens
--pf-t--global--dark--color--brand--100: var(--pf-t--color--red--30);
--pf-t--global--dark--color--brand--200: var(--pf-t--color--red--20);
--pf-t--global--dark--color--brand--300: var(--pf-t--color--red--10);

// font size
--pf-t--global--font--size--900: 2.5rem;
--pf-t--global--font--size--1000: 3rem;

// bumped by one
--pf-t--global--font--size--2xl: var(--pf-t--global--font--size--700);
--pf-t--global--font--size--3xl: var(--pf-t--global--font--size--800);
--pf-t--global--font--size--4xl: var(--pf-t--global--font--size--900);
--pf-t--global--font--size--lg: var(--pf-t--global--font--size--500);
--pf-t--global--font--size--md: var(--pf-t--global--font--size--400);
--pf-t--global--font--size--sm: var(--pf-t--global--font--size--300);
--pf-t--global--font--size--xl: var(--pf-t--global--font--size--600);
--pf-t--global--font--size--xs: var(--pf-t--global--font--size--200);

// icon sizes
--pf-t--global--icon--size--100: 1rem;
--pf-t--global--icon--size--200: 1.5rem;
--pf-t--global--icon--size--250: 2rem;
--pf-t--global--icon--size--300: 2.5rem;
--pf-t--global--icon--size--400: 6rem;
--pf-t--global--icon--size--500: 8rem;

// spacing
--pf-t--global--spacer--action--horizontal--compact: var(--pf-t--global--spacer--lg);
--pf-t--global--spacer--action--horizontal--default: var(--pf-t--global--spacer--xl);
--pf-t--global--spacer--action--horizontal--plain--compact: var(--pf-t--global--spacer--sm);
--pf-t--global--spacer--action--horizontal--plain--default: var(--pf-t--global--spacer--md);
--pf-t--global--spacer--action--horizontal--spacious: var(--pf-t--global--spacer--2xl);
--pf-t--global--spacer--control--horizontal--compact: var(--pf-t--global--spacer--md);
--pf-t--global--spacer--control--horizontal--default: var(--pf-t--global--spacer--xl);
--pf-t--global--spacer--control--horizontal--plain: var(--pf-t--global--spacer--md);
--pf-t--global--spacer--control--horizontal--spacious: var(--pf-t--global--spacer--xl);
--pf-t--global--spacer--control--vertical--compact: var(--pf-t--global--spacer--sm);
--pf-t--global--spacer--control--vertical--default: var(--pf-t--global--spacer--md);
--pf-t--global--spacer--control--vertical--plain: var(--pf-t--global--spacer--md);
--pf-t--global--spacer--control--vertical--spacious: var(--pf-t--global--spacer--lg);
--pf-t--global--spacer--gap--action-to-action--default: var(--pf-t--global--spacer--lg);
--pf-t--global--spacer--gap--action-to-action--plain: var(--pf-t--global--spacer--sm);
--pf-t--global--spacer--gap--control-to-control--default: var(--pf-t--global--spacer--sm);
--pf-t--global--spacer--gap--group--horizontal: var(--pf-t--global--spacer--lg);
--pf-t--global--spacer--gap--group--vertical: var(--pf-t--global--spacer--md);
--pf-t--global--spacer--gap--group-to-group--horizontal--compact: var(--pf-t--global--spacer--md);
--pf-t--global--spacer--gap--group-to-group--horizontal--default: var(--pf-t--global--spacer--3xl);
--pf-t--global--spacer--gap--group-to-group--vertical--compact: var(--pf-t--global--spacer--lg);
--pf-t--global--spacer--gap--group-to-group--vertical--default: var(--pf-t--global--spacer--xl);
--pf-t--global--spacer--gap--text-to-element--compact: var(--pf-t--global--spacer--sm);
--pf-t--global--spacer--gap--text-to-element--default: var(--pf-t--global--spacer--md);
--pf-t--global--spacer--gutter--default: var(--pf-t--global--spacer--lg);
--pf-t--global--spacer--inset--page-chrome: var(--pf-t--global--spacer--xl);

// Glass theme tokens
--pf-t--global--light--glass--background--color--glass--color: var(--pf-t--global--color--brand--500);
--pf-t--global--light--glass--background--color--glass--filter: blur(12.5px);
--pf-t--global--light--glass--background--color--glass--opacity: 10%;
--pf-t--global--light--glass--background--color--glass--default: color-mix(in srgb, var(--pf-t--global--light--glass--background--color--glass--color) var(--pf-t--global--light--glass--background--color--glass--opacity), transparent );
--pf-t--global--dark--glass--background--color--glass--color: var(--pf-t--global--color--brand--500);
--pf-t--global--dark--glass--background--color--glass--filter: blur(12.5px);
--pf-t--global--dark--glass--background--color--glass--opacity: 65%;
--pf-t--global--dark--glass--background--color--glass--default: color-mix(in srgb, var(--pf-t--global--dark--glass--background--color--glass--color) var(--pf-t--global--dark--glass--background--color--glass--opacity), transparent );

// Message bar tokens
--pf-v6-c-compass__message-bar--Width: 600px;
--pf-v6-c-compass__message-bar--MinWidth: 450px;
--pf-v6-c-compass__message-bar--MaxWidth: 900px;

// Thinking tokens
--pf-v6-global--thinking--BoxShadow--Spread: 5px;
--pf-v6-global--thinking--BoxShadow--Color--Start-Start: var(--pf-t--global--color--brand--100);
--pf-v6-global--thinking--BoxShadow--Color--Start-End: var(--pf-t--color--white);
--pf-v6-global--thinking--BoxShadow--Color--End-Start: var(--pf-t--global--color--brand--500);
--pf-v6-global--thinking--BoxShadow--Color--End-End: var(--pf-t--global--color--brand--300);
--pf-v6-global--thinking-active--BoxShadow--Spread: 10px;

.pf-v6-m-ai-indicator {
&::before {
background: linear-gradient(to right, #f56e6e 0%, var(--pf-t--global--color--brand--300) 65%, var(--pf-t--global--color--brand--500) 100%)
border-box;
}
}
}
```