Skip to content

Commit ee50f30

Browse files
committed
feat(report): redesign evidence workbench and playground
1 parent a92db40 commit ee50f30

15 files changed

Lines changed: 678 additions & 268 deletions

File tree

assets/report-app.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

assets/report-app.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

assets/report-preview.png

12.1 KB
Loading

crates/reforge-output/assets/report-app.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/reforge-output/assets/report-app.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

playground/app.js

Lines changed: 150 additions & 32 deletions
Large diffs are not rendered by default.

playground/index.html

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,40 @@
33
<head>
44
<meta charset="utf-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1">
6-
<meta name="description" content="Try Reforge in a browser with deliberately constructed, repository-owned examples.">
6+
<meta name="description" content="Explore real Reforge evidence with repository-owned examples.">
77
<title>Reforge Playground</title>
88
<link rel="stylesheet" href="styles.css">
99
</head>
1010
<body>
1111
<header class="hero">
12-
<nav><a href="../">Reforge docs</a><label><span data-i18n="language">Language</span><select id="locale" aria-label="Language"><option value="en">EN</option><option value="zh-CN">中文</option></select></label></nav>
13-
<p class="eyebrow">Reforge Playground</p>
14-
<h1 data-i18n="headline">Inspect the evidence before installing</h1>
15-
<p data-i18n="intro">Three deliberately constructed, repository-owned examples show one Reforge rule at a time. Analysis runs during the Pages build; no code is uploaded.</p>
12+
<nav><a class="wordmark" href="../"><img src="../assets/reforge-logo.png" alt=""><span>REFORGE</span></a><div><a href="../" data-i18n="docs">Documentation</a><label><span data-i18n="language">Language</span><select id="locale" aria-label="Language"><option value="en">EN</option><option value="zh-CN">中文</option></select></label></div></nav>
13+
<div class="hero-copy"><p class="eyebrow">Reforge Playground</p><h1 data-i18n="headline">Read the evidence.<br>Shape the code.</h1><p data-i18n="intro">Explore three focused findings generated from real source. Nothing runs in your browser and no code leaves your machine.</p></div>
14+
<div class="hero-glow" aria-hidden="true"></div>
1615
</header>
1716
<main>
18-
<section aria-labelledby="scenarios-heading">
19-
<h2 id="scenarios-heading" data-i18n="scenarios">Choose a scenario</h2>
20-
<div id="scenario-cards" class="scenario-cards"></div>
21-
</section>
22-
<article id="scenario-detail" class="detail" aria-live="polite">
23-
<div class="detail-heading"><div><p id="scenario-rule" class="eyebrow"></p><h2 id="scenario-title"></h2><p id="scenario-summary"></p></div><a id="report-link" class="primary" href="#" data-i18n="openReport">Open interactive report</a></div>
24-
<div class="review-grid">
25-
<section><h3 data-i18n="reviewQuestion">Review question</h3><p id="scenario-question"></p></section>
26-
<section><h3 data-i18n="reasonableException">Reasonable exception</h3><p id="scenario-exception"></p></section>
27-
</div>
28-
<section><h3 data-i18n="source">Complete source</h3><div id="source-files"></div></section>
29-
<section><h3 data-i18n="configuration">Configuration</h3><pre><code id="scenario-config"></code></pre></section>
30-
<section><h3 data-i18n="reproduce">Reproduce locally</h3><pre><code id="scenario-command"></code></pre></section>
17+
<section class="scenario-section" aria-labelledby="scenarios-heading"><div class="section-heading"><p class="eyebrow" data-i18n="stepOne">01 / Choose evidence</p><h2 id="scenarios-heading" data-i18n="scenarios">Choose a scenario</h2></div><div id="scenario-cards" class="scenario-cards"></div></section>
18+
<article id="scenario-detail" class="workbench" aria-live="polite">
19+
<section class="code-pane">
20+
<div class="pane-heading"><div><p class="eyebrow" data-i18n="workspace">02 / Inspect source</p><h2 id="scenario-title"></h2></div><span id="scenario-language" class="language-chip"></span></div>
21+
<div id="content-tabs" class="tabs" role="tablist" aria-label="Workbench content"><button role="tab" aria-selected="true" data-tab="source" data-i18n="source">Source</button><button role="tab" aria-selected="false" data-tab="config" data-i18n="configuration">Config</button><button role="tab" aria-selected="false" data-tab="command" data-i18n="reproduce">Command</button></div>
22+
<section id="source-panel" class="tab-panel" role="tabpanel"><div id="file-tabs" class="file-tabs" role="tablist" aria-label="Source files"></div><div id="source-files" class="source-files"></div></section>
23+
<section id="config-panel" class="tab-panel" role="tabpanel" hidden><pre><code id="scenario-config"></code></pre></section>
24+
<section id="command-panel" class="tab-panel" role="tabpanel" hidden><pre><code id="scenario-command"></code></pre><p class="command-note" data-i18n="commandNote">Run from the Reforge repository after building the CLI.</p></section>
25+
</section>
26+
<aside class="result-pane">
27+
<p class="eyebrow" data-i18n="stepThree">03 / Review finding</p>
28+
<div id="result-loading" class="result-state" data-i18n="loadingReport">Loading generated evidence…</div>
29+
<div id="result-error" class="result-state error-state" hidden></div>
30+
<div id="result-content" hidden>
31+
<div class="result-meta"><span id="issue-kind"></span><span id="issue-analysis"></span></div><p id="scenario-rule" class="rule"></p><h2 id="issue-title"></h2><p id="issue-guidance" class="guidance"></p>
32+
<section><h3 data-i18n="evidence">Evidence</h3><p id="evidence-message"></p><div id="evidence-locations" class="evidence-locations"></div><dl id="measurements" class="measurements"></dl></section>
33+
<section class="review-question"><h3 data-i18n="reviewQuestion">Review question</h3><p id="scenario-question"></p></section>
34+
</div>
35+
<a id="report-link" class="report-link" href="#"><span data-i18n="openReport">Open full report</span><span aria-hidden="true"></span></a>
36+
</aside>
3137
</article>
3238
</main>
33-
<footer data-i18n="footer">These examples are intentionally small and do not evaluate any third-party project.</footer>
39+
<footer><span class="brand-mark" aria-hidden="true"></span><span data-i18n="footer">Small, deliberate examples. Real Reforge output.</span></footer>
3440
<script type="module" src="app.js"></script>
3541
</body>
3642
</html>

playground/styles.css

Lines changed: 115 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
:root {
2-
font-family: Inter, ui-sans-serif, system-ui, sans-serif;
3-
color: #17333a;
4-
background: #eef3f1;
2+
--night: #071920;
3+
--night-2: #0d2932;
4+
--paper: #fffdf8;
5+
--canvas: #f1f0e9;
6+
--ink: #142b33;
7+
--muted: #61767b;
8+
--line: #d7ddd8;
9+
--orange: #f16b32;
10+
--cyan: #3dc8c7;
11+
font-family: Inter, ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans CJK SC", "Microsoft YaHei", sans-serif;
12+
color: var(--ink);
13+
background: var(--canvas);
514
font-synthesis: none;
615
}
716

@@ -10,55 +19,113 @@ html, body { max-width: 100%; overflow-x: hidden; }
1019
body { margin: 0; }
1120
button, select { font: inherit; }
1221
a { color: inherit; }
22+
:focus-visible { outline: 3px solid rgb(61 200 199 / 60%); outline-offset: 3px; }
1323

14-
.hero {
15-
padding: 24px max(24px, calc((100% - 1120px) / 2));
16-
background: #143e47;
17-
color: #f7fbf9;
18-
}
24+
.hero { position: relative; min-height: 490px; overflow: hidden; padding: 22px max(24px, calc((100% - 1260px) / 2)); background: var(--night); color: #f8f8f2; }
25+
.hero::before { position: absolute; inset: 0; background-image: linear-gradient(rgb(80 158 164 / 8%) 1px, transparent 1px), linear-gradient(90deg, rgb(80 158 164 / 8%) 1px, transparent 1px); background-size: 44px 44px; mask-image: linear-gradient(to right, black, transparent 75%); content: ""; }
26+
.hero nav { position: relative; z-index: 2; display: flex; justify-content: space-between; align-items: center; }
27+
.wordmark { display: flex; align-items: center; gap: 10px; font-size: 13px; font-weight: 800; letter-spacing: .2em; text-decoration: none; }
28+
.wordmark img { width: 34px; height: 34px; object-fit: contain; }
29+
.hero nav > div { display: flex; align-items: center; gap: 24px; }
30+
.hero nav > div > a { color: #adc0c3; font-size: 12px; text-decoration: none; }
31+
.hero label { display: flex; align-items: center; gap: 8px; color: #adc0c3; font-size: 11px; }
32+
select { padding: 6px 10px; border: 1px solid #4a6269; border-radius: 999px; background: #14323b; color: #fff; }
33+
.hero-copy { position: relative; z-index: 1; max-width: 900px; padding: 90px 0 45px; }
34+
.eyebrow { margin: 0; color: #278d91; font-size: 10px; font-weight: 800; letter-spacing: .17em; text-transform: uppercase; }
35+
.hero .eyebrow { color: var(--cyan); }
36+
.hero h1 { margin: 16px 0; font-size: clamp(50px, 7vw, 86px); line-height: .94; letter-spacing: -.055em; white-space: pre-line; }
37+
.hero-copy > p:last-child { max-width: 660px; margin: 24px 0 0; color: #b5c8ca; font-size: 17px; line-height: 1.65; }
38+
.hero-glow { position: absolute; right: 2%; bottom: -220px; width: 560px; height: 500px; border-radius: 50%; background: radial-gradient(circle, rgb(241 107 50 / 55%) 0, rgb(241 107 50 / 15%) 28%, transparent 67%); filter: blur(18px); }
1939

20-
nav, .detail-heading {
21-
display: flex;
22-
justify-content: space-between;
23-
align-items: flex-start;
24-
gap: 20px;
25-
}
40+
main { width: min(1308px, 100%); margin: auto; padding: 52px 24px 70px; }
41+
.section-heading { display: flex; align-items: baseline; gap: 22px; margin-bottom: 20px; }
42+
.section-heading h2 { margin: 0; font-size: 26px; letter-spacing: -.025em; }
43+
.scenario-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
44+
.scenario-card { position: relative; min-width: 0; min-height: 165px; display: grid; align-content: start; gap: 7px; padding: 20px; border: 1px solid #cbd3cf; border-radius: 14px; background: #f9f8f3; color: var(--ink); text-align: left; cursor: pointer; transition: border-color .2s, transform .2s, background .2s; }
45+
.scenario-card:hover { transform: translateY(-2px); border-color: #91aaa9; }
46+
.scenario-card[aria-pressed="true"] { border-color: var(--orange); background: var(--paper); box-shadow: 0 12px 35px rgb(19 43 51 / 9%); }
47+
.scenario-number { position: absolute; top: 16px; right: 17px; color: #bec7c4; font: 700 28px/1 "SFMono-Regular", Consolas, monospace; }
48+
.scenario-card strong { max-width: 85%; margin-top: 7px; font-size: 17px; line-height: 1.3; }
49+
.scenario-card > span:nth-last-of-type(1) { max-width: 85%; color: var(--muted); font-size: 12px; line-height: 1.4; }
50+
.scenario-card i { position: absolute; right: 18px; bottom: 15px; color: var(--orange); font-style: normal; font-size: 18px; opacity: 0; }
51+
.scenario-card[aria-pressed="true"] i { opacity: 1; }
2652

27-
nav label { display: flex; align-items: center; gap: 8px; }
28-
select { border: 1px solid #8fb5af; border-radius: 999px; padding: 7px 12px; background: #fff; color: #17333a; }
29-
.hero h1 { max-width: 800px; margin: 54px 0 12px; font: 700 clamp(38px, 6vw, 68px)/1.02 Georgia, serif; }
30-
.hero > p:last-child { max-width: 760px; color: #cce0dd; font-size: 18px; line-height: 1.6; }
31-
.eyebrow { color: #5da99d; font-size: 12px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; }
32-
.hero .eyebrow { color: #8fd0c2; }
53+
.workbench { min-width: 0; display: grid; grid-template-columns: minmax(0, 1.45fr) minmax(335px, .75fr); margin-top: 24px; border: 1px solid #263f47; border-radius: 18px; overflow: hidden; background: var(--night); box-shadow: 0 24px 70px rgb(15 37 44 / 18%); }
54+
.code-pane { min-width: 0; padding: 27px; color: #eaf2ef; }
55+
.pane-heading { display: flex; justify-content: space-between; align-items: start; gap: 20px; min-height: 75px; }
56+
.pane-heading h2 { margin: 8px 0 0; font-size: clamp(20px, 2.4vw, 30px); letter-spacing: -.025em; }
57+
.language-chip { flex: none; padding: 5px 9px; border: 1px solid #34515a; border-radius: 999px; color: #9ec1c3; font: 10px "SFMono-Regular", Consolas, monospace; }
58+
.tabs { display: flex; gap: 3px; padding: 4px; border-radius: 9px; background: #0d252d; }
59+
.tabs button { flex: 0 1 125px; padding: 8px 13px; border: 0; border-radius: 6px; background: transparent; color: #8eaaaf; font-size: 11px; font-weight: 700; cursor: pointer; }
60+
.tabs button[aria-selected="true"] { background: #1c3942; color: #fff; box-shadow: inset 0 -2px var(--cyan); }
61+
.tab-panel { min-width: 0; padding-top: 13px; }
62+
.file-tabs { display: flex; overflow-x: auto; gap: 2px; padding: 0 8px; border-bottom: 1px solid #27424a; }
63+
.file-tabs button { position: relative; flex: none; padding: 9px 12px; border: 0; border-bottom: 2px solid transparent; background: transparent; color: #7f9ca1; font: 10px "SFMono-Regular", Consolas, monospace; cursor: pointer; }
64+
.file-tabs button[aria-selected="true"] { border-bottom-color: var(--orange); color: #eff6f4; }
65+
.file-tabs button.has-evidence::after { position: absolute; top: 7px; right: 4px; width: 5px; height: 5px; border-radius: 50%; background: var(--orange); content: ""; }
66+
.source-files { min-height: 485px; max-height: 620px; overflow: auto; border-radius: 0 0 10px 10px; background: #06151b; }
67+
pre { max-width: 100%; margin: 0; overflow: auto; padding: 17px 0; background: #06151b; color: #dce8e6; font: 11px/1.65 "SFMono-Regular", Consolas, "Liberation Mono", monospace; tab-size: 2; }
68+
.source-file pre { overflow: visible; }
69+
.code-line { min-width: max-content; display: flex; padding-right: 18px; border-left: 2px solid transparent; }
70+
.line-number { width: 48px; flex: none; padding-right: 13px; color: #496169; text-align: right; user-select: none; }
71+
.line-code { white-space: pre; }
72+
.code-line.evidence-line { border-left-color: var(--orange); background: linear-gradient(90deg, rgb(241 107 50 / 19%), rgb(241 107 50 / 4%)); }
73+
.code-line.evidence-line .line-number { color: #f59a74; font-weight: 700; }
74+
.file-evidence-label { padding: 6px 13px; background: rgb(241 107 50 / 16%); color: #f1a080; font-size: 9px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; }
75+
#config-panel pre, #command-panel pre { min-height: 260px; padding: 20px; border-radius: 9px; white-space: pre-wrap; }
76+
.command-note { color: #718f95; font-size: 10px; }
3377

34-
main { max-width: 1120px; margin: auto; padding: 42px 24px; }
35-
h2 { font: 700 30px/1.2 Georgia, serif; }
36-
h3 { margin-bottom: 9px; }
37-
.scenario-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
38-
.scenario-card { min-width: 0; border: 1px solid #cbdad6; border-radius: 18px; padding: 20px; background: #fff; color: #17333a; text-align: left; cursor: pointer; }
39-
.scenario-card:hover, .scenario-card[aria-pressed="true"] { border-color: #c05f36; box-shadow: 0 8px 30px #17333a18; }
40-
.scenario-card[aria-pressed="true"] { border-width: 2px; }
41-
.scenario-card strong { display: block; margin: 8px 0; font-size: 20px; }
42-
.scenario-card span:last-child { color: #627a7e; }
43-
.detail { margin-top: 24px; padding: 28px; border: 1px solid #cbdad6; border-radius: 22px; background: #fff; box-shadow: 0 12px 40px #17333a10; }
44-
.detail-heading h2 { margin: 7px 0; }
45-
.detail-heading p { max-width: 700px; }
46-
.primary { flex: none; border-radius: 999px; padding: 12px 18px; background: #c05f36; color: #fff; font-weight: 700; text-decoration: none; }
47-
.review-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin: 24px 0; }
48-
.review-grid section { border-radius: 14px; padding: 4px 18px; background: #eef5f3; }
49-
.source-file { margin: 14px 0; }
50-
.source-file h4 { margin: 0; padding: 9px 13px; border-radius: 10px 10px 0 0; background: #dbe7e4; }
51-
pre { max-width: 100%; overflow: auto; margin-top: 0; padding: 16px; border-radius: 0 0 10px 10px; background: #102f36; color: #e8f4f1; line-height: 1.5; }
52-
section > pre { border-radius: 10px; }
53-
code { font-family: "SFMono-Regular", Consolas, monospace; }
54-
footer { padding: 28px 24px; color: #5b7377; text-align: center; }
78+
.result-pane { min-width: 0; display: flex; flex-direction: column; padding: 30px; border-left: 1px solid #d8ddd7; background: var(--paper); color: var(--ink); }
79+
.result-pane > .eyebrow { margin-bottom: 24px; }
80+
.result-state { padding: 24px 0; color: var(--muted); font-size: 12px; }
81+
.error-state { padding: 14px; border: 1px solid #efc5b3; border-radius: 9px; background: #fff0e8; color: #844022; line-height: 1.5; }
82+
.result-meta { display: flex; gap: 7px; }
83+
.result-meta span { padding: 4px 8px; border-radius: 999px; background: #e7efed; color: #4a6369; font-size: 9px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }
84+
.result-meta .policy { background: #ffe0d0; color: #8d3a15; }
85+
.result-meta .advisory { background: #dff3f1; color: #176367; }
86+
.rule { margin: 18px 0 7px; color: #258186; font: 10px/1.4 "SFMono-Regular", Consolas, monospace; overflow-wrap: anywhere; }
87+
.result-pane h2 { margin: 0; font-size: clamp(24px, 2.7vw, 36px); line-height: 1.1; letter-spacing: -.035em; }
88+
.guidance { margin: 16px 0 25px; color: #435e64; font-size: 13px; line-height: 1.58; }
89+
.result-pane section { padding: 19px 0; border-top: 1px solid var(--line); }
90+
.result-pane h3 { margin: 0 0 8px; color: #6d8083; font-size: 9px; letter-spacing: .13em; text-transform: uppercase; }
91+
.result-pane section > p { margin: 0; font-size: 12px; line-height: 1.5; }
92+
.evidence-locations { display: grid; gap: 5px; margin-top: 13px; }
93+
.evidence-locations button { display: grid; justify-items: start; padding: 8px 10px; border: 1px solid #c8dcda; border-radius: 6px; background: #eff7f5; color: #285a61; font: 10px/1.4 "SFMono-Regular", Consolas, monospace; text-align: left; overflow-wrap: anywhere; cursor: pointer; }
94+
.evidence-locations button span { color: #708689; }
95+
.measurements { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin: 13px 0 0; }
96+
.measurements div { padding: 9px; border: 1px solid var(--line); border-radius: 6px; }
97+
.measurements dt { color: var(--muted); font-size: 9px; overflow-wrap: anywhere; }
98+
.measurements dd { margin: 3px 0 0; font-size: 10px; }
99+
.measurements dd strong { font-size: 16px; }
100+
.measurements small { display: block; margin-top: 2px; color: #8a9698; }
101+
.review-question { border-left: 3px solid var(--orange); padding-left: 14px !important; }
102+
.report-link { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-top: auto; padding: 13px 0 5px; border-top: 1px solid var(--line); color: #983d18; font-size: 12px; font-weight: 800; text-decoration: none; }
103+
.report-link span:last-child { font-size: 18px; }
104+
footer { display: flex; justify-content: center; align-items: center; gap: 10px; padding: 28px; background: #e4e5df; color: #66787c; font-size: 11px; }
105+
.brand-mark { width: 11px; height: 14px; border: 1px solid var(--orange); border-top-width: 4px; border-radius: 2px 2px 5px 5px; transform: skew(-7deg); box-shadow: inset 0 -3px 0 var(--cyan); }
106+
[hidden] { display: none !important; }
107+
108+
@media (max-width: 820px) {
109+
.workbench { grid-template-columns: minmax(0, 1.2fr) minmax(290px, .8fr); }
110+
.code-pane, .result-pane { padding: 21px; }
111+
}
55112

56113
@media (max-width: 760px) {
57-
.hero { padding: 18px; }
58-
.hero h1 { margin-top: 42px; }
59-
main { padding: 28px 12px; }
60-
.scenario-cards, .review-grid { grid-template-columns: 1fr; }
61-
.detail { padding: 18px; }
62-
.detail-heading { display: block; }
63-
.primary { display: inline-block; margin-top: 8px; }
114+
.hero { min-height: 410px; padding: 17px; }
115+
.hero nav > div > a { display: none; }
116+
.hero label > span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
117+
.hero-copy { padding: 70px 0 32px; }
118+
.hero h1 { font-size: clamp(44px, 14vw, 62px); line-height: .98; }
119+
.hero-copy > p:last-child { font-size: 15px; }
120+
main { padding: 35px 12px 45px; }
121+
.section-heading { display: block; }
122+
.section-heading h2 { margin-top: 7px; }
123+
.scenario-cards { display: flex; margin-right: -12px; padding-right: 12px; overflow-x: auto; scroll-snap-type: x mandatory; }
124+
.scenario-card { min-width: min(82vw, 310px); min-height: 145px; scroll-snap-align: start; }
125+
.workbench { display: flex; flex-direction: column; border-radius: 13px; }
126+
.result-pane { order: 1; min-height: 520px; border-left: 0; border-bottom: 1px solid #29434b; }
127+
.code-pane { order: 2; padding: 19px 12px; }
128+
.pane-heading { padding-inline: 5px; }
129+
.source-files { min-height: 420px; max-height: 560px; }
130+
.tabs button { flex: 1; }
64131
}

0 commit comments

Comments
 (0)