square / maker

Maker Design System by Square

Home Page:https://square.github.io/maker/styleguide/latest-stable/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Button | Text] resolvedProps do not update when resolved pattern's props are added/deleted

bashunaimiroy opened this issue · comments

commented

Bug description

tldr

When you add or delete properties in a Pattern, components that use that pattern will not update to reflect the Pattern's new definition. You can partially fix this by initialising properties as undefined, but the bug still occurs when resetting, i.e. setting the value from anything back to undefined.

Setup:

In my theme, I'm defining a primary pattern for Button and buttonPrimary pattern for Text.

The primary button pattern has textPattern: 'buttonPrimary'.

On my page, I have a single MButton with pattern="primary".

I also expose controls that change the values in the button and text patterns. If a pattern doesn't already have a prop, I'll add it- e.g. I have an Italic button that toggles fontStyle: 'italic' on and off in the buttonPrimary text pattern.

Result

On initial page load, all of the properties in both MButton and the inner MText are resolved to the value of the props defined in their respective patterns. E.g. if I have fontSize: '20px' in the text pattern, the MText has resolvedFontSize: '20px'. So far so good.

Example screenshot. $0.__vue__ is an MText instance here. Note that the buttonPrimary pattern has just had fontStyle: 'italic' added to it. Also note that the MText's fontStyle prop is undefined, we're not passing anything into it.

image

Reproduction

  1. In the Theme Object, define a pattern for Button. It can be an empty object.
  2. Create an MButton instance with that pattern
  3. Confirm that the MButton renders according to the theme default, i.e. no pattern-specific styles
  4. Add any prop to that pattern, e.g. color
  5. Observe that the MButton doesn't render according to the new color prop's value
  6. Inspect the MButton's resolvedColor value and observe that it hasn't changed

Environment

System:
    OS: macOS 12.6
    CPU: (16) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 1.28 GB / 64.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 12.16.2 - ~/.nvm/versions/node/v12.16.2/bin/node
    npm: 6.14.4 - ~/.nvm/versions/node/v12.16.2/bin/npm

Addressed by

No response

Can you contribute a fix?

I don't have a fix for Maker, but on my side a partial fix is to define every possible property in my patterns, and simply pass undefined if I have no value for that property. This way I'm never adding or deleting a property from any pattern. This isn't ideal, but it works. It might be good to mention this in Maker Docs, if no fix is possible

Note: This only fixes it one-way; setting it from undefined to another value does cause the component to update, but setting it from another value back to undefined doesn't cause the component to update. E.g. if I have fontStyle: undefined in my text pattern, and I update to fontStyle: 'italic', the component updates. If I then set it back to fontStyle: undefined, the component remains italicised, with resolvedFontStyle: 'italic'.

I could work around this by setting it to 'inherit' or some other default value, but this seems bug-prone because I'd be guessing at the default values and anyways I want to fall back to the component's theme props (e.g. if theme.button.patterns.primary.fontStyle is undefined, I want to fall back to theme.button.fontStyle). I'd rather leave them undefined and have Maker resolve them to the component props or default values.

Thoughts

I'm guessing this has to do with the way Vue sets up the watchers. Maybe Vue.set / Vue.delete would fix this too

@bashunaimiroy

I don't have a fix for Maker, but on my side a partial fix is to define every possible property in my patterns, and simply pass undefined if I have no value for that property. This way I'm never adding or deleting a property from any pattern. This isn't ideal, but it works. It might be good to mention this in Maker Docs, if no fix is possible.

This is the workaround for a well-known reactivity pitfall/bug within Vue 2.x. There's nothing we can do within Maker to fix a foundational Vue bug. I can experiment with workarounds internally within Maker to potentially ease the burden on Maker users, but for the time being you're likely going to have to stick to toggling prop values between undefined and defined values instead of adding/removing the prop.

Note: This only fixes it one-way; setting it from undefined to another value does cause the component to update, but setting it from another value back to undefined doesn't cause the component to update. E.g. if I have fontStyle: undefined in my text pattern, and I update to fontStyle: 'italic', the component updates. If I then set it back to fontStyle: undefined, the component remains italicised, with resolvedFontStyle: 'italic'.

I'll look into this, this might be fixable within Maker.

@bashunaimiroy

Toggling between undefined and some defined value... doesn't seem to be fixable within Maker :/

However, I found another workaround! Instead of toggling between undefined and some defined value you can toggle between null and some defined value. Maker's theming system treats all undefined and null values identically so they're safely interchangeable, except that undefined seems to dodge Vue's reactivity triggers, so you have to explicitly set null when you want to "delete" or "clear" some prop value.

This issue has been automatically closed because it hasn't received any activity in over 6 months.