JSFiddle - React, Tailwind, and code Playground

by Dogbert

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootswatch/3.3.7/cosmo/bootstrap.min.css">
<div id="app">
  <field :field="field"></field>
</div>

<template id="field-template">
  <table v-if="field.type === 'section'" class="table table-bordered table-striped table-hover">
    <tbody>
      <tr>
        <th class="center">{{field.name}}</th>
        <td>
        <field v-for="child in field.children" :field="child"></field>
        </td>
      </tr>
    </tbody>
  </table>
  <input v-else-if="field.type === 'input'" class="form-control">
</template>

CSS

.center {
  vertical-align: middle !important;
}

JavaScript

function Section(name, ...children) {
  return {
    type: 'section',
    name,
    children,
    rowspan: children.reduce((acc, x) => x.rowspan + acc, 0),
  };
}

function Input() {
  return {
    type: 'input',
    rowspan: 1,
  };
}

var field = Section('Addon', Section('Before', Input(), Input()), Section('After', Input(), Input(), Input()));

Vue.component('field', {
  template: '#field-template',
  props: ['field'],
});

new Vue({
  el: '#app',
  data: {
    field,
  },
});