Skip to content

Commit

Permalink
feat(Popover): Enhance popover with new props and use it as a tooltip…
Browse files Browse the repository at this point in the history
… on copy link button
  • Loading branch information
dontry committed Nov 10, 2023
1 parent eb08cde commit fcbca07
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 45 deletions.
3 changes: 3 additions & 0 deletions src/components/ContentWrap.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -1048,6 +1048,9 @@ export default class ContentWrap extends Component {
<div className="promotion">
<div className="actions">
<Popover
closeOnBlur={true}
hasArrow={true}
placement={'bottom'}
trigger={
<Button
className="button icon-button hint--rounded hint--bottom-left"
Expand Down
54 changes: 38 additions & 16 deletions src/components/PopOver.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Component, createRef } from 'preact';
import PropTypes from 'prop-types';


export class Popover extends Component {
constructor(props) {
super(props);
Expand All @@ -12,40 +11,58 @@ export class Popover extends Component {
}

componentDidMount() {
document.addEventListener('click', this.handleDocumentClick, true);
this.props.closeOnBlur &&
document.addEventListener('click', this.handleDocumentClick, true);
}

componentWillUnmount() {
document.removeEventListener('click', this.handleDocumentClick);
this.props.closeOnBlur &&
document.removeEventListener('click', this.handleDocumentClick);
}

togglePopover = () => {
this.setState((prevState) => ({
isVisible: !prevState.isVisible,
}));
if (this.props.isVisible !== undefined) {
this.props.onVisibilityChange &&
this.props.onVisibilityChange(!this.props.isVisible);
} else {
this.setState((prevState) => ({
isVisible: !prevState.isVisible,
}));
}
};

handleDocumentClick = (event) => {
if (this.popoverRef.current && !this.popoverRef.current.contains(event.target)) {
if (
this.popoverRef.current &&
!this.popoverRef.current.contains(event.target)
) {
this.setState({ isVisible: false });
}
};


render() {
const { trigger, content } = this.props;
const { isVisible } = this.state;
const { trigger, content, closeOnBlur, placement, hasArrow, hasShadow } =
this.props;
const isVisible =
this.props.isVisible !== undefined
? this.props.isVisible
: this.state.isVisible;

return (
<div className="popover" >
<div className={`popover`}>
<div className="popover-trigger" onClick={this.togglePopover}>
{trigger}
</div>
{isVisible && (
<>
<div className="popover-backdrop" />
<div className="popover-content" ref={this.popoverRef}>
<div className="popover-arrow"></div>
{closeOnBlur && <div className="popover-backdrop" />}
<div
className={`popover-content ${placement} ${
hasShadow ? 'shadow' : ''
}`}
ref={this.popoverRef}
>
{hasArrow && <div className={`popover-arrow`}></div>}
{content}
</div>
</>
Expand All @@ -55,8 +72,13 @@ export class Popover extends Component {
}
}


Popover.propTypes = {
trigger: PropTypes.node.isRequired,
content: PropTypes.node.isRequired,
}
isVisible: PropTypes.bool,
onVisibilityChange: PropTypes.func,
closeOnBlur: PropTypes.bool,
hasArrow: PropTypes.bool,
hasShadow: PropTypes.bool,
placement: PropTypes.oneOf(['top', 'bottom']),
};
50 changes: 36 additions & 14 deletions src/components/SharePanel.jsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { Component } from 'preact';
import PropTypes from 'prop-types';
import { PreviewCard } from './PreviewCard';
import { Popover } from './PopOver';
import { Button } from './common';

export class SharePanel extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
link: '',
isTooltipVisible: false,
};
}

Expand All @@ -24,10 +27,16 @@ export class SharePanel extends Component {
handleCopyLink = () => {
const { link } = this.state;
navigator.clipboard.writeText(link);
this.setState({
isTooltipVisible: true,
});
setTimeout(() => {
this.setState({ isTooltipVisible: false });
}, 3000);
};

render() {
const { image, author, title } = this.props;
const { title, author, image } = this.props;
const { link, isLoading } = this.state;

return (
Expand All @@ -50,19 +59,32 @@ export class SharePanel extends Component {
description="Click and check the latest diagram. Install our Confluence plugin for an enhanced expperience when viewing in Confluence."
image={image}
/>
<button
aria-label="Copy link"
className="button icon-button copy-button"
title={link}
onClick={this.handleCopyLink}
>
{isLoading ? (
<div className="loader" />
) : (
<span className="material-symbols-outlined">link</span>
)}
<span>Copy link</span>
</button>
<Popover
isVisible={this.state.isTooltipVisible}
placement={'top'}
hasShadow={true}
trigger={
<Button
aria-label="Copy link"
className="button icon-button copy-button"
title={link}
onClick={this.handleCopyLink}
>
{isLoading ? (
<div className="loader" />
) : (
<span className="material-symbols-outlined">link</span>
)}
<span>Copy link</span>
</Button>
}
content={
<div className="tooltip">
<span class="material-symbols-outlined">check_circle</span>
<span>Link copied to clipboard</span>
</div>
}
/>
</div>
</div>
<span className="footnote">
Expand Down
26 changes: 26 additions & 0 deletions src/components/Tooltip.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React, { Component } from 'react';

class Tooltip extends Component {
state = {
isTooltipVisible: false,
};

handleMouseOver = () => {
this.setState({ isTooltipVisible: true });
};

handleMouseOut = () => {
this.setState({ isTooltipVisible: false });
};

render() {
return (
<div>
{this.props.children}
{this.state.isTooltipVisible && (
<div className="tooltip">{this.props.children}</div>
)}
</div>
);
}
}
69 changes: 54 additions & 15 deletions src/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -1980,16 +1980,52 @@ ol.editor-nav li {
.popover-content {
position: absolute;
background: #fff;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
border: 1px solid #ccc;
border-radius: 4px;
padding: 20px;
z-index: 3;
}

.popover-content.shadow {
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.4);
}

.popover-arrow {
position: absolute;
width: 0;
height: 0;
}

.popover-content.top {
top: auto;
bottom: calc(100% + 8px);
left: 50%;
transform: translateX(-50%);
}

.popover-content.bottom {
top: calc(100% + 8px);
left: 50%;
transform: translateX(-50%);
}

.popover-content.top .popover-arrow {
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-top: 8px solid #fff;
bottom: -8px;
left: 50%;
transform: translateX(-50%);
}

.popover-content.bottom .popover-arrow {
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-bottom: 8px solid #fff;
top: -8px;
left: 50%;
transform: translateX(-50%);
}

.popover-backdrop {
content: "";
position: fixed;
Expand All @@ -2002,22 +2038,11 @@ ol.editor-nav li {
z-index: 2;
}

.popover-arrow {
position: absolute;
width: 0;
height: 0;
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-bottom: 8px solid #fff;
top: -8px;
left: 50%;
transform: translateX(-50%);
}

.share-panel {
position: relative;
color: #000;
width: 450px;
width: 400px;
padding: 20px;
display: flex;
flex-direction: column;
gap: 4px;
Expand Down Expand Up @@ -2059,6 +2084,20 @@ ol.editor-nav li {
transform: rotate(315deg);
}

.share-panel .tooltip {
display: flex;
align-items: center;
flex-direction: row;
flex-wrap: nowrap;
white-space: nowrap;
padding: 8px;
gap: 12px;
}

.share-panel .tooltip .material-symbols-outlined {
color: #41b276;
}

.share-panel .footnote {
margin-top: 8px;
color: #acacac;
Expand Down

0 comments on commit fcbca07

Please sign in to comment.