facebook / stylex

StyleX is the styling system for ambitious user interfaces.
https://stylexjs.com
MIT License
8.34k stars 307 forks source link

API for CSS variable fallback #432

Closed olivierpascal closed 3 months ago

olivierpascal commented 7 months ago

Feature request

I would like to be able to use fallback for css variables.

Suggestion 1

I suggest an API like:

const styles = stylex.create({
  slot: {
    color: stylex.fallback(vars.specificSlotColor, vars.textColor),
  },
});

<div {...stylex.props(styles.slot)}>text</div>

Which would be compiled to:

.className {
  color: var(--specificSlotColor, --textColor);
}

Suggestion 2

Today, null and undefined values for style properties are not used:

Using null for a non-default condition has no effect and should be considered invalid. https://stylexjs.com/docs/learn/styling-ui/defining-styles/#combining-conditions

Also, in this example:

const vars = stylex.defineVars({
  textColor: 'black',
  specificSlotColor: undefined,
});

const styles = stylex.create({
  text: {
    color: vars.textColor,
  },
  specificSlot: {
    color: vars.specificSlotColor,
  },
});

<div {...stylex.props(styles.text, styles.specificSlot)}>text</div>

The final color is undefined because "The last style applied always wins".

I suggest that "the last defined style applied always wins", so that the textColor fallback is used.

Workaround

<div {...stylex.props(styles.text)}>
  <div {...stylex.props(styles.specificSlot)}>text</div>
</div>
nmn commented 7 months ago

The existing stylex.firstThatWorks will soon be extended to support this use-case.

necolas commented 7 months ago

Shouldn't undefined be disallowed for values in defineVars, and then the type system can tell you if you're using a var that's actually undefined? The value in defineVars is the fallback as currently defined.

nmn commented 7 months ago

@necolas There are cases when you need a variable to either be defined or not defined. This is particularly useful with Container Style Queries. For this use-case undefined and null are valid values for defineVars, although you need to manually type cast them to null | string so that a theme can set a value for it.

pnegahdar commented 3 months ago

Has this been released yet?

When I try:

backgroundColor: stylex.firstThatWorks("color-mix(in srgb, currentColor 20%, transparent)", cssVars.accent),

I get:

image

Looks like its unpacking the string as an array for some reason? 🤔

nmn commented 3 months ago

@pnegahdar Please share the definition for cssVars so I can test this and verify.

nmn commented 3 months ago

Reopening Issue to investigate bug report.

pnegahdar commented 3 months ago

@nmn The basic example seems to cause the issue:

const cssVars = stylex.defineVars({
    accent: "#42D80D"
})

Then used with a color-mix style:

const styles = stlyex.create({
    root: {
        backgroundColor: stylex.firstThatWorks("color-mix(in srgb, currentColor 20%, transparent)", cssVars.accent),
   }
})