UBER-376 Implement new style for the tooltips (#3418)

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Denis Bykhov 2023-06-09 18:06:15 +06:00 committed by GitHub
parent 95ffbd6d33
commit 626d36db7d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 149 additions and 120 deletions

View File

@ -1315,7 +1315,7 @@ export function createModel (builder: Builder): void {
group: 'create'
}
},
tracker.action.NewSubIssue
tracker.action.NewIssue
)
createAction(

View File

@ -154,6 +154,10 @@
--theme-calendar-holiday-bgcolor: rgba(235, 87, 87, .1);
--theme-calendar-weekend-bgcolor: rgba(242, 153, 74, .05);
--theme-tooltip-color: rgba(255, 255, 255, .8);
--theme-tooltip-bg: #353347;
--theme-tooltip-key-bg: rgba(255, 255, 255, .08);
--theme-inbox-notify: #F47758;
--theme-inbox-people-notify: #2B5190;
--theme-inbox-activity-bgcolor: #1A1A28;
@ -347,6 +351,10 @@
--theme-calendar-holiday-bgcolor: rgba(235, 87, 87, .1);
--theme-calendar-weekend-bgcolor: rgba(242, 153, 74, .1);
--theme-tooltip-color: #FFF;
--theme-tooltip-bg: #444248;
--theme-tooltip-key-bg: rgba(255, 255, 255, .08);
--theme-inbox-notify: #F47758;
--theme-inbox-people-notify: #2B5190;
--theme-inbox-activity-bgcolor: #fff;

View File

@ -19,6 +19,7 @@
import type { TooltipAlignment } from '../types'
import Component from './Component.svelte'
import Label from './Label.svelte'
import { capitalizeFirstLetter, formatKey } from '../utils'
let tooltipHTML: HTMLElement
let nubHTML: HTMLElement
@ -236,6 +237,25 @@
{:else if $tooltip.label && $tooltip.kind !== 'submenu'}
<div class="tooltip {dir ?? ''}" bind:this={tooltipHTML}>
<Label label={$tooltip.label} params={$tooltip.props ?? {}} />
{#if $tooltip.keys !== undefined}
<div class="keys">
{#each $tooltip.keys as key, i}
{#if i !== 0}
<div class="mr-1 ml-1">/</div>
{/if}
{#each formatKey(key) as k, jj}
<div class="key">
{#each k as kk, j}
{#if j !== 0}
+
{/if}
{capitalizeFirstLetter(kk.trim())}
{/each}
</div>
{/each}
{/each}
</div>
{/if}
</div>
{:else if $tooltip.kind === 'submenu'}
<div
@ -361,25 +381,36 @@
}
}
.keys {
margin-left: 0.5rem;
display: flex;
align-items: center;
gap: 0.125rem;
}
.key {
border-radius: 0.125rem;
font-size: 0.75rem;
min-width: 1.5rem;
padding: 0.25rem;
background-color: var(--theme-tooltip-key-bg);
}
.tooltip {
position: fixed;
padding: 0.5rem 0.75rem;
padding: 0.5rem;
text-align: center;
color: var(--theme-content-color);
background-color: var(--theme-popup-color);
font-size: 0.75rem;
color: var(--theme-tooltip-color);
background-color: var(--theme-tooltip-bg);
border: 1px solid var(--theme-popup-divider);
border-radius: 0.75rem;
border-radius: 0.25rem;
box-shadow: var(--theme-popup-shadow);
user-select: none;
z-index: 10000;
display: flex;
align-items: center;
&::after,
&::before {
content: '';
position: absolute;
width: 18px;
height: 7px;
}
&::before {
background-color: var(--theme-popup-color);
clip-path: url('#nub-bg');
@ -390,55 +421,6 @@
clip-path: url('#nub-border');
z-index: 2;
}
&.top::after,
&.bottom::after,
&.top::before,
&.bottom::before {
left: 50%;
margin-left: -9px;
}
&.top {
bottom: 100%;
&::after,
&::before {
bottom: -6px;
transform: rotate(180deg);
}
}
&.bottom {
top: 100%;
&::after,
&::before {
top: -7px;
}
}
&.right::after,
&.left::after,
&.right::before,
&.left::before {
top: 50%;
margin-top: -9px;
}
&.right {
left: 100%;
&::after,
&::before {
transform-origin: right top;
left: -24px;
transform: rotate(-90deg);
}
}
&.left {
right: 100%;
&::after,
&::before {
transform-origin: left top;
right: -24px;
transform: rotate(90deg);
}
}
}
.no-arrow {
box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.75);

View File

@ -27,6 +27,7 @@
TCellStyle,
ICell
} from './internal/DateUtils'
import { capitalizeFirstLetter } from '../../utils'
export let currentDate: Date | null
export let mondayStart: boolean = true
@ -42,7 +43,6 @@
if (areDatesEqual(today, new Date(viewDate.getFullYear(), viewDate.getMonth(), n))) return true
return false
}
const capitalizeFirstLetter = (str: string): string => str.charAt(0).toUpperCase() + str.slice(1)
let days: Array<ICell> = []
const getDateStyle = (date: Date): TCellStyle => {

View File

@ -18,6 +18,7 @@
import IconNavNext from '../icons/NavNext.svelte'
import Icon from '../Icon.svelte'
import { firstDay, day, getWeekDayName, areDatesEqual, getMonthName, weekday, isWeekend } from './internal/DateUtils'
import { capitalizeFirstLetter } from '../../utils'
export let currentDate: Date | null
export let viewDate: Date
@ -32,7 +33,6 @@
$: firstDayOfCurrentMonth = firstDay(viewDate, mondayStart)
let monthYear: string
const today: Date = new Date(Date.now())
const capitalizeFirstLetter = (str: string): string => str.charAt(0).toUpperCase() + str.slice(1)
afterUpdate(() => {
monthYear = capitalizeFirstLetter(getMonthName(viewDate)) + ' ' + viewDate.getFullYear()

View File

@ -10,6 +10,7 @@ const emptyTooltip: LabelAndProps = {
props: undefined,
anchor: undefined,
onUpdate: undefined,
keys: undefined,
kind: 'tooltip'
}
let storedValue: LabelAndProps = emptyTooltip
@ -27,10 +28,30 @@ export function tooltip (node: HTMLElement, options?: LabelAndProps): any {
if (opt.kind !== 'submenu') {
clearTimeout(toHandler)
toHandler = setTimeout(() => {
showTooltip(opt.label, node, opt.direction, opt.component, opt.props, opt.anchor, opt.onUpdate, opt.kind)
showTooltip(
opt.label,
node,
opt.direction,
opt.component,
opt.props,
opt.anchor,
opt.onUpdate,
opt.kind,
opt.keys
)
}, 250)
} else {
showTooltip(opt.label, node, opt.direction, opt.component, opt.props, opt.anchor, opt.onUpdate, opt.kind)
showTooltip(
opt.label,
node,
opt.direction,
opt.component,
opt.props,
opt.anchor,
opt.onUpdate,
opt.kind,
opt.keys
)
}
}
}
@ -45,7 +66,17 @@ export function tooltip (node: HTMLElement, options?: LabelAndProps): any {
if (node !== storedValue.element) return
const shown = !!(storedValue.label !== undefined || storedValue.component !== undefined)
if (shown) {
showTooltip(opt.label, node, opt.direction, opt.component, opt.props, opt.anchor, opt.onUpdate, opt.kind)
showTooltip(
opt.label,
node,
opt.direction,
opt.component,
opt.props,
opt.anchor,
opt.onUpdate,
opt.kind,
opt.keys
)
}
},
@ -64,7 +95,8 @@ export function showTooltip (
props?: any,
anchor?: HTMLElement,
onUpdate?: (result: any) => void,
kind?: 'tooltip' | 'submenu' | 'popup'
kind?: 'tooltip' | 'submenu' | 'popup',
keys?: string[]
): void {
storedValue = {
label,
@ -74,7 +106,8 @@ export function showTooltip (
props,
anchor,
onUpdate,
kind
kind,
keys
}
tooltipstore.update((old) => {
if (old.component === storedValue.component) {

View File

@ -238,6 +238,7 @@ export interface LabelAndProps {
anchor?: HTMLElement
onUpdate?: (result: any) => void
kind?: 'tooltip' | 'submenu' | 'popup'
keys?: string[]
}
export interface ListItem {

View File

@ -197,3 +197,36 @@ export interface IModeSelector {
config: Array<[string, IntlString, object]>
onChange: (_mode: string) => void
}
/**
* @public
*/
export function capitalizeFirstLetter (str: string): string {
return str.charAt(0).toUpperCase() + str.slice(1)
}
const isMac = /Macintosh/i.test(navigator.userAgent)
/**
* @public
*/
export function formatKey (key: string): string[][] {
const thens = key.split('->')
const result: string[][] = []
for (const r of thens) {
result.push(
r.split('+').map((it) =>
it
.replace(/key/g, '')
.replace(/Meta|meta/g, isMac ? '⌘' : 'Ctrl')
.replace(/ArrowUp/g, '↑')
.replace(/ArrowDown/g, '↓')
.replace(/ArrowLeft/g, '←')
.replace(/ArrowRight/g, '→')
.replace(/Backspace/g, '⌫')
.toLocaleLowerCase()
)
)
}
return result
}

View File

@ -14,8 +14,9 @@
-->
<script lang="ts">
import { Ref, Space } from '@hcengineering/core'
import { MultipleDraftController } from '@hcengineering/presentation'
import { MultipleDraftController, getClient } from '@hcengineering/presentation'
import { Button, IconAdd, showPopup } from '@hcengineering/ui'
import view from '@hcengineering/view'
import { onDestroy } from 'svelte'
import tracker from '../plugin'
import CreateIssue from './CreateIssue.svelte'
@ -38,18 +39,31 @@
closed = true
})
}
$: label = draftExists || !closed ? tracker.string.ResumeDraft : tracker.string.NewIssue
const client = getClient()
let keys: string[] | undefined = undefined
client.findOne(view.class.Action, { _id: tracker.action.NewIssue }).then((p) => (keys = p?.keyBinding))
</script>
<div class="antiNav-subheader">
<Button
icon={IconAdd}
label={draftExists || !closed ? tracker.string.ResumeDraft : tracker.string.NewIssue}
{label}
justify={'left'}
kind={'primary'}
width={'100%'}
size={'large'}
on:click={newIssue}
id="new-issue"
showTooltip={{
direction: 'bottom',
label,
keys
}}
>
<div slot="content" class="draft-circle-container">
{#if draftExists}

View File

@ -481,6 +481,7 @@ export default plugin(trackerId, {
MoveToProject: '' as Ref<Action>,
Duplicate: '' as Ref<Action>,
Relations: '' as Ref<Action>,
NewIssue: '' as Ref<Action>,
NewSubIssue: '' as Ref<Action>,
EditWorkflowStatuses: '' as Ref<Action>,
EditProject: '' as Ref<Action>,

View File

@ -25,7 +25,9 @@
Label,
EditWithIcon,
IconSearch,
deviceOptionsStore
deviceOptionsStore,
capitalizeFirstLetter,
formatKey
} from '@hcengineering/ui'
import { Action, ViewContext } from '@hcengineering/view'
import { filterActions, getSelection } from '../actions'
@ -167,30 +169,7 @@
handleSelection(key, selection)
}
}
const capitalizeFirstLetter = (str: string): string => str.charAt(0).toUpperCase() + str.slice(1)
const isMac = /Macintosh/i.test(navigator.userAgent)
function formatKey (key: string): string[][] {
const thens = key.split('->')
const result: string[][] = []
for (const r of thens) {
result.push(
r.split('+').map((it) =>
it
.replaceAll('key', '')
.replaceAll(/Meta|meta/g, isMac ? '⌘' : 'Ctrl')
.replaceAll('ArrowUp', '↑')
.replaceAll('ArrowDown', '↓')
.replaceAll('ArrowLeft', '←')
.replaceAll('ArrowRight', '→')
.replaceAll('Backspace', '⌫')
.toLocaleLowerCase()
)
)
}
return result
}
const dispatch = createEventDispatcher()
</script>

View File

@ -56,7 +56,7 @@
icon={view.icon.ViewButton}
label={view.string.View}
{kind}
showTooltip={{ label: view.string.CustomizeView }}
showTooltip={{ label: view.string.CustomizeView, direction: 'bottom' }}
bind:input={btn}
on:click={clickHandler}
/>

View File

@ -37,7 +37,7 @@
icon={view.icon.Configure}
label={view.string.Show}
{kind}
showTooltip={{ label: view.string.CustomizeView }}
showTooltip={{ label: view.string.CustomizeView, direction: 'bottom' }}
bind:input={btn}
on:click={clickHandler}
/>

View File

@ -3,7 +3,9 @@
import setting, { settingId } from '@hcengineering/setting'
import {
Button,
capitalizeFirstLetter,
closePopup,
formatKey,
getCurrentResolvedLocation,
Icon,
IconArrowLeft,
@ -34,28 +36,6 @@
navigate(loc)
}
const capitalizeFirstLetter = (str: string): string => str.charAt(0).toUpperCase() + str.slice(1)
function formatKey (key: string): string[][] {
const thens = key.split('->')
const result: string[][] = []
for (const r of thens) {
result.push(
r.split('+').map((it) =>
it
.replaceAll('key', '')
.replaceAll(/Meta|meta/g, isMac ? '⌘' : 'Ctrl')
.replaceAll('ArrowUp', '↑')
.replaceAll('ArrowDown', '↓')
.replaceAll('ArrowLeft', '←')
.replaceAll('ArrowRight', '→')
.replaceAll('Backspace', '⌫')
)
)
}
return result
}
async function getActions () {
categories = await getClient().findAll(view.class.ActionCategory, [])
const rawActions = await client.findAll(view.class.Action, [])
@ -82,8 +62,6 @@
}
getActions()
const isMac = /Macintosh/i.test(navigator.userAgent)
const cards = [
{
icon: DocumentationIcon,