diff --git a/docs/pages/components/popover.md b/docs/pages/components/popover.md index 6079c372b..fb089c609 100644 --- a/docs/pages/components/popover.md +++ b/docs/pages/components/popover.md @@ -9,7 +9,7 @@ folder: components summary: --- -The popover is a wrapping component that accepts a "control" as well as a "body. +The popover is a wrapping component that accepts a "control" as well as a "body". {: .docs-intro} A control can be anything that you want to trigger the interaction from. The body will be the contents of what you reveal on the page after triggering the popover. Commonly used as the interaction/wrapping component when composing "dropdowns", "contextual menus", "mega menu", etc, when paired with the menu component. @@ -23,13 +23,14 @@ The basic wrapping structure of a popover. * `fd-popover` - wrapper for the whole container * `fd-popover__control` - control element to toggle the display of the popover -* `fd-popover__body` - wrapper that contains the popover content +* `fd-popover__body` - wrapper that contains the popover content for CSS-only implementations +* `fd-popover__popper` - wrapper that contains the popover content when implemented using [popper.js](https://github.com/FezVrasta/popper.js) (use this instead of `fd-popover__body`). See [Implementation Options](#implementation-options) for more information.
## Modifiers * `--left`, `--right` - modifier classes for `fd-popover__body` placement -* `--no-arrow` - modifier to render `popover__body` without an arrow +* `--no-arrow` - modifier to render `fd-popover__body` or `fd-popover__popper` without an arrow
@@ -193,3 +194,13 @@ style="background-image: url('https://placeimg.com/400/400/nature');"> {% endcapture %} {% include display-component.html component=default-popoverwmenu %} + +
+ +## Implementation Options + +Using [popper.js](https://github.com/FezVrasta/popper.js) allows for programmatic positioning, but requires slightly different styling. Use the `fd-popover__popper` class for wrapping the popover content instead of `fd-popover__body`. See the implementation libraries for specifc details: + +* [Fundamental React](https://sap.github.io/fundamental-react/popover) +* [Fundamental NGX](https://sap.github.io/fundamental-ngx/popover) +* [Fundamental Vue](https://sap.github.io/fundamental-vue/#/example/popover) diff --git a/scss/components/popover.scss b/scss/components/popover.scss index 571e54ebb..57894e4d6 100644 --- a/scss/components/popover.scss +++ b/scss/components/popover.scss @@ -18,11 +18,13 @@ $block: #{$fd-namespace}-popover; $fd-popover-arrow-right: 14px !default; $fd-popover-arrow-x-offset: fd-space(2.5) !default; + $fd-popover-arrow-width: 13px; + $fd-popover-arrow-height: 8px; + $fd-popover-arrow-width-half: $fd-popover-arrow-width/2; + $fd-popover-transition-params: $fd-animation--speed !default; $fd-popover-transition-distance: -15px !default; - --fd-popover-background-color: var(--fd-color-background-2); - // Consider removing this reset, look into its use and seeing font-size/line-height/color... // @include fd-reset; position: relative; @@ -39,7 +41,7 @@ $block: #{$fd-namespace}-popover; white-space: nowrap; z-index: $fd-popover-z-index; border-radius: $fd-border-radius; - @include fd-var-color("background-color", $fd-popover-background-color, --fd-popover-background-color); + @include fd-var-color("background-color", $fd-popover-background-color, --fd-color-background-2); @if $fd-support-css-var-fallback { box-shadow: 0 5px 20px 0 fd-color("neutral", 3), 0 2px 8px 0 fd-color("neutral", 2); } @@ -140,4 +142,117 @@ $block: #{$fd-namespace}-popover; transform: translateY($fd-popover-transition-distance); } } + + &__popper { + border: $fd-popover-border; + position: absolute; + white-space: nowrap; + z-index: $fd-popover-z-index; + border-radius: $fd-border-radius; + @include fd-var-color("background-color", $fd-popover-background-color, --fd-color-background-2); + @if $fd-support-css-var-fallback { + box-shadow: 0 5px 20px 0 fd-color("neutral", 3), 0 2px 8px 0 fd-color("neutral", 2); + } + box-shadow: 0 5px 20px 0 var(--fd-color-neutral-3), 0 2px 8px 0 var(--fd-color-neutral-2); + opacity: 1; + + &--no-arrow { + margin: 0 !important; + + .fd-popover__arrow { + display: none; + } + } + + .fd-popover__arrow { + position: absolute; + width: 0; + height: 0; + border-style: solid; + border-color: transparent; + + &::after { + position: absolute; + content: ""; + border-style: solid; + border-color: transparent; + } + } + + &[data-x-out-of-boundaries] { + display: none; + } + + &[data-placement^="top"] { + margin-bottom: $fd-popover-arrow-height; + + .fd-popover__arrow { + bottom: -$fd-popover-arrow-height; + margin: 0 $fd-popover-arrow-width-half; + border-width: $fd-popover-arrow-height $fd-popover-arrow-width-half 0 $fd-popover-arrow-width-half; + @include fd-var-color("border-top-color", $fd-forms-border-color, --fd-color-neutral-4); + + &::after { + bottom: 1px; + margin: 0 (-$fd-popover-arrow-width-half); + border-width: $fd-popover-arrow-height $fd-popover-arrow-width-half 0 $fd-popover-arrow-width-half; + @include fd-var-color("border-top-color", $fd-popover-background-color, --fd-color-background-2); + } + } + } + + &[data-placement^="bottom"] { + margin-top: $fd-popover-arrow-height; + + .fd-popover__arrow { + top: -$fd-popover-arrow-height; + margin: 0 $fd-popover-arrow-width-half; + border-width: 0 $fd-popover-arrow-width-half $fd-popover-arrow-height $fd-popover-arrow-width-half; + @include fd-var-color("border-bottom-color", $fd-forms-border-color, --fd-color-neutral-4); + + &::after { + top: 1px; + margin: 0 (-$fd-popover-arrow-width-half); + border-width: 0 $fd-popover-arrow-width-half $fd-popover-arrow-height $fd-popover-arrow-width-half; + @include fd-var-color("border-bottom-color", $fd-popover-background-color, --fd-color-background-2); + } + } + } + + &[data-placement^="left"] { + margin-right: $fd-popover-arrow-height; + + .fd-popover__arrow { + right: -$fd-popover-arrow-height; + margin: $fd-popover-arrow-width-half 0; + border-width: $fd-popover-arrow-width-half 0 $fd-popover-arrow-width-half $fd-popover-arrow-height; + @include fd-var-color("border-left-color", $fd-forms-border-color, --fd-color-neutral-4); + + &::after { + right: 1px; + margin: -$fd-popover-arrow-width-half 0; + border-width: $fd-popover-arrow-width-half 0 $fd-popover-arrow-width-half $fd-popover-arrow-height; + @include fd-var-color("border-left-color", $fd-popover-background-color, --fd-color-background-2); + } + } + } + + &[data-placement^="right"] { + margin-left: $fd-popover-arrow-height; + + .fd-popover__arrow { + left: -$fd-popover-arrow-height; + margin: $fd-popover-arrow-width-half 0; + border-width: $fd-popover-arrow-width-half $fd-popover-arrow-height $fd-popover-arrow-width-half 0; + @include fd-var-color("border-right-color", $fd-forms-border-color, --fd-color-neutral-4); + + &::after { + left: 1px; + margin: -$fd-popover-arrow-width-half 0; + border-width: $fd-popover-arrow-width-half $fd-popover-arrow-height $fd-popover-arrow-width-half 0; + @include fd-var-color("border-right-color", $fd-popover-background-color, --fd-color-background-2); + } + } + } + } } diff --git a/scss/components/time-picker.scss b/scss/components/time-picker.scss index bd8edf4d3..7e2746b00 100644 --- a/scss/components/time-picker.scss +++ b/scss/components/time-picker.scss @@ -11,7 +11,8 @@ $block: #{$fd-namespace}-time-picker; .#{$block} { .#{$fd-namespace}-popover { - &__body { + &__body, + &__popper { padding: fd-space(s); } } diff --git a/test/templates/popover/component.njk b/test/templates/popover/component.njk index 926f4897d..6d2259a42 100644 --- a/test/templates/popover/component.njk +++ b/test/templates/popover/component.njk @@ -14,6 +14,13 @@ popover: {%- endmacro -%} +{%- macro popover_popperjs(properties={}, modifier={}, state={}, aria={ hidden: true }) -%} +
+ {{ popover_control({ control: properties.control }) | indent(2) }} + {{ popover_popper(properties={ body: properties.body, id: properties.id }, modifier={ block: modifier.block }) }} +
+{%- endmacro -%} + {%- macro popover_control(properties={}, modifier={}, state={}) -%}
{{properties.control}}
{%- endmacro -%} @@ -23,3 +30,10 @@ popover: {{properties.body}} {%- endmacro -%} + +{%- macro popover_popper(properties={}, modifier={}, state={}, aria={ hidden: true }) -%} +
+ {{properties.body}} +
+
+{%- endmacro -%} diff --git a/test/templates/popover/index.njk b/test/templates/popover/index.njk index ba34c792f..e79337cc9 100644 --- a/test/templates/popover/index.njk +++ b/test/templates/popover/index.njk @@ -1,7 +1,7 @@ {% extends "layout.njk" %} {% import "./../utils.njk" as utils %} {% from "./../format.njk" import format %} -{% from "./component.njk" import popover %} +{% from "./component.njk" import popover, popover_popperjs %} {% from "./../menu/component.njk" import menu %} @@ -18,6 +18,8 @@ {%- set _id2 = utils.id() %} {%- set _id3 = utils.id() %} {%- set _id4 = utils.id() %} +{%- set _id5 = utils.id() %} +{%- set _id6 = utils.id() %} {%- macro sample_control(properties={}) -%} @@ -105,5 +107,53 @@ {% endset %} {{ format(example) }} +



+ +

Use with popper.js

+

NOTE: This will not be functional as the popper.js library is not being used here so this +is simply a styling example.

+{% set example %} + +{{ popover_popperjs(properties={ + id: _id5, + control: sample_control(properties={id: _id5}), + body: menu(properties={ + items: [ + { "label": "Option 1" }, + { "label": "Option 2" }, + { "label": "Option 3" }, + { "label": "Option 4" } + ] + }) + }, modifier={ block: []}) +}} + +{% endset %} +{{ format(example) }} + +



+ +

No Arrow with popper.js

+

NOTE: This will not be functional as the popper.js library is not being used here so this +is simply a styling example.

+{% set example %} + +{{ popover_popperjs(properties={ + id: _id6, + control: sample_control(properties={id: _id6}), + body: menu(properties={ + items: [ + { "label": "Option 1" }, + { "label": "Option 2" }, + { "label": "Option 3" }, + { "label": "Option 4" } + ] + }) + }, modifier={ block: ['no-arrow']}) +}} + +{% endset %} +{{ format(example) }} + {% endblock %}