--- tags: theming --- # Web / Native Consistency Just jotting down some topics to talk about and questions to resolve between fluent web and react-native. ## Questions ### What parts of the theme are locked down? Are there parts of the definition we can share? Jason's general sentiment about colors is that there is no perfect solution because the ideal solution/heirarchy/approach depends on scenario and scenarios vary. We should just pick standards, either based on what is out there or based on our own prior art, and move forward. **Jason**: Will be covered by David's topic https://hackmd.io/CtOj9T-qQQmaRiDsYo1o1A ### Do themes only contain component tokens or also props/styles? Pretty straightforward, currently in native the combination of default slot props and default tokens can be retrieved from constants in the component, overrides in the theme, or functions that query the theme. These are all layered together and cached. - Is this overkill? Can we just use tokens for those permutations - This pushes default constants for each to code in the component - Probably a good limitation to just use tokens - Would className be a token value for web? - How would customizers set styles on sub-components with a token only model? ``` <Button icon={{ props }} Theme = { components: { Button: { // this coudl be tokens tokens: // button tokens root: // root props (view props) content: // content props () } or Button: { // these are tokens className: "" } or Button: { root: root style content: } } } ``` Is it sufficient to have: - tokens from the theme, tokens from constants, token functions - some notion of props that are tokens - style functions to produce slot props style function: (tokens, theme, cache) => props { tokens: { // my tokens }, tokenProps: ['color'], slotProps: { root: () => { }, slot1: (tokens, theme, cache) => { } } } const cache = getMemoCache(); const [tokens, nextCache] = cache(() => { // merge settings }, [theme]); return { Object.keys(Settings.styles).map(key => { return { [key]: Settings.styles[key](tokens, theme, nextCache(null, [fn])[1]) } }) } ### What is the state/override pattern? Current web thinking appears to be: ``` tokens: { ...values, hover: { }, press: { } } ``` This is great from a human perspective, it's a bit manual from a code perspective. Applying/adapting the native pattern might look like: ``` tokens: { ...values, backgroundColor: precedence: ['hover', 'press'], states: { hover: { backgroundColor: }, press: { } } } ``` The precedence allows a component to dictate the order states are applied, rather than having it buried in code. The states wrapping object makes the code simpler as the core framework can handle merging and applying these states based on a common and repeating structure. This also allows for an unanticipated component to have a new state that matters without changing the framework code. ### How do we want variables to work? Let's assume that: - Themes => Set of variables, either of the CSS variety, or as what amounts to a dictionary - Component tokens and component styles can refer to these variables Can we have a framework that routes to the right value? For instance: ```ts export function var(value: string): string | (theme: ITheme) => any { return useCssVariables() // this might turn `palette.colorname` to 'palette-colorname' ? `var(--${decorateThemeValueName(value)})` // part of theme building might be creating a lookup table // this table would match the variables the theme would create : (theme: ITheme) => theme.variables[value]; } ``` A component would have default tokens defined as: ```ts tokens: { backgroundColor: var('palette.neutralBackgroundColor'), color: var('button.foregroundText') } ``` `var` would be executed when the object is instantiated, this produces a set of tokens that may or may not have functions within. - If the tokens have (theme) => val functions we know the style/class needs to be created for each theme - If the tokens are flat, the base class/style can be global and won't need to be recalculated. This means that re-theming won't require any new classes (which I believe is a requirement) This seems workable, it allows sharing the token code between native/web and allows web to use the native code paths to handle the IE 11 cases if so desired. If not desireable I would propose a babel plugin to convert var() references into 'var(--)' statements. Open questions if we wanted to do something like this: - What is the pattern for turning theme values into flat keys? - How can components define their own aliases or points where things can be interjected? So can we define the equivalent of semantic colors which refer to theme palette colors, I think that system was useful, the issue was how to extend it for a new component.