GH-629 - Property Popover in Kanban view (#643)
This commit is contained in:
parent
4328375324
commit
5b82dfda4b
5 changed files with 175 additions and 12 deletions
|
@ -76,6 +76,9 @@
|
|||
}
|
||||
|
||||
.gallery-props {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
flex-grow: 0;
|
||||
margin: 0;
|
||||
padding: 5px 10px;
|
||||
|
|
|
@ -20,6 +20,7 @@ import {useSortable} from '../../hooks/sortable'
|
|||
import ImageElement from '../content/imageElement'
|
||||
import ContentElement from '../content/contentElement'
|
||||
import PropertyValueElement from '../propertyValueElement'
|
||||
import Tooltip from '../../widgets/tooltip'
|
||||
|
||||
import './galleryCard.scss'
|
||||
|
||||
|
@ -108,13 +109,18 @@ const GalleryCard = React.memo((props: Props) => {
|
|||
{visiblePropertyTemplates.length > 0 &&
|
||||
<div className='gallery-props'>
|
||||
{visiblePropertyTemplates.map((template) => (
|
||||
<PropertyValueElement
|
||||
<Tooltip
|
||||
key={template.id}
|
||||
readOnly={true}
|
||||
card={cardTree.card}
|
||||
propertyTemplate={template}
|
||||
emptyDisplayValue=''
|
||||
/>
|
||||
title={template.name}
|
||||
placement='top'
|
||||
>
|
||||
<PropertyValueElement
|
||||
readOnly={true}
|
||||
card={cardTree.card}
|
||||
propertyTemplate={template}
|
||||
emptyDisplayValue=''
|
||||
/>
|
||||
</Tooltip>
|
||||
))}
|
||||
</div>}
|
||||
</div>
|
||||
|
|
|
@ -16,6 +16,7 @@ import {useSortable} from '../../hooks/sortable'
|
|||
|
||||
import './kanbanCard.scss'
|
||||
import PropertyValueElement from '../propertyValueElement'
|
||||
import Tooltip from '../../widgets/tooltip'
|
||||
|
||||
type Props = {
|
||||
card: Card
|
||||
|
@ -86,13 +87,17 @@ const KanbanCard = React.memo((props: Props) => {
|
|||
<div key='__title'>{card.title || intl.formatMessage({id: 'KanbanCard.untitled', defaultMessage: 'Untitled'})}</div>
|
||||
</div>
|
||||
{visiblePropertyTemplates.map((template) => (
|
||||
<PropertyValueElement
|
||||
<Tooltip
|
||||
key={template.id}
|
||||
readOnly={true}
|
||||
card={card}
|
||||
propertyTemplate={template}
|
||||
emptyDisplayValue=''
|
||||
/>
|
||||
title={template.name}
|
||||
>
|
||||
<PropertyValueElement
|
||||
readOnly={true}
|
||||
card={card}
|
||||
propertyTemplate={template}
|
||||
emptyDisplayValue=''
|
||||
/>
|
||||
</Tooltip>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
|
|
120
webapp/src/widgets/tooltip.scss
Normal file
120
webapp/src/widgets/tooltip.scss
Normal file
|
@ -0,0 +1,120 @@
|
|||
|
||||
// Tooltip arrow width
|
||||
$tooltip-arrow-width: 6px;
|
||||
// Space between element after transform
|
||||
$tooltop-horizontal-offset: 2px;
|
||||
$tooltop-vertical-offset: 2px;
|
||||
|
||||
%hover_tooltip_body {
|
||||
position: absolute;
|
||||
content: attr(data-tooltip);
|
||||
line-height: 16px;
|
||||
padding: 2px 4px;
|
||||
line-height: 1;
|
||||
font-size: 1.0em;
|
||||
text-align: center;
|
||||
color: rgb(255, 255, 255);
|
||||
background: rgb(0, 0, 0);
|
||||
// opacity: 0.8;
|
||||
border: 4px solid rgb(0, 0, 0);
|
||||
border-radius: 4px;
|
||||
text-shadow: rgba(0, 0, 0, 0.098) 1px 1px 1px;
|
||||
box-shadow: rgba(0, 0, 0, 0.1) 1px 1px 2px 0px;
|
||||
min-width: 2em;
|
||||
max-width: 21em;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: block;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
%hover_tooltip_arrow {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-width: $tooltip-arrow-width;
|
||||
border-style: solid;
|
||||
border-color: #000000 transparent transparent transparent;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.octo-tooltip {
|
||||
display: inline;
|
||||
// Tooltip itself needs to be relative so
|
||||
// content and arrow can be absolute to it
|
||||
position: relative;
|
||||
// Arrow gets added before content
|
||||
&:hover:before {
|
||||
@extend %hover_tooltip_arrow
|
||||
}
|
||||
// Tooltip message gets added after content
|
||||
&:hover:after {
|
||||
@extend %hover_tooltip_body
|
||||
}
|
||||
|
||||
// Top tooltip arrow style
|
||||
&.tooltip-top:hover:before {
|
||||
left: 50%;
|
||||
bottom: calc(100% - 2px);
|
||||
-webkit-transform: translate(-50%, #{$tooltop-horizontal-offset});
|
||||
transform: translate(-50%, #{$tooltop-horizontal-offset});
|
||||
}
|
||||
// Top tooltip body style
|
||||
&.tooltip-top:hover:after {
|
||||
bottom: calc(100% + 10px);
|
||||
left: 50%;
|
||||
-webkit-transform: translate(-50%, #{$tooltop-horizontal-offset});
|
||||
transform: translate(-50%, #{$tooltop-horizontal-offset});
|
||||
}
|
||||
|
||||
// Right tooltip arrow style
|
||||
&.tooltip-right:hover:before {
|
||||
border-color: transparent #000000 transparent transparent;
|
||||
top: 50%;
|
||||
right: calc(0em - 2px);
|
||||
-webkit-transform: translate(#{$tooltop-vertical-offset}, -50%);
|
||||
transform: translate(#{$tooltop-vertical-offset}, -50%);
|
||||
}
|
||||
// Right tooltip body style
|
||||
&.tooltip-right:hover:after {
|
||||
top: 50%;
|
||||
left: calc(100% + 2px);
|
||||
-webkit-transform: translate(#{$tooltop-vertical-offset}, -50%);
|
||||
transform: translate(#{$tooltop-vertical-offset}, -50%);
|
||||
}
|
||||
|
||||
// Left tooltip arrow style
|
||||
&.tooltip-left:hover:before {
|
||||
top: 50%;
|
||||
left: calc(0em - 2px);
|
||||
border-color: transparent transparent transparent #000000;
|
||||
-webkit-transform: translate(-#{$tooltop-vertical-offset}, -50%);
|
||||
transform: translate(-#{$tooltop-vertical-offset}, -50%);
|
||||
}
|
||||
// Left tooltip body style
|
||||
&.tooltip-left:hover:after {
|
||||
left: undefined;
|
||||
top: 50%;
|
||||
right: calc(100% + 2px);
|
||||
-webkit-transform: translate(-#{$tooltop-vertical-offset}, -50%);
|
||||
transform: translate(-#{$tooltop-vertical-offset}, -50%);
|
||||
}
|
||||
|
||||
// Bottom tooltip arrow style
|
||||
&.tooltip-bottom:hover:before {
|
||||
left: 50%;
|
||||
top: calc(100% - 8px);
|
||||
border-color: transparent transparent #000000 transparent ;
|
||||
-webkit-transform: translate(-50%, -#{$tooltop-horizontal-offset});
|
||||
transform: translate(-50%, -#{$tooltop-horizontal-offset});
|
||||
}
|
||||
// Bottom tooltip body style
|
||||
&.tooltip-bottom:hover:after {
|
||||
left: 50%;
|
||||
top: calc(100% + 4px);
|
||||
-webkit-transform: translate(-50%, -#{$tooltop-horizontal-offset});
|
||||
transform: translate(-50%, -#{$tooltop-horizontal-offset});
|
||||
}
|
||||
}
|
29
webapp/src/widgets/tooltip.tsx
Normal file
29
webapp/src/widgets/tooltip.tsx
Normal file
|
@ -0,0 +1,29 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react'
|
||||
|
||||
import './tooltip.scss'
|
||||
|
||||
type Props = {
|
||||
title: string
|
||||
children: React.ReactNode
|
||||
placement?: 'top'|'left'|'right'|'bottom'
|
||||
}
|
||||
|
||||
// Adds tooltip div over children elements, the popup will
|
||||
// be positioned based on the specified placement
|
||||
// Default position is 'top'
|
||||
function Tooltip(props: Props): JSX.Element {
|
||||
const placement = props.placement || 'top'
|
||||
const className = `octo-tooltip tooltip-${placement}`
|
||||
return (
|
||||
<div
|
||||
className={className}
|
||||
data-tooltip={props.title}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default React.memo(Tooltip)
|
Loading…
Reference in a new issue