Skip to content

Commit

Permalink
Merge pull request #3 from wysher/feat/nested
Browse files Browse the repository at this point in the history
Feat/nested
  • Loading branch information
wysher authored Jun 7, 2020
2 parents ae3e0bb + 62f4af5 commit d25e7d4
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 44 deletions.
66 changes: 56 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ it and how it looks.

## Features
- it's portaled (always visible, even if inside e.g modal with overflow: hidden)
- may be nested
- if content has not enough space on one side it will try to render on other side. For instance if position is set to `top-left` and there's no room on top position will be set to `bottom-left`. This feature listens to window resize event
- may be open/closed on every trigger and content event or from outside
- you decide how trigger and content looks
Expand Down Expand Up @@ -93,10 +94,35 @@ Each slot gets theese props, available through let:propName

## Usage

### Close on escape keydown and click outside
### Close on escape keydown and click outside [REPL](https://svelte.dev/repl/08a2a569d1354426ab747445ece60fcb?version=3.22.2)

```javascript
<script>
import Overlay from 'svelte-overlay';
let isOpen = false;

function handleWindowKeyDown(event) {
if (event.key === 'Escape') {
isOpen = false;
}
}
</script>

<Overlay
onWindowKeyDown={handleWindowKeyDown}
closeOnClickOutside
bind:isOpen={isOpen}
>
<button slot="parent" let:toggle on:click={toggle}>
Click Me!
</button>

<div slot="content" let:close>
<p>Lorem ipsum dolor sit.</p>
<button on:click={close}>Close</button>
</div>

</Overlay>
```

### Close from content [REPL](https://svelte.dev/repl/a13dde11268a4ec6a560add54287c8f2?version=3.22.2)
Expand Down Expand Up @@ -145,21 +171,15 @@ Each slot gets theese props, available through let:propName
import Overlay from 'svelte-overlay';
let isOpen = false;

function handleToggle(event) {
if (event.detail !== isOpen) {
isOpen = event.detail;
}
}

function toggleFromOutside() {
isOpen = !isOpen;
}
</script>

<button on:click={toggleFromOutside}>Toggle from outside</button>

<Overlay {isOpen} >
<div slot="parent" on:toggle={handleToggle}>
<Overlay bind:isOpen={isOpen} >
<div slot="parent">
I am a parent
</div>

Expand Down Expand Up @@ -195,7 +215,7 @@ Each slot gets theese props, available through let:propName
on:toggle={handleToggle}
closeOnClickOutside
zIndex={100}
{isOpen}>
bind:isOpen={isOpen}>
<button slot="parent" let:toggle on:click={toggle}>Click Me!</button>
<div slot="content" transition:fly={{ y: 5, duration: 200 }} class="content">
Lorem ipsum dolor sit.
Expand Down Expand Up @@ -229,6 +249,32 @@ Each slot gets theese props, available through let:propName

```

### Nested with click outside and close on esc key [REPL](https://svelte.dev/repl/284b4a09eddc4b64b5bd6734712d30ee?version=3.22.2)

```javascript
<script>
import Overlay from 'svelte-overlay';
let isOpen = false;

function toggleFromOutside() {
isOpen = !isOpen;
}
</script>

<button on:click={toggleFromOutside}>Toggle from outside</button>

<Overlay bind:isOpen={isOpen} >
<div slot="parent">
I am a parent
</div>

<div slot="content">
Lorem ipsum dolor sit.
</div>

</Overlay>
```

---

## License
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "svelte-overlay",
"version": "1.3.1",
"version": "1.4.0",
"description": "Svelte Overlay component. Great for creating dropdowns, tooltips and popovers",
"author": "Mariusz Wachowski",
"keywords": [
Expand Down
32 changes: 21 additions & 11 deletions src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,17 @@
import { fly } from 'svelte/transition';
let isOpen = false;
let isNestedOpen = false
let selectedPosition = POSITIONS[0];
let mouseOnContent = false;
function handleKeyDown(event, { close }) {
if (event.key === 'Escape') close();
}
function handleToggle(event) {
if (event.detail !== isOpen) isOpen = event.detail;
function handleKeyDown(event) {
if (event.key === 'Escape') {
if (!isNestedOpen) {
isOpen = false;
} else {
isNestedOpen = false;
}
}
}
</script>

Expand All @@ -40,14 +41,23 @@
position={selectedPosition}
onWindowKeyDown={handleKeyDown}
closeOnClickOutside
on:toggle={handleToggle}
closeOnScroll
{isOpen}>
bind:isOpen={isOpen}
>
<button slot="parent" let:toggle on:click={toggle}>Click Me!</button>
<div transition:fly={{ y: 5, duration: 200 }} slot="content" class="content" let:close>
<Overlay
position={selectedPosition}
onWindowKeyDown={handleKeyDown}
closeOnClickOutside
bind:isOpen={isNestedOpen}
>
<button slot="parent" let:toggle on:click={toggle}>Click Me!</button>
<div transition:fly={{ y: 5, duration: 200 }} slot="content" class="content" let:close>
Lorem ipsum dolor sit amet consectetur, adipisicing elit. At eligendi vel quidem voluptatum sed, eius illo? Explicabo nam numquam tenetur blanditiis eum quisquam recusandae non consectetur saepe! Nihil commodi amet repudiandae nulla facere temporibus doloribus cupiditate. Aperiam quam consequatur eos magnam quaerat dolorem deserunt ratione similique nobis quasi, impedit hic ipsa officia, aut, praesentium porro. Repellendus beatae nisi earum error nam laboriosam incidunt repudiandae consectetur rem corporis perferendis, tempora quidem qui alias praesentium, hic ad excepturi corrupti quod? Nulla at magnam, harum, esse ullam sunt ipsam, assumenda voluptates accusantium dolor velit officiis cupiditate reprehenderit facere aliquid? Dolor, minima repellat corrupti odio fuga similique quo magnam accusamus officiis porro, ad dolorem quod. Sequi aspernatur suscipit ex nulla necessitatibus molestias inventore quidem iusto esse odit soluta totam atque assumenda, voluptatibus ratione et explicabo expedita obcaecati iure iste maiores impedit cupiditate. Facere a voluptates deserunt animi obcaecati adipisci voluptatem maiores dolores cum natus?
</div>
</Overlay>
</div>
</Overlay>
</section>

<style>
Expand Down
35 changes: 13 additions & 22 deletions src/components/Overlay.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
createEventDispatcher,
} from 'svelte';
import POSITIONS from './positions';
import { getNextPosition } from './helpers';
import { isBrowser, getNextPosition } from './helpers';
const dispatch = createEventDispatcher();
const DEFAULT_POSITION = POSITIONS[0];
Expand All @@ -25,9 +25,8 @@
let currentPosition = null;
let parent;
let contentWrapper;
let content;
let portal;
let target;
let topStyle = 0;
let leftStyle = 0;
Expand All @@ -42,11 +41,6 @@
$: openedState = isOpen && hasParent && hasContent;
// for SSR
function isBrowser() {
return typeof window !== 'undefined' && typeof document !== 'undefined';
}
function addListeners() {
if (!isBrowser()) return;
window.addEventListener('resize', updatePosition);
Expand All @@ -62,11 +56,6 @@
}
onMount(() => {
if (!isBrowser()) return;
portal = document.createElement('div');
document.body.appendChild(portal);
portal.appendChild(contentWrapper);
if (openedState) {
addListeners();
}
Expand All @@ -75,7 +64,6 @@
onDestroy(() => {
if (!isBrowser()) return;
removeListeners();
document.body.removeChild(portal);
});
Expand Down Expand Up @@ -108,16 +96,19 @@
if (openedState) toggle(false);
}
function handleWindowClick(event) {
if (!closeOnClickOutside || !openedState) return;
function contains (event) {
const path = event.path || event.composedPath();
if (path.includes(parent) || path.includes(content)) return;
return path.includes(parent) || path.includes(content);
}
function handleWindowClick(event) {
if (!closeOnClickOutside || !openedState || contains(event)) return;
close();
}
function handleWindowKeyDown(event) {
if (!openedState) return;
onWindowKeyDown(event, { isOpen: openedState, open, close, toggle });
if (!onWindowKeyDown || !openedState) return;
onWindowKeyDown(event, { isOpen: openedState, open, close, toggle, contains });
}
async function updatePosition() {
Expand Down Expand Up @@ -153,14 +144,14 @@
on:mousedown={handleWindowClick}
on:keydown={handleWindowKeyDown} />

<div class={`overlay ${className}`} style={`z-index:${zIndex}; ${style}`}>
<div bind:this={target} class={`overlay ${className}`} style={`z-index:${zIndex}; ${style}`}>
<div bind:this={parent}>
<slot name="parent" {toggle} isOpen={openedState} {open} {close} />
</div>
<div
bind:this={contentWrapper}
class="content-wrapper"
style={`top: ${topStyle}px; left: ${leftStyle}px; width: ${widthStyle}px; height: ${heightStyle}px; z-index:${zIndex};`}>
style={`top: ${topStyle}px; left: ${leftStyle}px; width: ${widthStyle}px; height: ${heightStyle}px; z-index:${zIndex};`}
>
{#if openedState}
<div class={`content ${currentPosition || ''}`} bind:this={content}>
<slot name="content" {toggle} isOpen={openedState} {open} {close} />
Expand Down
5 changes: 5 additions & 0 deletions src/components/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ const TOP = "top";
const CENTER = "center";
const BOTTOM = "bottom";

// for SSR
export function isBrowser() {
return typeof window !== 'undefined' && typeof document !== 'undefined';
}

export const getNextPosition = (position, dimensions) => {
const clientHeight = Math.min(document.body.clientHeight, document.documentElement.clientHeight);
const clientWidth = Math.min(document.body.clientWidth, document.documentElement.clientWidth);
Expand Down

0 comments on commit d25e7d4

Please sign in to comment.