utils/tailwind.ts: Tailwind/SoapboxConfig conversion functions
This commit is contained in:
parent
12617bf7de
commit
7fc4950387
3 changed files with 234 additions and 1 deletions
|
@ -6,5 +6,5 @@ export type TailwindColorObject = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type TailwindColorPalette = {
|
export type TailwindColorPalette = {
|
||||||
[key: string]: TailwindColorObject,
|
[key: string]: TailwindColorObject | string,
|
||||||
}
|
}
|
||||||
|
|
189
app/soapbox/utils/__tests__/tailwind-test.js
Normal file
189
app/soapbox/utils/__tests__/tailwind-test.js
Normal file
|
@ -0,0 +1,189 @@
|
||||||
|
import { Map as ImmutableMap } from 'immutable';
|
||||||
|
|
||||||
|
import { toTailwind, fromLegacyColors, expandPalette } from '../tailwind';
|
||||||
|
|
||||||
|
describe('toTailwind()', () => {
|
||||||
|
it('converts brandColor into a Tailwind color palette', () => {
|
||||||
|
const soapboxConfig = ImmutableMap({ brandColor: '#0482d8' });
|
||||||
|
|
||||||
|
const expected = {
|
||||||
|
primary: {
|
||||||
|
50: '#f2f9fd',
|
||||||
|
100: '#e6f3fb',
|
||||||
|
200: '#c0e0f5',
|
||||||
|
300: '#9bcdef',
|
||||||
|
400: '#4fa8e4',
|
||||||
|
500: '#0482d8',
|
||||||
|
600: '#0475c2',
|
||||||
|
700: '#0362a2',
|
||||||
|
800: '#024e82',
|
||||||
|
900: '#02406a',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = toTailwind(soapboxConfig);
|
||||||
|
expect(result.toJS()).toMatchObject(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('prefers Tailwind colors object over legacy colors', () => {
|
||||||
|
const soapboxConfig = ImmutableMap({
|
||||||
|
brandColor: '#0482d8',
|
||||||
|
colors: ImmutableMap({
|
||||||
|
primary: ImmutableMap({
|
||||||
|
300: '#ff0000',
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const expected = {
|
||||||
|
primary: {
|
||||||
|
50: '#f2f9fd',
|
||||||
|
100: '#e6f3fb',
|
||||||
|
200: '#c0e0f5',
|
||||||
|
300: '#ff0000', // <--
|
||||||
|
400: '#4fa8e4',
|
||||||
|
500: '#0482d8',
|
||||||
|
600: '#0475c2',
|
||||||
|
700: '#0362a2',
|
||||||
|
800: '#024e82',
|
||||||
|
900: '#02406a',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = toTailwind(soapboxConfig);
|
||||||
|
expect(result.toJS()).toMatchObject(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('fromLegacyColors()', () => {
|
||||||
|
it('converts only brandColor', () => {
|
||||||
|
const soapboxConfig = ImmutableMap({ brandColor: '#0482d8' });
|
||||||
|
|
||||||
|
const expected = {
|
||||||
|
primary: {
|
||||||
|
50: '#f2f9fd',
|
||||||
|
100: '#e6f3fb',
|
||||||
|
200: '#c0e0f5',
|
||||||
|
300: '#9bcdef',
|
||||||
|
400: '#4fa8e4',
|
||||||
|
500: '#0482d8',
|
||||||
|
600: '#0475c2',
|
||||||
|
700: '#0362a2',
|
||||||
|
800: '#024e82',
|
||||||
|
900: '#02406a',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = fromLegacyColors(soapboxConfig);
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('converts both legacy colors', () => {
|
||||||
|
const soapboxConfig = ImmutableMap({
|
||||||
|
brandColor: '#0482d8',
|
||||||
|
accentColor: '#2bd110',
|
||||||
|
});
|
||||||
|
|
||||||
|
const expected = {
|
||||||
|
primary: {
|
||||||
|
50: '#f2f9fd',
|
||||||
|
100: '#e6f3fb',
|
||||||
|
200: '#c0e0f5',
|
||||||
|
300: '#9bcdef',
|
||||||
|
400: '#4fa8e4',
|
||||||
|
500: '#0482d8',
|
||||||
|
600: '#0475c2',
|
||||||
|
700: '#0362a2',
|
||||||
|
800: '#024e82',
|
||||||
|
900: '#02406a',
|
||||||
|
},
|
||||||
|
accent: {
|
||||||
|
50: '#f4fdf3',
|
||||||
|
100: '#eafae7',
|
||||||
|
200: '#caf4c3',
|
||||||
|
300: '#aaed9f',
|
||||||
|
400: '#6bdf58',
|
||||||
|
500: '#2bd110',
|
||||||
|
600: '#27bc0e',
|
||||||
|
700: '#209d0c',
|
||||||
|
800: '#1a7d0a',
|
||||||
|
900: '#156608',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = fromLegacyColors(soapboxConfig);
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('expandPalette()', () => {
|
||||||
|
it('expands one color', () => {
|
||||||
|
const palette = { primary: '#0482d8' };
|
||||||
|
|
||||||
|
const expected = {
|
||||||
|
primary: {
|
||||||
|
50: '#f2f9fd',
|
||||||
|
100: '#e6f3fb',
|
||||||
|
200: '#c0e0f5',
|
||||||
|
300: '#9bcdef',
|
||||||
|
400: '#4fa8e4',
|
||||||
|
500: '#0482d8',
|
||||||
|
600: '#0475c2',
|
||||||
|
700: '#0362a2',
|
||||||
|
800: '#024e82',
|
||||||
|
900: '#02406a',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = expandPalette(palette);
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('expands mixed palette', () => {
|
||||||
|
const palette = {
|
||||||
|
primary: {
|
||||||
|
50: '#f2f9fd',
|
||||||
|
100: '#e6f3fb',
|
||||||
|
200: '#c0e0f5',
|
||||||
|
300: '#9bcdef',
|
||||||
|
400: '#4fa8e4',
|
||||||
|
500: '#0482d8',
|
||||||
|
600: '#0475c2',
|
||||||
|
700: '#0362a2',
|
||||||
|
800: '#024e82',
|
||||||
|
900: '#02406a',
|
||||||
|
},
|
||||||
|
accent: '#2bd110',
|
||||||
|
};
|
||||||
|
|
||||||
|
const expected = {
|
||||||
|
primary: {
|
||||||
|
50: '#f2f9fd',
|
||||||
|
100: '#e6f3fb',
|
||||||
|
200: '#c0e0f5',
|
||||||
|
300: '#9bcdef',
|
||||||
|
400: '#4fa8e4',
|
||||||
|
500: '#0482d8',
|
||||||
|
600: '#0475c2',
|
||||||
|
700: '#0362a2',
|
||||||
|
800: '#024e82',
|
||||||
|
900: '#02406a',
|
||||||
|
},
|
||||||
|
accent: {
|
||||||
|
50: '#f4fdf3',
|
||||||
|
100: '#eafae7',
|
||||||
|
200: '#caf4c3',
|
||||||
|
300: '#aaed9f',
|
||||||
|
400: '#6bdf58',
|
||||||
|
500: '#2bd110',
|
||||||
|
600: '#27bc0e',
|
||||||
|
700: '#209d0c',
|
||||||
|
800: '#1a7d0a',
|
||||||
|
900: '#156608',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = expandPalette(palette);
|
||||||
|
expect(result).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
44
app/soapbox/utils/tailwind.ts
Normal file
44
app/soapbox/utils/tailwind.ts
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||||
|
|
||||||
|
import tintify from 'soapbox/utils/colors';
|
||||||
|
|
||||||
|
import type { TailwindColorPalette } from 'soapbox/types/colors';
|
||||||
|
|
||||||
|
type SoapboxConfig = ImmutableMap<string, any>;
|
||||||
|
type SoapboxColors = ImmutableMap<string, any>;
|
||||||
|
|
||||||
|
/** Check if the value is a valid hex color */
|
||||||
|
const isHex = (value: any): boolean => /^#([0-9A-F]{3}){1,2}$/i.test(value);
|
||||||
|
|
||||||
|
/** Expand hex colors into tints */
|
||||||
|
export const expandPalette = (palette: TailwindColorPalette): TailwindColorPalette => {
|
||||||
|
// Generate palette only for present colors
|
||||||
|
return Object.entries(palette).reduce((result: TailwindColorPalette, colorData) => {
|
||||||
|
const [colorName, color] = colorData;
|
||||||
|
|
||||||
|
// Conditionally handle hex color and Tailwind color object
|
||||||
|
if (typeof color === 'string' && isHex(color)) {
|
||||||
|
result[colorName] = tintify(color);
|
||||||
|
} else if (typeof color === 'object') {
|
||||||
|
result[colorName] = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}, {});
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Build a color object from legacy colors */
|
||||||
|
export const fromLegacyColors = (soapboxConfig: SoapboxConfig): TailwindColorPalette => {
|
||||||
|
return expandPalette({
|
||||||
|
primary: soapboxConfig.get('brandColor'),
|
||||||
|
accent: soapboxConfig.get('accentColor'),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Convert Soapbox Config into Tailwind colors */
|
||||||
|
export const toTailwind = (soapboxConfig: SoapboxConfig): SoapboxColors => {
|
||||||
|
const colors: SoapboxColors = ImmutableMap(soapboxConfig.get('colors'));
|
||||||
|
const legacyColors: SoapboxColors = ImmutableMap(fromJS(fromLegacyColors(soapboxConfig)));
|
||||||
|
|
||||||
|
return legacyColors.mergeDeep(colors);
|
||||||
|
};
|
Loading…
Reference in a new issue