mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-17 21:24:11 +00:00
Colorised spreadsheet (#1643)
* feat: colorise spreadSheet with rundown color * feat: add colorisation in spreadsheet for block * feat: border color * fix: cleanup accessible color * fix: review before merge (https://github.com/cpvalente/ontime/pull/1608) * fix: usgae of map instead foreach (https://github.com/cpvalente/ontime/pull/1608) * Update apps/server/src/services/sheet-service/SheetService.ts Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com> * fix: comment condition * fix: Remove Color plugin (but don't can get color like 'red' or 'black') * fix: isLight for more clean code * fix: remove map on isLight function * fix: remove debug logger * refactor colour * lint --------- Co-authored-by: Gwenitora <gwenitora.gardu74@gmail.com> Co-authored-by: Gwenitora <61121870+Gwenitora@users.noreply.github.com> Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
984dcb0181
commit
4872cd0a48
@@ -21,7 +21,6 @@
|
||||
"@tanstack/react-table": "^8.21.3",
|
||||
"autosize": "^6.0.1",
|
||||
"axios": "^1.9.0",
|
||||
"color": "^4.2.3",
|
||||
"csv-stringify": "^6.4.5",
|
||||
"framer-motion": "^10.10.0",
|
||||
"prismjs": "^1.29.0",
|
||||
@@ -67,7 +66,6 @@
|
||||
"devDependencies": {
|
||||
"@sentry/vite-plugin": "^2.16.1",
|
||||
"@tanstack/eslint-plugin-query": "^5.8.4",
|
||||
"@types/color": "^3.0.3",
|
||||
"@types/prismjs": "^1.26.5",
|
||||
"@types/react": "^18.0.26",
|
||||
"@types/react-dom": "^18.0.10",
|
||||
|
||||
@@ -18,19 +18,19 @@ describe('getAccessibleColour()', () => {
|
||||
it('handles named colours', () => {
|
||||
const colour = 'red';
|
||||
const { backgroundColor, color } = getAccessibleColour(colour);
|
||||
expect(backgroundColor).toBe('#FF0000FF');
|
||||
expect(backgroundColor).toBe('#ff0000ff');
|
||||
expect(color).toBe('#fffffa');
|
||||
});
|
||||
it('handles hex colours', () => {
|
||||
const colour = '#0F0';
|
||||
const { backgroundColor, color } = getAccessibleColour(colour);
|
||||
expect(backgroundColor).toBe('#00FF00FF');
|
||||
expect(backgroundColor).toBe('#00ff00ff');
|
||||
expect(color).toBe('black');
|
||||
});
|
||||
it('handles transparens', () => {
|
||||
const colour = '#0F08';
|
||||
const { backgroundColor, color } = getAccessibleColour(colour);
|
||||
expect(backgroundColor).toBe('#0C940CFF');
|
||||
expect(backgroundColor).toBe('#0c940cff');
|
||||
expect(color).toBe('#fffffa');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,27 +1,27 @@
|
||||
import Color from 'color';
|
||||
import { RGBColour } from 'ontime-types';
|
||||
import { colourToHex, cssOrHexToColour, isLightColour, mixColours } from 'ontime-utils';
|
||||
|
||||
type ColourCombination = {
|
||||
backgroundColor: string;
|
||||
color: string;
|
||||
};
|
||||
|
||||
const defaultUiBackground: RGBColour = { red: 26, green: 26, blue: 26, alpha: 1 };
|
||||
/**
|
||||
* @description Selects text colour to maintain accessible contrast
|
||||
* @param bgColour
|
||||
* @return {{backgroundColor, color: string}}
|
||||
*/
|
||||
export const getAccessibleColour = (bgColour?: string): ColourCombination => {
|
||||
if (bgColour) {
|
||||
try {
|
||||
const originalColour = Color(bgColour);
|
||||
const backgroundColorMix = originalColour.alpha(1).mix(Color('#1a1a1a'), 1 - originalColour.alpha());
|
||||
const textColor = backgroundColorMix.isLight() ? 'black' : '#fffffa';
|
||||
return { backgroundColor: backgroundColorMix.hexa(), color: textColor };
|
||||
} catch (_error) {
|
||||
/* we do not handle errors here */
|
||||
}
|
||||
}
|
||||
return { backgroundColor: '#1a1a1a', color: '#fffffa' };
|
||||
if (!bgColour) return { backgroundColor: '#1a1a1a', color: '#fffffa' };
|
||||
|
||||
const originalColour = cssOrHexToColour(bgColour);
|
||||
if (!originalColour) return { backgroundColor: '#1a1a1a', color: '#fffffa' };
|
||||
|
||||
const backgroundColorMix = mixColours(defaultUiBackground, originalColour, 1 - originalColour.alpha);
|
||||
const textColor = isLightColour(backgroundColorMix) ? 'black' : '#fffffa';
|
||||
|
||||
return { backgroundColor: colourToHex(backgroundColorMix), color: textColor };
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -39,11 +39,8 @@ export const timerPlaceholderMin = '––:––';
|
||||
* Adds opacity to a given colour if possible
|
||||
*/
|
||||
export function alpha(colour: string, amount: number): string {
|
||||
try {
|
||||
const withAlpha = Color(colour).alpha(amount).hexa();
|
||||
return withAlpha;
|
||||
} catch (_error) {
|
||||
/* we do not handle errors here */
|
||||
}
|
||||
return colour;
|
||||
const originalColour = cssOrHexToColour(colour);
|
||||
if (!originalColour) return colour;
|
||||
originalColour.alpha = amount;
|
||||
return colourToHex(originalColour);
|
||||
}
|
||||
|
||||
+8
-7
@@ -1,7 +1,7 @@
|
||||
import { MutableRefObject } from 'react';
|
||||
import { RowModel, Table } from '@tanstack/react-table';
|
||||
import Color from 'color';
|
||||
import { isOntimeBlock, isOntimeDelay, isOntimeEvent, OntimeEntry } from 'ontime-types';
|
||||
import { colourToHex, cssOrHexToColour } from 'ontime-utils';
|
||||
|
||||
import { useSelectedEventId } from '../../../../common/hooks/useSocket';
|
||||
import { lazyEvaluate } from '../../../../common/utils/lazyEvaluate';
|
||||
@@ -76,12 +76,13 @@ export default function CuesheetBody(props: CuesheetBodyProps) {
|
||||
if (isSelected) {
|
||||
rowBgColour = '#D20300'; // $red-700
|
||||
} else if (entry.colour) {
|
||||
try {
|
||||
// the colour is user defined and might be invalid
|
||||
const accessibleBackgroundColor = Color(getAccessibleColour(entry.colour).backgroundColor);
|
||||
rowBgColour = accessibleBackgroundColor.fade(0.75).hexa();
|
||||
} catch (_error) {
|
||||
/* we do not handle errors here */
|
||||
// the colour is user defined and might be invalid
|
||||
const accessibleBackgroundColor = cssOrHexToColour(getAccessibleColour(entry.colour).backgroundColor);
|
||||
if (accessibleBackgroundColor !== null) {
|
||||
rowBgColour = colourToHex({
|
||||
...accessibleBackgroundColor,
|
||||
alpha: accessibleBackgroundColor.alpha * 0.25,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { memo, MutableRefObject, useLayoutEffect, useRef, useState } from 'react';
|
||||
import { IoEllipsisHorizontal } from 'react-icons/io5';
|
||||
import { flexRender, Table } from '@tanstack/react-table';
|
||||
import Color from 'color';
|
||||
import { OntimeEntry, OntimeEvent } from 'ontime-types';
|
||||
import { OntimeEntry, OntimeEvent, RGBColour } from 'ontime-types';
|
||||
import { colourToHex, cssOrHexToColour } from 'ontime-utils';
|
||||
|
||||
import IconButton from '../../../../common/components/buttons/IconButton';
|
||||
import { cx, getAccessibleColour } from '../../../../common/utils/styleUtils';
|
||||
@@ -75,7 +75,8 @@ function EventRow(props: EventRowProps) {
|
||||
}, [ownRef, selectedRef]);
|
||||
|
||||
const { color, backgroundColor } = getAccessibleColour(event.colour);
|
||||
const mutedText = Color(color).fade(0.4).hexa();
|
||||
const tmpColour = cssOrHexToColour(color) as RGBColour; // we know this to be a correct colour
|
||||
const mutedText = colourToHex({ ...tmpColour, alpha: tmpColour.alpha * 0.6 });
|
||||
|
||||
return (
|
||||
<tr
|
||||
|
||||
Reference in New Issue
Block a user