Skip to content

Commit

Permalink
feat(article-footer): redesign footer + add feedback buttons (#10625)
Browse files Browse the repository at this point in the history
* refactor(article-footer): rename Metadata => ArticleFooter

* enhance(article-footer): apply new structure

* fix(article-footer): consolidate CSS

* refactor(article-footer): extract Contribute component

* feat(article-footer): add feedback buttons

* feat(article-footer): add background image

* fix(article-footer): avoid layout shift on vote

* refactor(document): move article-footer out of main-page-content

* chore(article-footer): replace pipe by bullet

* feat(article-footer): add feedback form on "No" vote

* refactor(article-footer): rename article-footer-{content-container => inner}

* chore(article-footer): crop background image

* chore(article-footer): move background-image to inner container

* chore(article-footer): remove label padding

* chore(article-footer): remove button margin

* fix(article-footer): restrict label style

* chore(article-footer): add consistent 0.5rem margin

* chore(article-footer): always show Contribute link

* fix(article-footer): adjust space between thanks and contribute

* feat(ui): redefine background-tertiary

* fix(article-footer): use SVG element + --background-tertiary

* chore(article-footer): use single heading

* chore(article-footer): remove periods from GitHub links

* chore(article-footer): reuse thumbs key to reuse queries
  • Loading branch information
caugner authored Mar 5, 2024
1 parent 4900d37 commit 40659a8
Show file tree
Hide file tree
Showing 14 changed files with 282 additions and 127 deletions.
1 change: 1 addition & 0 deletions client/src/assets/article-footer/article-footer.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 5 additions & 2 deletions client/src/document/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -254,10 +254,13 @@

@media screen and (min-width: $screen-sm) {
padding: 3rem;
// Reduce space to article footer.
padding-bottom: 0;
}

@media screen and (min-width: $screen-md) {
margin-bottom: 0.5rem;
// Reduce space to article footer.
margin-bottom: 0;
padding: 0;
}
}
Expand All @@ -276,7 +279,7 @@ table {
width: 100%;

th {
background: var(--background-tertiary);
background: var(--background-primary);
font-weight: var(--font-body-strong-weight);
line-height: 1.5;
text-align: left;
Expand Down
4 changes: 2 additions & 2 deletions client/src/document/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import { RenderSideBar } from "./organisms/sidebar";
import { RetiredLocaleNote } from "./molecules/retired-locale-note";
import { MainContentContainer } from "../ui/atoms/page-content";
import { Loading } from "../ui/atoms/loading";
import { Metadata } from "./organisms/metadata";
import { ArticleFooter } from "./organisms/article-footer";
import { PageNotFound } from "../page-not-found";

import "./index.scss";
Expand Down Expand Up @@ -265,8 +265,8 @@ export function Document(props /* TODO: define a TS interface for this */) {
</header>
<DocumentSurvey doc={doc} />
<RenderDocumentBody doc={doc} />
<Metadata doc={doc} locale={locale} />
</article>
<ArticleFooter doc={doc} locale={locale} />
</MainContentContainer>
{false && <PlayQueue standalone={true} />}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
}

th {
background: var(--background-tertiary);
background: var(--background-primary);
padding: 0.4rem;
vertical-align: bottom;
}
Expand Down
56 changes: 7 additions & 49 deletions client/src/document/on-github.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,59 +3,17 @@ import { Doc } from "../../../libs/types/document";
export function OnGitHubLink({ doc }: { doc: Doc }) {
return (
<div id="on-github" className="on-github">
<h3>Found a content problem with this page?</h3>
<ul>
<li>
<EditOnGitHubLink doc={doc}>Edit the page on GitHub</EditOnGitHubLink>
.
</li>
<li>
<NewIssueOnGitHubLink doc={doc}>
Report the content issue
</NewIssueOnGitHubLink>
.
</li>
<li>
<SourceOnGitHubLink doc={doc}>
View the source on GitHub
</SourceOnGitHubLink>
.
</li>
</ul>
Want to get more involved?{" "}
<a
href="https://github.com/mdn/content/blob/main/CONTRIBUTING.md"
title={`This will take you to our contribution guidelines on GitHub.`}
target="_blank"
rel="noopener noreferrer"
>
Learn how to contribute
</a>
.
<SourceOnGitHubLink doc={doc}>
View this page on GitHub
</SourceOnGitHubLink>
{" "}
<NewIssueOnGitHubLink doc={doc}>
Report a problem with this content
</NewIssueOnGitHubLink>
</div>
);
}

function EditOnGitHubLink({
doc,
children,
}: {
doc: Doc;
children: React.ReactNode;
}) {
const { github_url } = doc.source;
return (
<a
href={github_url.replace("/blob/", "/edit/")}
title={`This will take you to GitHub, where you'll need to sign in first.`}
target="_blank"
rel="noopener noreferrer"
>
{children}
</a>
);
}

const METADATA_TEMPLATE = `
<!-- Do not make changes below this line -->
<details>
Expand Down
105 changes: 105 additions & 0 deletions client/src/document/organisms/article-footer/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
@use "../../../ui/vars" as *;

.article-footer {
background-color: var(--background-secondary);
border: 1px solid var(--border-primary);
border-radius: var(--elem-radius);
box-shadow: var(--shadow-01);
margin: 0;
padding: 1rem;

@media screen and (max-width: $screen-md) {
margin: 3rem;
// Reduce space to article content.
margin-top: 0;
}

.article-footer-inner {
margin: 0 auto;
max-width: 1440px;
width: 100%;

.svg-container {
position: relative;

svg {
height: auto;
position: absolute;
right: 0;
top: 0;
width: 25%;
}
}

h2 {
margin-top: 0;
padding: 0;
}

.feedback {
border: none;
margin: 0;
margin-bottom: 0.25rem;
padding: 0;

> label {
display: block;
margin-bottom: 0.25rem;
}

.thank-you {
display: block;
margin-bottom: calc(2.75rem + 2px);
}

.button-container {
// Ensure both buttons take minimal width.
display: inline-flex;
gap: 0.75rem;
margin: 0.25rem 0;
}

button {
// Ensure both buttons have same size.
flex: 1;
min-width: 0;

&:not(:hover) {
--button-bg: var(--background-secondary);
--button-color: var(--text-primary);
}

&.yes {
--button-bg-hover: var(--text-primary-green);
}

&.no {
--button-bg-hover: var(--text-primary-red);
}
}

.button-wrap {
display: flex;
// Increase space between icon and button label.
gap: 0.5rem;
padding: 1rem;
}

.radio-container {
align-items: center;
display: flex;
gap: 0.25rem;
margin: 0.25rem 0;
}
}

.contribute {
margin-top: 0.25rem;
}

.last-modified-date {
margin-bottom: 0;
margin-top: 3rem;
}
}
}
154 changes: 154 additions & 0 deletions client/src/document/organisms/article-footer/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { useState } from "react";
import { Button } from "../../../ui/atoms/button";
import { OnGitHubLink } from "../../on-github";
import { ReactComponent as ArticleFooterSVG } from "../../../assets/article-footer/article-footer.svg";
import "./index.scss";
import { useGleanClick } from "../../../telemetry/glean-context";
import { ARTICLE_FOOTER, THUMBS } from "../../../telemetry/constants";

export function LastModified({ value, locale }) {
if (!value) {
return <span>Last modified date not known</span>;
}
const date = new Date(value);
// Justification for these is to match historically
const dateStringOptions: Intl.DateTimeFormatOptions = {
year: "numeric",
month: "short",
day: "numeric",
};
return (
<>
This page was last modified on{" "}
<time dateTime={value} suppressHydrationWarning>
{date.toLocaleString(locale, dateStringOptions)}
</time>
</>
);
}

export function Authors({ url }) {
return <a href={`${url}/contributors.txt`}>MDN contributors</a>;
}

enum ArticleFooterView {
Vote,
Feedback,
Thanks,
}

type FeedbackReason = "outdated" | "incomplete" | "code_examples" | "other";

const FEEDBACK_REASONS: Required<Record<FeedbackReason, string>> = {
outdated: "Content is out of date",
incomplete: "Missing information",
code_examples: "Code examples not working as expected",
other: "Other",
};

export function ArticleFooter({ doc, locale }) {
const [view, setView] = useState<ArticleFooterView>(ArticleFooterView.Vote);
const [reason, setReason] = useState<FeedbackReason>();

const gleanClick = useGleanClick();

function handleVote(value: boolean) {
setView(value ? ArticleFooterView.Thanks : ArticleFooterView.Feedback);
// Reusing Thumbs' key to be able to reuse queries.
gleanClick(`${THUMBS}: ${ARTICLE_FOOTER} -> ${Number(value)}`);
}

function handleFeedback() {
setView(ArticleFooterView.Thanks);
gleanClick(`${ARTICLE_FOOTER}: feedback -> ${reason}`);
}

return (
<aside className="article-footer">
<div className="article-footer-inner">
<div className="svg-container">
<ArticleFooterSVG role="none" />
</div>
<h2>Help improve MDN</h2>

<fieldset className="feedback">
{view === ArticleFooterView.Vote ? (
<>
<label>Was this page helpful to you?</label>
<div className="button-container">
<Button
icon="thumbs-up"
extraClasses="yes"
onClickHandler={() => handleVote(true)}
>
Yes
</Button>
<Button
icon="thumbs-down"
extraClasses="no"
onClickHandler={() => handleVote(false)}
>
No
</Button>
</div>
</>
) : view === ArticleFooterView.Feedback ? (
<>
<label>Why was this page not helpful to you?</label>
{Object.entries(FEEDBACK_REASONS).map(([key, label]) => (
<div className="radio-container" key={key}>
<input
type="radio"
id={`reason_${key}`}
name="reason"
value={key}
checked={reason === key}
onChange={(event) =>
setReason(event.target.value as FeedbackReason)
}
/>
<label htmlFor={`reason_${key}`}>{label}</label>
</div>
))}
<div className="button-container">
<Button
type="primary"
isDisabled={!reason}
onClickHandler={() => handleFeedback()}
>
Submit
</Button>
</div>
</>
) : (
<span className="thank-you">Thank you for your feedback! ❤️</span>
)}
</fieldset>

<Contribute />
<p className="last-modified-date">
<LastModified value={doc.modified} locale={locale} /> by{" "}
<Authors url={doc.mdn_url} />.
</p>
{doc.isActive && <OnGitHubLink doc={doc} />}
</div>
</aside>
);
}

function Contribute() {
return (
<>
<a
className="contribute"
href="https://github.com/mdn/content/blob/main/CONTRIBUTING.md"
title={`This will take you to our contribution guidelines on GitHub.`}
target="_blank"
rel="noopener noreferrer"
>
Learn how to contribute
</a>
.
</>
);
}
Loading

0 comments on commit 40659a8

Please sign in to comment.