Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,16 @@ import { Content } from './components/Content/Content';
export type AppContextValue = {
appState: AppState;
dispatchAppState: React.Dispatch<DispatchTheme>;
name: string;
setName: React.Dispatch<React.SetStateAction<string>>;
};

// eslint-disable-next-line @fluentui/no-context-default-value
export const AppContext = createContext<AppContextValue>({
appState: initialAppState,
dispatchAppState: () => null,
name: 'Untitled',
setName: () => null,
});

/**
Expand All @@ -27,14 +31,15 @@ export const ThemeDesigner: React.FC<ThemeDesignerProps> = props => {
useStaticStyles();

const [appState, dispatchAppState] = useThemeDesignerReducer();
const [name, setName] = React.useState<string>('Untitled');

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

return (
<FluentProvider theme={webLightTheme}>
<AppContext.Provider value={{ appState, dispatchAppState }}>
<AppContext.Provider value={{ appState, dispatchAppState, name, setName }}>
<div className={styles.root}>
<Nav className={styles.nav} />
<Sidebar className={styles.sidebar} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@ import {
import { brandRamp } from './getOverridableTokenBrandColors';
import { Brands, BrandVariants } from '@fluentui/react-theme';
import { CircleFilled, WarningRegular } from '@fluentui/react-icons';

import { usageList } from './UsageList';
import { ColorOverrideBrands } from './ColorTokens';
import { ContrastRatioList } from './getAccessibilityChecker';
import { useContextSelector } from '@fluentui/react-context-selector';
import { AppContext } from '../../ThemeDesigner';

export interface ColorTokensListProps {
brand: BrandVariants;
Expand Down Expand Up @@ -75,13 +76,17 @@ const useStyles = makeStyles({
const ColorTokenRow: React.FunctionComponent<ColorTokenRowProps> = props => {
const styles = useStyles();
const { brand, brandValue, brandValueString, selected } = props;

const name = useContextSelector(AppContext, ctx => ctx.name);
return (
<MenuItemRadio
icon={<CircleFilled primaryFill={brand[brandValue]} />}
name={brandValueString}
value={brandValueString}
>
<span className={selected ? styles.selected : ''}>Untitled {brandValueString}</span>
<span className={selected ? styles.selected : ''}>
{name} {brandValueString}
</span>
</MenuItemRadio>
);
};
Expand All @@ -92,6 +97,8 @@ export const ColorTokensList: React.FunctionComponent<ColorTokensListProps> = pr
const { brand, brandColors, colorOverride, coveredTokens, failList, onNewOverride } = props;
const newColors: ColorOverrideBrands = { ...brandColors, ...colorOverride };

const name = useContextSelector(AppContext, ctx => ctx.name);

return (
<div>
{coveredTokens.map(color => {
Expand Down Expand Up @@ -119,7 +126,7 @@ export const ColorTokensList: React.FunctionComponent<ColorTokensListProps> = pr
<Menu>
<MenuTrigger>
<MenuButton shape="circular" icon={<CircleFilled primaryFill={brand[colorValue]} />}>
Untitled {colorValue}
{name} {colorValue}
</MenuButton>
</MenuTrigger>
<MenuPopover>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
RadioGroup,
Checkbox,
Avatar,
useId,
Caption2,
} from '@fluentui/react-components';
import { Dropdown, Option } from '@fluentui/react-components/unstable';
Expand Down Expand Up @@ -121,6 +122,7 @@ export const Column1 = () => {

export const Column2 = () => {
const styles = useStyles();
const dropdownId = useId('dropdown-default');
return (
<div className={styles.col2}>
<TabList defaultSelectedValue="tab1">
Expand All @@ -132,7 +134,7 @@ export const Column2 = () => {
placeholder="Find"
contentAfter={<Button aria-label="Find" appearance="transparent" icon={<SearchRegular />} size="small" />}
/>
<Dropdown placeholder="Select" inlinePopup>
<Dropdown aria-labelledby={dropdownId} placeholder="Select" inlinePopup>
<Option value="Action 1">Action 1</Option>
<Option value="Action 2">Action 2 </Option>
<Option value="Action 3">Action 3</Option>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,22 @@ export const ExportButton = () => {
const appState = useContextSelector(AppContext, ctx => ctx.appState);
const { brand, darkOverrides, lightOverrides } = appState;

const name = useContextSelector(AppContext, ctx => ctx.name);

const [selectedValue, setSelectedValue] = React.useState<TabValue>('Code');

const onTabSelect = (event: SelectTabEvent, data: SelectTabData) => {
setSelectedValue(data.value);
};

const codeValue = dedent`
const brand: BrandVariants = { ${objectToString(brand, '\u00A0\u00A0')} };
const ${name}: BrandVariants = { ${objectToString(brand, '\u00A0\u00A0')} };

const lightTheme: Theme = {
...createLightTheme(brand), ${getBrandValues(brand, lightOverrides, '\u00A0\u00A0')} };
...createLightTheme(${name}), ${getBrandValues(brand, lightOverrides, name, '\u00A0\u00A0')} };

const darkTheme: Theme = {
...createDarkTheme(brand), ${getBrandValues(brand, darkOverrides, '\u00A0\u00A0')} };
...createDarkTheme(${name}), ${getBrandValues(brand, darkOverrides, name, '\u00A0\u00A0')} };
`;

const jsonValue = dedent`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export const ExportLink = () => {
const appState = useContextSelector(AppContext, ctx => ctx.appState);
const { brand, darkOverrides, lightOverrides } = appState;

const name = useContextSelector(AppContext, ctx => ctx.name);

const content = dedent`
import * as React from "react";
import {
Expand Down Expand Up @@ -284,13 +286,13 @@ export const ExportLink = () => {
import type { BrandVariants, Theme } from '@fluentui/react-components';
import { Example } from './example';

const brand: BrandVariants = { ${objectToString(brand, '\u00A0\u00A0')} };
const ${name}: BrandVariants = { ${objectToString(brand, '\u00A0\u00A0')} };

const lightTheme: Theme = {
...createLightTheme(brand), ${getBrandValues(brand, lightOverrides, '\u00A0\u00A0')} };
...createLightTheme(${name}), ${getBrandValues(brand, lightOverrides, name, '\u00A0\u00A0')} };

const darkTheme: Theme = {
...createDarkTheme(brand), ${getBrandValues(brand, darkOverrides, '\u00A0\u00A0')} };
...createDarkTheme(${name}), ${getBrandValues(brand, darkOverrides, name, '\u00A0\u00A0')} };

ReactDOM.render(
<Example lightTheme={lightTheme} darkTheme={darkTheme} />,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import * as React from 'react';
import { makeStyles, mergeClasses, webDarkTheme, FluentProvider, Text } from '@fluentui/react-components';
import { CircleRegular, ChevronRightRegular } from '@fluentui/react-icons';
import { makeStyles, mergeClasses, webDarkTheme, FluentProvider, Text, Input, useId } from '@fluentui/react-components';
import { CircleRegular, ChevronRightRegular, EditRegular } from '@fluentui/react-icons';
import { ExportButton } from '../ExportButton/ExportButton';
import { useContextSelector } from '@fluentui/react-context-selector';
import { AppContext } from '../../ThemeDesigner';

export interface NavProps {
className?: string;
Expand Down Expand Up @@ -32,17 +34,27 @@ const useStyles = makeStyles({
},
});

export const Name = () => {
const styles = useStyles();
return (
<div className={styles.element}>
<Text>Untitled</Text>
</div>
);
};

export const Nav: React.FC<NavProps> = props => {
const styles = useStyles();

const underlineId = useId('input-underline');
const name = useContextSelector(AppContext, ctx => ctx.name);
const setName = useContextSelector(AppContext, ctx => ctx.setName);

const handleNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newName = e.target.value;

if (newName.length === 0) {
setName('Untitled');
} else {
const camelizeName = e.target.value
.replace(/(?:^\w|[A-Z]|\b\w)/g, (ltr, idx) => (idx === 0 ? ltr.toLowerCase() : ltr.toUpperCase()))
.replace(/\s+/g, '');

setName(camelizeName);
}
};

return (
<FluentProvider theme={webDarkTheme} className={mergeClasses(styles.root, props.className)}>
<div className={styles.logo}>
Expand All @@ -52,7 +64,16 @@ export const Nav: React.FC<NavProps> = props => {
<div className={styles.element}>
UI Colors <ChevronRightRegular /> New palette
</div>
<Name />
<div className={styles.element}>
<Input
appearance="underline"
id={underlineId}
// eslint-disable-next-line react/jsx-no-bind
onChange={handleNameChange}
contentAfter={<EditRegular />}
placeholder={name}
/>
</div>
<ExportButton />
</FluentProvider>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { makeStyles, mergeClasses } from '@griffel/react';
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 { bundleIcon, CopyFilled, CopyRegular } from '@fluentui/react-icons';
import { AppContext } from '../../ThemeDesigner';
import { useContextSelector } from '@fluentui/react-context-selector';

Expand Down Expand Up @@ -55,6 +55,7 @@ export const Palette: React.FC<PaletteProps> = props => {
const styles = useStyles();

const { brand } = useContextSelector(AppContext, ctx => ctx.appState);
const CopyIcon = bundleIcon(CopyFilled, CopyRegular);

return (
<div>
Expand All @@ -77,7 +78,7 @@ export const Palette: React.FC<PaletteProps> = props => {
<Button
size="small"
appearance="transparent"
icon={<CopyRegular color={textColor} />}
icon={<CopyIcon color={textColor} />}
onClick={() => navigator.clipboard.writeText(brandColor)} // eslint-disable-line react/jsx-no-bind
/>
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { BrandVariants, Theme } from '@fluentui/react-components';
import { brandRamp } from '../components/ColorTokens/getOverridableTokenBrandColors';

export const getBrandValues = (brand: BrandVariants, overrideList: Partial<Theme>, spacer: string) => {
export const getBrandValues = (brand: BrandVariants, overrideList: Partial<Theme>, name: string, spacer: string) => {
const hexToBrand: Record<string, string> = {};

brandRamp.map(i => {
hexToBrand[brand[i]] = 'brand[' + `${i as number}` + ']';
hexToBrand[brand[i]] = name + '[' + `${i as number}` + ']';
return;
});

Expand Down