Subscribe on changes!

✨ Using inject for `defineProps` object syntax

avatar
May 26th 2023

What problem does this feature solve?

Hi 👋🏻

I'm building Anu and I find it's convenient (or must from user's perspective) to provide props defaults from user side for UI library. For example, if UI library has size prop and user wants button with small size in entire project then user have to write size="small" everywhere. Additionally, This causes problem if the designer decided the size the size from small to something else and developer has to replace the prop value each & every place 😬

<!-- Inconventient & Duplicate code -->
<Btn size="small">...</Btn>
<Btn size="small" other-prop="val">...</Btn>
<Btn size="small">...</Btn>
<Btn size="small" block>...</Btn>

This approache is similar to vuetify 3's global configuration where vuetify allows props defaults while intializing vue plugin.

When I was trying to implement above mentioned feature, I noticed I can't use provide/inject in defineProps' object syntax like below:

// `getAlertProps` is import from another file because we can't use variable from SFC for `defineProps`
const props = defineProps(getAlertProps())

// meta.ts
export const aAlertProps = {
  size: {
    type: string as PropType<'sm' | 'md' | 'xl'>,
    default: 'md'
  }
}

export const getProps = () => {
  /* Error: [Vue warn]: inject() can only be used inside setup() or functional components. */
  const defaults = inject(ANU_DEFAULTS)  // <------ 🫣 Can't use inject

  // Assume `defaults.alert` will have only defaults like `{ size: { default: 'sm' } }`
  return defu(aAlertProps, ...(defaults.alert || {}))
}

What does the proposed API look like?

IDK if this is even possible at Vue side, Maybe we can have vue macros from Kevin for this FR. Once, this is implemented we can use inject as shown in above code example for allowing user to change component's props defaults.

Additional notes

  • Maybe we can try this in Vue Macros first before officially adding it to core
  • Above FR just explains updating prop defaults via config (under the hood provide) however inject will allow updating props defaults when component is rendered inside certain components. For example, user might configure button to be size of xs when used inside table for saving space via config like this:
app.use(plugin, ({
  // other plugin config
  defaults: {
    ABtn: { size: 'sm' },
    ATable: { ABtn: { size: 'xs' } },
  }
})
avatar
May 26th 2023

After skimming vuetify's code I found that they uses getCurrentInstance()?.vnode.props for getting props applied to current component instance. I also implemented POC for anu's global prop defaults.

I just have to run the some piece of code at the start of each SFC.

Closing this as this can be achievable via this approach.