Add tooltip to Article details (#98)

* Add tooltip to Article details

* Hide popover f SharePopup is visible
This commit is contained in:
Ilya Y 2023-05-17 07:04:38 +03:00 committed by GitHub
parent 3710812668
commit c60b7e5c53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 113 additions and 72 deletions

View File

@ -149,6 +149,7 @@ img {
display: inline-block; display: inline-block;
margin: 0 3.2rem 1em 0; margin: 0 3.2rem 1em 0;
vertical-align: baseline; vertical-align: baseline;
cursor: pointer;
.icon { .icon {
height: 1.6em; height: 1.6em;
@ -194,10 +195,6 @@ img {
margin-right: 0; margin-right: 0;
} }
.iconEdit {
margin-right: 0.3em;
}
&:hover { &:hover {
background: #000; background: #000;

View File

@ -20,6 +20,7 @@ import { useLocalize } from '../../context/localize'
import stylesHeader from '../Nav/Header.module.scss' import stylesHeader from '../Nav/Header.module.scss'
import styles from './Article.module.scss' import styles from './Article.module.scss'
import { imageProxy } from '../../utils/imageProxy' import { imageProxy } from '../../utils/imageProxy'
import { Popover } from '../_shared/Popover'
interface ArticleProps { interface ArticleProps {
article: Shout article: Shout
@ -213,11 +214,17 @@ export const FullArticle = (props: ArticleProps) => {
{props.article.stat?.viewed} {props.article.stat?.viewed}
</div> </div>
</Show> </Show>
<div class={styles.shoutStatsItem} onClick={scrollToComments}> <Popover content={t('Comment')}>
{(triggerRef: (el) => void) => (
<div class={styles.shoutStatsItem} ref={triggerRef} onClick={scrollToComments}>
<Icon name="comment" class={styles.icon} /> <Icon name="comment" class={styles.icon} />
{props.article.stat?.commented ?? ''} {props.article.stat?.commented ?? ''}
</div> </div>
<div class={styles.shoutStatsItem}> )}
</Popover>
<Popover content={t('Share')}>
{(triggerRef: (el) => void) => (
<div class={styles.shoutStatsItem} ref={triggerRef}>
<SharePopup <SharePopup
title={props.article.title} title={props.article.title}
description={getDescription(props.article.body)} description={getDescription(props.article.body)}
@ -230,22 +237,30 @@ export const FullArticle = (props: ArticleProps) => {
} }
/> />
</div> </div>
)}
<div class={styles.shoutStatsItem} onClick={handleBookmarkButtonClick}> </Popover>
<Popover content={t('Add to bookmarks')}>
{(triggerRef: (el) => void) => (
<div class={styles.shoutStatsItem} ref={triggerRef} onClick={handleBookmarkButtonClick}>
<div class={styles.shoutStatsItemInner}> <div class={styles.shoutStatsItemInner}>
<Icon name="bookmark" class={styles.icon} /> <Icon name="bookmark" class={styles.icon} />
</div> </div>
</div> </div>
)}
</Popover>
<Show when={canEdit()}> <Show when={canEdit()}>
<div class={styles.shoutStatsItem}> <Popover content={t('Edit')}>
{(triggerRef: (el) => void) => (
<div class={styles.shoutStatsItem} ref={triggerRef}>
<a <a
href={getPagePath(router, 'edit', { shoutId: props.article.id.toString() })} href={getPagePath(router, 'edit', { shoutId: props.article.id.toString() })}
class={styles.shoutStatsItemInner} class={styles.shoutStatsItemInner}
> >
<Icon name="edit" class={clsx(styles.icon, styles.iconEdit)} /> <Icon name="pencil-outline" class={styles.icon} />
{t('Edit')}
</a> </a>
</div> </div>
)}
</Popover>
</Show> </Show>
<div class={clsx(styles.shoutStatsItem, styles.shoutStatsItemAdditionalData)}> <div class={clsx(styles.shoutStatsItem, styles.shoutStatsItemAdditionalData)}>
<div class={clsx(styles.shoutStatsItem, styles.shoutStatsItemAdditionalDataItem)}> <div class={clsx(styles.shoutStatsItem, styles.shoutStatsItemAdditionalDataItem)}>

View File

@ -5,12 +5,14 @@ import styles from '../_shared/Popup/Popup.module.scss'
import type { PopupProps } from '../_shared/Popup' import type { PopupProps } from '../_shared/Popup'
import { Popup } from '../_shared/Popup' import { Popup } from '../_shared/Popup'
import { useLocalize } from '../../context/localize' import { useLocalize } from '../../context/localize'
import { createEffect, createSignal } from 'solid-js'
type SharePopupProps = { type SharePopupProps = {
title: string title: string
shareUrl?: string shareUrl?: string
imageUrl: string imageUrl: string
description: string description: string
isVisible?: (value: boolean) => void
} & Omit<PopupProps, 'children'> } & Omit<PopupProps, 'children'>
export const getShareUrl = (params: { pathname?: string } = {}) => { export const getShareUrl = (params: { pathname?: string } = {}) => {
@ -21,6 +23,14 @@ export const getShareUrl = (params: { pathname?: string } = {}) => {
export const SharePopup = (props: SharePopupProps) => { export const SharePopup = (props: SharePopupProps) => {
const { t } = useLocalize() const { t } = useLocalize()
const [isVisible, setIsVisible] = createSignal(false)
createEffect(() => {
if (props.isVisible) {
props.isVisible(isVisible())
}
})
const [share] = createSocialShare(() => ({ const [share] = createSocialShare(() => ({
title: props.title, title: props.title,
url: props.shareUrl, url: props.shareUrl,
@ -29,8 +39,9 @@ export const SharePopup = (props: SharePopupProps) => {
const copyLink = async () => { const copyLink = async () => {
await navigator.clipboard.writeText(props.shareUrl) await navigator.clipboard.writeText(props.shareUrl)
} }
return ( return (
<Popup {...props} variant="bordered"> <Popup {...props} variant="bordered" onVisibilityChange={(value) => setIsVisible(value)}>
<ul class="nodash"> <ul class="nodash">
<li> <li>
<button role="button" class={styles.shareControl} onClick={() => share(VK)}> <button role="button" class={styles.shareControl} onClick={() => share(VK)}>

View File

@ -15,6 +15,7 @@ import { useLocalize } from '../../context/localize'
import { getPagePath, openPage } from '@nanostores/router' import { getPagePath, openPage } from '@nanostores/router'
import { router, useRouter } from '../../stores/router' import { router, useRouter } from '../../stores/router'
import { imageProxy } from '../../utils/imageProxy' import { imageProxy } from '../../utils/imageProxy'
import { Popover } from '../_shared/Popover'
interface ArticleCardProps { interface ArticleCardProps {
settings?: { settings?: {
@ -174,6 +175,7 @@ export const ArticleCard = (props: ArticleCardProps) => {
</Show> </Show>
<Show when={props.settings?.isFeedMode}> <Show when={props.settings?.isFeedMode}>
<p>asdasd</p>
<section <section
class={styles.shoutCardDetails} class={styles.shoutCardDetails}
classList={{ [styles.shoutCardDetailsActive]: isSharePopupActive() }} classList={{ [styles.shoutCardDetailsActive]: isSharePopupActive() }}
@ -195,25 +197,36 @@ export const ArticleCard = (props: ArticleCardProps) => {
</div> </div>
<div class={styles.shoutCardDetailsContent}> <div class={styles.shoutCardDetailsContent}>
<div class={styles.shoutCardDetailsItem}> <Popover content={t('Edit')}>
{(triggerRef: (el) => void) => (
<div class={styles.shoutCardDetailsItem} ref={triggerRef}>
<a href={getPagePath(router, 'edit', { shoutId: id.toString() })}> <a href={getPagePath(router, 'edit', { shoutId: id.toString() })}>
<Icon name="pencil-outline" class={clsx(styles.icon, styles.feedControlIcon)} /> <Icon name="pencil-outline" class={clsx(styles.icon, styles.feedControlIcon)} />
</a> </a>
</div> </div>
)}
</Popover>
<div class={styles.shoutCardDetailsItem}> <Popover content={t('Add to bookmarks')}>
{(triggerRef: (el) => void) => (
<div class={styles.shoutCardDetailsItem} ref={triggerRef}>
<button> <button>
<Icon name="bookmark" class={clsx(styles.icon, styles.feedControlIcon)} /> <Icon name="bookmark" class={clsx(styles.icon, styles.feedControlIcon)} />
</button> </button>
</div> </div>
)}
</Popover>
<div class={styles.shoutCardDetailsItem}> <Popover content={t('Share')} disabled={isSharePopupActive()}>
{(triggerRef: (el) => void) => (
<div class={styles.shoutCardDetailsItem} ref={triggerRef}>
<SharePopup <SharePopup
containerCssClass={stylesHeader.control} containerCssClass={stylesHeader.control}
title={title} title={title}
description={getDescription(body)} description={getDescription(body)}
imageUrl={cover} imageUrl={cover}
shareUrl={getShareUrl({ pathname: `/${slug}` })} shareUrl={getShareUrl({ pathname: `/${slug}` })}
isVisible={(value) => setIsSharePopupActive(value)}
trigger={ trigger={
<button> <button>
<Icon name="share-outline" class={clsx(styles.icon, styles.feedControlIcon)} /> <Icon name="share-outline" class={clsx(styles.icon, styles.feedControlIcon)} />
@ -221,6 +234,8 @@ export const ArticleCard = (props: ArticleCardProps) => {
} }
/> />
</div> </div>
)}
</Popover>
<div class={styles.shoutCardDetailsItem}> <div class={styles.shoutCardDetailsItem}>
<FeedArticlePopup <FeedArticlePopup

View File

@ -5,6 +5,7 @@ import styles from './Popover.module.scss'
type Props = { type Props = {
children: (setTooltipEl: (el: HTMLElement | null) => void) => JSX.Element children: (setTooltipEl: (el: HTMLElement | null) => void) => JSX.Element
content: string content: string
disabled?: boolean
} }
export const Popover = (props: Props) => { export const Popover = (props: Props) => {
@ -35,6 +36,7 @@ export const Popover = (props: Props) => {
const handleMouseOver = () => setShow(true) const handleMouseOver = () => setShow(true)
const handleMouseOut = () => setShow(false) const handleMouseOut = () => setShow(false)
if (!props.disabled) {
onMount(() => { onMount(() => {
showEvents.forEach((event) => { showEvents.forEach((event) => {
anchor().addEventListener(event, handleMouseOver) anchor().addEventListener(event, handleMouseOver)
@ -51,11 +53,12 @@ export const Popover = (props: Props) => {
}) })
} }
}) })
}
return ( return (
<> <>
{props.children(setAnchor)} {props.children(setAnchor)}
<Show when={show()}> <Show when={show() && !props.disabled}>
<div ref={setPopper} class={styles.tooltip} role="tooltip"> <div ref={setPopper} class={styles.tooltip} role="tooltip">
{props.content} {props.content}
<div class={styles.arrow} data-popper-arrow={true} /> <div class={styles.arrow} data-popper-arrow={true} />

View File

@ -10,7 +10,7 @@ export type PopupProps = {
popupCssClass?: string popupCssClass?: string
trigger: JSX.Element trigger: JSX.Element
children: JSX.Element children: JSX.Element
onVisibilityChange?: (isVisible) => void onVisibilityChange?: (isVisible: boolean) => void
horizontalAnchor?: HorizontalAnchor horizontalAnchor?: HorizontalAnchor
variant?: 'bordered' | 'tiny' variant?: 'bordered' | 'tiny'
} }