JSFiddle - React, Tailwind, and code Playground

by simati

HTML

<div id="app">
<Child title="level 1">
  <section>
    <p>Not a child</p>
    <Child title="level 2">
      <Child title="level 3"/>
    </Child>
  </section>
</Child>
</div>

CSS

section {
  background: rgba(0,0,0,.1);
  margin-left: 20px;
  padding: 20px;
  position: relative;
}

input {
  position: absolute;
  top: 0;
  right: 0;
}

Babel + JSX

const Child = {
  props: ['title'],
  provide() {
    return {
      injectedContext: this.context
    };
  },
  inject: ['injectedContext'],
  data() {
    return {
      titleData: this.title,
      $private: {
        context: this.computeContext()
      }
    }
  },
  computed: {
  	context: {
      get() {
	      return this.$data.$private.context;
      }
    }
  },
  watch: {
    // Update context when local properties change
    titleData() { this.updateContext(); }
  },
  methods: {
    computeContext() {
      const leadingBreadcrumb = this.injectedContext ? `${this.injectedContext.breadcrumb} > ` : '';
    	return {
        breadcrumb: `${leadingBreadcrumb}${this.titleData}`
      }
    },
  	updateContext() {
      const computed = this.computeContext();
      this.$data.$private.context.breadcrumb = computed.breadcrumb;
    }
  },
  created() {
    // Update context when inherited context changes
    this.$watch('injectedContext', () => this.updateContext(), { deep: true, immediate: true });
  },
  template: `<section>{{ context.breadcrumb }}<input type="text" v-model="titleData"/><slot name="default"/></section>`
}

new Vue({
  el: '#app',
  provide() {
  	return {
    	injectedContext: null
    }
  },
  components: { Child }
})