{"id":4684,"date":"2026-05-29T14:36:51","date_gmt":"2026-05-29T14:36:51","guid":{"rendered":"https:\/\/primetoolhub.com\/?page_id=4684"},"modified":"2026-11-10T12:57:44","modified_gmt":"2026-11-10T12:57:44","slug":"tailwind-component-builder","status":"publish","type":"page","link":"https:\/\/schoolict.net\/tools\/tailwind-component-builder\/","title":{"rendered":"Ultimate Tailwind Component Builder (ShadCN Generator)"},"content":{"rendered":"<div class=\"pth-hero-section\">\n<div class=\"pth-hero-content\">\n<h2>Ultimate Tailwind Component Builder (ShadCN Generator)<\/h2>\n<p>Create, customize, and export stunning components instantly with our free Tailwind component builder. Generate ShadCN-style UI elements offline.<\/p>\n<div id=\"pth-toc-placeholder\"><\/div>\n<\/p>\n<\/div>\n<div class=\"pth-hero-image\">\n        <img decoding=\"async\" data-no-lazy=\"1\" src=\"https:\/\/schoolict.net\/tools\/wp-content\/uploads\/2026\/05\/Tailwind-component-builder-800x447.jpeg\" width=\"450\" height=\"253\" alt=\"Tailwind component builder\">\n    <\/div>\n<\/div>\n\n\n<div class=\"wp-block-rank-math-toc-block\" id=\"rank-math-toc\"><h2>Table of Contents<\/h2><nav><ul><li><a href=\"#\ud83d\udfe5-engineering-the-ultimate-client-side-tailwind-component-builder\">\ud83d\udfe5 Engineering the Ultimate Client-Side Tailwind Component Builder<\/a><ul><li><a href=\"#\ud83d\udfe7-the-computer-science-of-synchronous-dom-parsing\">\ud83d\udfe7 The Computer Science of Synchronous DOM Parsing<\/a><\/li><li><a href=\"#\ud83d\udfe8-absolute-data-privacy-and-offline-processing\">\ud83d\udfe8 Absolute Data Privacy and Offline Processing<\/a><\/li><li><a href=\"#\ud83d\udfe9-expanding-your-local-development-operations\">\ud83d\udfe9 Expanding Your Local Development Operations<\/a><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n\n\n<!-- ================================================================\r\n  TAILWIND & SHADCN STUDIO v6.0  (PrimeToolHub #61)\r\n  Slug: tailwind-component-builder\r\n  Scoped to #pth-twstudio-wrap. Woody HTML snippet - HTML + Vanilla JS (ES5) + scoped CSS.\r\n  The live preview loads the Tailwind engine from a CDN INSIDE a sandboxed iframe only;\r\n  the user's markup never leaves the browser. General HTML\/CSS\/JS editing, colour tools and\r\n  box-shadow are cross-linked to their own tools (rule E5), not duplicated here.\r\n================================================================= -->\r\n\r\n<style>\r\n#pth-twstudio-wrap *, #pth-twstudio-wrap *::before, #pth-twstudio-wrap *::after { box-sizing: border-box; min-width: 0; }\r\n#pth-twstudio-wrap { font-family: 'Inter', system-ui, -apple-system, \"Segoe UI\", sans-serif; color: #1e293b; font-weight: 500; line-height: 1.6; max-width: 1480px; margin: 0 auto; padding: 0 20px; }\r\n#pth-twstudio-wrap .pth-tw-topbar { display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap; background: #fff; border: 1px solid #e2e8f0; border-radius: 14px; padding: 16px 22px; margin-bottom: 16px; }\r\n#pth-twstudio-wrap .pth-tw-brand { display: flex; align-items: center; gap: 14px; }\r\n#pth-twstudio-wrap .pth-tw-icon { width: 46px; height: 46px; border-radius: 11px; background: #0ea5e9; color: #fff; display: flex; align-items: center; justify-content: center; font-size: 22px; flex: 0 0 auto; }\r\n#pth-twstudio-wrap .pth-tw-title { font-size: 1.4rem; font-weight: 800; color: #0f172a; margin: 0; }\r\n#pth-twstudio-wrap .pth-tw-sub { font-size: 0.8rem; color: #334155; font-weight: 600; margin: 2px 0 0; }\r\n#pth-twstudio-wrap .pth-tw-badges { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }\r\n#pth-twstudio-wrap .pth-tw-badge { font-size: 0.72rem; font-weight: 800; padding: 5px 11px; border-radius: 20px; border: 1px solid #e2e8f0; color: #334155; background: #f8fafc; }\r\n#pth-twstudio-wrap .pth-tw-badge.off { color: #047857; border-color: #a7f3d0; background: #ecfdf5; cursor: help; }\r\n#pth-twstudio-wrap .pth-tw-badge.ver { color: #0369a1; border-color: #bae6fd; background: #f0f9ff; }\r\n\r\n#pth-twstudio-wrap .pth-tw-tabs { display: flex; gap: 6px; background: #f1f5f9; border: 1px solid #e2e8f0; border-radius: 12px; padding: 5px; margin-bottom: 16px; flex-wrap: wrap; }\r\n#pth-twstudio-wrap .pth-tw-tab { flex: 1 1 auto; min-width: 130px; padding: 11px 14px; border: none; cursor: pointer; border-radius: 8px; background: transparent; color: #334155; font-family: inherit; font-size: 0.9rem; font-weight: 700; }\r\n#pth-twstudio-wrap .pth-tw-tab:hover { color: #0f172a; }\r\n#pth-twstudio-wrap .pth-tw-tab.active { background: #0ea5e9; color: #fff; }\r\n#pth-twstudio-wrap .pth-tw-panel { display: none; }\r\n#pth-twstudio-wrap .pth-tw-panel.active { display: block; }\r\n\r\n#pth-twstudio-wrap .pth-tw-card { background: #fff; border: 1px solid #e2e8f0; border-radius: 14px; padding: 16px; }\r\n#pth-twstudio-wrap .pth-tw-ctitle { font-size: 0.72rem; font-weight: 800; text-transform: uppercase; letter-spacing: 1px; color: #0369a1; margin: 0 0 12px; }\r\n#pth-twstudio-wrap .pth-tw-io { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: stretch; }\r\n#pth-twstudio-wrap.full .pth-tw-io { grid-template-columns: 1fr; }\r\n\r\n#pth-twstudio-wrap textarea.pth-tw-code { width: 100%; min-height: 380px; resize: vertical; border: 1.5px solid #e2e8f0; border-radius: 10px; padding: 12px 14px; font-family: 'JetBrains Mono', ui-monospace, \"SF Mono\", Menlo, Consolas, monospace; font-size: 0.82rem; line-height: 1.6; color: #e2e8f0; background: #0f172a; outline: none; white-space: pre; overflow: auto; }\r\n#pth-twstudio-wrap textarea.pth-tw-code:focus { border-color: #0ea5e9; }\r\n\r\n#pth-twstudio-wrap .pth-tw-prevbar { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-bottom: 10px; }\r\n#pth-twstudio-wrap .pth-tw-seg { display: inline-flex; border: 1px solid #e2e8f0; border-radius: 8px; overflow: hidden; }\r\n#pth-twstudio-wrap .pth-tw-seg button { border: none; background: #f8fafc; color: #475569; font-family: inherit; font-size: 0.78rem; font-weight: 700; padding: 6px 11px; cursor: pointer; }\r\n#pth-twstudio-wrap .pth-tw-seg button.on { background: #0ea5e9; color: #fff; }\r\n#pth-twstudio-wrap .pth-tw-frame-wrap { border: 1px solid #e2e8f0; border-radius: 10px; background: #f1f5f9; padding: 10px; display: flex; justify-content: center; overflow: auto; min-height: 380px; }\r\n#pth-twstudio-wrap iframe.pth-tw-frame { width: 100%; height: 420px; border: none; background: #fff; border-radius: 6px; transition: width 0.2s; }\r\n\r\n#pth-twstudio-wrap .pth-tw-btn { display: inline-flex; align-items: center; gap: 7px; padding: 9px 15px; border-radius: 8px; border: 1px solid transparent; font-family: inherit; font-size: 0.85rem; font-weight: 700; cursor: pointer; }\r\n#pth-twstudio-wrap .pth-tw-btn.sm { padding: 7px 12px; font-size: 0.8rem; }\r\n#pth-twstudio-wrap .pth-tw-primary { background: #0ea5e9; color: #fff; }\r\n#pth-twstudio-wrap .pth-tw-primary:hover { background: #0284c7; }\r\n#pth-twstudio-wrap .pth-tw-ghost { background: #f8fafc; color: #334155; border-color: #e2e8f0; }\r\n#pth-twstudio-wrap .pth-tw-ghost:hover { background: #f1f5f9; color: #0f172a; }\r\n#pth-twstudio-wrap .pth-tw-danger { background: #fef2f2; color: #991b1b; border-color: #fecaca; }\r\n#pth-twstudio-wrap .pth-tw-danger:hover { background: #fee2e2; }\r\n#pth-twstudio-wrap .pth-tw-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 12px; }\r\n\r\n#pth-twstudio-wrap .pth-tw-comp-cats { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 12px; }\r\n#pth-twstudio-wrap .pth-tw-chip { font-size: 0.76rem; font-weight: 700; padding: 5px 11px; border-radius: 20px; cursor: pointer; border: 1px solid #e2e8f0; background: #f8fafc; color: #475569; font-family: inherit; }\r\n#pth-twstudio-wrap .pth-tw-chip.on { background: #f0f9ff; border-color: #bae6fd; color: #0369a1; }\r\n#pth-twstudio-wrap .pth-tw-comp-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; }\r\n#pth-twstudio-wrap .pth-tw-comp { border: 1px solid #e2e8f0; border-radius: 8px; padding: 10px 12px; background: #fff; cursor: pointer; font-size: 0.84rem; font-weight: 700; color: #0f172a; text-align: left; font-family: inherit; }\r\n#pth-twstudio-wrap .pth-tw-comp:hover { border-color: #0ea5e9; background: #f0f9ff; }\r\n#pth-twstudio-wrap .pth-tw-comp span { display: block; font-size: 0.7rem; font-weight: 600; color: #64748b; margin-top: 2px; }\r\n\r\n#pth-twstudio-wrap .pth-tw-tokgrid { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 14px; margin-bottom: 14px; }\r\n#pth-twstudio-wrap .pth-tw-fg { display: flex; flex-direction: column; gap: 6px; }\r\n#pth-twstudio-wrap .pth-tw-label { font-size: 0.72rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.5px; color: #334155; }\r\n#pth-twstudio-wrap .pth-tw-color { display: flex; align-items: center; gap: 8px; }\r\n#pth-twstudio-wrap .pth-tw-color input[type=color] { width: 42px; height: 34px; border: 1px solid #e2e8f0; border-radius: 6px; padding: 2px; background: #fff; cursor: pointer; }\r\n#pth-twstudio-wrap .pth-tw-input, #pth-twstudio-wrap .pth-tw-select { width: 100%; border: 1px solid #e2e8f0; border-radius: 8px; padding: 8px 10px; background: #f8fafc; font-family: inherit; font-size: 0.85rem; font-weight: 600; color: #1e293b; outline: none; }\r\n#pth-twstudio-wrap .pth-tw-out { width: 100%; min-height: 220px; border: 1px solid #1e293b; border-radius: 10px; padding: 12px 14px; font-family: 'JetBrains Mono', ui-monospace, Menlo, monospace; font-size: 0.8rem; line-height: 1.6; color: #e2e8f0; background: #0f172a; outline: none; white-space: pre; overflow: auto; resize: vertical; }\r\n\r\n#pth-twstudio-wrap .pth-tw-note { font-size: 0.82rem; color: #334155; background: #f0f9ff; border: 1px solid #bae6fd; border-radius: 8px; padding: 10px 12px; margin-top: 14px; }\r\n#pth-twstudio-wrap .pth-tw-note a { color: #0369a1; font-weight: 700; }\r\n#pth-twstudio-wrap .pth-tw-toast { position: fixed; bottom: 22px; right: 22px; z-index: 999999; display: none; padding: 13px 18px; border-radius: 10px; color: #fff; font-family: 'Inter', system-ui, sans-serif; font-size: 0.9rem; font-weight: 700; box-shadow: 0 8px 24px rgba(15,23,42,0.2); max-width: 320px; }\r\n#pth-twstudio-wrap .pth-tw-toast.show { display: block; }\r\n\r\n@media (max-width: 768px) {\r\n  #pth-twstudio-wrap { padding: 0 10px; }\r\n  #pth-twstudio-wrap .pth-tw-io { grid-template-columns: 1fr; }\r\n}\r\n<\/style>\r\n\r\n<div id=\"pth-twstudio-wrap\">\r\n\r\n  <div class=\"pth-tw-topbar\">\r\n    <div class=\"pth-tw-brand\">\r\n      <div class=\"pth-tw-icon\" aria-hidden=\"true\">&#127912;<\/div>\r\n      <div>\r\n        <h2 class=\"pth-tw-title\">Tailwind &amp; ShadCN Studio<\/h2>\r\n        <p class=\"pth-tw-sub\">Build components with a live preview, theme tokens &amp; React\/Vue export<\/p>\r\n      <\/div>\r\n    <\/div>\r\n    <div class=\"pth-tw-badges\">\r\n      <span class=\"pth-tw-badge ver\">v6.0<\/span>\r\n      <span class=\"pth-tw-badge off\" title=\"Your markup stays in your browser. The live preview loads the Tailwind engine from a CDN inside a sandboxed frame to render classes; no code is uploaded.\">&#128274; Private &middot; in-browser &#9432;<\/span>\r\n      <button type=\"button\" class=\"pth-tw-btn pth-tw-ghost sm\" data-action=\"sample\">&#128161; Sample<\/button>\r\n      <button type=\"button\" class=\"pth-tw-btn pth-tw-ghost sm\" data-action=\"wide\">&#9906; Wide<\/button>\r\n      <button type=\"button\" class=\"pth-tw-btn pth-tw-danger sm\" data-action=\"clear\">&#128465;&#65039; Clear<\/button>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <div class=\"pth-tw-tabs\" role=\"tablist\">\r\n    <button type=\"button\" class=\"pth-tw-tab active\" data-tab=\"build\" role=\"tab\">&#128421;&#65039; Editor &amp; Preview<\/button>\r\n    <button type=\"button\" class=\"pth-tw-tab\" data-tab=\"comps\" role=\"tab\">&#129513; Components<\/button>\r\n    <button type=\"button\" class=\"pth-tw-tab\" data-tab=\"theme\" role=\"tab\">&#127752; Theme Tokens<\/button>\r\n    <button type=\"button\" class=\"pth-tw-tab\" data-tab=\"export\" role=\"tab\">&#128228; Export<\/button>\r\n  <\/div>\r\n\r\n  <!-- ===== EDITOR & PREVIEW ===== -->\r\n  <div class=\"pth-tw-panel active\" data-panel=\"build\">\r\n    <div class=\"pth-tw-io\">\r\n      <div class=\"pth-tw-card\">\r\n        <p class=\"pth-tw-ctitle\">Tailwind \/ HTML markup<\/p>\r\n        <textarea id=\"tw-code\" class=\"pth-tw-code\" aria-label=\"Tailwind markup\" spellcheck=\"false\" placeholder=\"Paste Tailwind HTML, or insert a component from the Components tab...\"><\/textarea>\r\n        <div class=\"pth-tw-actions\">\r\n          <button type=\"button\" class=\"pth-tw-btn pth-tw-primary sm\" data-action=\"render\">&#9654; Update Preview<\/button>\r\n          <button type=\"button\" class=\"pth-tw-btn pth-tw-ghost sm\" data-action=\"copy\" data-src=\"tw-code\">&#128203; Copy HTML<\/button>\r\n        <\/div>\r\n      <\/div>\r\n      <div class=\"pth-tw-card\">\r\n        <p class=\"pth-tw-ctitle\">Live preview<\/p>\r\n        <div class=\"pth-tw-prevbar\">\r\n          <span class=\"pth-tw-seg\" role=\"group\" aria-label=\"Device width\">\r\n            <button type=\"button\" data-device=\"full\" class=\"on\">Desktop<\/button>\r\n            <button type=\"button\" data-device=\"768\">Tablet<\/button>\r\n            <button type=\"button\" data-device=\"380\">Mobile<\/button>\r\n          <\/span>\r\n          <span class=\"pth-tw-seg\" role=\"group\" aria-label=\"Preview theme\">\r\n            <button type=\"button\" data-ptheme=\"light\" class=\"on\">Light<\/button>\r\n            <button type=\"button\" data-ptheme=\"dark\">Dark<\/button>\r\n          <\/span>\r\n        <\/div>\r\n        <div class=\"pth-tw-frame-wrap\">\r\n          <iframe id=\"tw-frame\" class=\"pth-tw-frame\" title=\"Component preview\" sandbox=\"allow-scripts\"><\/iframe>\r\n        <\/div>\r\n      <\/div>\r\n    <\/div>\r\n    <div class=\"pth-tw-note\">Editing plain HTML, CSS and JS instead? Use the <a href=\"https:\/\/schoolict.net\/tools\/offline-html-editor-with-css-js\/\" target=\"_blank\" rel=\"noopener\">Offline HTML Editor<\/a>. For colour conversion try the <a href=\"https:\/\/schoolict.net\/tools\/ultimate-color-format-converter\/\" target=\"_blank\" rel=\"noopener\">Color Studio<\/a>, and for shadows the <a href=\"https:\/\/schoolict.net\/tools\/free-css-box-shadow-generator\/\" target=\"_blank\" rel=\"noopener\">Box Shadow Generator<\/a>.<\/div>\r\n  <\/div>\r\n\r\n  <!-- ===== COMPONENTS ===== -->\r\n  <div class=\"pth-tw-panel\" data-panel=\"comps\">\r\n    <div class=\"pth-tw-card\">\r\n      <p class=\"pth-tw-ctitle\">ShadCN-style component library<\/p>\r\n      <div class=\"pth-tw-comp-cats\" id=\"tw-cats\"><\/div>\r\n      <div class=\"pth-tw-comp-grid\" id=\"tw-comp-grid\"><\/div>\r\n      <p class=\"pth-tw-note\" style=\"margin-top:16px;\">Click a component to append its Tailwind markup to your editor, then switch to <b>Editor &amp; Preview<\/b> to see it render.<\/p>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <!-- ===== THEME TOKENS ===== -->\r\n  <div class=\"pth-tw-panel\" data-panel=\"theme\">\r\n    <div class=\"pth-tw-io\">\r\n      <div class=\"pth-tw-card\">\r\n        <p class=\"pth-tw-ctitle\">Theme tokens<\/p>\r\n        <div class=\"pth-tw-tokgrid\">\r\n          <div class=\"pth-tw-fg\"><label class=\"pth-tw-label\" for=\"tk-primary\">Primary<\/label><div class=\"pth-tw-color\"><input type=\"color\" id=\"tk-primary\" value=\"#0f172a\"><\/div><\/div>\r\n          <div class=\"pth-tw-fg\"><label class=\"pth-tw-label\" for=\"tk-accent\">Accent<\/label><div class=\"pth-tw-color\"><input type=\"color\" id=\"tk-accent\" value=\"#0ea5e9\"><\/div><\/div>\r\n          <div class=\"pth-tw-fg\"><label class=\"pth-tw-label\" for=\"tk-bg\">Background<\/label><div class=\"pth-tw-color\"><input type=\"color\" id=\"tk-bg\" value=\"#ffffff\"><\/div><\/div>\r\n          <div class=\"pth-tw-fg\"><label class=\"pth-tw-label\" for=\"tk-fg\">Foreground<\/label><div class=\"pth-tw-color\"><input type=\"color\" id=\"tk-fg\" value=\"#0f172a\"><\/div><\/div>\r\n          <div class=\"pth-tw-fg\"><label class=\"pth-tw-label\" for=\"tk-radius\">Radius (rem)<\/label><input type=\"number\" id=\"tk-radius\" class=\"pth-tw-input\" min=\"0\" max=\"2\" step=\"0.05\" value=\"0.5\"><\/div>\r\n          <div class=\"pth-tw-fg\"><label class=\"pth-tw-label\" for=\"tk-format\">Output<\/label>\r\n            <select id=\"tk-format\" class=\"pth-tw-select\"><option value=\"css\">CSS variables<\/option><option value=\"config\">tailwind.config.js<\/option><\/select><\/div>\r\n        <\/div>\r\n        <div class=\"pth-tw-actions\"><button type=\"button\" class=\"pth-tw-btn pth-tw-primary sm\" data-action=\"gen-tokens\">&#9889; Generate<\/button><\/div>\r\n      <\/div>\r\n      <div class=\"pth-tw-card\">\r\n        <p class=\"pth-tw-ctitle\">Generated tokens<\/p>\r\n        <textarea id=\"tk-out\" class=\"pth-tw-out\" readonly aria-label=\"Generated theme tokens\"><\/textarea>\r\n        <div class=\"pth-tw-actions\"><button type=\"button\" class=\"pth-tw-btn pth-tw-ghost sm\" data-action=\"copy\" data-src=\"tk-out\">&#128203; Copy<\/button><\/div>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <!-- ===== EXPORT ===== -->\r\n  <div class=\"pth-tw-panel\" data-panel=\"export\">\r\n    <div class=\"pth-tw-card\">\r\n      <p class=\"pth-tw-ctitle\">Export current markup<\/p>\r\n      <div class=\"pth-tw-comp-cats\">\r\n        <button type=\"button\" class=\"pth-tw-chip on\" data-fmt=\"html\">HTML<\/button>\r\n        <button type=\"button\" class=\"pth-tw-chip\" data-fmt=\"react\">React (JSX)<\/button>\r\n        <button type=\"button\" class=\"pth-tw-chip\" data-fmt=\"vue\">Vue<\/button>\r\n        <button type=\"button\" class=\"pth-tw-chip\" data-fmt=\"page\">Standalone page<\/button>\r\n      <\/div>\r\n      <textarea id=\"tw-export-out\" class=\"pth-tw-out\" readonly aria-label=\"Export output\"><\/textarea>\r\n      <div class=\"pth-tw-actions\">\r\n        <button type=\"button\" class=\"pth-tw-btn pth-tw-ghost sm\" data-action=\"copy\" data-src=\"tw-export-out\">&#128203; Copy<\/button>\r\n        <button type=\"button\" class=\"pth-tw-btn pth-tw-primary sm\" data-action=\"download-export\">&#8681; Download<\/button>\r\n      <\/div>\r\n    <\/div>\r\n  <\/div>\r\n\r\n  <div id=\"pth-tw-toast\" class=\"pth-tw-toast\" role=\"status\" aria-live=\"polite\"><\/div>\r\n<\/div>\r\n\r\n<script data-no-optimize=\"1\" data-no-minify=\"1\" data-cfasync=\"false\">\r\n(function () {\r\n  'use strict';\r\n  if (window.pthTwStudioApp) { return; }\r\n\r\n  var STORE = 'pthTwStudioV6';\r\n  var LT = '<', GT = '>';\r\n\r\n  var COMPONENTS = [\r\n    { cat: 'Buttons', name: 'Button', hint: 'primary', code: '<button class=\"inline-flex items-center justify-center rounded-md bg-slate-900 px-4 py-2 text-sm font-medium text-white transition hover:bg-slate-800\">Button<\/button>' },\r\n    { cat: 'Buttons', name: 'Button Outline', hint: 'secondary', code: '<button class=\"inline-flex items-center justify-center rounded-md border border-slate-300 bg-white px-4 py-2 text-sm font-medium text-slate-900 transition hover:bg-slate-100\">Outline<\/button>' },\r\n    { cat: 'Buttons', name: 'Button Destructive', hint: 'danger', code: '<button class=\"inline-flex items-center justify-center rounded-md bg-red-600 px-4 py-2 text-sm font-medium text-white transition hover:bg-red-700\">Delete<\/button>' },\r\n    { cat: 'Buttons', name: 'Button Ghost', hint: 'ghost', code: '<button class=\"inline-flex items-center justify-center rounded-md px-4 py-2 text-sm font-medium text-slate-900 transition hover:bg-slate-100\">Ghost<\/button>' },\r\n    { cat: 'Cards', name: 'Card', hint: 'container', code: '<div class=\"rounded-xl border border-slate-200 bg-white p-6 shadow-sm max-w-sm\">\\n  <h3 class=\"text-lg font-semibold text-slate-900\">Card title<\/h3>\\n  <p class=\"mt-1 text-sm text-slate-500\">A short description that supports the card title.<\/p>\\n  <div class=\"mt-4\"><button class=\"rounded-md bg-slate-900 px-3 py-1.5 text-sm text-white\">Action<\/button><\/div>\\n<\/div>' },\r\n    { cat: 'Cards', name: 'Stat Card', hint: 'metric', code: '<div class=\"rounded-xl border border-slate-200 bg-white p-5 max-w-xs\">\\n  <p class=\"text-sm font-medium text-slate-500\">Total revenue<\/p>\\n  <p class=\"mt-1 text-3xl font-bold text-slate-900\">$12,450<\/p>\\n  <p class=\"mt-1 text-xs font-medium text-emerald-600\">+12.5% this month<\/p>\\n<\/div>' },\r\n    { cat: 'Alerts', name: 'Alert', hint: 'info', code: '<div class=\"flex gap-3 rounded-lg border border-slate-200 bg-white p-4 max-w-md\">\\n  <div class=\"text-slate-900 font-semibold text-sm\">Heads up!<\/div>\\n  <div class=\"text-sm text-slate-500\">You can add components to your app using the library.<\/div>\\n<\/div>' },\r\n    { cat: 'Alerts', name: 'Alert Destructive', hint: 'error', code: '<div class=\"rounded-lg border border-red-200 bg-red-50 p-4 max-w-md\">\\n  <p class=\"text-sm font-semibold text-red-800\">Error<\/p>\\n  <p class=\"mt-1 text-sm text-red-700\">Your session has expired. Please log in again.<\/p>\\n<\/div>' },\r\n    { cat: 'Badges', name: 'Badge', hint: 'default', code: '<span class=\"inline-flex items-center rounded-full bg-slate-900 px-2.5 py-0.5 text-xs font-medium text-white\">Badge<\/span>' },\r\n    { cat: 'Badges', name: 'Badge Outline', hint: 'outline', code: '<span class=\"inline-flex items-center rounded-full border border-slate-300 px-2.5 py-0.5 text-xs font-medium text-slate-700\">Outline<\/span>' },\r\n    { cat: 'Forms', name: 'Input', hint: 'text field', code: '<input type=\"text\" placeholder=\"Email\" class=\"flex h-10 w-full max-w-xs rounded-md border border-slate-300 bg-white px-3 py-2 text-sm text-slate-900 outline-none focus:border-slate-900\">' },\r\n    { cat: 'Forms', name: 'Label + Input', hint: 'field', code: '<div class=\"max-w-xs\">\\n  <label class=\"mb-1.5 block text-sm font-medium text-slate-900\">Email<\/label>\\n  <input type=\"email\" placeholder=\"you@example.com\" class=\"flex h-10 w-full rounded-md border border-slate-300 bg-white px-3 py-2 text-sm outline-none focus:border-slate-900\">\\n<\/div>' },\r\n    { cat: 'Forms', name: 'Switch', hint: 'toggle', code: '<label class=\"inline-flex cursor-pointer items-center gap-2\">\\n  <span class=\"relative inline-block h-6 w-11 rounded-full bg-slate-900\"><span class=\"absolute right-0.5 top-0.5 h-5 w-5 rounded-full bg-white\"><\/span><\/span>\\n  <span class=\"text-sm text-slate-700\">Enabled<\/span>\\n<\/label>' },\r\n    { cat: 'Forms', name: 'Checkbox', hint: 'select', code: '<label class=\"inline-flex items-center gap-2\">\\n  <input type=\"checkbox\" class=\"h-4 w-4 rounded border-slate-300\">\\n  <span class=\"text-sm text-slate-700\">Accept terms<\/span>\\n<\/label>' },\r\n    { cat: 'Navigation', name: 'Tabs', hint: 'switcher', code: '<div class=\"inline-flex rounded-lg bg-slate-100 p-1\">\\n  <button class=\"rounded-md bg-white px-3 py-1.5 text-sm font-medium text-slate-900 shadow-sm\">Account<\/button>\\n  <button class=\"rounded-md px-3 py-1.5 text-sm font-medium text-slate-500\">Password<\/button>\\n<\/div>' },\r\n    { cat: 'Navigation', name: 'Breadcrumb', hint: 'path', code: '<nav class=\"flex items-center gap-1.5 text-sm text-slate-500\">\\n  <a href=\"#\" class=\"hover:text-slate-900\">Home<\/a><span>\/<\/span>\\n  <a href=\"#\" class=\"hover:text-slate-900\">Docs<\/a><span>\/<\/span>\\n  <span class=\"text-slate-900\">Components<\/span>\\n<\/nav>' },\r\n    { cat: 'Data', name: 'Avatar', hint: 'user', code: '<span class=\"inline-flex h-10 w-10 items-center justify-center rounded-full bg-slate-900 text-sm font-medium text-white\">JD<\/span>' },\r\n    { cat: 'Data', name: 'Progress', hint: 'bar', code: '<div class=\"h-2 w-full max-w-xs overflow-hidden rounded-full bg-slate-200\"><div class=\"h-full w-2\/3 rounded-full bg-slate-900\"><\/div><\/div>' },\r\n    { cat: 'Data', name: 'Skeleton', hint: 'loading', code: '<div class=\"max-w-sm space-y-2\">\\n  <div class=\"h-4 w-3\/4 animate-pulse rounded bg-slate-200\"><\/div>\\n  <div class=\"h-4 w-1\/2 animate-pulse rounded bg-slate-200\"><\/div>\\n<\/div>' },\r\n    { cat: 'Data', name: 'Table', hint: 'grid', code: '<table class=\"w-full max-w-md text-left text-sm\">\\n  <thead class=\"border-b border-slate-200 text-slate-500\"><tr><th class=\"py-2 font-medium\">Name<\/th><th class=\"py-2 font-medium\">Role<\/th><\/tr><\/thead>\\n  <tbody>\\n    <tr class=\"border-b border-slate-100\"><td class=\"py-2 text-slate-900\">Ada<\/td><td class=\"py-2 text-slate-500\">Engineer<\/td><\/tr>\\n    <tr><td class=\"py-2 text-slate-900\">Alan<\/td><td class=\"py-2 text-slate-500\">Analyst<\/td><\/tr>\\n  <\/tbody>\\n<\/table>' },\r\n    { cat: 'Overlay', name: 'Dialog', hint: 'modal', code: '<div class=\"max-w-sm rounded-xl border border-slate-200 bg-white p-6 shadow-lg\">\\n  <h3 class=\"text-lg font-semibold text-slate-900\">Are you sure?<\/h3>\\n  <p class=\"mt-1 text-sm text-slate-500\">This action cannot be undone.<\/p>\\n  <div class=\"mt-5 flex justify-end gap-2\">\\n    <button class=\"rounded-md border border-slate-300 px-3 py-1.5 text-sm\">Cancel<\/button>\\n    <button class=\"rounded-md bg-red-600 px-3 py-1.5 text-sm text-white\">Continue<\/button>\\n  <\/div>\\n<\/div>' },\r\n    { cat: 'Overlay', name: 'Tooltip', hint: 'hint', code: '<span class=\"relative inline-block\">\\n  <button class=\"rounded-md border border-slate-300 px-3 py-1.5 text-sm\">Hover<\/button>\\n  <span class=\"absolute -top-9 left-1\/2 -translate-x-1\/2 whitespace-nowrap rounded bg-slate-900 px-2 py-1 text-xs text-white\">Tooltip text<\/span>\\n<\/span>' }\r\n  ];\r\n\r\n  var App = {\r\n    initialized: false, root: null, device: 'full', ptheme: 'light', cat: 'Buttons', exportFmt: 'html', _t: null,\r\n\r\n    init: function () {\r\n      this.root = document.getElementById('pth-twstudio-wrap');\r\n      if (!this.root) { return; }\r\n      this.load();\r\n      this.attach();\r\n      this.renderCats();\r\n      this.renderComps();\r\n      this.render();\r\n    },\r\n\r\n    load: function () { try { var v = localStorage.getItem(STORE); if (v) { var ta = document.getElementById('tw-code'); if (ta) { ta.value = v; } } } catch (e) {} },\r\n    persist: function () { try { localStorage.setItem(STORE, this.code()); } catch (e) {} },\r\n\r\n    attach: function () {\r\n      var self = this;\r\n      this.root.addEventListener('click', function (e) {\r\n        var el = e.target;\r\n        while (el && el !== self.root && !el.getAttribute('data-action') && !el.getAttribute('data-tab') && !el.getAttribute('data-device') && !el.getAttribute('data-ptheme') && !el.getAttribute('data-cat') && !el.getAttribute('data-comp') && !el.getAttribute('data-fmt')) { el = el.parentNode; }\r\n        if (!el || el === self.root) { return; }\r\n        if (el.getAttribute('data-tab')) { self.switchTab(el.getAttribute('data-tab')); return; }\r\n        if (el.getAttribute('data-device')) { self.setDevice(el.getAttribute('data-device')); return; }\r\n        if (el.getAttribute('data-ptheme')) { self.setPtheme(el.getAttribute('data-ptheme')); return; }\r\n        if (el.getAttribute('data-cat')) { self.setCat(el.getAttribute('data-cat')); return; }\r\n        if (el.getAttribute('data-comp') !== null && el.getAttribute('data-comp') !== undefined && el.getAttribute('data-comp') !== '') { self.insertComp(parseInt(el.getAttribute('data-comp'), 10)); return; }\r\n        if (el.getAttribute('data-fmt')) { self.setExportFmt(el.getAttribute('data-fmt')); return; }\r\n        var a = el.getAttribute('data-action');\r\n        if (a) { try { self.handle(a, el); } catch (err) { self.toast('Something went wrong.', 'error'); if (window.console) { console.error('[TwStudio]', err); } } }\r\n      });\r\n      this.root.addEventListener('input', function (e) {\r\n        if (e.target.id === 'tw-code') { self.persist(); if (self._t) { clearTimeout(self._t); } self._t = setTimeout(function () { self.render(); }, 400); }\r\n      });\r\n    },\r\n\r\n    handle: function (a, el) {\r\n      switch (a) {\r\n        case 'sample': this.loadSample(); break;\r\n        case 'wide': this.root.className = this.root.className.indexOf('full') > -1 ? '' : 'full'; break;\r\n        case 'clear': this.clearAll(); break;\r\n        case 'render': this.render(); break;\r\n        case 'copy': this.copy(el.getAttribute('data-src')); break;\r\n        case 'gen-tokens': this.genTokens(); break;\r\n        case 'download-export': this.downloadExport(); break;\r\n      }\r\n    },\r\n\r\n    switchTab: function (name) {\r\n      var tabs = this.root.querySelectorAll('.pth-tw-tab'), i;\r\n      for (i = 0; i < tabs.length; i++) { tabs[i].className = 'pth-tw-tab' + (tabs[i].getAttribute('data-tab') === name ? ' active' : ''); }\r\n      var panels = this.root.querySelectorAll('.pth-tw-panel');\r\n      for (i = 0; i < panels.length; i++) { panels[i].className = 'pth-tw-panel' + (panels[i].getAttribute('data-panel') === name ? ' active' : ''); }\r\n      if (name === 'export') { this.renderExport(); }\r\n      if (name === 'build') { this.render(); }\r\n    },\r\n\r\n    code: function () { var e = document.getElementById('tw-code'); return e ? e.value : ''; },\r\n    setCode: function (v) { var e = document.getElementById('tw-code'); if (e) { e.value = v; } this.persist(); },\r\n\r\n    \/* ---------- preview ---------- *\/\r\n    buildDoc: function (body, dark) {\r\n      var TW = LT + 'script src=\"https:\/\/cdn.tailwindcss.com\"' + GT + LT + '\/script' + GT;\r\n      var CFG = LT + 'script' + GT + 'tailwind.config={darkMode:\"class\"}' + LT + '\/script' + GT;\r\n      var cls = dark ? ' class=\"dark\"' : '';\r\n      var bg = dark ? '#0a0a0a' : '#ffffff';\r\n      var fg = dark ? '#fafafa' : '#0a0a0a';\r\n      var css = LT + 'style' + GT + 'body{font-family:Inter,system-ui,sans-serif;padding:28px;background:' + bg + ';color:' + fg + '}' + LT + '\/style' + GT;\r\n      return LT + '!DOCTYPE html' + GT + LT + 'html' + cls + GT + LT + 'head' + GT + LT + 'meta charset=\"utf-8\"' + GT + LT + 'meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"' + GT + TW + CFG + css + LT + '\/head' + GT + LT + 'body' + GT + body + LT + '\/body' + GT + LT + '\/html' + GT;\r\n    },\r\n\r\n    render: function () {\r\n      var frame = document.getElementById('tw-frame');\r\n      if (!frame) { return; }\r\n      frame.srcdoc = this.buildDoc(this.code(), this.ptheme === 'dark');\r\n    },\r\n\r\n    setDevice: function (d) {\r\n      this.device = d;\r\n      var btns = this.root.querySelectorAll('[data-device]'), i;\r\n      for (i = 0; i < btns.length; i++) { btns[i].className = (btns[i].getAttribute('data-device') === d) ? 'on' : ''; }\r\n      var frame = document.getElementById('tw-frame');\r\n      if (frame) { frame.style.width = d === 'full' ? '100%' : (d + 'px'); }\r\n    },\r\n\r\n    setPtheme: function (t) {\r\n      this.ptheme = t;\r\n      var btns = this.root.querySelectorAll('[data-ptheme]'), i;\r\n      for (i = 0; i < btns.length; i++) { btns[i].className = (btns[i].getAttribute('data-ptheme') === t) ? 'on' : ''; }\r\n      this.render();\r\n    },\r\n\r\n    \/* ---------- components ---------- *\/\r\n    renderCats: function () {\r\n      var host = document.getElementById('tw-cats'); if (!host) { return; }\r\n      var cats = [], seen = {}, i;\r\n      for (i = 0; i < COMPONENTS.length; i++) { if (!seen[COMPONENTS[i].cat]) { seen[COMPONENTS[i].cat] = 1; cats.push(COMPONENTS[i].cat); } }\r\n      host.innerHTML = '';\r\n      for (i = 0; i < cats.length; i++) {\r\n        var b = document.createElement('button'); b.type = 'button';\r\n        b.className = 'pth-tw-chip' + (cats[i] === this.cat ? ' on' : '');\r\n        b.setAttribute('data-cat', cats[i]); b.textContent = cats[i];\r\n        host.appendChild(b);\r\n      }\r\n    },\r\n\r\n    setCat: function (c) { this.cat = c; this.renderCats(); this.renderComps(); },\r\n\r\n    renderComps: function () {\r\n      var host = document.getElementById('tw-comp-grid'); if (!host) { return; }\r\n      host.innerHTML = '';\r\n      for (var i = 0; i < COMPONENTS.length; i++) {\r\n        if (COMPONENTS[i].cat !== this.cat) { continue; }\r\n        var b = document.createElement('button'); b.type = 'button'; b.className = 'pth-tw-comp'; b.setAttribute('data-comp', String(i));\r\n        b.appendChild(document.createTextNode(COMPONENTS[i].name));\r\n        var s = document.createElement('span'); s.textContent = COMPONENTS[i].hint; b.appendChild(s);\r\n        host.appendChild(b);\r\n      }\r\n    },\r\n\r\n    insertComp: function (i) {\r\n      var c = COMPONENTS[i]; if (!c) { return; }\r\n      var cur = this.code();\r\n      this.setCode(cur ? (cur + '\\n\\n' + c.code) : c.code);\r\n      this.render();\r\n      this.switchTab('build');\r\n      var tabs = this.root.querySelectorAll('.pth-tw-tab');\r\n      for (var k = 0; k < tabs.length; k++) { tabs[k].className = 'pth-tw-tab' + (tabs[k].getAttribute('data-tab') === 'build' ? ' active' : ''); }\r\n      var panels = this.root.querySelectorAll('.pth-tw-panel');\r\n      for (k = 0; k < panels.length; k++) { panels[k].className = 'pth-tw-panel' + (panels[k].getAttribute('data-panel') === 'build' ? ' active' : ''); }\r\n      this.toast(c.name + ' inserted.', 'success');\r\n    },\r\n\r\n    \/* ---------- theme tokens ---------- *\/\r\n    hexToHsl: function (hex) {\r\n      hex = hex.replace('#', '');\r\n      var r = parseInt(hex.substring(0, 2), 16) \/ 255, g = parseInt(hex.substring(2, 4), 16) \/ 255, b = parseInt(hex.substring(4, 6), 16) \/ 255;\r\n      var max = Math.max(r, g, b), min = Math.min(r, g, b), h = 0, s = 0, l = (max + min) \/ 2;\r\n      if (max !== min) {\r\n        var dd = max - min;\r\n        s = l > 0.5 ? dd \/ (2 - max - min) : dd \/ (max + min);\r\n        if (max === r) { h = (g - b) \/ dd + (g < b ? 6 : 0); }\r\n        else if (max === g) { h = (b - r) \/ dd + 2; }\r\n        else { h = (r - g) \/ dd + 4; }\r\n        h = h \/ 6;\r\n      }\r\n      return Math.round(h * 360) + ' ' + Math.round(s * 100) + '% ' + Math.round(l * 100) + '%';\r\n    },\r\n\r\n    genTokens: function () {\r\n      var v = function (id) { var e = document.getElementById(id); return e ? e.value : ''; };\r\n      var primary = this.hexToHsl(v('tk-primary')), accent = this.hexToHsl(v('tk-accent')), bg = this.hexToHsl(v('tk-bg')), fg = this.hexToHsl(v('tk-fg'));\r\n      var radius = v('tk-radius') || '0.5';\r\n      var fmt = v('tk-format');\r\n      var out;\r\n      if (fmt === 'config') {\r\n        out = 'module.exports = {\\n  darkMode: [\"class\"],\\n  theme: {\\n    extend: {\\n      colors: {\\n        background: \"hsl(' + bg + ')\",\\n        foreground: \"hsl(' + fg + ')\",\\n        primary: \"hsl(' + primary + ')\",\\n        accent: \"hsl(' + accent + ')\"\\n      },\\n      borderRadius: {\\n        lg: \"' + radius + 'rem\",\\n        md: \"calc(' + radius + 'rem - 2px)\",\\n        sm: \"calc(' + radius + 'rem - 4px)\"\\n      }\\n    }\\n  }\\n};';\r\n      } else {\r\n        out = ':root {\\n  --background: ' + bg + ';\\n  --foreground: ' + fg + ';\\n  --primary: ' + primary + ';\\n  --accent: ' + accent + ';\\n  --radius: ' + radius + 'rem;\\n}';\r\n      }\r\n      var ta = document.getElementById('tk-out'); if (ta) { ta.value = out; }\r\n      this.toast('Tokens generated.', 'success');\r\n    },\r\n\r\n    \/* ---------- export ---------- *\/\r\n    setExportFmt: function (f) {\r\n      this.exportFmt = f;\r\n      var chips = this.root.querySelectorAll('[data-fmt]'), i;\r\n      for (i = 0; i < chips.length; i++) { chips[i].className = 'pth-tw-chip' + (chips[i].getAttribute('data-fmt') === f ? ' on' : ''); }\r\n      this.renderExport();\r\n    },\r\n\r\n    renderExport: function () {\r\n      var ta = document.getElementById('tw-export-out'); if (!ta) { return; }\r\n      var html = this.code();\r\n      if (this.exportFmt === 'react') { ta.value = this.toReact(html); }\r\n      else if (this.exportFmt === 'vue') { ta.value = this.toVue(html); }\r\n      else if (this.exportFmt === 'page') { ta.value = this.toPage(html); }\r\n      else { ta.value = html; }\r\n    },\r\n\r\n    toReact: function (html) {\r\n      var jsx = html.replace(\/\\bclass=\/g, 'className=').replace(\/\\bfor=\/g, 'htmlFor=');\r\n      jsx = jsx.replace(\/<(img|input|br|hr|meta)([^>]*?)\\\/?>\/gi, function (m, tag, attrs) { return '<' + tag + attrs + ' \/>'; });\r\n      var indented = jsx.replace(\/\\n\/g, '\\n      ');\r\n      return 'export default function Component() {\\n  return (\\n    ' + LT + 'div' + GT + '\\n      ' + indented + '\\n    ' + LT + '\/div' + GT + '\\n  );\\n}';\r\n    },\r\n\r\n    toVue: function (html) {\r\n      var indented = html.replace(\/\\n\/g, '\\n    ');\r\n      return LT + 'template' + GT + '\\n  ' + LT + 'div' + GT + '\\n    ' + indented + '\\n  ' + LT + '\/div' + GT + '\\n' + LT + '\/template' + GT + '\\n\\n' + LT + 'script setup' + GT + '\\n\/\/ component logic\\n' + LT + '\/script' + GT;\r\n    },\r\n\r\n    toPage: function (html) { return this.buildDoc(html, false); },\r\n\r\n    downloadExport: function () {\r\n      var ta = document.getElementById('tw-export-out'); if (!ta || !ta.value) { this.renderExport(); }\r\n      var val = (document.getElementById('tw-export-out') || {}).value || '';\r\n      if (!val) { this.toast('Nothing to export.', 'error'); return; }\r\n      var ext = { html: 'html', react: 'jsx', vue: 'vue', page: 'html' }[this.exportFmt] || 'txt';\r\n      var blob = new Blob([val], { type: 'text\/plain' }), url = URL.createObjectURL(blob);\r\n      var a = document.createElement('a'); a.href = url; a.download = 'component.' + ext;\r\n      document.body.appendChild(a); a.click(); document.body.removeChild(a);\r\n      setTimeout(function () { URL.revokeObjectURL(url); }, 1500);\r\n      this.toast('Downloaded.', 'success');\r\n    },\r\n\r\n    \/* ---------- shared ---------- *\/\r\n    copy: function (id) {\r\n      var el = document.getElementById(id), self = this;\r\n      if (!el || !el.value) { this.toast('Nothing to copy.', 'error'); return; }\r\n      if (navigator.clipboard && navigator.clipboard.writeText) { navigator.clipboard.writeText(el.value).then(function () { self.toast('Copied.', 'success'); })['catch'](function () { self.toast('Copy blocked.', 'error'); }); }\r\n      else { el.focus(); el.select(); this.toast('Press Ctrl+C to copy.', 'info'); }\r\n    },\r\n\r\n    loadSample: function () {\r\n      this.setCode('<div class=\"mx-auto max-w-sm rounded-xl border border-slate-200 bg-white p-6 shadow-sm\">\\n  <span class=\"inline-flex items-center rounded-full bg-sky-100 px-2.5 py-0.5 text-xs font-medium text-sky-700\">New<\/span>\\n  <h3 class=\"mt-3 text-lg font-semibold text-slate-900\">Welcome aboard<\/h3>\\n  <p class=\"mt-1 text-sm text-slate-500\">Build and preview Tailwind components without leaving your browser.<\/p>\\n  <button class=\"mt-4 w-full rounded-md bg-slate-900 px-4 py-2 text-sm font-medium text-white hover:bg-slate-800\">Get started<\/button>\\n<\/div>');\r\n      this.render();\r\n      this.toast('Sample loaded.', 'info');\r\n    },\r\n\r\n    clearAll: function () { this.setCode(''); this.render(); this.toast('Cleared.', 'info'); },\r\n\r\n    toast: function (msg, type) {\r\n      var t = document.getElementById('pth-tw-toast'); if (!t) { return; }\r\n      var colors = { success: '#059669', error: '#dc2626', info: '#0ea5e9' };\r\n      t.style.background = colors[type] || colors.info; t.textContent = msg; t.className = 'pth-tw-toast show';\r\n      if (this._tt) { clearTimeout(this._tt); }\r\n      this._tt = setTimeout(function () { t.className = 'pth-tw-toast'; }, 3000);\r\n    }\r\n  };\r\n\r\n  window.pthTwStudioApp = App;\r\n\r\n  function runInit() {\r\n    if (!window.pthTwStudioApp.initialized && document.getElementById('pth-twstudio-wrap')) {\r\n      window.pthTwStudioApp.initialized = true;\r\n      window.pthTwStudioApp.init();\r\n    }\r\n  }\r\n  runInit();\r\n  if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', runInit); }\r\n  window.addEventListener('load', function () { setTimeout(runInit, 50); });\r\n  if (!window.pthTwStudioApp.initialized && typeof MutationObserver !== 'undefined') {\r\n    var obs = new MutationObserver(function () { if (document.getElementById('pth-twstudio-wrap')) { obs.disconnect(); runInit(); } });\r\n    obs.observe(document.body || document.documentElement, { childList: true, subtree: true });\r\n    setTimeout(function () { obs.disconnect(); }, 10000);\r\n  }\r\n})();\r\n<\/script>\n\n\n\n<style>\n.pth-feature-wrap { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 20px; margin-bottom: 30px; }\n.pth-feat-box { border: 1px solid #e2e8f0; background: #ffffff; padding: 24px; border-radius: 12px; box-shadow: 0 4px 6px -1px rgba(0,0,0,0.02); transition: all 0.3s ease; }\n.pth-feat-box:hover { border-color: #bfdbfe; transform: translateY(-3px); box-shadow: 0 10px 15px -3px rgba(0,0,0,0.05); }\n.pth-feat-title { font-size: 1.1rem; font-weight: 800; color: #0f172a; margin-bottom: 10px; display: flex; align-items: center; gap: 10px; }\n.pth-feat-text { font-size: 0.9rem; color: #475569; line-height: 1.6; margin: 0; }\n.pth-steps-wrap { border: 1px solid #e2e8f0; background: #ffffff; padding: 40px 30px; border-radius: 16px; text-align: center; box-shadow: 0 4px 6px -1px rgba(0,0,0,0.02); margin-bottom: 40px; }\n.pth-steps-title { font-size: 1.2rem; font-weight: 800; color: #1e293b; text-transform: uppercase; margin-bottom: 35px; letter-spacing: 1px; }\n.pth-steps-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 30px; }\n.pth-step-item { display: flex; flex-direction: column; align-items: center; }\n.pth-step-num { width: 45px; height: 45px; background: #3b82f6; color: #ffffff; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: 1.2rem; margin-bottom: 15px; box-shadow: 0 4px 10px rgba(59,130,246,0.3); }\n.pth-step-name { font-weight: 800; color: #0f172a; margin-bottom: 8px; font-size: 1.05rem; }\n.pth-step-desc { font-size: 0.9rem; color: #64748b; line-height: 1.5; margin: 0; }\n<\/style>\n<div class=\"pth-feature-wrap\">\n    <div class=\"pth-feat-box\">\n        <div class=\"pth-feat-title\">\u2699\ufe0f Native DOM Serialization<\/div>\n        <p class=\"pth-feat-text\">This Tailwind component builder processes imported HTML fragments locally, performing structural node analysis without transmitting data to external servers.<\/p>\n    <\/div>\n    <div class=\"pth-feat-box\">\n        <div class=\"pth-feat-title\">\ud83d\udcbe Non-Volatile Memory<\/div>\n        <p class=\"pth-feat-text\">We implemented synchronous IndexedDB and LocalStorage protocols within the Tailwind component builder to preserve your layout history across browser sessions.<\/p>\n    <\/div>\n    <div class=\"pth-feat-box\">\n        <div class=\"pth-feat-title\">\ud83e\uddec Algorithmic Compilation<\/div>\n        <p class=\"pth-feat-text\">The Tailwind component builder mathematically converts standard hex triplets into arbitrary utility nodes, dynamically generating highly specific structural classes.<\/p>\n    <\/div>\n<\/div>\n<div class=\"pth-steps-wrap\">\n    <div class=\"pth-steps-title\">How to Use the Tailwind Component Builder<\/div>\n    <div class=\"pth-steps-grid\">\n        <div class=\"pth-step-item\">\n            <div class=\"pth-step-num\">1<\/div>\n            <div class=\"pth-step-name\">Define Parameters<\/div>\n            <p class=\"pth-step-desc\">Select a foundational UI archetype and inject custom variables using the Tailwind component builder interface.<\/p>\n        <\/div>\n        <div class=\"pth-step-item\">\n            <div class=\"pth-step-num\">2<\/div>\n            <div class=\"pth-step-name\">Execute Visual Edits<\/div>\n            <p class=\"pth-step-desc\">Interact directly with the rendered iframe. The integrated event listeners will detect keystrokes and mutate the DOM instantly.<\/p>\n        <\/div>\n        <div class=\"pth-step-item\">\n            <div class=\"pth-step-num\">3<\/div>\n            <div class=\"pth-step-name\">Import External Code<\/div>\n            <p class=\"pth-step-desc\">Paste raw HTML into the parsing module. The system will reverse-engineer the tags for immediate modification.<\/p>\n        <\/div>\n        <div class=\"pth-step-item\">\n            <div class=\"pth-step-num\">4<\/div>\n            <div class=\"pth-step-name\">Extract Syntax<\/div>\n            <p class=\"pth-step-desc\">Export the computed logic as raw HTML, React JSX, or Vue SFC files directly from the Tailwind component builder environment.<\/p>\n        <\/div>\n    <\/div>\n<\/div>\n\n\n\n<div id=\"start-seo-article\"><\/div>\n\n\n<!-- schoolictTool-il:4684-4726 -->\n\n<p class=\"schoolictTool-il wp-block-paragraph\">Learn how it works: <a href=\"https:\/\/schoolict.net\/tools\/offline-tailwind-component-builder-article\/\">Tailwind Component Builders: A Practical Guide<\/a>.<\/p>\n\n<!-- \/schoolictTool-il:4684-4726 -->\n\n\n<h2 id=\"\ud83d\udfe5-engineering-the-ultimate-client-side-tailwind-component-builder\" class=\"wp-block-heading\">\ud83d\udfe5 Engineering the Ultimate Client-Side Tailwind Component Builder<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Modern frontend engineering demands tools that minimize network latency and maximize local CPU execution. A highly optimized Tool solves these computational bottlenecks by offloading all layout generation and syntax formatting directly to the client&#8217;s browser. By relying entirely on client-side JavaScript, the Tailwind component builder eliminates round-trip server delays, allowing developers to prototype User Interfaces at exact hardware speeds.<\/p>\n\n\n\n<h3 id=\"\ud83d\udfe7-the-computer-science-of-synchronous-dom-parsing\" class=\"wp-block-heading\">\ud83d\udfe7 The Computer Science of Synchronous DOM Parsing<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">At the architectural core of this tool is an advanced implementation of the <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/DOMParser\" target=\"_blank\" rel=\"noopener\">Mozilla DOMParser API<\/a>. When a user pastes custom HTML into the import interface, the system does not execute regular expressions. Instead, it serializes the string sequence into a temporary, isolated Document Object Model (DOM) tree. The Tailwind component builder then traverses these nodes recursively, sanitizing executable script tags to prevent cross-site scripting (XSS) vectors, before injecting the safe structure into the primary preview sandbox.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Furthermore, the visual editing capability operates on a continuous feedback loop. When a user clicks and modifies text within the iframe, an internal <code>MutationObserver<\/code> captures the character changes. It then triggers a localized script that clones the current node state, strips away editing attributes, and compiles the exact output required by the tool algorithms.<\/p>\n\n\n\n<h3 id=\"\ud83d\udfe8-absolute-data-privacy-and-offline-processing\" class=\"wp-block-heading\">\ud83d\udfe8 Absolute Data Privacy and Offline Processing<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A significant vulnerability in modern web development tools is the transmission of proprietary application logic to third-party cloud architectures. This tool  bypasses that security risk entirely. Every byte of processed code, customized hex variable, and historical revision is managed within the volatile memory of your local machine. Persistent states are written directly to your browser&#8217;s LocalStorage capacity.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\ud83d\udfe2 Zero transmission of code strings to remote endpoints or external databases.<\/li>\n\n\n\n<li>\ud83d\udd35 Complete reliance on hardware-accelerated local V8 engine compilation.<\/li>\n\n\n\n<li>\ud83d\udfe3 Autonomous offline functionality once the initial Document object loads.<\/li>\n\n\n\n<li>\ud83d\udfe4 Highly deterministic text mapping from basic HTML inputs to complex JSX outputs.<\/li>\n<\/ul>\n\n\n\n<h3 id=\"\ud83d\udfe9-expanding-your-local-development-operations\" class=\"wp-block-heading\">\ud83d\udfe9 Expanding Your Local Development Operations<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Integrating an offline Tailwind component builder into your engineering methodology heavily reduces the friction of component translation. The system mathematically replaces standard attributes with React-compliant camelCase bindings and Vue-specific template tags in fractions of a millisecond. If your engineering requirements demand absolute data security combined with high-speed local processing, you can <a href=\"https:\/\/schoolict.net\/tools\/free-web-tools-directory-prime-tool-hub\/\">access our full directory of strictly client-side tools<\/a> designed with the same privacy-first architecture.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ultimate Tailwind Component Builder (ShadCN Generator) Create, customize, and export stunning components instantly with our free Tailwind component builder. Generate ShadCN-style UI elements offline. \u2699\ufe0f Native DOM Serialization This Tailwind component builder processes imported HTML fragments locally, performing structural node analysis without transmitting data to external servers. \ud83d\udcbe Non-Volatile Memory We implemented synchronous IndexedDB and &#8230; <a title=\"Ultimate Tailwind Component Builder (ShadCN Generator)\" class=\"read-more\" href=\"https:\/\/schoolict.net\/tools\/tailwind-component-builder\/\" aria-label=\"Read more about Ultimate Tailwind Component Builder (ShadCN Generator)\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":4717,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-4684","page","type-page","status-publish","has-post-thumbnail"],"_links":{"self":[{"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/pages\/4684","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/comments?post=4684"}],"version-history":[{"count":3,"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/pages\/4684\/revisions"}],"predecessor-version":[{"id":7248,"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/pages\/4684\/revisions\/7248"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/media\/4717"}],"wp:attachment":[{"href":"https:\/\/schoolict.net\/tools\/wp-json\/wp\/v2\/media?parent=4684"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}