Skip to content

Commit 5fed982

Browse files
committed
[Docs Site] Add feedback prompt
1 parent c2efdd3 commit 5fed982

File tree

7 files changed

+218
-0
lines changed

7 files changed

+218
-0
lines changed

astro.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ export default defineConfig({
158158
PageTitle: "./src/components/overrides/PageTitle.astro",
159159
SocialIcons: "./src/components/overrides/SocialIcons.astro",
160160
SkipLink: "./src/components/overrides/SkipLink.astro",
161+
TableOfContents: "./src/components/overrides/TableOfContents.astro",
161162
},
162163
sidebar: await autogenSections(),
163164
customCss: [

package-lock.json

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
"@cloudflare/vitest-pool-workers": "^0.5.24",
3434
"@cloudflare/workers-types": "^4.20241022.0",
3535
"@codingheads/sticky-header": "^1.0.2",
36+
"@iconify-json/material-symbols": "^1.2.6",
3637
"@stoplight/json-schema-tree": "^4.0.0",
3738
"@types/dompurify": "^3.0.5",
3839
"@types/he": "^1.2.3",
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
---
2+
import { AstroIcon } from "~/components";
3+
---
4+
5+
<feedback-prompt class="not-content">
6+
<div id="feedback-thumbs">
7+
<h2>Was this helpful?</h2>
8+
<div class="not-content">
9+
<AstroIcon name="material-symbols:thumb-up-outline-rounded" title="Yes" />
10+
<AstroIcon
11+
name="material-symbols:thumb-down-outline-rounded"
12+
title="No"
13+
/>
14+
</div>
15+
</div>
16+
<div id="feedback-yes" class="hidden">
17+
<h2>What did you like?</h2>
18+
<form>
19+
<fieldset>
20+
<div>
21+
<input type="radio" id="accurate" name="reason" />
22+
<label for="accurate">Accurate</label>
23+
</div>
24+
<div>
25+
<input type="radio" id="easy-to-understand" name="reason" />
26+
<label for="easy-to-understand">Easy to understand</label>
27+
</div>
28+
<div>
29+
<input type="radio" id="solved-my-problem" name="reason" />
30+
<label for="solved-my-problem">Solved my problem</label>
31+
</div>
32+
<div>
33+
<input
34+
type="radio"
35+
id="helped-me-decide-to-use-the-product"
36+
name="reason"
37+
/>
38+
<label for="helped-me-decide-to-use-the-product"
39+
>Helped me decide to use the product</label
40+
>
41+
</div>
42+
<div>
43+
<input type="radio" id="other" name="reason" />
44+
<label for="other">Other</label>
45+
<input
46+
type="text"
47+
placeholder="Tell us more about your experience."
48+
id="other-answer"
49+
name="other-answer"
50+
/>
51+
</div>
52+
<input type="submit" value="Submit" />
53+
</fieldset>
54+
</form>
55+
</div>
56+
<div id="feedback-no" class="hidden">
57+
<h2>What went wrong?</h2>
58+
<form>
59+
<fieldset>
60+
<div>
61+
<input
62+
type="radio"
63+
id="hard-to-understand"
64+
value="hard-to-understand"
65+
name="reason"
66+
/>
67+
<label for="hard-to-understand">Hard to understand</label>
68+
</div>
69+
<div>
70+
<input type="radio" id="incorrect-information" name="reason" />
71+
<label for="incorrect-information">Incorrect information</label>
72+
</div>
73+
<div>
74+
<input type="radio" id="missing-the-information" name="reason" />
75+
<label for="missing-the-information">Missing the information</label>
76+
</div>
77+
<div>
78+
<input type="radio" id="other" name="reason" />
79+
<label for="other">Other</label>
80+
<input
81+
type="text"
82+
placeholder="Tell us more about your experience."
83+
id="other-answer"
84+
name="other-answer"
85+
/>
86+
</div>
87+
<input type="submit" value="Submit" />
88+
</fieldset>
89+
</form>
90+
</div>
91+
92+
<div id="feedback-thanks" class="hidden">
93+
<h2>Thank you for helping improve Cloudflare's documentation!</h2>
94+
</div>
95+
</feedback-prompt>
96+
97+
<style>
98+
fieldset {
99+
padding-top: 0;
100+
padding-left: 0;
101+
}
102+
103+
label {
104+
font-size: small;
105+
color: var(--sl-color-gray-3);
106+
}
107+
108+
input[type="submit"],
109+
input::placeholder {
110+
font-size: x-small;
111+
}
112+
113+
h2 {
114+
color: var(--sl-color-white);
115+
font-size: var(--sl-text-h5);
116+
font-weight: 600;
117+
line-height: var(--sl-line-height-headings);
118+
margin-bottom: 0.5rem;
119+
}
120+
121+
#other-answer {
122+
display: none;
123+
}
124+
125+
#other:checked ~ #other-answer {
126+
display: flex;
127+
}
128+
129+
[data-icon] {
130+
cursor: pointer;
131+
color: var(--sl-color-gray-3);
132+
font-size: 1.5rem;
133+
margin-right: 0.5rem;
134+
135+
&:hover {
136+
color: var(--sl-color-text-accent);
137+
border-color: var(--sl-color-text-accent);
138+
}
139+
}
140+
</style>
141+
142+
<script>
143+
class FeedbackPrompt extends HTMLElement {
144+
connectedCallback() {
145+
const icons = {
146+
'[data-icon="material-symbols:thumb-up-outline-rounded"]':
147+
"#feedback-yes",
148+
'[data-icon="material-symbols:thumb-down-outline-rounded"]':
149+
"#feedback-no",
150+
};
151+
152+
const thumbsDiv = this.querySelector("#feedback-thumbs");
153+
const thanksDiv = this.querySelector("#feedback-thanks");
154+
155+
if (!thumbsDiv || !thanksDiv) return;
156+
157+
for (const [button, questions] of Object.entries(icons)) {
158+
this.querySelector(button)?.addEventListener("click", () => {
159+
thumbsDiv.classList.add("hidden");
160+
161+
const questionsDiv = this.querySelector(questions);
162+
163+
if (!questionsDiv) return;
164+
165+
questionsDiv.classList.remove("hidden");
166+
167+
const form = questionsDiv.querySelector("form");
168+
169+
if (!form) return;
170+
171+
form.addEventListener("submit", async (e) => {
172+
e.preventDefault();
173+
174+
fetch("https://feedback.developers.cloudflare.com", {
175+
method: "POST",
176+
body: new FormData(e.target as HTMLFormElement),
177+
});
178+
179+
questionsDiv.classList.add("hidden");
180+
thanksDiv.classList.remove("hidden");
181+
});
182+
});
183+
}
184+
}
185+
}
186+
187+
customElements.define("feedback-prompt", FeedbackPrompt);
188+
</script>

src/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export { default as Example } from "./Example.astro";
1515
export { default as ExternalResources } from "./ExternalResources.astro";
1616
export { default as Feature } from "./Feature.astro";
1717
export { default as FeatureTable } from "./FeatureTable.astro";
18+
export { default as FeedbackPrompt } from "./FeedbackPrompt.astro";
1819
export { default as Flex } from "./Flex.astro";
1920
export { default as GitHubCode } from "./GitHubCode.astro";
2021
export { default as Glossary } from "./Glossary.astro";

src/components/overrides/MarkdownContent.astro

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
---
22
import type { Props } from "@astrojs/starlight/props";
33
import '@astrojs/starlight/style/markdown.css';
4+
45
import ImageZoom from "starlight-image-zoom/components/ImageZoom.astro";
6+
7+
import { FeedbackPrompt } from "~/components";
58
/*
69
MIT License
710
@@ -40,6 +43,9 @@ const { tableOfContents } = Astro.props.entry.data;
4043
<ImageZoom />
4144
<div class="sl-markdown-content">
4245
<slot />
46+
<div class="block !mt-[1.5em] md:hidden">
47+
<FeedbackPrompt />
48+
</div>
4349
</div>
4450
<style>
4551
/* Custom styles for heading anchor links. */
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
import type { Props } from "@astrojs/starlight/props";
3+
import Default from "@astrojs/starlight/components/TableOfContents.astro";
4+
5+
import { FeedbackPrompt } from "~/components";
6+
---
7+
8+
<Default {...Astro.props} />
9+
<br />
10+
<FeedbackPrompt />

0 commit comments

Comments
 (0)