
The create-adaptable-composable skill guides developers in building reusable Vue composables that accept both reactive and non-reactive inputs (values, refs, or getters) through MaybeRef and MaybeRefOrGetter type utilities. It's designed for Vue 3+ developers who need to create library-grade composables that work flexibly across different contexts by normalizing inputs with toValue() and toRef() inside reactive effects. This skill solves the problem of creating composables with inconsistent APIs by establishing clear patterns for handling inputs that may or may not be reactive.
$ npx -y skills add vuejs-ai/skills --skill create-adaptable-composable --agent claude-codeInstalls into .claude/skills of the current project.
Adaptable composables are reusable functions that can accept both reactive and non-reactive inputs. This allows developers to use the composable in a variety of contexts without worrying about the reactivity of the inputs.
Steps to design an adaptable composable in Vue.js:
toValue() or toRef() to normalize inputs inside reactive effects./**
* value or writable ref (value/ref/shallowRef/writable computed)
*/
export type MaybeRef<T = any> = T | Ref<T> | ShallowRef<T> | WritableComputedRef<T>;
/**
* MaybeRef<T> + ComputedRef<T> + () => T
*/
export type MaybeRefOrGetter<T = any> = MaybeRef<T> | ComputedRef<T> | (() => T);
MaybeRefOrGetterMaybeRefMaybeRefOrGetter, or you may accidentally invoke it as a getter.MaybeRefOrGetter.When MaybeRefOrGetter or MaybeRef is used:
toRef() (e.g. watcher source)toValue()Adaptable useDocumentTitle Composable: read-only title parameter
import { watch, toRef } from 'vue'
import type { MaybeRefOrGetter } from 'vue'
export function useDocumentTitle(title: MaybeRefOrGetter<string>) {
watch(toRef(title), (t) => {
document.title = t
}, { immediate: true })
}
Adaptable useCounter Composable: two-way writable count parameter
import { watch, toRef } from 'vue'
import type { MaybeRef } from 'vue'
function useCounter(count: MaybeRef<number>) {
const countRef = toRef(count)
function add() {
countRef.value++
}
return { add }
}
Sponsors