如何在库中生成 Fluent UI 主题?

How to generate a Fluent UI theme with in the library?

我正在使用 Fluent 创建一个 React 应用程序 UI - React,我希望每个用户在注册时都可以选择原色、文本颜色和背景颜色,他们的应用程序将在其中主题就像在 Theming Designer

中完成的一样

主题设计师给了我以下输出。

const appTheme: PartialTheme = createTheme({
  palette: {
    themePrimary: "#ff5460",
    themeLighterAlt: "#0a0304",
    themeLighter: "#290d0f",
    themeLight: "#4d191d",
    themeTertiary: "#993239",
    themeSecondary: "#e04a54",
    themeDarkAlt: "#ff656f",
    themeDark: "#ff7d86",
    themeDarker: "#ff9fa6",
    neutralLighterAlt: "#000000",
    neutralLighter: "#000000",
    neutralLight: "#000000",
    neutralQuaternaryAlt: "#000000",
    neutralQuaternary: "#000000",
    neutralTertiaryAlt: "#000000",
    neutralTertiary: "#c8c8c8",
    neutralSecondary: "#d0d0d0",
    neutralPrimaryAlt: "#dadada",
    neutralPrimary: "#ffffff",
    neutralDark: "#f4f4f4",
    black: "#f8f8f8",
    white: "#000000",
  },
});

在 Fluent 中是否有生成主题的函数 UI 其中我只想提供原色、文本颜色和背景颜色并提供整个主题以便我可以将其添加到主题中提供商组件。

通过创建一个函数解决了它,

import {
  BaseSlots,
  createTheme,
  getColorFromString,
  isDark,
  Theme,
  ThemeGenerator,
  themeRulesStandardCreator,
} from "@fluentui/react";

const generateTheme = (
  primaryColor: string,
  textColor: string,
  backgroundColor: string
): Theme => {
  const themeRules = themeRulesStandardCreator();
  const colors = {
    pColor: getColorFromString(primaryColor)!,
    tColor: getColorFromString(textColor)!,
    bColor: getColorFromString(backgroundColor)!,
  };

  const currentIsDark = isDark(
    themeRules[BaseSlots[BaseSlots.backgroundColor]].color!
  );

  ThemeGenerator.insureSlots(themeRules, currentIsDark);
  ThemeGenerator.setSlot(
    themeRules[BaseSlots[BaseSlots.primaryColor]],
    colors.pColor,
    currentIsDark,
    true,
    true
  );
  ThemeGenerator.setSlot(
    themeRules[BaseSlots[BaseSlots.foregroundColor]],
    colors.tColor,
    currentIsDark,
    true,
    true
  );
  ThemeGenerator.setSlot(
    themeRules[BaseSlots[BaseSlots.backgroundColor]],
    colors.bColor,
    currentIsDark,
    true,
    true
  );

  const themeAsJson: {
    [key: string]: string;
  } = ThemeGenerator.getThemeAsJson(themeRules);

  const finalTheme = createTheme({
    ...{ palette: themeAsJson },
    isInverted: currentIsDark,
  });

  return finalTheme;
};

export default generateTheme;

实际上,这必须是 Fluent 的一部分 UI

Aravid Jaimon 的答案中给出的代码确实为我产生了不完整的结果。

这是我为此提出的解决方案。它主要是从 ThemingDesigner.tsx source code:

import {
    BaseSlots,
    createTheme,
    getColorFromString,
    isDark,
    IThemeRules,
    ThemeGenerator,
    themeRulesStandardCreator,
} from '@fluentui/react';

function generateTheme(
    {
        primaryColor, textColor, backgroundColor,
    }: {
        primaryColor: string, textColor: string, backgroundColor: string,
    },
) {
    const themeRules = themeRulesStandardCreator();
    const colors = {
        primaryColor: getColorFromString(primaryColor)!,
        textColor: getColorFromString(textColor)!,
        backgroundColor: getColorFromString(backgroundColor)!,
    };

    const isCustomization = false;
    const overwriteCustomColor = true;

    ThemeGenerator.setSlot(
        themeRules[BaseSlots[BaseSlots.backgroundColor]],
        colors.backgroundColor,
        undefined,
        isCustomization,
        overwriteCustomColor,
    );

    const currentIsDark = isDark(themeRules[BaseSlots[BaseSlots.backgroundColor]].color!);

    ThemeGenerator.setSlot(
        themeRules[BaseSlots[BaseSlots.primaryColor]],
        colors.primaryColor,
        currentIsDark,
        isCustomization,
        overwriteCustomColor,
    );
    ThemeGenerator.setSlot(
        themeRules[BaseSlots[BaseSlots.foregroundColor]],
        colors.textColor,
        currentIsDark,
        isCustomization,
        overwriteCustomColor,
    );

    // strip out the unnecessary shade slots from the final output theme
    const abridgedTheme: IThemeRules = Object.entries(themeRules).reduce(
        (acc, [ruleName, ruleValue]) => (
            (
                ruleName.indexOf('ColorShade') === -1
                && ruleName !== 'primaryColor'
                && ruleName !== 'backgroundColor'
                && ruleName !== 'foregroundColor'
                && ruleName.indexOf('body') === -1
            )
                ? {
                    ...acc,
                    [ruleName]: ruleValue,
                }
                : acc
        ),
        {} as IThemeRules,
    );

    return createTheme({ palette: ThemeGenerator.getThemeAsJson(abridgedTheme) });
}