Skip to content

Commit

Permalink
Merge pull request #722 from MisRob/teleport
Browse files Browse the repository at this point in the history
Let's teleport + make 'sidebar' icon flip in RTL languages
  • Loading branch information
MisRob authored Aug 30, 2024
2 parents d3d40d2 + 1df5fab commit e4a16e2
Show file tree
Hide file tree
Showing 13 changed files with 194 additions and 33 deletions.
3 changes: 2 additions & 1 deletion docs/pages/installation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
<li>Installs <code>$themeBrand</code>, <code>$themeTokens</code> <code>$themePalette</code>, and <code>$computedClass</code> helpers on all Vue instances (see <DocsInternalLink href="/colors/#usage" text="Colors" />).</li>
<li>Provides <code>$coreOutline</code>, <code>$inputModality</code>, <code>$mediaType</code>, and <code>$isPrint</code> computed properties as well as <code>$print</code> method to all Vue instances.</li>
<li>Globally registers all KDS Vue components.</li>
<li>Inserts assertive and polite ARIA live regions to your application's document body (see <DocsInternalLink href="/usekliveregion" text="useKLiveRegion" />).</li>
<li>Inserts assertive and polite ARIA live regions <code>#k-live-region</code> to an application's document body (see <DocsInternalLink href="/usekliveregion" text="useKLiveRegion" />).</li>
<li>Inserts the overlay container element <code>#k-overlay</code> to an application's document body (see <DocsLibraryLink component="KOverlay" /> or search for <code>appendToOverlay</code> prop on components).</li>
</ul>
</DocsPageSection>

Expand Down
29 changes: 29 additions & 0 deletions docs/pages/koverlay.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<template>

<DocsPageTemplate apiDocs>
<DocsPageSection title="Overview" anchor="#overview">
<p>Use <code>KOverlay</code> to move an element from its original place in the DOM to the overlay container element <code>#k-overlay</code> that is inserted to an application's document body automatically <DocsInternalLink href="/installation#install-plugin" text="during the KDS installation process" />. This is often useful for modals, tooltips, dropdowns, or other elements that should appear on top of other content.</p>
</DocsPageSection>

<DocsPageSection title="Usage" anchor="#usage">
<p>First, check whether you need <code>KOverlay</code>. Some KDS components already utilize it internally and you only need to instruct them to activate it, typically via the <code>appendToOverlay</code> prop.</p>

<p>If you need to use <code>KOverlay</code>, simply wrap an element or a component in it:</p>

<DocsShowCode language="html">
<KOverlay>
<YourComponent />
</KOverlay>
</DocsShowCode>
</DocsPageSection>

<DocsPageSection title="Related" anchor="#related">
<ul>
<li>
<DocsInternalLink href="/installation#install-plugin" text="KDS installation step" /> that attaches the overlay container element <code>#k-overlay</code> to an application's document body
</li>
</ul>
</DocsPageSection>
</DocsPageTemplate>

</template>
8 changes: 2 additions & 6 deletions docs/pages/usekliveregion.vue
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
<DocsPageSection title="Related" anchor="#related">
<ul>
<li>
<DocsInternalLink href="/installation#install-plugin" text="KDS installation step" /> that attaches live regions to an application's DOM
<DocsInternalLink href="/installation#install-plugin" text="KDS installation step" /> that attaches live regions to an application's document body
</li>
</ul>
</DocsPageSection>
Expand All @@ -93,7 +93,7 @@
export default {
setup() {
const { _mountLiveRegion, sendPoliteMessage, sendAssertiveMessage } = useKLiveRegion();
const { sendPoliteMessage, sendAssertiveMessage } = useKLiveRegion();
const politeMessageInput = ref('Polite hello');
const updatePoliteMessage = message => {
Expand All @@ -106,7 +106,6 @@
};
return {
_mountLiveRegion,
updatePoliteMessage,
politeMessageInput,
updateAssertiveMessage,
Expand All @@ -115,9 +114,6 @@
sendAssertiveMessage,
};
},
mounted() {
this._mountLiveRegion(this.$root.$el);
},
};
</script>
5 changes: 5 additions & 0 deletions docs/tableOfContents.js
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,11 @@ export default [
isCode: true,
keywords: tabsRelatedKeywords,
}),
new Page({
path: '/koverlay',
title: 'KOverlay',
isCode: true,
}),
new Page({
path: '/ktransition',
title: 'KTransition',
Expand Down
1 change: 1 addition & 0 deletions lib/KIcon/iconDefinitions.js
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@ const KolibriIcons = {
email: { icon: require('./precompiled-icons/material-icons/mail_outline/baseline.vue').default },
sidebar: {
icon: require('./precompiled-icons/material-icons/vertical_split/baseline.vue').default,
rtlFlip: true,
},

bookmark: { icon: require('./precompiled-icons/mdi/bookmark.vue').default },
Expand Down
16 changes: 5 additions & 11 deletions lib/KModal.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>

<component :is="wrapper" v-bind="wrapperProps">
<component :is="wrapper">
<!-- Accessibility properties for the overlay -->
<transition name="modal-fade" appear>
<div
Expand Down Expand Up @@ -103,7 +103,6 @@

<script>
import Teleport from 'vue2-teleport';
import debounce from 'lodash/debounce';
import useKResponsiveWindow from './composables/useKResponsiveWindow';
Expand All @@ -120,9 +119,6 @@
*/
export default {
name: 'KModal',
components: {
Teleport,
},
setup() {
const { windowHeight, windowWidth } = useKResponsiveWindow();
return { windowHeight, windowWidth };
Expand Down Expand Up @@ -197,9 +193,10 @@
required: false,
},
/**
* Whether or not the modal should be teleported to the root of the document
* Whether or not the modal should be moved
* to the overlay container element `#k-overlay`
*/
appendToRoot: {
appendToOverlay: {
type: Boolean,
default: false,
},
Expand Down Expand Up @@ -236,10 +233,7 @@
};
},
wrapper() {
return this.appendToRoot ? 'Teleport' : 'div';
},
wrapperProps() {
return this.appendToRoot ? { to: 'body' } : {};
return this.appendToOverlay ? 'KOverlay' : 'div';
},
},
created() {
Expand Down
36 changes: 36 additions & 0 deletions lib/KOverlay/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<template>

<Teleport :to="overlayElSelector">
<!-- @slot Content to be moved to the overlay container element `#k-overlay` -->
<slot></slot>
</Teleport>

</template>


<script>
import Teleport from 'vue2-teleport';
import _useOverlay from '../composables/_useOverlay';
/**
* Moves an element from its original place in the DOM
* to the overlay container element #k-overlay that is inserted
* to an application's document body automatically during
* the KDS installation process (see KThemePlugin.js).
* This is often useful for modals, tooltips, dropdowns, or other
* elements that should appear on top of other content.
*/
export default {
name: 'KOverlay',
components: {
Teleport,
},
setup() {
const { overlayElSelector } = _useOverlay();
return { overlayElSelector };
},
};
</script>

9 changes: 5 additions & 4 deletions lib/KThemePlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import KSwitch from './KSwitch';
import KTabs from './tabs/KTabs';
import KTabsList from './tabs/KTabsList';
import KTabsPanel from './tabs/KTabsPanel';
import KOverlay from './KOverlay';
import KTextbox from './KTextbox';
import KTooltip from './KTooltip';
import KTransition from './KTransition';
Expand All @@ -43,8 +44,10 @@ import { themeTokens, themeBrand, themePalette, themeOutlineStyle } from './styl
import globalThemeState from './styles/globalThemeState';

import useKLiveRegion from './composables/useKLiveRegion';
import _useOverlay from './composables/_useOverlay';

const { _mountLiveRegion } = useKLiveRegion();
const { mountOverlay } = _useOverlay();

require('./grids/globalStyles.js'); // global grid styles

Expand All @@ -53,13 +56,10 @@ require('./grids/globalStyles.js'); // global grid styles
* Also, set up global state, listeners, and styles.
*/
export default function KThemePlugin(Vue) {
// Note that if DOM live regions need to be demostrated
// on the KDS website, and therefore attached to the DOM,
// just call _mountLiveRegion() in the relevant documentation
// page's 'mounted' (see 'docs/pages/usekliveregio.vue' for an example)
if (!isNuxtServerSideRendering()) {
const onDomReady = () => {
_mountLiveRegion();
mountOverlay();
document.removeEventListener('DOMContentLoaded', onDomReady);
};

Expand Down Expand Up @@ -152,6 +152,7 @@ export default function KThemePlugin(Vue) {
Vue.component('KTabs', KTabs);
Vue.component('KTabsList', KTabsList);
Vue.component('KTabsPanel', KTabsPanel);
Vue.component('KOverlay', KOverlay);
Vue.component('KTextbox', KTextbox);
Vue.component('KTooltip', KTooltip);
Vue.component('KTransition', KTransition);
Expand Down
30 changes: 20 additions & 10 deletions lib/KTooltip/Popper.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
Vendored from https://github.com/RobinCK/vue-popper/
pending
https://github.com/RobinCK/vue-popper/pull/73
LE customizations
- Allow for appending to a chosen element rather than to body,
typically to the overlay container element #k-overlay.
'appendToBody' prop changedto 'appendToEl' and related changes.
-->


Expand Down Expand Up @@ -89,9 +94,14 @@
default: false,
},
dataValue: { default: null }, // eslint-disable-line
appendToBody: {
type: Boolean,
default: false,
/* An HTML element the tooltip should be appended to */
// 'type: HTMLElement' breaks the documentation build (??)
// 'type: Object' causes 'Invalid prop: type check failed for prop
// "appendToEl". Expected Object, got HTMLDivElement' warning
// in consumers
appendToEl: {
type: null,
default: null,
},
visibleArrow: {
type: Boolean,
Expand Down Expand Up @@ -155,7 +165,7 @@
created() {
this.appendedArrow = false;
this.appendedToBody = false;
this.isAppendedToEl = false;
this.popperOptions = Object.assign(this.popperOptions, this.options);
},
Expand Down Expand Up @@ -210,9 +220,9 @@
this.popperJS = null;
}
if (this.appendedToBody) {
this.appendedToBody = false;
document.body.removeChild(this.popper.parentElement);
if (this.isAppendedToEl) {
this.isAppendedToEl = false;
this.appendToEl.removeChild(this.popper.parentElement);
}
},
Expand All @@ -222,9 +232,9 @@
this.appendArrow(this.popper);
}
if (this.appendToBody && !this.appendedToBody) {
this.appendedToBody = true;
document.body.appendChild(this.popper.parentElement);
if (this.appendToEl && !this.isAppendedToEl) {
this.isAppendedToEl = true;
this.appendToEl.appendChild(this.popper.parentElement);
}
if (this.popperJS && this.popperJS.destroy) {
Expand Down
17 changes: 17 additions & 0 deletions lib/KTooltip/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
:disabled="disabled"
:visibleArrow="false"
:options="options"
:appendToEl="appendToEl"
trigger="hover"
>
<div
Expand All @@ -28,6 +29,7 @@
<script>
import isArray from 'lodash/isArray';
import _useOverlay from '../composables/_useOverlay';
import Popper from './Popper';
/**
Expand All @@ -38,6 +40,12 @@
components: {
Popper,
},
setup(props) {
const { getOverlayEl } = _useOverlay();
const appendToEl = props.appendToOverlay ? getOverlayEl() : null;
return { appendToEl };
},
props: {
/**
* Name of `ref` element within the parent's `$refs` object. Tooltip will be
Expand Down Expand Up @@ -86,6 +94,15 @@
type: String,
default: null,
},
/**
* Whether or not the tooltip should be moved
* to the overlay container element `#k-overlay`
*/
// eslint-disable-next-line kolibri/vue-no-unused-properties
appendToOverlay: {
type: Boolean,
default: false,
},
},
data() {
return {
Expand Down
10 changes: 10 additions & 0 deletions lib/composables/_useOverlay/__tests__/index.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
describe('_useOverlay', () => {
// this is taken care of by KThemePlugin.js that is already registered
// in the global jest setup
it(`document body contains the overlay container element #k-overlay upon the KDS plugin initialization`, () => {
expect(`
<div id="k-overlay">
</div>
`).toBeInDom();
});
});
Loading

0 comments on commit e4a16e2

Please sign in to comment.