feat(v11): Popover

* Breaking changes *

- The `Popover` now uses a different markup. The trigger becomes a child of the component.
- The new `PopoverContent` becomes an additional child of the `Popover` component.
- remove `relative` property
This commit is contained in:
Gregor Wassmann 2023-04-02 22:06:09 +02:00
commit d139d19524
13 changed files with 245 additions and 174 deletions

View file

@ -1,6 +1,6 @@
# Component Index
> 163 components exported from carbon-components-svelte@0.80.0.
> 164 components exported from carbon-components-svelte@0.80.0.
## Components
@ -95,6 +95,7 @@
- [`PaginationSkeleton`](#paginationskeleton)
- [`PasswordInput`](#passwordinput)
- [`Popover`](#popover)
- [`PopoverContent`](#popovercontent)
- [`ProgressBar`](#progressbar)
- [`ProgressIndicator`](#progressindicator)
- [`ProgressIndicatorSkeleton`](#progressindicatorskeleton)
@ -2798,14 +2799,14 @@ None.
### Props
| Prop name | Required | Kind | Reactive | Type | Default value | Description |
| :------------------ | :------- | :--------------- | :------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ------------------------------------------------------ |
| :------------------ | :------- | :--------------- | :------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | ------------------------------------------------------ |
| open | No | <code>let</code> | Yes | <code>boolean</code> | <code>false</code> | Set to `true` to display the popover |
| closeOnOutsideClick | No | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to close the popover on an outside click |
| caret | No | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` render a caret |
| align | No | <code>let</code> | No | <code>"top" &#124; "top-left" &#124; "top-right" &#124; "bottom" &#124; "bottom-left" &#124; "bottom-right" &#124; "left" &#124; "left-bottom" &#124; "left-top" &#124; "right" &#124; "right-bottom" &#124; "right-top"</code> | <code>"top"</code> | Specify the alignment of the caret |
| light | No | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to enable the light variant |
| isTabTip | No | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to render the tab tip variant |
| caret | No | <code>let</code> | No | <code>boolean</code> | <code>undefined</code> | Set to `true` render a caret |
| align | No | <code>let</code> | No | <code>"top" &#124; "top-left" &#124; "top-right" &#124; "bottom" &#124; "bottom-left" &#124; "bottom-right" &#124; "left" &#124; "left-bottom" &#124; "left-top" &#124; "right" &#124; "right-bottom" &#124; "right-top"</code> | <code>undefined</code> | Specify the alignment of the caret |
| dropShadow | No | <code>let</code> | No | <code>boolean</code> | <code>true</code> | Set to `false` to omit the drop shadow |
| highContrast | No | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to enable the high contrast variant |
| relative | No | <code>let</code> | No | <code>boolean</code> | <code>false</code> | Set to `true` to use a relative position |
### Slots
@ -2819,6 +2820,25 @@ None.
| :------------ | :--------- | :------------------------------------ |
| click:outside | dispatched | <code>{ target: HTMLElement; }</code> |
## `PopoverContent`
### Props
| Prop name | Required | Kind | Reactive | Type | Default value | Description |
| :----------- | :------- | :--------------- | :------- | --------------- | ----------------- | ----------- |
| className | No | <code>let</code> | No | -- | <code>null</code> | -- |
| contentProps | No | <code>let</code> | No | <code>{}</code> | <code>{}</code> | -- |
### Slots
| Slot name | Default | Props | Fallback |
| :-------- | :------ | :---- | :------- |
| -- | Yes | -- | -- |
### Events
None.
## `ProgressBar`
### Props

View file

@ -1,5 +1,5 @@
{
"total": 163,
"total": 164,
"components": [
{
"moduleName": "Accordion",
@ -8911,12 +8911,23 @@
"constant": false,
"reactive": false
},
{
"name": "isTabTip",
"kind": "let",
"description": "Set to `true` to render the tab tip variant",
"type": "boolean",
"value": "false",
"isFunction": false,
"isFunctionDeclaration": false,
"isRequired": false,
"constant": false,
"reactive": false
},
{
"name": "caret",
"kind": "let",
"description": "Set to `true` render a caret",
"type": "boolean",
"value": "false",
"isFunction": false,
"isFunctionDeclaration": false,
"isRequired": false,
@ -8928,7 +8939,6 @@
"kind": "let",
"description": "Specify the alignment of the caret",
"type": "\"top\" | \"top-left\" | \"top-right\" | \"bottom\" | \"bottom-left\" | \"bottom-right\" | \"left\" | \"left-bottom\" | \"left-top\" | \"right\" | \"right-bottom\" | \"right-top\"",
"value": "\"top\"",
"isFunction": false,
"isFunctionDeclaration": false,
"isRequired": false,
@ -8936,11 +8946,11 @@
"reactive": false
},
{
"name": "light",
"name": "dropShadow",
"kind": "let",
"description": "Set to `true` to enable the light variant",
"description": "Set to `false` to omit the drop shadow",
"type": "boolean",
"value": "false",
"value": "true",
"isFunction": false,
"isFunctionDeclaration": false,
"isRequired": false,
@ -8958,18 +8968,6 @@
"isRequired": false,
"constant": false,
"reactive": false
},
{
"name": "relative",
"kind": "let",
"description": "Set to `true` to use a relative position",
"type": "boolean",
"value": "false",
"isFunction": false,
"isFunctionDeclaration": false,
"isRequired": false,
"constant": false,
"reactive": false
}
],
"moduleExports": [],
@ -8982,7 +8980,39 @@
}
],
"typedefs": [],
"rest_props": { "type": "Element", "name": "div" }
"rest_props": { "type": "Element", "name": "span" }
},
{
"moduleName": "PopoverContent",
"filePath": "src/Popover/PopoverContent.svelte",
"props": [
{
"name": "className",
"kind": "let",
"value": "null",
"isFunction": false,
"isFunctionDeclaration": false,
"isRequired": false,
"constant": false,
"reactive": false
},
{
"name": "contentProps",
"kind": "let",
"type": "{}",
"value": "{}",
"isFunction": false,
"isFunctionDeclaration": false,
"isRequired": false,
"constant": false,
"reactive": false
}
],
"moduleExports": [],
"slots": [{ "name": "__default__", "default": true, "slot_props": "{}" }],
"events": [],
"typedefs": [],
"rest_props": { "type": "Element", "name": "span" }
},
{
"moduleName": "ProgressBar",

View file

@ -121,6 +121,10 @@ html[theme="g90"] .code-override {
margin-bottom: var(--bx-spacing-05);
}
.p-05 {
padding: var(--bx-spacing-05);
}
.table {
position: sticky;
max-height: calc(100vh - 3rem);

View file

@ -1,153 +1,128 @@
---
components: ["Popover", "PopoverContent"]
---
<script>
import { Popover } from "carbon-components-svelte";
import { Popover, PopoverContent, Button } from "carbon-components-svelte";
import Preview from "../../components/Preview.svelte";
import Settings from "carbon-icons-svelte/lib/Settings.svelte";
</script>
## Default
By default, the position of the popover component is absolute.
By default, the alignment of the popover is at the bottom.
<div data-outline>
Parent
<Popover open>
<div style="padding: var(--bx-spacing-05)">Content</div>
<div data-outline>Parent</div>
<PopoverContent className="p-05">Content</PopoverContent>
</Popover>
</div>
## Relative position
Set `relative` to `true` to use a relative position.
<div data-outline>
Parent
<Popover relative open>
<div style="padding: var(--bx-spacing-05)">Content</div>
</Popover>
</div>
## Close on outside click
Set `closeOnOutsideClick` to set `open` to `false` when clicking outside of the popover.
<div data-outline>
Parent
<Popover open closeOnOutsideClick on:click:outside={() => {console.log('on:click:outside')}}>
<div style="padding: var(--bx-spacing-05)">Content</div>
</Popover>
</div>
## Popover alignment
Customize the popover alignment using the `align` prop. Valid values include: `"top" | "top-left" | "top-right" | "bottom" | "bottom-left" | "bottom-right" | "left" | "left-bottom" | "left-top" | "right" | "right-bottom" | "right-top"`.
The default `align` value is `"top"`.
The default `align` value is `"bottom"`.
<div data-outline>
Parent
<Popover open align="top-left">
<div style="padding: var(--bx-spacing-05)">top-left</div>
</Popover>
</div>
<div data-outline>
Parent
<Popover open align="top-right">
<div style="padding: var(--bx-spacing-05)">top-right</div>
</Popover>
</div>
<div data-outline>
Parent
**At the bottom**
<div style="display: flex; justify-content: space-between;">
<Popover open align="bottom">
<div style="padding: var(--bx-spacing-05)">bottom</div>
<div data-outline>Parent</div>
<PopoverContent className="p-05">bottom</PopoverContent>
</Popover>
</div>
<div data-outline>
Parent
<Popover open align="bottom-left">
<div style="padding: var(--bx-spacing-05)">bottom-left</div>
<div data-outline>Parent</div>
<PopoverContent className="p-05">bottom-left</PopoverContent>
</Popover>
</div>
<div data-outline>
Parent
<Popover open align="bottom-right">
<div style="padding: var(--bx-spacing-05)">bottom-right</div>
<div data-outline>Parent</div>
<PopoverContent className="p-05">bottom-right</PopoverContent>
</Popover>
</div>
<div data-outline>
Parent
**To the left**
<div style="display: flex; justify-content: space-around; ">
<Popover open align="left">
<div style="padding: var(--bx-spacing-05)">left</div>
<div data-outline style="line-height: 2rem">Parent</div><!-- Height of 32px/2rem is assumed by @carbon/styles. Otherwise caret is misaligned. -->
<PopoverContent className="p-05">left</PopoverContent>
</Popover>
</div>
<div data-outline>
Parent
<Popover open align="left-bottom">
<div style="padding: var(--bx-spacing-05)">left-bottom</div>
<div data-outline style="line-height: 2rem">Parent</div><!-- Height of 32px/2rem is assumed by @carbon/styles. Otherwise caret is misaligned. -->
<PopoverContent className="p-05">left-bottom</PopoverContent>
</Popover>
<Popover open align="left-top">
<div data-outline style="line-height: 2rem">Parent</div><!-- Height of 32px/2rem is assumed by @carbon/styles. Otherwise caret is misaligned. -->
<PopoverContent className="p-05">left-top</PopoverContent>
</Popover>
</div>
<div data-outline>
Parent
<Popover open align="left-right">
<div style="padding: var(--bx-spacing-05)">left-right</div>
</Popover>
</div>
<div data-outline>
Parent
**To the right**
<div style="display: flex; justify-content: space-around ">
<Popover open align="right">
<div style="padding: var(--bx-spacing-05)">right</div>
<div data-outline style="line-height: 2rem">Parent</div><!-- Height of 32px/2rem is assumed by @carbon/styles. Otherwise caret is misaligned. -->
<PopoverContent className="p-05">right</PopoverContent>
</Popover>
</div>
<div data-outline>
Parent
<Popover open align="right-bottom">
<div style="padding: var(--bx-spacing-05)">right-bottom</div>
<div data-outline style="line-height: 2rem">Parent</div><!-- Height of 32px/2rem is assumed by @carbon/styles. Otherwise caret is misaligned. -->
<PopoverContent className="p-05">right-bottom</PopoverContent>
</Popover>
</div>
<div data-outline>
Parent
<Popover open align="right-top">
<div style="padding: var(--bx-spacing-05)">right-top</div>
<div data-outline style="line-height: 2rem">Parent</div><!-- Height of 32px/2rem is assumed by @carbon/styles. Otherwise caret is misaligned. -->
<PopoverContent className="p-05">right-top</PopoverContent>
</Popover>
</div>
## With caret
**At the top**
<div data-outline>
Parent
<Popover caret open>
<div style="padding: var(--bx-spacing-05)">Content</div>
<div style="display: flex; justify-content: space-between;">
<Popover open align="top-left">
<div data-outline>Parent</div>
<PopoverContent className="p-05">top-left</PopoverContent>
</Popover>
<Popover open align="top">
<div data-outline>Parent</div>
<PopoverContent className="p-05">top</PopoverContent>
</Popover>
<Popover open align="top-right">
<div data-outline>Parent</div>
<PopoverContent className="p-05">top-right</PopoverContent>
</Popover>
</div>
## Custom caret alignment
By default, the caret is aligned "top".
## Without caret
Possible `align` values include `"top"`, `"top-left"`, `"top-right"`, `"bottom"`, `"bottom-left"`, `"bottom-right"`, `"left"`, `"left-bottom"`, `"left-top"`, `"right"`, `"right-bottom"` or `"right-top"`.
<div data-outline>
Parent
<Popover caret align="top-left" open>
<div style="padding: var(--bx-spacing-05)">Content</div>
<Popover caret={false} open align='right'>
<div data-outline>Parent</div>
<PopoverContent className="p-05">Content</PopoverContent>
</Popover>
</div>
## Light variant
## Tab tip variant
<div data-outline>
Parent
<Popover light open>
<div style="padding: var(--bx-spacing-05)">Content</div>
<Popover isTabTip open align='bottom-left'>
<Button iconOnly kind="ghost" icon={Settings} />
<PopoverContent className="p-05">Content</PopoverContent>
</Popover>
</div>
## High contrast variant
<div data-outline>
Parent
<Popover highContrast open>
<div style="padding: var(--bx-spacing-05)">Content</div>
Set `highContrast` to use the high contrast variant.
<Popover highContrast open align='right'>
<div data-outline>Parent</div>
<PopoverContent className="p-05">Content</PopoverContent>
</Popover>
## Without drop shadow
Set `dropShadow` to `false` to remove the drop shadow.
<Popover open dropShadow={false} align='right'>
<div data-outline>Parent</div>
<PopoverContent className="p-05">Content</PopoverContent>
</Popover>
</div>
## External element

View file

@ -1,20 +1,20 @@
<script>
import { Popover, Button } from "carbon-components-svelte";
import { Popover, PopoverContent, Button } from "carbon-components-svelte";
let open = true;
let ref = null;
</script>
<div bind:this="{ref}" style:position="relative">
<Button on:click="{() => (open = !open)}">Toggle popover</Button>
<div bind:this="{ref}">
<Popover
bind:open
align="bottom-left"
isTabTip
on:click:outside="{({ detail }) => {
console.log('on:click:outside');
open = ref.contains(detail.target);
}}"
>
<div style="padding: var(--cds-spacing-05)">Content</div>
<Button on:click="{() => (open = !open)}">Toggle popover</Button>
<PopoverContent className="p-05">Content</PopoverContent>
</Popover>
</div>

View file

@ -9,24 +9,27 @@
/** Set to `true` to close the popover on an outside click */
export let closeOnOutsideClick = false;
/** Set to `true` render a caret */
export let caret = false;
/** Set to `true` to render the tab tip variant */
export let isTabTip = false;
/**
* Set to `true` render a caret
* @type {boolean}
* */
export let caret = isTabTip ? false : true;
/**
* Specify the alignment of the caret
* @type {"top" | "top-left" | "top-right" | "bottom" | "bottom-left" | "bottom-right" | "left" | "left-bottom" | "left-top" | "right" | "right-bottom" | "right-top"}
*/
export let align = "top";
export let align = isTabTip ? "bottom-left" : "bottom";
/** Set to `true` to enable the light variant */
export let light = false;
/** Set to `false` to omit the drop shadow */
export let dropShadow = true;
/** Set to `true` to enable the high contrast variant */
export let highContrast = false;
/** Set to `true` to use a relative position */
export let relative = false;
import { createEventDispatcher } from "svelte";
const dispatch = createEventDispatcher();
@ -44,11 +47,11 @@
}}"
/>
<div
<span
bind:this="{ref}"
class:bx--popover="{true}"
class:bx--popover-container="{true}"
class:bx--popover--caret="{caret}"
class:bx--popover--light="{light}"
class:bx--popover--drop-shadow="{dropShadow}"
class:bx--popover--high-contrast="{highContrast}"
class:bx--popover--top="{align === 'top'}"
class:bx--popover--top-left="{align === 'top-left'}"
@ -63,11 +66,8 @@
class:bx--popover--right-bottom="{align === 'right-bottom'}"
class:bx--popover--right-top="{align === 'right-top'}"
class:bx--popover--open="{open}"
class:bx--popover--relative="{relative}"
style:position="{relative ? "relative" : undefined}"
{...$$restProps}
style="{$$restProps.style}"
>
<div class:bx--popover-contents="{true}">
<slot />
</div>
</div>
</span>

View file

@ -0,0 +1,18 @@
<script>
export let className = null;
export let contentProps = {};
/** Obtain a reference to the popover content HTML element */
export let ref = null;
</script>
<span class:bx--popover="{true}" bind:this="{ref}" {...$$restProps}>
<span
class:bx--popover-content="{true}"
class="{className}"
{...contentProps}
>
<slot />
</span>
<span class:bx--popover-caret="{true}"></span>
</span>

View file

@ -1 +1,2 @@
export { default as Popover } from "./Popover.svelte";
export { default as PopoverContent } from "./PopoverContent.svelte";

View file

@ -84,7 +84,7 @@ export { OrderedList } from "./OrderedList";
export { OverflowMenu, OverflowMenuItem } from "./OverflowMenu";
export { Pagination, PaginationSkeleton } from "./Pagination";
export { PaginationNav } from "./PaginationNav";
export { Popover } from "./Popover";
export { Popover, PopoverContent } from "./Popover";
export { ProgressBar } from "./ProgressBar";
export {
ProgressIndicator,

View file

@ -1,5 +1,5 @@
<script lang="ts">
import { Popover } from "../types";
import { Popover, PopoverContent } from "../types";
let open = false;
</script>
@ -9,12 +9,10 @@
closeOnOutsideClick
align="right"
caret
relative
light
highContrast
on:click:outside="{() => {
console.log('on:click:outside');
}}"
>
<div style="padding: var(--bx-spacing-05)">Content</div>
<PopoverContent style="padding: var(--bx-spacing-05)">Content</PopoverContent>
</Popover>

View file

@ -1,7 +1,7 @@
import type { SvelteComponentTyped } from "svelte";
import type { SvelteHTMLElements } from "svelte/elements";
type RestProps = SvelteHTMLElements["div"];
type RestProps = SvelteHTMLElements["span"];
export interface PopoverProps extends RestProps {
/**
@ -17,14 +17,20 @@ export interface PopoverProps extends RestProps {
closeOnOutsideClick?: boolean;
/**
* Set to `true` render a caret
* Set to `true` to render the tab tip variant
* @default false
*/
isTabTip?: boolean;
/**
* Set to `true` render a caret
* @default undefined
*/
caret?: boolean;
/**
* Specify the alignment of the caret
* @default "top"
* @default undefined
*/
align?:
| "top"
@ -41,10 +47,10 @@ export interface PopoverProps extends RestProps {
| "right-top";
/**
* Set to `true` to enable the light variant
* @default false
* Set to `false` to omit the drop shadow
* @default true
*/
light?: boolean;
dropShadow?: boolean;
/**
* Set to `true` to enable the high contrast variant
@ -52,12 +58,6 @@ export interface PopoverProps extends RestProps {
*/
highContrast?: boolean;
/**
* Set to `true` to use a relative position
* @default false
*/
relative?: boolean;
[key: `data-${string}`]: any;
}

View file

@ -0,0 +1,24 @@
import type { SvelteComponentTyped } from "svelte";
import type { SvelteHTMLElements } from "svelte/elements";
type RestProps = SvelteHTMLElements["span"];
export interface PopoverContentProps extends RestProps {
/**
* @default null
*/
className?: undefined;
/**
* @default {}
*/
contentProps?: {};
[key: `data-${string}`]: any;
}
export default class PopoverContent extends SvelteComponentTyped<
PopoverContentProps,
Record<string, any>,
{ default: {} }
> {}

1
types/index.d.ts vendored
View file

@ -91,6 +91,7 @@ export { default as Pagination } from "./Pagination/Pagination.svelte";
export { default as PaginationSkeleton } from "./Pagination/PaginationSkeleton.svelte";
export { default as PaginationNav } from "./PaginationNav/PaginationNav.svelte";
export { default as Popover } from "./Popover/Popover.svelte";
export { default as PopoverContent } from "./Popover/PopoverContent.svelte";
export { default as ProgressBar } from "./ProgressBar/ProgressBar.svelte";
export { default as ProgressIndicator } from "./ProgressIndicator/ProgressIndicator.svelte";
export { default as ProgressIndicatorSkeleton } from "./ProgressIndicator/ProgressIndicatorSkeleton.svelte";