diff --git a/web/index.html b/web/index.html index 9515c84..d14eb30 100644 --- a/web/index.html +++ b/web/index.html @@ -107,35 +107,59 @@ } .btn-ghost:hover { border-color: color-mix(in srgb, var(--af-accent) 50%, transparent); } - /* ---- Live check demo ---- */ - .feed-caption { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.6rem; font-size: 0.8rem; color: var(--af-text-muted); } + /* ---- Directory tree centerpiece ---- */ + .diagram-caption { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.6rem; font-size: 0.8rem; color: var(--af-text-muted); } .pulse-dot { position: relative; width: 8px; height: 8px; border-radius: 50%; background: var(--af-accent); flex: none; } .pulse-dot::after { content: ""; position: absolute; inset: 0; border-radius: 50%; background: var(--af-accent); animation: pulse 2s ease-out infinite; } @keyframes pulse { 0% { opacity: 0.6; transform: scale(1); } 100% { opacity: 0; transform: scale(2.8); } } - #feed-window { box-shadow: 0 30px 60px -20px rgb(0 0 0 / 0.6); max-width: 100%; } - #feed-body { min-height: 15.5rem; max-height: 15.5rem; padding: 0.85rem 1rem; overflow: hidden; font-family: var(--af-font-mono); font-size: 0.78rem; } - .feed-line { - display: grid; grid-template-columns: auto minmax(0, 10.5rem) minmax(0, 1fr) minmax(0, 7rem); gap: 0.6rem; align-items: baseline; - padding: 0.3rem 0; color: var(--af-text-muted); - animation: feed-in 0.4s cubic-bezier(0.16, 1, 0.3, 1); - } - .feed-line .title { overflow-wrap: anywhere; } - @keyframes feed-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: translateY(0); } } - .feed-line .sev { text-transform: none; font-size: 0.7rem; overflow-wrap: anywhere; } - .feed-line .title { color: var(--af-text); } - .feed-line .who { color: var(--af-text-muted); opacity: 0.75; text-align: right; overflow-wrap: anywhere; } - .feed-tone { width: 6px; height: 6px; border-radius: 50%; align-self: center; } + .feed-tone { width: 6px; height: 6px; border-radius: 50%; align-self: center; flex: none; } .feed-tone-info { background: #22d3ee; } .feed-tone-warn { background: #ffb000; } .feed-tone-critical { background: var(--af-accent); box-shadow: 0 0 8px color-mix(in srgb, var(--af-accent) 60%, transparent); } - .feed-summary { color: var(--af-text-muted); } - .feed-summary .ok { color: #22d3ee; } - .feed-summary .bad { color: var(--af-accent); } + + .tree-panel { padding: 1.35rem 1.4rem 1.15rem; box-shadow: 0 30px 60px -20px rgb(0 0 0 / 0.6); max-width: 100%; overflow-x: auto; } + .file-tree, .file-tree ul { list-style: none; margin: 0; padding: 0; } + .file-tree { font-family: var(--af-font-mono); font-size: 0.86rem; } + .t-row { display: flex; align-items: stretch; flex-wrap: wrap; min-height: 1.9rem; } + .t-row.t-root { min-height: 1.7rem; } + .t-rail, .t-elbow { position: relative; width: 1.05rem; flex: none; } + .t-vline { + position: absolute; left: 50%; top: 0; width: 1px; background: var(--af-line); + transform: translateX(-50%) scaleY(1); transform-origin: top; + } + .t-rail .t-vline, .t-tee .t-vline { height: 100%; } + .t-corner .t-vline { height: 50%; } + .t-hline { + position: absolute; left: 50%; top: 50%; height: 1px; width: 0.6rem; background: var(--af-line); + transform: scaleX(1); transform-origin: left; + } + .node { + align-self: center; display: inline-flex; align-items: center; padding: 0.12rem 0.5rem; margin: 0.18rem 0; + border-radius: 4px; white-space: nowrap; color: var(--af-text-muted); + } + .node-dir { color: var(--af-text); font-weight: 600; } + .node-file { color: var(--af-text-muted); } + .node-violation { + color: var(--af-text); font-weight: 600; + background: color-mix(in srgb, var(--af-accent) 14%, transparent); + border: 1px solid color-mix(in srgb, var(--af-accent) 55%, transparent); + } + .node-violation.is-pulsing { box-shadow: 0 0 0 4px color-mix(in srgb, var(--af-accent) 25%, transparent); } + .violation-flag { + align-self: center; flex-basis: 100%; margin: 0.1rem 0 0.2rem calc(1.05rem + 0.5rem); + display: inline-flex; align-items: center; gap: 0.35rem; font-size: 0.72rem; color: var(--af-text-muted); + overflow-wrap: anywhere; + } + .tree-verdict { + margin-top: 0.9rem; padding-top: 0.85rem; border-top: 1px solid var(--af-line); + font-family: var(--af-font-mono); font-size: 0.8rem; color: var(--af-text-muted); + display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; + } + .tree-verdict strong { color: var(--af-accent); font-weight: 700; } @media (prefers-reduced-motion: reduce) { - .feed-line { animation: none; } .pulse-dot::after { animation: none; opacity: 0; } } @@ -200,8 +224,9 @@ @media (max-width: 480px) { .topbar .wrap { flex-wrap: wrap; row-gap: 0.6rem; padding-top: 0.75rem; padding-bottom: 0.75rem; min-height: 0; } .topbar { min-height: 0; } - .feed-line { grid-template-columns: auto minmax(0, 1fr); } - .feed-line .sev, .feed-line .who { display: none; } + .file-tree { font-size: 0.76rem; } + .t-rail, .t-elbow { width: 0.85rem; } + .violation-flag { margin-left: calc(0.85rem + 0.4rem); } } .table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; } @@ -242,13 +267,46 @@

Stop directory drift before it ships.

-
Live demo (simulated output, not a real run)
-
-
- - structlint validate -
-
+
Sample project, one .structlint.yaml run
+
+
    +
  • + myapp/ +
  • +
  • + + cmd/ +
  • +
  • + + + main.go +
  • +
  • + + internal/ +
  • +
  • + + + domain/ +
  • +
  • + + + db/ +
  • +
  • + + go.mod +
  • +
  • + + .env.local + disallowed_file_pattern +
  • +
+
1 violation found — disallowed_file_pattern on .env.local
@@ -400,43 +458,110 @@

One line to get started

gumshoe.

+ +