-
Notifications
You must be signed in to change notification settings - Fork 94
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
add tooltip and popover components #442
Changes from all commits
9842af1
0046f33
a47ee16
ea916fb
0daf1d8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
## Overview | ||
|
||
A popover is used to provide contextual information for another component on click. The popover itself is made up of two main elements: arrow and content. The content element follows the pattern of the popover box component, with a close icon in the top right corner, as well as a header and body. One of the directional modifiers (`.pf-m-left`, `.pf-m-top`, etc.) is required on the popover component | ||
|
||
## Accessibility | ||
|
||
| Attribute | Applies to | Outcome | | ||
| -- | -- | -- | | ||
| `role="dialog"` | `.pf-c-popover` | Identifies the element that serves as the popover container. **Required**| | ||
| `aria-labeledby="[id value of .pf-c-popover__header-title]"` | `.pf-c-popover` | Gives the popover an accessible name by referring to the element that provides the dialog title. **Required when .pf-c-popover__header-title is present** | | ||
| `aria-label="[title of popover]"` | `.pf-c-popover` | Gives the popover an accessible name. **Required when .pf-c-popover__header-title is _not_ present** | | ||
| `aria-describedby="[id value of applicable content]"` | `.pf-c-popover` | Gives the popover an accessible description by referring to the popover content that describes the primary message or purpose of the dialog. Not used if there is no static text that describes the popover. | | ||
| `aria-popover="true"` | `.pf-c-popover` | Tells assistive technologies that the windows underneath the current popover are not available for interaction. **Required**| | ||
| `aria-label="Close Dialog"` | `.pf-c-popover__close .pf-c-button` | Provides an accessible name for the close button as it uses an icon instead of text. **Required**| | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mcarrano Did you have a text string you wanted to use for the Close buttons on popovers? This looks like it was copied over from the Modal example, but I'm assuming we'd want something different for popovers. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jgiardino Do we even need the label to reference the object? What if we just say "Close?" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That works for me. Would you want the same label for the ModalBox example? If so, we should open an issue to update that one, too. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I think so @jgiardino . We shouldn't assume users will know what we mean when we use words like "dialog" or "popover." Aren't popovers some kind of puff pastry? :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But that would go nicely with our food theme: kebab, hamburger, toast... I opened an issue to capture the text string changes for both this and the modal so that we can track that change separately from this PR: #525 |
||
|
||
|
||
## Usage | ||
|
||
| Class | Applied To | Outcome | | ||
| -- | -- | -- | | ||
| `.pf-c-popover` | `<div>` | Creates a popover. | | ||
| `.pf-c-popover__arrow` | `.pf-c-popover` | Creates an arrow pointing towards the element the popover describes. ** Required.** | | ||
| `.pf-c-popover__content` | `.pf-c-popover` | Creates the body of the popover. ** Required.** | | ||
| `.pf-c-popover__close` | `.pf-c-popover__content` | Contains and positions the close icon in the top-right corner of the popover. ** Required.** | | ||
| `.pf-c-popover__header` | `.pf-c-popover__content` | The header text area of the popover. | | ||
| `.pf-c-popover__title` | `.pf-c-popover__header` | The actual popover title. | | ||
| `.pf-c-popover__body` | `.pf-c-popover__content` | The popover's body text. ** Required.** | | ||
| `.pf-m-left` | `.pf-c-popover` | Puts arrow to the left of the popover's content. | | ||
| `.pf-m-right` | `.pf-c-popover` | Puts arrow to the right of the popover's content. | | ||
| `.pf-m-top` | `.pf-c-popover` | Puts arrow on top of the popover's content. | | ||
| `.pf-m-bottom` | `.pf-c-popover` | Puts arrow on the bottom of the popover's content. | | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These last four rows are accurate. The class There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I opened #527 to track these changes separately from this PR. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# design md file | ||
|
||
TODO: design documentation |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import React from 'react'; | ||
import Documentation from '@siteComponents/Documentation'; | ||
import Example from '@siteComponents/Example'; | ||
|
||
import PopoverExampleRaw from '!raw!./popover-example.hbs'; | ||
|
||
import PopoverExample from './popover-example.hbs'; | ||
|
||
import docs from '../docs/code.md'; | ||
import '../styles.scss'; | ||
|
||
export const Docs = docs; | ||
|
||
export default () => { | ||
const popoverExample = PopoverExample(); | ||
|
||
return ( | ||
<Documentation docs={Docs}> | ||
<Example | ||
className="is-popover" | ||
heading="Popover" | ||
handlebars={PopoverExampleRaw} | ||
> | ||
{popoverExample} | ||
</Example> | ||
</Documentation> | ||
); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
{{#> popover direction="pf-m-right" header="hello"}} | ||
World! I am a popover | ||
{{#*inline "popover-parent"}} | ||
{{#> button btnClass='pf-m-primary'}} | ||
parent | ||
{{/button}} | ||
{{/inline}} | ||
{{/popover}} | ||
{{#> popover direction="pf-m-top" header="I can have a long title"}} | ||
And also very, very, very, very, very, very, very, very, very, very, very, very, very, very, very, very, very, very, very, very long body text. | ||
{{#*inline "popover-parent"}} | ||
{{#> button btnClass='pf-m-primary'}} | ||
parent | ||
{{/button}} | ||
{{/inline}} | ||
{{/popover}} | ||
{{#> popover direction="pf-m-bottom"}} | ||
Or no body text, and be short | ||
{{#*inline "popover-parent"}} | ||
{{#> button btnClass='pf-m-primary'}} | ||
parent | ||
{{/button}} | ||
{{/inline}} | ||
{{/popover}} | ||
{{#> popover direction="pf-m-left"}} | ||
! | ||
{{#*inline "popover-parent"}} | ||
{{#> button btnClass='pf-m-primary'}} | ||
parent | ||
{{/button}} | ||
{{/inline}} | ||
{{/popover}} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<div class="Preview__overlay"> | ||
<div class="Preview__overlay-container {{direction}}"> | ||
<div class="pf-c-popover {{direction}}"> | ||
<div class="pf-c-popover__arrow"></div> | ||
<div class="pf-c-popover__content" role="dialog" aria-modal="true" aria-labelledby="popover-title" aria-describedby="popover-description"> | ||
<div class="pf-c-popover__close"> | ||
<button class="pf-c-button pf-m-action" aria-label="Close Dialog"> | ||
<i class="fas fa-times"></i> | ||
</button> | ||
</div> | ||
<header class="pf-c-popover__header"> | ||
<h1 class="pf-c-popover__header-title" id="popover-title"> | ||
{{header}} | ||
</h1> | ||
</header> | ||
<div class="pf-c-popover__body" id="popover-description"> | ||
{{> @partial-block}} | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
{{#> popover-parent }} {{/popover-parent}} | ||
</div> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
@import "../../patternfly-utilities"; | ||
|
||
.pf-c-popover { | ||
// Component variables | ||
--pf-c-popover--MinWidth: pf-size-prem(100px); | ||
--pf-c-popover--MaxWidth: pf-size-prem(300px); | ||
--pf-c-popover--BoxShadow: var(--pf-global--BoxShadow); | ||
// Set margin to arrow width for placement | ||
--pf-c-popover--MarginBottom: var(--pf-global--arrow--width-lg); | ||
--pf-c-popover--MarginTop: var(--pf-global--arrow--width-lg); | ||
--pf-c-popover--MarginRight: var(--pf-global--arrow--width-lg); | ||
--pf-c-popover--MarginLeft: var(--pf-global--arrow--width-lg); | ||
|
||
// Content variables | ||
--pf-c-popover__content--BackgroundColor: var(--pf-global--BackgroundColor--100); | ||
|
||
// Arrow variables | ||
--pf-c-popover__arrow--Width: var(--pf-global--arrow--width-lg); | ||
// Set arrow margin to half arrow width for placement | ||
--pf-c-popover__arrow--Margin: var(--pf-global--arrow--width-lg) / 2; | ||
--pf-c-popover__arrow--BoxShadow: var(--pf-global--BoxShadow); | ||
--pf-c-popover__arrow--BackgroundColor: var(--pf-global--BackgroundColor--100); | ||
// used in the directional modifiers for placement | ||
--pf-c-popover__arrow-half-size: var(--pf-global--arrow--width) / 2; | ||
|
||
// Close container variables | ||
--pf-c-popover__close--Top: var(--pf-global--spacer--sm); | ||
--pf-c-popover__close--Right: var(--pf-global--spacer--md); | ||
|
||
// Header variables | ||
--pf-c-popover__header--PaddingTop: var(--pf-global--spacer--xl); | ||
--pf-c-popover__header--PaddingRight: var(--pf-global--spacer--xl); | ||
--pf-c-popover__header--PaddingBottom: var(--pf-global--spacer--sm); | ||
--pf-c-popover__header--PaddingLeft: var(--pf-global--spacer--xl); | ||
|
||
// Header title variables | ||
--pf-c-popover__header-title--FontSize: var(--pf-c-title--m-3xl--FontSize); | ||
--pf-c-popover__header-title--FontWeight: var(--pf-c-title--m-3xl--FontWeight); | ||
--pf-c-popover__header-title--LineHeight: var(--pf-c-title--m-3xl--LineHeight); | ||
|
||
// Body variables | ||
--pf-c-popover__body--PaddingTop: var(--pf-global--spacer--sm); | ||
--pf-c-popover__body--PaddingRight: var(--pf-global--spacer--xl); | ||
--pf-c-popover__body--PaddingBottom: var(--pf-global--spacer--xl); | ||
--pf-c-popover__body--PaddingLeft: var(--pf-global--spacer--xl); | ||
--pf-c-popover__body--MarginTop: var(--pf-global--spacer--xl); | ||
|
||
$half-size: $pf-global--arrow--width-lg / 2; | ||
|
||
position: relative; | ||
min-width: var(--pf-c-popover--MinWidth); | ||
max-width: var(--pf-c-popover--MaxWidth); | ||
box-shadow: var(--pf-c-popover--BoxShadow); | ||
|
||
&__content { | ||
position: relative; | ||
display: flex; | ||
flex-direction: column; | ||
background-color: var(--pf-c-popover__content--BackgroundColor); | ||
} | ||
|
||
&__arrow { | ||
position: absolute; | ||
// Popover arrow is square, sharing width value to prevent positioning errors | ||
width: var(--pf-c-popover__arrow--Width); | ||
height: var(--pf-c-popover__arrow--Width); | ||
margin: var(--pf-c-popover__arrow--Margin); | ||
pointer-events: none; | ||
background-color: var(--pf-c-popover__arrow--BackgroundColor); | ||
box-shadow: var(--pf-c-popover__arrow--BoxShadow); | ||
transform: rotate(45deg); | ||
} | ||
|
||
&__close { | ||
position: absolute; | ||
top: var(--pf-c-popover__close--Top); | ||
right: var(--pf-c-popover__close--Right); | ||
} | ||
|
||
// Header | ||
&__header { | ||
flex: 0 0 auto; | ||
padding: var(--pf-c-popover__header--PaddingTop) var(--pf-c-popover__header--PaddingRight) var(--pf-c-popover__header--PaddingBottom) var(--pf-c-popover__header--PaddingLeft); | ||
|
||
// Header title | ||
&-title { | ||
font-size: var(--pf-c-popover__header-title--FontSize); | ||
font-weight: var(--pf-c-popover__header-title--FontWeight); | ||
line-height: var(--pf-c-popover__header-title--LineHeight); | ||
} | ||
} | ||
|
||
// Body | ||
&__body { | ||
flex: 1 1 auto; | ||
padding: var(--pf-c-popover__body--PaddingTop) var(--pf-c-popover__body--PaddingRight) var(--pf-c-popover__body--PaddingBottom) var(--pf-c-popover__body--PaddingLeft); | ||
// Adding margin top here for no header being present. When the header is present, margin-top is removed | ||
margin-top: var(--pf-c-popover__body--MarginTop); | ||
overflow-x: hidden; | ||
overflow-y: auto; | ||
overscroll-behavior: contain; | ||
word-break: break-word; | ||
} | ||
|
||
// Removing top margin when header is present | ||
&__header + &__body { | ||
margin-top: 0; | ||
} | ||
|
||
&.pf-m-top { | ||
margin-bottom: var(--pf-c-popover--MarginBottom); | ||
} | ||
|
||
&.pf-m-bottom { | ||
margin-top: var(--pf-c-popover--MarginTop); | ||
} | ||
|
||
&.pf-m-left { | ||
margin-right: var(--pf-c-popover--MarginRight); | ||
} | ||
|
||
&.pf-m-right { | ||
margin-left: var(--pf-c-popover--MarginLeft); | ||
} | ||
|
||
&.pf-m-top > &__arrow { | ||
bottom: calc(var(--pf-c-popover__arrow-half-size) * -1); | ||
left: calc(50% - var(--pf-c-popover__arrow-half-size)); | ||
} | ||
|
||
&.pf-m-bottom > &__arrow { | ||
top: calc(var(--pf-c-popover__arrow-half-size) * -1); | ||
left: calc(50% - var(--pf-c-popover__arrow-half-size)); | ||
} | ||
|
||
&.pf-m-right > &__arrow { | ||
top: calc(50% - var(--pf-c-popover__arrow-half-size)); | ||
left: calc(var(--pf-c-popover__arrow-half-size) * -1); | ||
} | ||
|
||
&.pf-m-left > &__arrow { | ||
top: calc(50% - var(--pf-c-popover__arrow-half-size)); | ||
right: calc(var(--pf-c-popover__arrow-half-size) * -1); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
## Overview | ||
|
||
A tooltip is used to provide contextual information for another component on hover. The tooltip itself is made up of two elements: arrow and content. One of the directional modifiers (`.pf-m-left`, `.pf-m-top`, etc.) is required on the tooltip component | ||
|
||
## Accessibility | ||
|
||
| Attribute | Applied To | Outcome | | ||
| -- | -- | -- | | ||
| `aria-describedby="[id value of applicable content]"` | `.pf-c-tooltip` | Gives the tooltip an accessible description by referring to the tooltip content that describes the primary message or purpose of the dialog. Not used if there is no static text that describes the popover. | | ||
|
||
|
||
## Usage | ||
|
||
| Class | Applied To | Outcome | | ||
| -- | -- | -- | | ||
| `.pf-c-tooltip` | `<div>` | Creates a tooltip. | | ||
| `.pf-c-tooltip__arrow` | `.pf-c-tooltip` | Creates an arrow pointing towards the element the tooltip describes. ** Required.** | | ||
| `.pf-c-tooltip__content` | `.pf-c-tooltip` | Creates the body of the tooltip. ** Required.** | | ||
| `.pf-m-left` | `.pf-c-tooltip` | Puts arrow to the left of the tooltip's content. | | ||
| `.pf-m-right` | `.pf-c-tooltip` | Puts arrow to the right of the tooltip's content. | | ||
| `.pf-m-top` | `.pf-c-tooltip` | Puts arrow on top of the tooltip's content. | | ||
| `.pf-m-bottom` | `.pf-c-tooltip` | Puts arrow on the bottom of the tooltip's content. | |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# design md file | ||
|
||
TODO: design documentation |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import React from 'react'; | ||
import Documentation from '@siteComponents/Documentation'; | ||
import Example from '@siteComponents/Example'; | ||
|
||
import TooltipExampleRaw from '!raw!./tooltip-example.hbs'; | ||
|
||
import TooltipExample from './tooltip-example.hbs'; | ||
|
||
import docs from '../docs/code.md'; | ||
import '../styles.scss'; | ||
|
||
export const Docs = docs; | ||
|
||
export default () => { | ||
const tooltipExample = TooltipExample(); | ||
return ( | ||
<Documentation docs={Docs}> | ||
<Example | ||
className="is-tooltip" | ||
heading="Tooltip" | ||
handlebars={TooltipExampleRaw} | ||
> | ||
{tooltipExample} | ||
</Example> | ||
</Documentation> | ||
); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
{{#> tooltip direction="pf-m-right"}} | ||
Hello! | ||
{{#*inline "tooltip-parent"}} | ||
{{#> button btnClass='pf-m-primary' btnAttributes="aria-describedby=\"tooltip-description\" "}} | ||
parent | ||
{{/button}} | ||
{{/inline}} | ||
{{/tooltip}} | ||
{{#> tooltip direction="pf-m-top"}} | ||
I am a tooltip component! | ||
{{#*inline "tooltip-parent"}} | ||
{{#> button btnClass='pf-m-primary' btnAttributes="aria-describedby=\"tooltip-description\" "}} | ||
parent | ||
{{/button}} | ||
{{/inline}} | ||
{{/tooltip}} | ||
{{#> tooltip direction="pf-m-left"}} | ||
I can container a very, very, very, very, very, very, very, very, very, very, very, very, very, very, very, very, very, very, long piece of content. As well as very short. | ||
{{#*inline "tooltip-parent"}} | ||
{{#> button btnClass='pf-m-primary' btnAttributes="aria-describedby=\"tooltip-description\" "}} | ||
parent | ||
{{/button}} | ||
{{/inline}} | ||
{{/tooltip}} | ||
{{#> tooltip direction="pf-m-bottom"}} | ||
! | ||
{{#*inline "tooltip-parent"}} | ||
{{#> button btnClass='pf-m-primary' btnAttributes="aria-describedby=\"tooltip-description\" "}} | ||
parent | ||
{{/button}} | ||
{{/inline}} | ||
{{/tooltip}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like a Find/Replace mistake. 😉 I don't see
aria-popover
listed as an aria attribute.I think you meant
aria-modal="true"
instead.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I opened #527 to track this one separately from this PR.