Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions packages/react-components/theme-designer/src/ThemeDesigner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as React from 'react';
import type { ThemeDesignerProps } from './ThemeDesigner.types';
import { useStaticStyles, useStyles } from './ThemeDesigner.styles';
import { AppState, DispatchTheme, initialAppState, useThemeDesignerReducer } from './useThemeDesignerReducer';
import { teamsLightTheme, FluentProvider } from '@fluentui/react-components';
import { FluentProvider, webLightTheme } from '@fluentui/react-components';
import { createContext } from '@fluentui/react-context-selector';
import { Nav } from './components/Nav/Nav';
import { Sidebar } from './components/Sidebar/Sidebar';
Expand All @@ -27,13 +27,19 @@ export const ThemeDesigner: React.FC<ThemeDesignerProps> = props => {

const [appState, dispatchAppState] = useThemeDesignerReducer();

const { darkOverrides, isDark, lightOverrides, theme } = appState;
const overrides = isDark ? darkOverrides : lightOverrides;
const overridenTheme = { ...theme, ...overrides };

return (
<FluentProvider theme={teamsLightTheme}>
<FluentProvider theme={webLightTheme}>
<AppContext.Provider value={{ appState, dispatchAppState }}>
<div className={styles.root}>
<Nav className={styles.nav} />
<Sidebar className={styles.sidebar} />
<Content className={styles.content} />
<FluentProvider theme={overridenTheme}>
<Content className={styles.content} />
</FluentProvider>
</div>
</AppContext.Provider>
</FluentProvider>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
/* eslint-disable react/jsx-no-bind */
import * as React from 'react';
import { makeStyles, teamsDarkTheme, teamsLightTheme, Button, Caption1 } from '@fluentui/react-components';
import type { Brands, Theme } from '@fluentui/react-theme';
import { makeStyles, webDarkTheme, webLightTheme, Button, Caption1 } from '@fluentui/react-components';
import type { Brands } from '@fluentui/react-theme';
import { getOverridableTokenBrandColors } from './getOverridableTokenBrandColors';
import { brandTeams } from '../../utils/brandColors';
import { themeNames } from '../../utils/themeList';
import { AccessibilityList } from './AccessibilityList';
import { AppContext } from '../../ThemeDesigner';
import { useContextSelector } from '@fluentui/react-context-selector';
import { brandWeb } from '../../utils/brandColors';

export interface ColorTokensProps {
theme: Theme;
}
export interface ColorTokensProps {}

export type ColorOverrideBrands = Record<string, Brands>;

Expand Down Expand Up @@ -41,18 +39,20 @@ const useStyles = makeStyles({
},
});

const lightBrandColors: ColorOverrideBrands = getOverridableTokenBrandColors(teamsLightTheme, brandTeams);
const darkBrandColors: ColorOverrideBrands = getOverridableTokenBrandColors(teamsDarkTheme, brandTeams);
const lightBrandColors: ColorOverrideBrands = getOverridableTokenBrandColors(webLightTheme, brandWeb);
const darkBrandColors: ColorOverrideBrands = getOverridableTokenBrandColors(webDarkTheme, brandWeb);

export const ColorTokens: React.FunctionComponent<ColorTokensProps> = props => {
const styles = useStyles();

const { theme } = props;
const appState = useContextSelector(AppContext, ctx => ctx.appState);
const { brand, darkOverrides, isDark, lightOverrides, theme, themeName } = appState;
const dispatchAppState = useContextSelector(AppContext, ctx => ctx.dispatchAppState);
const { brand, isDark, themeName } = appState;
const brandColors = isDark ? darkBrandColors : lightBrandColors;

const overrides = isDark ? darkOverrides : lightOverrides;
const overridenTheme = { ...theme, ...overrides };

const themeLabel = themeName + (isDark ? 'Dark' : 'Light');

const colorOverrideReducer: (
Expand Down Expand Up @@ -117,7 +117,7 @@ export const ColorTokens: React.FunctionComponent<ColorTokensProps> = props => {
brandColors={brandColors}
colorOverride={getCurrentOverride(themeLabel, colorOverride)}
onNewOverride={onNewOverride}
theme={theme}
theme={overridenTheme}
/>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export const getOverridableTokenBrandColors = (theme: Theme, brand: BrandVariant
const brandColors: ColorOverrideBrands = {};
for (let i = 0; i < sortedOverrideableColorTokens.length; i++) {
const key = sortedOverrideableColorTokens[i];
const themeColor = ((theme as unknown) as Record<string, string>)[key];
const themeColor = ((theme as unknown) as Record<string, string>)[key].toUpperCase();
brandColors[key] = hexColorToBrand[themeColor];
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import * as React from 'react';
import { makeStyles, mergeClasses, shorthands, tokens, Divider, FluentProvider } from '@fluentui/react-components';
import { makeStyles, mergeClasses, shorthands, tokens, Divider } from '@fluentui/react-components';
import { Alert } from '@fluentui/react-alert';
import { Demo } from '../Demo/Demo';
import { Palette } from '../Palette/Palette';
import { ColorTokens } from '../ColorTokens/ColorTokens';
import { AppContext } from '../../ThemeDesigner';
import { useContextSelector } from '@fluentui/react-context-selector';

export interface ContentProps {
className?: string;
Expand All @@ -25,21 +23,17 @@ const useStyles = makeStyles({
export const Content: React.FC<ContentProps> = props => {
const styles = useStyles();

const { brand, darkOverrides, isDark, lightOverrides, theme } = useContextSelector(AppContext, ctx => ctx.appState);
const overrides = isDark ? darkOverrides : lightOverrides;
const overridenTheme = { ...theme, ...overrides };

return (
<FluentProvider theme={overridenTheme}>
<>
<Alert intent="warning" action={{ appearance: 'transparent' }}>
This tool is still a work in progress - colors are still subject to adjustment.
</Alert>
<div className={mergeClasses(styles.root, props.className)}>
<Palette brandColors={brand} />
<Palette />
<Demo />
<Divider />
<ColorTokens theme={overridenTheme} />
<ColorTokens />
</div>
</FluentProvider>
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { Button, Caption1, Text } from '@fluentui/react-components';
import { Brands, BrandVariants } from '@fluentui/react-theme';
import { contrast, hex_to_sRGB } from '@fluent-blocks/colors';
import { CopyRegular } from '@fluentui/react-icons';
import { AppContext } from '../../ThemeDesigner';
import { useContextSelector } from '@fluentui/react-context-selector';

export interface PaletteProps {
className?: string;
brandColors: BrandVariants;
}

const hexCopyClassName = 'hexCopy';
Expand Down Expand Up @@ -53,12 +54,14 @@ const getBrands = (colors: BrandVariants): Brands[] => {
export const Palette: React.FC<PaletteProps> = props => {
const styles = useStyles();

const { brand } = useContextSelector(AppContext, ctx => ctx.appState);

return (
<div>
<Caption1>Generated palette</Caption1>
<div className={mergeClasses(styles.root, props.className)}>
{getBrands(props.brandColors).map(brandKey => {
const brandColor = props.brandColors[brandKey];
{getBrands(brand).map(brandKey => {
const brandColor = brand[brandKey].toUpperCase();
const textColor = contrast(hex_to_sRGB(brandColor), hex_to_sRGB('#FFFFFF')) <= 4.5 ? 'black' : 'white';
return (
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ export const Form: React.FC<FormProps> = props => {
}, [debouncedForm]);

const handleKeyColorChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setKeyColor(e.target.value);
// check if the newly inputted hex code has a #
const newHexColor = '#' + e.target.value.replace(/\W/g, '').toUpperCase();
setKeyColor(newHexColor);
};
const handleHueTorsionChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setHueTorsion(parseInt(e.target.value, 10));
Expand All @@ -113,6 +115,7 @@ export const Form: React.FC<FormProps> = props => {
id={sidebarId + 'keyColor'}
value={form.keyColor}
onChange={handleKeyColorChange}
maxLength={7}
/>
<div className={styles.colorPicker} style={{ backgroundColor: form.keyColor }}>
<input
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,11 @@ export const Sidebar: React.FC<SidebarProps> = props => {
setTab(data.value);
};

const [theme, setTheme] = React.useState<string>('Teams');
const [theme, setTheme] = React.useState<string>('Web');
const [isDark, setIsDark] = React.useState<boolean>(false);

const [formState, setFormState] = React.useState<CustomAttributes>({
keyColor: '#006bc7',
keyColor: '#0F6CBD',
hueTorsion: 0,
darkCp: 0.66,
lightCp: 0.33,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';
import { createDarkTheme, createLightTheme } from '@fluentui/react-components';
import { getBrandTokensFromPalette } from './utils/getBrandTokensFromPalette';
import { brandTeams } from './utils/brandColors';
import { brandWeb } from './utils/brandColors';
import type { BrandVariants, Theme } from '@fluentui/react-components';
import { themeList, themeNames } from './utils/themeList';

Expand Down Expand Up @@ -33,9 +33,9 @@ export type AppState = {
};

export const initialAppState = {
themeName: 'Teams',
brand: brandTeams,
theme: createLightTheme(brandTeams),
themeName: 'Web',
brand: brandWeb,
theme: createLightTheme(brandWeb),
isDark: false,
lightOverrides: {},
darkOverrides: {},
Expand Down
66 changes: 14 additions & 52 deletions packages/react-components/theme-designer/src/utils/brandColors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,56 +3,18 @@ import type { BrandVariants } from '@fluentui/react-theme';
export const brandWeb: BrandVariants = {
10: `#061724`,
20: `#082338`,
30: `#0a2e4a`,
40: `#0c3b5e`,
50: `#0e4775`,
60: `#0f548c`,
70: `#115ea3`,
80: `#0f6cbd`,
90: `#2886de`,
100: `#479ef5`,
110: `#62abf5`,
120: `#77b7f7`,
130: `#96c6fa`,
140: `#b4d6fa`,
150: `#cfe4fa`,
160: `#ebf3fc`,
};

export const brandTeams: BrandVariants = {
10: `#2b2b40`,
20: `#2f2f4a`,
30: `#333357`,
40: `#383966`,
50: `#3d3e78`,
60: `#444791`,
70: `#4f52b2`,
80: `#5b5fc7`,
90: `#7579eb`,
100: `#7f85f5`,
110: `#9299f7`,
120: `#aab1fa`,
130: `#b6bcfa`,
140: `#c5cbfa`,
150: `#dce0fa`,
160: `#e8ebfa`,
};

export const brandOffice: BrandVariants = {
10: `#29130b`,
20: `#4d2415`,
30: `#792000`,
40: `#99482b`,
50: `#a52c00`,
60: `#c33400`,
70: `#e06a3f`,
80: `#d83b01`,
90: `#dd4f1b`,
100: `#fe7948`,
110: `#ff865a`,
120: `#ff9973`,
130: `#e8825d`,
140: `#ffb498`,
150: `#f4beaa`,
160: `#f9dcd1`,
30: `#0A2E4A`,
40: `#0C3B5E`,
50: `#0E4775`,
60: `#0F548C`,
70: `#115EA3`,
80: `#0F6CBD`,
90: `#2886DE`,
100: `#479EF5`,
110: `#62ABF5`,
120: `#77B7F7`,
130: `#96C6FA`,
140: `#B4D6FA`,
150: `#CFE4FA`,
160: `#EBF3FC`,
};
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { BrandVariants } from '@fluentui/react-components';
import { brandTeams, brandWeb } from './brandColors';
import { brandWeb } from './brandColors';

export type ThemeList = Record<string, { brand?: BrandVariants }>;

export const themeList: ThemeList = {
Teams: { brand: brandTeams },
Web: { brand: brandWeb },
Custom: {},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const getBrandValues = (brand: BrandVariants, overrideList: Partial<Theme
export const objectToString = (input: Record<string, string>, spacer: string) => {
return (
Object.keys(input).map(key => {
return '\n' + spacer + key + ': "' + input[key] + '"';
return '\n' + spacer + key + ': "' + input[key].toUpperCase() + '"';
}) + '\n'
);
};
Expand Down