antoniandre / wave-ui

A UI framework for Vue.js 3 (and 2) with only the bright side. ☀️
https://antoniandre.github.io/wave-ui
MIT License
544 stars 39 forks source link

Storybook integration Vue3 component utilizing WaveUi's w-tooltip custom element throwing error when referencing $WaveUI #110

Closed hashsequence closed 1 year ago

hashsequence commented 1 year ago

I'm not sure whats going on, but it seems that the w-tooltip is throwing an error when trying to reference this.$waveui in the Styles() method:

image

error message:

TypeError: Cannot read properties of undefined (reading 'colors')
    at Proxy.styles (http://localhost:6006/node_modules/wave-ui/src/wave-ui/components/w-tooltip.vue:88:46)
    at ReactiveEffect.run (http://localhost:6006/node_modules/.cache/.vite-storybook/deps/chunk-RU6VEUXL.js?v=2ef12470:1264:23)
    at get value [as value] (http://localhost:6006/node_modules/.cache/.vite-storybook/deps/chunk-RU6VEUXL.js?v=2ef12470:1474:39)
    at Object.get [as styles] (http://localhost:6006/node_modules/.cache/.vite-storybook/deps/chunk-RU6VEUXL.js?v=2ef12470:4165:22)
    at http://localhost:6006/node_modules/wave-ui/src/wave-ui/components/w-tooltip.vue?v=2ef12470&vue&type=template&lang.js:16:47
    at Proxy.renderFnWithContext (http://localhost:6006/node_modules/.cache/.vite-storybook/deps/chunk-RU6VEUXL.js?v=2ef12470:2153:13)
    at Proxy.<anonymous> (http://localhost:6006/node_modules/.cache/.vite-storybook/deps/chunk-RU6VEUXL.js?v=2ef12470:8302:83)
    at renderComponentRoot (http://localhost:6006/node_modules/.cache/.vite-storybook/deps/chunk-RU6VEUXL.js?v=2ef12470:2201:17)
    at ReactiveEffect.componentUpdateFn [as fn] (http://localhost:6006/node_modules/.cache/.vite-storybook/deps/chunk-RU6VEUXL.js?v=2ef12470:6386:26)
    at ReactiveEffect.run (http://localhost:6006/node_modules/.cache/.vite-storybook/deps/chunk-RU6VEUXL.js?v=2ef12470:1264:23)
hashsequence commented 1 year ago

I managed to find the issue:

It turns out that when Storybook reloads a story it needs to rerun app.use(WaveUI, options), but since the #registered is a private static variable, it only runs once and will not run the other logic after the first run.

constructor (app, options = {}) {
    if (WaveUI.#registered) {
      console.warn('Wave UI is already instantiated.')
      return
    }

    this.$waveui._notificationManager = new NotificationManager()

    if (!options.theme) options.theme = 'light'
    // Move colors inside a theme if there are option.colors without theme.
    // E.g. colors: { primary, ... } & not colors: { light { primary, ... }, dark: { primary, ... } })
    if (options.colors) {
      const colors = { ...options.colors }
      if (!options.colors.light) options.colors.light = colors
      if (!options.colors.dark) options.colors.dark = colors
      // Cleanup anything else than themes in config.colors.
      options.colors = { light: options.colors.light, dark: options.colors.dark }
    }

    // Merge user options into the default config.
    let { components, ...config } = options
    config = this.$waveui.config = mergeConfig(config)

    // Generates color shades for each color of each theme and store in the config.colors object.
    if (config.css.colorShades) generateColorShades(config)

    // Make Wave UI reactive and expose the single instance in the app.
    const $waveui = reactive(this.$waveui)
    app.config.globalProperties.$waveui = $waveui
    app.provide('$waveui', $waveui)

    if (config.theme !== 'auto') {
      this.$waveui.colors = flattenColors(config.colors[config.theme], colorPalette)
    }
  }
}

The fix was to add this line of code:

const waveui = new WaveUI(app,options)
app.config.globalProperties.$waveui = waveui['$waveui']

You can probably add the other logic from the constructor also if possible, but I haven't tested it out yet to see if they are neccessary