Add popover util (#96)
* Add popover component * [WIP] Popover component * update ref * conversation resolve * conversation resolve (conditional render icon) * conversation resolve (onMount instead createEffect)
This commit is contained in:
parent
cbb254a907
commit
4d147e3eb7
35
package-lock.json
generated
35
package-lock.json
generated
|
@ -18,6 +18,7 @@
|
||||||
"i18next": "22.4.15",
|
"i18next": "22.4.15",
|
||||||
"mailgun.js": "8.2.1",
|
"mailgun.js": "8.2.1",
|
||||||
"node-fetch": "3.3.1",
|
"node-fetch": "3.3.1",
|
||||||
|
"solid-popper": "0.3.0",
|
||||||
"typograf": "7.1.0"
|
"typograf": "7.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -5541,7 +5542,6 @@
|
||||||
"version": "2.11.7",
|
"version": "2.11.7",
|
||||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.7.tgz",
|
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.7.tgz",
|
||||||
"integrity": "sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw==",
|
"integrity": "sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw==",
|
||||||
"dev": true,
|
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
"url": "https://opencollective.com/popperjs"
|
"url": "https://opencollective.com/popperjs"
|
||||||
|
@ -8389,8 +8389,7 @@
|
||||||
"node_modules/csstype": {
|
"node_modules/csstype": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz",
|
||||||
"integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==",
|
"integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/damerau-levenshtein": {
|
"node_modules/damerau-levenshtein": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
|
@ -18106,7 +18105,6 @@
|
||||||
"version": "0.5.1",
|
"version": "0.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/seroval/-/seroval-0.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/seroval/-/seroval-0.5.1.tgz",
|
||||||
"integrity": "sha512-ZfhQVB59hmIauJG5Ydynupy8KHyr5imGNtdDhbZG68Ufh1Ynkv9KOYOAABf71oVbQxJ8VkWnMHAjEHE7fWkH5g==",
|
"integrity": "sha512-ZfhQVB59hmIauJG5Ydynupy8KHyr5imGNtdDhbZG68Ufh1Ynkv9KOYOAABf71oVbQxJ8VkWnMHAjEHE7fWkH5g==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
|
@ -18305,12 +18303,23 @@
|
||||||
"version": "1.7.5",
|
"version": "1.7.5",
|
||||||
"resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.7.5.tgz",
|
"resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.7.5.tgz",
|
||||||
"integrity": "sha512-GfJ8na1e9FG1oAF5xC24BM+ATLym0sfH+ZblkbBFpueYdq3fWAoA5Ve+jGeIeLI7jmMGfa0rUaKruszNm2sH8w==",
|
"integrity": "sha512-GfJ8na1e9FG1oAF5xC24BM+ATLym0sfH+ZblkbBFpueYdq3fWAoA5Ve+jGeIeLI7jmMGfa0rUaKruszNm2sH8w==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"csstype": "^3.1.0",
|
"csstype": "^3.1.0",
|
||||||
"seroval": "^0.5.0"
|
"seroval": "^0.5.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/solid-popper": {
|
||||||
|
"version": "0.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/solid-popper/-/solid-popper-0.3.0.tgz",
|
||||||
|
"integrity": "sha512-XlfEWAyxGGqFgg/uRpF+BemSfCqjbLA8p6fToDa+6v3paw3eBQj0TU08aBOIj2VeigaEiz8ZTlDx1eBLVRivBg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@popperjs/core": "^2.11",
|
||||||
|
"solid-js": "^1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/solid-refresh": {
|
"node_modules/solid-refresh": {
|
||||||
"version": "0.5.1",
|
"version": "0.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.5.1.tgz",
|
||||||
|
@ -24661,8 +24670,7 @@
|
||||||
"@popperjs/core": {
|
"@popperjs/core": {
|
||||||
"version": "2.11.7",
|
"version": "2.11.7",
|
||||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.7.tgz",
|
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.7.tgz",
|
||||||
"integrity": "sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw==",
|
"integrity": "sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"@remirror/core-constants": {
|
"@remirror/core-constants": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
|
@ -26768,8 +26776,7 @@
|
||||||
"csstype": {
|
"csstype": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz",
|
||||||
"integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==",
|
"integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"damerau-levenshtein": {
|
"damerau-levenshtein": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
|
@ -33967,8 +33974,7 @@
|
||||||
"seroval": {
|
"seroval": {
|
||||||
"version": "0.5.1",
|
"version": "0.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/seroval/-/seroval-0.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/seroval/-/seroval-0.5.1.tgz",
|
||||||
"integrity": "sha512-ZfhQVB59hmIauJG5Ydynupy8KHyr5imGNtdDhbZG68Ufh1Ynkv9KOYOAABf71oVbQxJ8VkWnMHAjEHE7fWkH5g==",
|
"integrity": "sha512-ZfhQVB59hmIauJG5Ydynupy8KHyr5imGNtdDhbZG68Ufh1Ynkv9KOYOAABf71oVbQxJ8VkWnMHAjEHE7fWkH5g=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"set-blocking": {
|
"set-blocking": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
|
@ -34107,12 +34113,17 @@
|
||||||
"version": "1.7.5",
|
"version": "1.7.5",
|
||||||
"resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.7.5.tgz",
|
"resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.7.5.tgz",
|
||||||
"integrity": "sha512-GfJ8na1e9FG1oAF5xC24BM+ATLym0sfH+ZblkbBFpueYdq3fWAoA5Ve+jGeIeLI7jmMGfa0rUaKruszNm2sH8w==",
|
"integrity": "sha512-GfJ8na1e9FG1oAF5xC24BM+ATLym0sfH+ZblkbBFpueYdq3fWAoA5Ve+jGeIeLI7jmMGfa0rUaKruszNm2sH8w==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"csstype": "^3.1.0",
|
"csstype": "^3.1.0",
|
||||||
"seroval": "^0.5.0"
|
"seroval": "^0.5.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"solid-popper": {
|
||||||
|
"version": "0.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/solid-popper/-/solid-popper-0.3.0.tgz",
|
||||||
|
"integrity": "sha512-XlfEWAyxGGqFgg/uRpF+BemSfCqjbLA8p6fToDa+6v3paw3eBQj0TU08aBOIj2VeigaEiz8ZTlDx1eBLVRivBg==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
"solid-refresh": {
|
"solid-refresh": {
|
||||||
"version": "0.5.1",
|
"version": "0.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/solid-refresh/-/solid-refresh-0.5.1.tgz",
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
"i18next": "22.4.15",
|
"i18next": "22.4.15",
|
||||||
"mailgun.js": "8.2.1",
|
"mailgun.js": "8.2.1",
|
||||||
"node-fetch": "3.3.1",
|
"node-fetch": "3.3.1",
|
||||||
|
"solid-popper": "0.3.0",
|
||||||
"typograf": "7.1.0"
|
"typograf": "7.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import styles from './Header.module.scss'
|
import styles from './Header.module.scss'
|
||||||
import { clsx } from 'clsx'
|
import { clsx } from 'clsx'
|
||||||
import { router, useRouter } from '../../stores/router'
|
import { router, useRouter } from '../../stores/router'
|
||||||
|
|
||||||
import { Icon } from '../_shared/Icon'
|
import { Icon } from '../_shared/Icon'
|
||||||
import { createMemo, createSignal, Show } from 'solid-js'
|
import { createEffect, createMemo, createSignal, onCleanup, onMount, Show } from 'solid-js'
|
||||||
import Notifications from './Notifications'
|
import Notifications from './Notifications'
|
||||||
import { ProfilePopup } from './ProfilePopup'
|
import { ProfilePopup } from './ProfilePopup'
|
||||||
import Userpic from '../Author/Userpic'
|
import Userpic from '../Author/Userpic'
|
||||||
|
@ -14,11 +13,18 @@ import { useLocalize } from '../../context/localize'
|
||||||
import { getPagePath } from '@nanostores/router'
|
import { getPagePath } from '@nanostores/router'
|
||||||
import { Button } from '../_shared/Button'
|
import { Button } from '../_shared/Button'
|
||||||
import { useEditorContext } from '../../context/editor'
|
import { useEditorContext } from '../../context/editor'
|
||||||
|
import { Popover } from '../_shared/Popover'
|
||||||
|
|
||||||
type HeaderAuthProps = {
|
type HeaderAuthProps = {
|
||||||
setIsProfilePopupVisible: (value: boolean) => void
|
setIsProfilePopupVisible: (value: boolean) => void
|
||||||
}
|
}
|
||||||
|
type IconedButton = {
|
||||||
|
value: string
|
||||||
|
icon: string
|
||||||
|
action: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
const MD_WIDTH_BREAKPOINT = 992
|
||||||
export const HeaderAuth = (props: HeaderAuthProps) => {
|
export const HeaderAuth = (props: HeaderAuthProps) => {
|
||||||
const { t } = useLocalize()
|
const { t } = useLocalize()
|
||||||
const { page } = useRouter()
|
const { page } = useRouter()
|
||||||
|
@ -64,6 +70,40 @@ export const HeaderAuth = (props: HeaderAuthProps) => {
|
||||||
publishShout()
|
publishShout()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const [width, setWidth] = createSignal(0)
|
||||||
|
const handleResize = () => setWidth(window.innerWidth)
|
||||||
|
onMount(() => {
|
||||||
|
handleResize()
|
||||||
|
window.addEventListener('resize', handleResize)
|
||||||
|
onCleanup(() => window.removeEventListener('resize', handleResize))
|
||||||
|
})
|
||||||
|
|
||||||
|
const renderIconedButton = (iconedButtonProps: IconedButton) => {
|
||||||
|
return (
|
||||||
|
<Show
|
||||||
|
when={width() < MD_WIDTH_BREAKPOINT}
|
||||||
|
fallback={
|
||||||
|
<Button
|
||||||
|
value={<span class={styles.textLabel}>{iconedButtonProps.value}</span>}
|
||||||
|
variant={'outline'}
|
||||||
|
onClick={handleSaveButtonClick}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Popover content={iconedButtonProps.value}>
|
||||||
|
{(ref) => (
|
||||||
|
<Button
|
||||||
|
ref={ref}
|
||||||
|
variant={'outline'}
|
||||||
|
onClick={handleSaveButtonClick}
|
||||||
|
value={<Icon name={iconedButtonProps.icon} class={styles.icon} />}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Popover>
|
||||||
|
</Show>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ShowOnlyOnClient>
|
<ShowOnlyOnClient>
|
||||||
<Show when={isSessionLoaded()} keyed={true}>
|
<Show when={isSessionLoaded()} keyed={true}>
|
||||||
|
@ -90,37 +130,32 @@ export const HeaderAuth = (props: HeaderAuthProps) => {
|
||||||
|
|
||||||
<Show when={showSaveButton()}>
|
<Show when={showSaveButton()}>
|
||||||
<div class={clsx(styles.userControlItem, styles.userControlItemVerbose)}>
|
<div class={clsx(styles.userControlItem, styles.userControlItemVerbose)}>
|
||||||
<Button
|
{renderIconedButton({
|
||||||
value={
|
value: t('Save'),
|
||||||
<>
|
icon: 'save',
|
||||||
<span class={styles.textLabel}>{t('Save')}</span>
|
action: handleSaveButtonClick
|
||||||
<Icon name="save" class={styles.icon} />
|
})}
|
||||||
</>
|
|
||||||
}
|
|
||||||
variant={'outline'}
|
|
||||||
onClick={handleSaveButtonClick}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class={clsx(styles.userControlItem, styles.userControlItemVerbose)}>
|
<div class={clsx(styles.userControlItem, styles.userControlItemVerbose)}>
|
||||||
<Button
|
{renderIconedButton({
|
||||||
value={
|
value: t('Publish'),
|
||||||
<>
|
icon: 'publish',
|
||||||
<span class={styles.textLabel}>{t('Publish')}</span>
|
action: handlePublishButtonClick
|
||||||
<Icon name="publish" class={styles.icon} />
|
})}
|
||||||
</>
|
|
||||||
}
|
|
||||||
variant={'outline'}
|
|
||||||
onClick={handlePublishButtonClick}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class={clsx(styles.userControlItem, styles.userControlItemVerbose)}>
|
<div class={clsx(styles.userControlItem, styles.userControlItemVerbose)}>
|
||||||
|
<Popover content={t('Settings')}>
|
||||||
|
{(ref) => (
|
||||||
<Button
|
<Button
|
||||||
|
ref={ref}
|
||||||
value={<Icon name="burger" />}
|
value={<Icon name="burger" />}
|
||||||
variant={'outline'}
|
variant={'outline'}
|
||||||
onClick={handleBurgerButtonClick}
|
onClick={handleBurgerButtonClick}
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
|
</Popover>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
|
|
||||||
|
|
|
@ -11,11 +11,19 @@ type Props = {
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
onClick?: () => void
|
onClick?: () => void
|
||||||
class?: string
|
class?: string
|
||||||
|
ref?: HTMLButtonElement | ((el: HTMLButtonElement) => void)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Button = (props: Props) => {
|
export const Button = (props: Props) => {
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
|
ref={(el) => {
|
||||||
|
if (typeof props.ref === 'function') {
|
||||||
|
props.ref(el)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
props.ref = el
|
||||||
|
}}
|
||||||
onClick={props.onClick}
|
onClick={props.onClick}
|
||||||
type={props.type ?? 'button'}
|
type={props.type ?? 'button'}
|
||||||
disabled={props.loading || props.disabled}
|
disabled={props.loading || props.disabled}
|
||||||
|
|
43
src/components/_shared/Popover/Popover.module.scss
Normal file
43
src/components/_shared/Popover/Popover.module.scss
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
.tooltip {
|
||||||
|
padding: 8px;
|
||||||
|
background: #141414;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 4px;
|
||||||
|
position: relative;
|
||||||
|
z-index: 100;
|
||||||
|
|
||||||
|
.arrow,
|
||||||
|
.arrow::before {
|
||||||
|
position: absolute;
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
background: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow::before {
|
||||||
|
visibility: visible;
|
||||||
|
content: '';
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-popper-placement^='top'] > .arrow {
|
||||||
|
bottom: -4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-popper-placement^='bottom'] > .arrow {
|
||||||
|
top: -4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-popper-placement^='left'] > .arrow {
|
||||||
|
right: -4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-popper-placement^='right'] > .arrow {
|
||||||
|
left: -4px;
|
||||||
|
}
|
||||||
|
}
|
66
src/components/_shared/Popover/Popover.tsx
Normal file
66
src/components/_shared/Popover/Popover.tsx
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
import { createEffect, createSignal, JSX, JSXElement, onMount, Show } from 'solid-js'
|
||||||
|
import usePopper from 'solid-popper'
|
||||||
|
import styles from './Popover.module.scss'
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
children: (setTooltipEl: (el: HTMLElement | null) => void) => JSX.Element
|
||||||
|
content: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Popover = (props: Props) => {
|
||||||
|
const [show, setShow] = createSignal(false)
|
||||||
|
const [anchor, setAnchor] = createSignal<HTMLElement>()
|
||||||
|
const [popper, setPopper] = createSignal<HTMLElement>()
|
||||||
|
|
||||||
|
usePopper(anchor, popper, {
|
||||||
|
modifiers: [
|
||||||
|
{
|
||||||
|
name: 'offset',
|
||||||
|
options: {
|
||||||
|
offset: [0, 8]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'flip',
|
||||||
|
options: {
|
||||||
|
fallbackPlacements: ['top', 'bottom']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
const showEvents = ['mouseenter', 'focus']
|
||||||
|
const hideEvents = ['mouseleave', 'blur']
|
||||||
|
|
||||||
|
const handleMouseOver = () => setShow(true)
|
||||||
|
const handleMouseOut = () => setShow(false)
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
showEvents.forEach((event) => {
|
||||||
|
anchor().addEventListener(event, handleMouseOver)
|
||||||
|
})
|
||||||
|
hideEvents.forEach((event) => {
|
||||||
|
anchor().addEventListener(event, handleMouseOut)
|
||||||
|
})
|
||||||
|
return () => {
|
||||||
|
showEvents.forEach((event) => {
|
||||||
|
anchor().removeEventListener(event, handleMouseOver)
|
||||||
|
})
|
||||||
|
hideEvents.forEach((event) => {
|
||||||
|
anchor().removeEventListener(event, handleMouseOut)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{props.children(setAnchor)}
|
||||||
|
<Show when={show()}>
|
||||||
|
<div ref={setPopper} class={styles.tooltip} role="tooltip">
|
||||||
|
{props.content}
|
||||||
|
<div class={styles.arrow} data-popper-arrow={true} />
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
22
src/components/_shared/Popover/README.md
Normal file
22
src/components/_shared/Popover/README.md
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
## Usage Example
|
||||||
|
|
||||||
|
```JS
|
||||||
|
import Popover from './Popover';
|
||||||
|
|
||||||
|
<Popover content={'This is popover text'}>
|
||||||
|
{(triggerRef: (el) => void) => (
|
||||||
|
<Button value="Hover me" ref={triggerRef} />
|
||||||
|
)}
|
||||||
|
</Popover>
|
||||||
|
```
|
||||||
|
### or
|
||||||
|
|
||||||
|
```JS
|
||||||
|
import Popover from './Popover';
|
||||||
|
|
||||||
|
<Popover content={'This is popover text'}>
|
||||||
|
{(triggerRef: (el) => void) => (
|
||||||
|
<div ref={triggerRef}>Hover me</div>
|
||||||
|
)}
|
||||||
|
</Popover>
|
||||||
|
```
|
1
src/components/_shared/Popover/index.ts
Normal file
1
src/components/_shared/Popover/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export { Popover } from './Popover'
|
Loading…
Reference in New Issue
Block a user