mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-28 12:35:02 +02:00
UBER-206: Redefined color palettes (#3243)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
@@ -29,13 +29,12 @@
|
||||
import { createQuery, getClient, statusStore, ActionContext } from '@hcengineering/presentation'
|
||||
import { Kanban, SpaceWithStates, Task, TaskGrouping, TaskOrdering } from '@hcengineering/task'
|
||||
import {
|
||||
ColorDefinition,
|
||||
defaultBackground,
|
||||
getEventPositionElement,
|
||||
Label,
|
||||
showPopup,
|
||||
deviceOptionsStore as deviceInfo,
|
||||
hslToRgb,
|
||||
rgbToHsl,
|
||||
AccentColor
|
||||
themeStore
|
||||
} from '@hcengineering/ui'
|
||||
import {
|
||||
AttributeModel,
|
||||
@@ -81,8 +80,11 @@
|
||||
|
||||
$: dontUpdateRank = orderBy[0] !== TaskOrdering.Manual
|
||||
|
||||
$: lth = $deviceInfo.theme === 'theme-light'
|
||||
const accentColors: AccentColor[] = []
|
||||
let accentColors: Map<string, ColorDefinition> = new Map()
|
||||
const setAccentColor = (n: number, ev: CustomEvent<ColorDefinition>) => {
|
||||
accentColors.set(`${n}${$themeStore.dark}${groupByKey}`, ev.detail)
|
||||
accentColors = accentColors
|
||||
}
|
||||
|
||||
const spaceQuery = createQuery()
|
||||
|
||||
@@ -170,14 +172,6 @@
|
||||
viewOptionsModel: ViewOptionModel[] | undefined
|
||||
) {
|
||||
categories = await getCategories(client, _class, docs, groupByKey, $statusStore, viewlet.descriptor)
|
||||
categories.forEach((_, i) => {
|
||||
if (accentColors[i] === undefined) {
|
||||
accentColors[i] = {
|
||||
textColor: 'var(--theme-caption-color)',
|
||||
backgroundColor: lth ? '230, 230, 230' : '100, 100, 108'
|
||||
}
|
||||
}
|
||||
})
|
||||
for (const viewOption of viewOptionsModel ?? []) {
|
||||
if (viewOption.actionTarget !== 'category') continue
|
||||
const categoryFunc = viewOption as CategoryOption
|
||||
@@ -244,16 +238,6 @@
|
||||
})
|
||||
|
||||
const getDoneUpdate = (e: any) => ({ doneState: e.detail._id } as DocumentUpdate<Doc>)
|
||||
|
||||
const setAccentColor = (n: number, ev: CustomEvent) => {
|
||||
const accColor = rgbToHsl(ev.detail.r, ev.detail.g, ev.detail.b)
|
||||
const textColor = !lth ? { r: 255, g: 255, b: 255 } : hslToRgb(accColor.h, accColor.s, 0.3)
|
||||
const bgColor = !lth ? hslToRgb(accColor.h, accColor.s, 0.55) : hslToRgb(accColor.h, accColor.s, 0.9)
|
||||
accentColors[n] = {
|
||||
textColor: !lth ? 'var(--theme-caption-color)' : `rgb(${textColor.r}, ${textColor.g}, ${textColor.b})`,
|
||||
backgroundColor: `${bgColor.r}, ${bgColor.g}, ${bgColor.b}`
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{#await cardPresenter then presenter}
|
||||
@@ -283,37 +267,33 @@
|
||||
on:contextmenu={(evt) => showMenu(evt.detail.evt, evt.detail.objects)}
|
||||
>
|
||||
<svelte:fragment slot="header" let:state let:count let:index>
|
||||
<!-- {@const status = $statusStore.get(state._id)} -->
|
||||
{#key lth}
|
||||
<div
|
||||
style:--kanban-header-rgb-color={accentColors[index]?.backgroundColor}
|
||||
class="header flex-row-center"
|
||||
class:gradient={!lth}
|
||||
{@const color = accentColors.get(`${index}${$themeStore.dark}${groupByKey}`)}
|
||||
{@const headerBGColor = color?.background ?? defaultBackground($themeStore.dark)}
|
||||
|
||||
<div style:background={headerBGColor} class="header flex-row-center">
|
||||
<span
|
||||
class="clear-mins fs-bold overflow-label pointer-events-none"
|
||||
style:color={color?.title ?? 'var(--theme-caption-color)'}
|
||||
>
|
||||
<span
|
||||
class="clear-mins fs-bold overflow-label pointer-events-none"
|
||||
style:color={accentColors[index]?.textColor}
|
||||
>
|
||||
{#if groupByKey === noCategory}
|
||||
<Label label={view.string.NoGrouping} />
|
||||
{:else if headerComponent}
|
||||
<svelte:component
|
||||
this={headerComponent.presenter}
|
||||
value={state}
|
||||
{space}
|
||||
size={'small'}
|
||||
kind={'list-header'}
|
||||
colorInherit={lth}
|
||||
accent
|
||||
on:accent-color={(ev) => setAccentColor(index, ev)}
|
||||
/>
|
||||
{/if}
|
||||
</span>
|
||||
<span class="counter ml-1">
|
||||
{count}
|
||||
</span>
|
||||
</div>
|
||||
{/key}
|
||||
{#if groupByKey === noCategory}
|
||||
<Label label={view.string.NoGrouping} />
|
||||
{:else if headerComponent}
|
||||
<svelte:component
|
||||
this={headerComponent.presenter}
|
||||
value={state}
|
||||
{space}
|
||||
size={'small'}
|
||||
kind={'list-header'}
|
||||
colorInherit={!$themeStore.dark}
|
||||
accent
|
||||
on:accent-color={(ev) => setAccentColor(index, ev)}
|
||||
/>
|
||||
{/if}
|
||||
</span>
|
||||
<span class="counter ml-1">
|
||||
{count}
|
||||
</span>
|
||||
</div>
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="card" let:object let:dragged>
|
||||
<svelte:component this={presenter} {object} {dragged} {groupByKey} />
|
||||
@@ -340,17 +320,6 @@
|
||||
border: 1px solid var(--theme-divider-color);
|
||||
border-radius: 0.25rem;
|
||||
|
||||
&:not(.gradient) {
|
||||
background: rgba(var(--kanban-header-rgb-color), 1);
|
||||
}
|
||||
&.gradient {
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
rgba(var(--kanban-header-rgb-color), 0.15),
|
||||
rgba(var(--kanban-header-rgb-color), 0.05)
|
||||
);
|
||||
}
|
||||
|
||||
.counter {
|
||||
color: var(--theme-dark-color);
|
||||
}
|
||||
|
||||
@@ -16,19 +16,22 @@
|
||||
<script lang="ts">
|
||||
import type { DoneState } from '@hcengineering/task'
|
||||
import task from '@hcengineering/task'
|
||||
import { getPlatformColor } from '@hcengineering/ui'
|
||||
import Won from '../icons/Won.svelte'
|
||||
import { PaletteColorIndexes, getPlatformColorDef, themeStore } from '@hcengineering/ui'
|
||||
import Lost from '../icons/Lost.svelte'
|
||||
import Won from '../icons/Won.svelte'
|
||||
|
||||
export let value: DoneState | null | undefined
|
||||
export let showTitle: boolean = true
|
||||
|
||||
$: color = value?._class === task.class.WonState ? getPlatformColor(0) : getPlatformColor(11)
|
||||
$: color =
|
||||
value?._class === task.class.WonState
|
||||
? getPlatformColorDef(PaletteColorIndexes.Crocodile, $themeStore.dark)
|
||||
: getPlatformColorDef(PaletteColorIndexes.Firework, $themeStore.dark)
|
||||
</script>
|
||||
|
||||
{#if value}
|
||||
<div class="flex-center">
|
||||
<div class:mr-2={showTitle} style="color: {color};">
|
||||
<div class:mr-2={showTitle} style="color: {color.color};">
|
||||
<svelte:component this={value._class === task.class.WonState ? Won : Lost} size={'small'} />
|
||||
</div>
|
||||
{#if showTitle}
|
||||
|
||||
@@ -18,12 +18,18 @@
|
||||
import { statusStore } from '@hcengineering/presentation'
|
||||
import type { DoneState } from '@hcengineering/task'
|
||||
import DoneStatePresenter from './DoneStatePresenter.svelte'
|
||||
import DoneStateEditor from './DoneStateEditor.svelte'
|
||||
|
||||
export let value: Ref<DoneState> | StatusValue
|
||||
export let showTitle: boolean = true
|
||||
export let onChange: ((value: Ref<DoneState>) => void) | undefined = undefined
|
||||
</script>
|
||||
|
||||
{#if value}
|
||||
{@const state = $statusStore.get(typeof value === 'string' ? value : value.values[0]._id)}
|
||||
<DoneStatePresenter value={state} {showTitle} />
|
||||
{#if onChange !== undefined && state !== undefined}
|
||||
<DoneStateEditor value={state._id} space={state.space} {onChange} kind="link" size="medium" />
|
||||
{:else}
|
||||
<DoneStatePresenter value={state} {showTitle} />
|
||||
{/if}
|
||||
{/if}
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
import { Class, Doc, Ref, SortingOrder } from '@hcengineering/core'
|
||||
import { createQuery } from '@hcengineering/presentation'
|
||||
import { DoneState, SpaceWithStates } from '@hcengineering/task'
|
||||
import { getPlatformColor, Label, resizeObserver } from '@hcengineering/ui'
|
||||
import { Label, PaletteColorIndexes, getPlatformColor, resizeObserver, themeStore } from '@hcengineering/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import task from '../../plugin'
|
||||
import Won from '../icons/Won.svelte'
|
||||
import Lost from '../icons/Lost.svelte'
|
||||
import Unknown from '../icons/Unknown.svelte'
|
||||
import Won from '../icons/Won.svelte'
|
||||
|
||||
export let space: Ref<SpaceWithStates>
|
||||
let states: DoneState[] = []
|
||||
@@ -42,7 +42,9 @@
|
||||
}
|
||||
)
|
||||
function getColor (_class: Ref<Class<Doc>>): string {
|
||||
return _class === task.class.WonState ? getPlatformColor(0) : getPlatformColor(11)
|
||||
return _class === task.class.WonState
|
||||
? getPlatformColor(PaletteColorIndexes.Crocodile, $themeStore.dark)
|
||||
: getPlatformColor(PaletteColorIndexes.Firework, $themeStore.dark)
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -14,9 +14,15 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
import type { State } from '@hcengineering/task'
|
||||
import { getColorNumberByText, getPlatformColor, hexToRgb, deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
|
||||
import {
|
||||
ColorDefinition,
|
||||
defaultBackground,
|
||||
getColorNumberByText,
|
||||
getPlatformColorDef,
|
||||
themeStore
|
||||
} from '@hcengineering/ui'
|
||||
import { createEventDispatcher, onMount } from 'svelte'
|
||||
|
||||
export let value: State | undefined
|
||||
export let shouldShowAvatar = true
|
||||
@@ -28,25 +34,24 @@
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
const defaultFill = 'currentColor'
|
||||
$: fill = value ? getPlatformColor(value.color ?? getColorNumberByText(value.name)) : defaultFill
|
||||
$: lth = $deviceInfo.theme === 'theme-light'
|
||||
const dispatchAccentColor = (fill: string) =>
|
||||
dispatch(
|
||||
'accent-color',
|
||||
fill !== defaultFill ? hexToRgb(fill) : lth ? { r: 220, g: 220, b: 220 } : { r: 100, g: 100, b: 108 }
|
||||
)
|
||||
$: dispatchAccentColor(fill)
|
||||
$: color = value ? getPlatformColorDef(value.color ?? getColorNumberByText(value.name), $themeStore.dark) : undefined
|
||||
const dispatchAccentColor = (color?: ColorDefinition) => dispatch('accent-color', color)
|
||||
|
||||
$: dispatchAccentColor(color)
|
||||
|
||||
onMount(() => {
|
||||
dispatchAccentColor(fill)
|
||||
dispatchAccentColor(color)
|
||||
})
|
||||
</script>
|
||||
|
||||
{#if value}
|
||||
<div class="flex-presenter" class:inline-presenter={inline}>
|
||||
{#if shouldShowAvatar}
|
||||
<div class="state-container" class:inline style="background-color: {fill}" />
|
||||
<div
|
||||
class="state-container"
|
||||
class:inline
|
||||
style="background-color: {color?.color ?? defaultBackground($themeStore.dark)}"
|
||||
/>
|
||||
{/if}
|
||||
<span class="overflow-label label" class:nowrap={oneLine} class:no-underline={disabled}>{value.name}</span>
|
||||
</div>
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
import { Ref } from '@hcengineering/core'
|
||||
import { BreadcrumbsElement, statusStore } from '@hcengineering/presentation'
|
||||
import task, { SpaceWithStates, State } from '@hcengineering/task'
|
||||
import { getColorNumberByText, getPlatformColor, ScrollerBar } from '@hcengineering/ui'
|
||||
import { ScrollerBar, getColorNumberByText, getPlatformColor, themeStore } from '@hcengineering/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import type { StatesBarPosition } from '../..'
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
label={item.name}
|
||||
position={getPosition(i)}
|
||||
selected={item._id === state}
|
||||
color={getPlatformColor(item.color ?? getColorNumberByText(item.name))}
|
||||
color={getPlatformColor(item.color ?? getColorNumberByText(item.name), $themeStore.dark)}
|
||||
on:click={(ev) => {
|
||||
ev.stopPropagation()
|
||||
if (item._id !== state) selectItem(ev, item)
|
||||
|
||||
@@ -19,22 +19,25 @@
|
||||
import type { DoneState, KanbanTemplate, KanbanTemplateSpace, State } from '@hcengineering/task'
|
||||
import {
|
||||
CircleButton,
|
||||
Component,
|
||||
IconAdd,
|
||||
IconCircles,
|
||||
IconMoreH,
|
||||
Label,
|
||||
showPopup,
|
||||
getPlatformColor,
|
||||
PaletteColorIndexes,
|
||||
defaultBackground,
|
||||
eventToHTMLElement,
|
||||
Component,
|
||||
IconCircles,
|
||||
getColorNumberByText
|
||||
getColorNumberByText,
|
||||
getPlatformColorDef,
|
||||
showPopup,
|
||||
themeStore
|
||||
} from '@hcengineering/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { ColorsPopup } from '@hcengineering/view-resources'
|
||||
import StatusesPopup from './StatusesPopup.svelte'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import task from '../../plugin'
|
||||
import Won from '../icons/Won.svelte'
|
||||
import Lost from '../icons/Lost.svelte'
|
||||
import Won from '../icons/Won.svelte'
|
||||
import StatusesPopup from './StatusesPopup.svelte'
|
||||
|
||||
export let template: KanbanTemplate | undefined = undefined
|
||||
export let space: KanbanTemplateSpace | undefined = undefined
|
||||
@@ -77,7 +80,7 @@
|
||||
const onColorChange =
|
||||
(state: State) =>
|
||||
async (color: number | undefined): Promise<void> => {
|
||||
if (color === undefined) {
|
||||
if (color == null) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -104,10 +107,12 @@
|
||||
</div>
|
||||
<div class="mt-3">
|
||||
{#each states as state, i}
|
||||
{@const color = getPlatformColorDef(state.color ?? getColorNumberByText(state.name), $themeStore.dark)}
|
||||
{#if state}
|
||||
<div
|
||||
bind:this={elements[i]}
|
||||
class="flex-between states"
|
||||
style:background={color.background ?? defaultBackground($themeStore.dark)}
|
||||
draggable={true}
|
||||
on:dragover|preventDefault={(ev) => {
|
||||
dragover(ev, i)
|
||||
@@ -127,14 +132,9 @@
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div
|
||||
class="color"
|
||||
style="background-color: {getPlatformColor(state.color ?? getColorNumberByText(state.name))}"
|
||||
style:background-color={color.color}
|
||||
on:click={() => {
|
||||
showPopup(
|
||||
ColorsPopup,
|
||||
{ selected: getPlatformColor(state.color ?? getColorNumberByText(state.name)) },
|
||||
elements[i],
|
||||
onColorChange(state)
|
||||
)
|
||||
showPopup(ColorsPopup, { selected: color.name }, elements[i], onColorChange(state))
|
||||
}}
|
||||
/>
|
||||
<div class="flex-grow caption-color">
|
||||
@@ -173,8 +173,13 @@
|
||||
</div>
|
||||
<div class="mt-4">
|
||||
{#each wonStates as state}
|
||||
{@const color = getPlatformColorDef(PaletteColorIndexes.Crocodile, $themeStore.dark)}
|
||||
{#if state}
|
||||
<div class="states flex-row-center">
|
||||
<div
|
||||
class="states flex-row-center"
|
||||
style:color={color.title}
|
||||
style:background={color.background ?? defaultBackground($themeStore.dark)}
|
||||
>
|
||||
<div class="bar" />
|
||||
<div class="mr-2">
|
||||
<Won size={'medium'} />
|
||||
@@ -216,8 +221,13 @@
|
||||
</div>
|
||||
<div class="mt-4 mb-10">
|
||||
{#each lostStates as state}
|
||||
{@const color = getPlatformColorDef(PaletteColorIndexes.Firework, $themeStore.dark)}
|
||||
{#if state}
|
||||
<div class="states flex-row-center">
|
||||
<div
|
||||
class="states flex-row-center"
|
||||
style:color={color.title}
|
||||
style:background={color.background ?? defaultBackground($themeStore.dark)}
|
||||
>
|
||||
<div class="bar" />
|
||||
<div class="mr-2">
|
||||
<Lost size={'medium'} />
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
import { Ref, SortingOrder } from '@hcengineering/core'
|
||||
import { createQuery } from '@hcengineering/presentation'
|
||||
import task, { SpaceWithStates, State } from '@hcengineering/task'
|
||||
import { getColorNumberByText, getPlatformColor, resizeObserver } from '@hcengineering/ui'
|
||||
import { getColorNumberByText, getPlatformColorDef, resizeObserver, themeStore } from '@hcengineering/ui'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
|
||||
export let space: Ref<SpaceWithStates>
|
||||
@@ -42,16 +42,14 @@
|
||||
<div class="scroll">
|
||||
<div class="box">
|
||||
{#each states as state}
|
||||
{@const color = getPlatformColorDef(state.color ?? getColorNumberByText(state.name), $themeStore.dark)}
|
||||
<button
|
||||
class="menu-item"
|
||||
on:click={() => {
|
||||
dispatch('close', state)
|
||||
}}
|
||||
>
|
||||
<div
|
||||
class="color"
|
||||
style="background-color: {getPlatformColor(state.color ?? getColorNumberByText(state.name))}"
|
||||
/>
|
||||
<div class="color" style:background-color={color.color} />
|
||||
<span class="label">{state.name}</span>
|
||||
</button>
|
||||
{/each}
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
</script>
|
||||
|
||||
{#if value}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div class="flex-presenter" class:inline-presenter={inline} on:click={(ev) => show(ev.target)}>
|
||||
<div class="icon">
|
||||
<Icon icon={task.icon.Task} size={'small'} />
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
// limitations under the License.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { getPlatformColor, Label } from '@hcengineering/ui'
|
||||
import { getPlatformColor, Label, themeStore } from '@hcengineering/ui'
|
||||
import task from '../../plugin'
|
||||
export let value: boolean
|
||||
|
||||
$: color = value ? getPlatformColor(2) : getPlatformColor(10)
|
||||
$: color = value ? getPlatformColor(2, $themeStore.dark) : getPlatformColor(16, $themeStore.dark)
|
||||
$: text = value ? task.string.DoneState : task.string.UndoneState
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user