Copy Build a permission-inheritance explorer with Tailwind CSS. Show an organization, workspace, project, and environment as a connected hierarchy. Each level displays its assigned role, inherited permissions, and override count. Selecting a node should open a detail panel listing effective capabilities and their source. Add JavaScript that switches the selected node, renders its effective permissions, and lets a user toggle between effective-access and explicit-rules views. <div class="mx-auto max-w-4xl p-6"><section class="overflow-hidden rounded-2xl border border-neutral-200 bg-white shadow-sm"><header class="flex items-center justify-between border-b border-neutral-100 px-5 py-4"><div><h2 class="text-sm font-semibold text-neutral-900">Access inheritance</h2><p class="text-xs text-neutral-400">Trace how permissions reach production.</p></div><div id="permissionMode" class="flex rounded-lg bg-neutral-100 p-1"><button data-mode="effective" class="rounded-md bg-white px-3 py-1.5 text-xs font-medium shadow-sm">Effective</button><button data-mode="explicit" class="rounded-md px-3 py-1.5 text-xs text-neutral-500">Explicit</button></div></header><div class="grid md:grid-cols-[1fr_1.1fr]"><div id="permissionTree" class="space-y-2 border-b border-neutral-100 p-5 md:border-b-0 md:border-r"><button data-node="org" class="flex w-full items-center gap-3 rounded-xl bg-neutral-900 p-3 text-left text-white"><span class="flex h-8 w-8 items-center justify-center rounded-lg bg-white/10 text-xs">OR</span><span class="flex-1"><b class="block text-sm">Northstar, Inc.</b><small class="text-white/50">Organization · Owner</small></span><span class="text-xs text-white/50">0 overrides</span></button><div class="ml-4 border-l border-neutral-200 pl-4"><button data-node="workspace" class="flex w-full items-center gap-3 rounded-xl p-3 text-left hover:bg-neutral-50"><span class="flex h-8 w-8 items-center justify-center rounded-lg bg-violet-50 text-xs text-violet-700">WS</span><span class="flex-1"><b class="block text-sm text-neutral-800">Commerce</b><small class="text-neutral-400">Workspace · Admin</small></span><span class="text-xs text-neutral-400">1 override</span></button><div class="ml-4 border-l border-neutral-200 pl-4"><button data-node="project" class="flex w-full items-center gap-3 rounded-xl p-3 text-left hover:bg-neutral-50"><span class="flex h-8 w-8 items-center justify-center rounded-lg bg-blue-50 text-xs text-blue-700">PR</span><span class="flex-1"><b class="block text-sm text-neutral-800">Checkout API</b><small class="text-neutral-400">Project · Editor</small></span><span class="text-xs text-neutral-400">2 overrides</span></button><button data-node="environment" class="mt-2 flex w-full items-center gap-3 rounded-xl p-3 text-left hover:bg-neutral-50"><span class="flex h-8 w-8 items-center justify-center rounded-lg bg-amber-50 text-xs text-amber-700">PD</span><span class="flex-1"><b class="block text-sm text-neutral-800">Production</b><small class="text-neutral-400">Environment · Viewer</small></span><span class="text-xs text-neutral-400">1 override</span></button></div></div></div><div class="p-5"><p id="permissionEyebrow" class="text-xs font-semibold uppercase tracking-wider text-neutral-400"></p><h3 id="permissionTitle" class="mt-1 text-lg font-semibold text-neutral-900"></h3><div id="permissionList" class="mt-5 space-y-2"></div></div></div></section></div> var permissionData = { org: { title: "Northstar, Inc.", role: "Owner", effective: [["Manage billing", "Direct"], ["Invite members", "Direct"], ["Deploy", "Direct"]], explicit: [["Organization owner", "Assigned"]] }, workspace: { title: "Commerce", role: "Admin", effective: [["Invite members", "Northstar, Inc."], ["Create projects", "Direct"], ["Deploy", "Northstar, Inc."]], explicit: [["Workspace admin", "Assigned"], ["Export data", "Denied"]] }, project: { title: "Checkout API", role: "Editor", effective: [["Edit code", "Direct"], ["Deploy preview", "Commerce"], ["View secrets", "Denied"]], explicit: [["Project editor", "Assigned"], ["View secrets", "Denied"]] }, environment: { title: "Production", role: "Viewer", effective: [["View logs", "Direct"], ["Deploy", "Denied"], ["Rollback", "Commerce"]], explicit: [["Environment viewer", "Assigned"], ["Deploy", "Denied"]] } };
var currentNode = "org"; var currentMode = "effective"; var nodes = [].slice.call(document.querySelectorAll("[data-node]"));
function renderPermission() { var data = permissionData[currentNode]; document.getElementById("permissionEyebrow").textContent = data.role + " access"; document.getElementById("permissionTitle").textContent = data.title; document.getElementById("permissionList").innerHTML = data[currentMode].map(function (item) { var denied = item[1] === "Denied"; return '<div class="flex items-center justify-between rounded-xl border border-neutral-100 px-3 py-2.5"><span class="text-sm text-neutral-700">' + item[0] + '</span><span class="text-xs ' + (denied ? 'text-red-600' : 'text-neutral-400') + '">' + item[1] + '</span></div>'; }).join(""); nodes.forEach(function (node) { var on = node.getAttribute("data-node") === currentNode; node.classList.toggle("bg-neutral-900", on); node.classList.toggle("text-white", on); }); }
nodes.forEach(function (node) { node.addEventListener("click", function () { currentNode = node.getAttribute("data-node"); renderPermission(); }); }); document.getElementById("permissionMode").addEventListener("click", function (event) { var button = event.target.closest("[data-mode]"); if (!button) return; currentMode = button.getAttribute("data-mode"); [].slice.call(event.currentTarget.children).forEach(function (item) { item.className = item === button ? "rounded-md bg-white px-3 py-1.5 text-xs font-medium shadow-sm" : "rounded-md px-3 py-1.5 text-xs text-neutral-500"; }); renderPermission(); }); renderPermission();