Refactoring help component (and fragmenting it too) (#10895)
* Refactoring Help component * Fixing typo * Adding missing prop types * Removing setCommonProps * Moving show to parent component * Renaming Format component * Converting help component to functional component * Removing html from state * Fixing modal toggle and eslint errors * Adding arria hidden * Using optional chaining * Fixing variable names * Renaming state variable * Adding jsdoc Co-authored-by: Nick Taylor <nick@dev.to>
This commit is contained in:
parent
e8df3b0915
commit
41cc771839
6 changed files with 313 additions and 311 deletions
|
|
@ -1,311 +0,0 @@
|
|||
import { h, Component } from 'preact';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Modal } from '@crayons';
|
||||
|
||||
export class Help extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
liquidHelpHTML:
|
||||
document.getElementById('editor-liquid-help') &&
|
||||
document.getElementById('editor-liquid-help').innerHTML,
|
||||
markdownHelpHTML:
|
||||
document.getElementById('editor-markdown-help') &&
|
||||
document.getElementById('editor-markdown-help').innerHTML,
|
||||
frontmatterHelpHTML:
|
||||
document.getElementById('editor-frontmatter-help') &&
|
||||
document.getElementById('editor-frontmatter-help').innerHTML,
|
||||
liquidShowing: false,
|
||||
markdownShowing: false,
|
||||
frontmatterShowing: false,
|
||||
};
|
||||
}
|
||||
|
||||
showModal = (sectionShowing, isOpen) => () => {
|
||||
this.setState({ [sectionShowing]: isOpen });
|
||||
};
|
||||
|
||||
renderArticleFormTitleHelp = () => {
|
||||
return (
|
||||
<div
|
||||
data-testid="title-help"
|
||||
className="crayons-article-form__help crayons-article-form__help--title"
|
||||
>
|
||||
<h4 className="mb-2 fs-l">Writing a Great Post Title</h4>
|
||||
<ul className="list-disc pl-6 color-base-70">
|
||||
<li>
|
||||
Think of your post title as a super short (but compelling!)
|
||||
description — like an overview of the actual post in one short
|
||||
sentence.
|
||||
</li>
|
||||
<li>
|
||||
Use keywords where appropriate to help ensure people can find your
|
||||
post by search.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
renderTagInputHelp = () => {
|
||||
return (
|
||||
<div
|
||||
data-testid="basic-tag-input-help"
|
||||
className="crayons-article-form__help crayons-article-form__help--tags"
|
||||
>
|
||||
<h4 className="mb-2 fs-l">Tagging Guidelines</h4>
|
||||
<ul className="list-disc pl-6 color-base-70">
|
||||
<li>Tags help people find your post.</li>
|
||||
<li>
|
||||
Think of tags as the topics or categories that best describe your
|
||||
post.
|
||||
</li>
|
||||
<li>
|
||||
Add up to four comma-separated tags per post. Combine tags to reach
|
||||
the appropriate subcommunities.
|
||||
</li>
|
||||
<li>Use existing tags whenever possible.</li>
|
||||
<li>
|
||||
Some tags, such as “help” or “healthydebate”, have special posting
|
||||
guidelines.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
renderBasicEditorHelp = () => {
|
||||
return (
|
||||
<div
|
||||
data-testid="basic-editor-help"
|
||||
className="crayons-card crayons-card--secondary p-4 mb-6"
|
||||
>
|
||||
You are currently using the basic markdown editor that uses{' '}
|
||||
<a
|
||||
href="#frontmatter"
|
||||
onClick={this.showModal('frontmatterShowing', true)}
|
||||
>
|
||||
Jekyll front matter
|
||||
</a>
|
||||
. You can also use the <em>rich+markdown</em> editor you can find in{' '}
|
||||
<a href="/settings/customization">
|
||||
UX settings
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
className="crayons-icon"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
role="img"
|
||||
aria-labelledby="c038a36b2512ed25db907e179ab45cfc"
|
||||
>
|
||||
<title id="c038a36b2512ed25db907e179ab45cfc">
|
||||
Open UX settings
|
||||
</title>
|
||||
<path d="M10.667 8v1.333H7.333v7.334h7.334v-3.334H16v4a.666.666 0 01-.667.667H6.667A.666.666 0 016 17.333V8.667A.667.667 0 016.667 8h4zM18 6v5.333h-1.333V8.275l-5.196 5.196-.942-.942 5.194-5.196h-3.056V6H18z" />
|
||||
</svg>
|
||||
</a>
|
||||
.
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
renderFormatHelp = () => {
|
||||
return (
|
||||
<div
|
||||
data-testid="format-help"
|
||||
className="crayons-article-form__help crayons-article-form__help--body"
|
||||
>
|
||||
<h4 className="mb-2 fs-l">Editor Basics</h4>
|
||||
<ul className="list-disc pl-6 color-base-70">
|
||||
<li>
|
||||
Use{' '}
|
||||
<a
|
||||
href="#markdown"
|
||||
onClick={this.showModal('markdownShowing', true)}
|
||||
>
|
||||
Markdown
|
||||
</a>{' '}
|
||||
to write and format posts.
|
||||
<details className="fs-s my-1">
|
||||
<summary class="cursor-pointer">Commonly used syntax</summary>
|
||||
<table className="crayons-card crayons-card--secondary crayons-table crayons-table--compact w-100 mt-2 mb-4 lh-tight">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="ff-monospace">
|
||||
# Header
|
||||
<br />
|
||||
...
|
||||
<br />
|
||||
###### Header
|
||||
</td>
|
||||
<td>
|
||||
H1 Header
|
||||
<br />
|
||||
...
|
||||
<br />
|
||||
H6 Header
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="ff-monospace">*italics* or _italics_</td>
|
||||
<td>
|
||||
<em>italics</em>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="ff-monospace">**bold**</td>
|
||||
<td>
|
||||
<strong>bold</strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="ff-monospace">[Link](https://...)</td>
|
||||
<td>
|
||||
<a href="https://forem.com">Link</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="ff-monospace">
|
||||
* item 1<br />* item 2
|
||||
</td>
|
||||
<td>
|
||||
<ul class="list-disc ml-5">
|
||||
<li>item 1</li>
|
||||
<li>item 2</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="ff-monospace">
|
||||
1. item 1<br />
|
||||
2. item 2
|
||||
</td>
|
||||
<td>
|
||||
<ul class="list-decimal ml-5">
|
||||
<li>item 1</li>
|
||||
<li>item 2</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="ff-monospace">> quoted text</td>
|
||||
<td>
|
||||
<span className="pl-2 border-0 border-solid border-l-4 border-base-50">
|
||||
quoted text
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="ff-monospace">`inline code`</td>
|
||||
<td>
|
||||
<code>inline code</code>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="ff-monospace">
|
||||
<span class="fs-xs">```</span>
|
||||
<br />
|
||||
code block
|
||||
<br />
|
||||
<span class="fs-xs">```</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="highlight p-2 overflow-hidden">
|
||||
<code>code block</code>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</details>
|
||||
</li>
|
||||
<li>
|
||||
You can use{' '}
|
||||
<a href="#liquid" onClick={this.showModal('liquidShowing', true)}>
|
||||
Liquid tags
|
||||
</a>{' '}
|
||||
to add rich content such as Tweets, YouTube videos, etc.
|
||||
</li>
|
||||
<li>
|
||||
In addition to images for the post's content, you can also drag and
|
||||
drop a cover image
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
renderModal = (onClose, title, helpHtml) => {
|
||||
return (
|
||||
<Modal onClose={onClose} title={title}>
|
||||
<div
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{ __html: helpHtml }}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { previewShowing, helpFor, helpPosition, version } = this.props;
|
||||
|
||||
const {
|
||||
liquidHelpHTML,
|
||||
markdownHelpHTML,
|
||||
frontmatterHelpHTML,
|
||||
liquidShowing,
|
||||
markdownShowing,
|
||||
frontmatterShowing,
|
||||
} = this.state;
|
||||
|
||||
return (
|
||||
<div className="crayons-article-form__aside">
|
||||
{!previewShowing && (
|
||||
<div
|
||||
data-testid="article-form__help-section"
|
||||
className="sticky"
|
||||
style={{ top: version === 'v1' ? '56px' : helpPosition }}
|
||||
>
|
||||
{helpFor === 'article-form-title' &&
|
||||
this.renderArticleFormTitleHelp()}
|
||||
{helpFor === 'tag-input' && this.renderTagInputHelp()}
|
||||
{version === 'v1' && this.renderBasicEditorHelp()}
|
||||
{(helpFor === 'article_body_markdown' || version === 'v1') &&
|
||||
this.renderFormatHelp()}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{liquidShowing &&
|
||||
this.renderModal(
|
||||
this.showModal('liquidShowing', false),
|
||||
'🌊 Liquid Tags',
|
||||
liquidHelpHTML,
|
||||
)}
|
||||
|
||||
{markdownShowing &&
|
||||
this.renderModal(
|
||||
this.showModal('markdownShowing', false),
|
||||
'✍️ Markdown',
|
||||
markdownHelpHTML,
|
||||
)}
|
||||
|
||||
{frontmatterShowing &&
|
||||
this.renderModal(
|
||||
this.showModal('frontmatterShowing', false),
|
||||
'Jekyll Front Matter',
|
||||
frontmatterHelpHTML,
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Help.propTypes = {
|
||||
previewShowing: PropTypes.bool.isRequired,
|
||||
helpFor: PropTypes.string.isRequired,
|
||||
helpPosition: PropTypes.string.isRequired,
|
||||
version: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
Help.displayName = 'Help';
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
import { h } from 'preact';
|
||||
|
||||
export const ArticleFormTitle = () => (
|
||||
<div
|
||||
data-testid="title-help"
|
||||
className="crayons-article-form__help crayons-article-form__help--title"
|
||||
>
|
||||
<h4 className="mb-2 fs-l">Writing a Great Post Title</h4>
|
||||
<ul className="list-disc pl-6 color-base-70">
|
||||
<li>
|
||||
Think of your post title as a super short (but compelling!) description
|
||||
— like an overview of the actual post in one short sentence.
|
||||
</li>
|
||||
<li>
|
||||
Use keywords where appropriate to help ensure people can find your post
|
||||
by search.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
35
app/javascript/article-form/components/Help/BasicEditor.jsx
Normal file
35
app/javascript/article-form/components/Help/BasicEditor.jsx
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
import { h } from 'preact';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export const BasicEditor = ({ openModal }) => (
|
||||
<div
|
||||
data-testid="basic-editor-help"
|
||||
className="crayons-card crayons-card--secondary p-4 mb-6"
|
||||
>
|
||||
You are currently using the basic markdown editor that uses{' '}
|
||||
<a href="#frontmatter" onClick={() => openModal('frontmatterShowing')}>
|
||||
Jekyll front matter
|
||||
</a>
|
||||
. You can also use the <em>rich+markdown</em> editor you can find in{' '}
|
||||
<a href="/settings/customization">
|
||||
UX settings
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
className="crayons-icon"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
role="img"
|
||||
aria-labelledby="c038a36b2512ed25db907e179ab45cfc"
|
||||
aria-hidden
|
||||
>
|
||||
<path d="M10.667 8v1.333H7.333v7.334h7.334v-3.334H16v4a.666.666 0 01-.667.667H6.667A.666.666 0 016 17.333V8.667A.667.667 0 016.667 8h4zM18 6v5.333h-1.333V8.275l-5.196 5.196-.942-.942 5.194-5.196h-3.056V6H18z" />
|
||||
</svg>
|
||||
</a>
|
||||
.
|
||||
</div>
|
||||
);
|
||||
|
||||
BasicEditor.propTypes = {
|
||||
toggleModal: PropTypes.func.isRequired,
|
||||
};
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
import { h } from 'preact';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
export const EditorFormattingHelp = ({ openModal }) => (
|
||||
<div
|
||||
data-testid="format-help"
|
||||
className="crayons-article-form__help crayons-article-form__help--body"
|
||||
>
|
||||
<h4 className="mb-2 fs-l">Editor Basics</h4>
|
||||
<ul className="list-disc pl-6 color-base-70">
|
||||
<li>
|
||||
Use{' '}
|
||||
<a href="#markdown" onClick={() => openModal('markdownShowing')}>
|
||||
Markdown
|
||||
</a>{' '}
|
||||
to write and format posts.
|
||||
<details className="fs-s my-1">
|
||||
<summary class="cursor-pointer">Commonly used syntax</summary>
|
||||
<table className="crayons-card crayons-card--secondary crayons-table crayons-table--compact w-100 mt-2 mb-4 lh-tight">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className="ff-monospace">
|
||||
# Header
|
||||
<br />
|
||||
...
|
||||
<br />
|
||||
###### Header
|
||||
</td>
|
||||
<td>
|
||||
H1 Header
|
||||
<br />
|
||||
...
|
||||
<br />
|
||||
H6 Header
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="ff-monospace">*italics* or _italics_</td>
|
||||
<td>
|
||||
<em>italics</em>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="ff-monospace">**bold**</td>
|
||||
<td>
|
||||
<strong>bold</strong>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="ff-monospace">[Link](https://...)</td>
|
||||
<td>
|
||||
<a href="https://forem.com">Link</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="ff-monospace">
|
||||
* item 1<br />* item 2
|
||||
</td>
|
||||
<td>
|
||||
<ul class="list-disc ml-5">
|
||||
<li>item 1</li>
|
||||
<li>item 2</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="ff-monospace">
|
||||
1. item 1<br />
|
||||
2. item 2
|
||||
</td>
|
||||
<td>
|
||||
<ul class="list-decimal ml-5">
|
||||
<li>item 1</li>
|
||||
<li>item 2</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="ff-monospace">> quoted text</td>
|
||||
<td>
|
||||
<span className="pl-2 border-0 border-solid border-l-4 border-base-50">
|
||||
quoted text
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="ff-monospace">`inline code`</td>
|
||||
<td>
|
||||
<code>inline code</code>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="ff-monospace">
|
||||
<span class="fs-xs">```</span>
|
||||
<br />
|
||||
code block
|
||||
<br />
|
||||
<span class="fs-xs">```</span>
|
||||
</td>
|
||||
<td>
|
||||
<div class="highlight p-2 overflow-hidden">
|
||||
<code>code block</code>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</details>
|
||||
</li>
|
||||
<li>
|
||||
You can use{' '}
|
||||
<a href="#liquid" onClick={() => openModal('liquidShowing')}>
|
||||
Liquid tags
|
||||
</a>{' '}
|
||||
to add rich content such as Tweets, YouTube videos, etc.
|
||||
</li>
|
||||
<li>
|
||||
In addition to images for the post's content, you can also drag and drop
|
||||
a cover image
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
|
||||
EditorFormattingHelp.propTypes = {
|
||||
toggleModal: PropTypes.func.isRequired,
|
||||
};
|
||||
25
app/javascript/article-form/components/Help/TagInput.jsx
Normal file
25
app/javascript/article-form/components/Help/TagInput.jsx
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import { h } from 'preact';
|
||||
|
||||
export const TagInput = () => (
|
||||
<div
|
||||
data-testid="basic-tag-input-help"
|
||||
className="crayons-article-form__help crayons-article-form__help--tags"
|
||||
>
|
||||
<h4 className="mb-2 fs-l">Tagging Guidelines</h4>
|
||||
<ul className="list-disc pl-6 color-base-70">
|
||||
<li>Tags help people find your post.</li>
|
||||
<li>
|
||||
Think of tags as the topics or categories that best describe your post.
|
||||
</li>
|
||||
<li>
|
||||
Add up to four comma-separated tags per post. Combine tags to reach the
|
||||
appropriate subcommunities.
|
||||
</li>
|
||||
<li>Use existing tags whenever possible.</li>
|
||||
<li>
|
||||
Some tags, such as “help” or “healthydebate”, have special posting
|
||||
guidelines.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
106
app/javascript/article-form/components/Help/index.jsx
Normal file
106
app/javascript/article-form/components/Help/index.jsx
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
import { h } from 'preact';
|
||||
import { useState } from 'preact/hooks';
|
||||
import PropTypes from 'prop-types';
|
||||
import { ArticleFormTitle } from './ArticleFormTitle';
|
||||
import { TagInput } from './TagInput';
|
||||
import { BasicEditor } from './BasicEditor';
|
||||
import { EditorFormattingHelp } from './EditorFormattingHelp';
|
||||
import { Modal } from '@crayons';
|
||||
|
||||
const renderModal = (onClose, title, selector) => {
|
||||
const helpHtml = document.getElementById(selector)?.innerHTML;
|
||||
|
||||
return (
|
||||
<Modal onClose={onClose} title={title}>
|
||||
<div
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{ __html: helpHtml }}
|
||||
/>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Renders help component for given section
|
||||
*
|
||||
* @param {boolean} props.previewShowing Boolean to decide if to show the preview
|
||||
* @param {string} props.helpFor Section for which help is shown
|
||||
* @param {string} props.helpPosition Offset from the top of the help component
|
||||
* @param {string} props.version Version of the editor used for article
|
||||
*
|
||||
* @returns Help component for the given section
|
||||
*/
|
||||
export const Help = ({ previewShowing, helpFor, helpPosition, version }) => {
|
||||
const [helpSectionVisibility, setHelpSectionVisibility] = useState({
|
||||
liquidShowing: false,
|
||||
markdownShowing: false,
|
||||
frontmatterShowing: false,
|
||||
});
|
||||
|
||||
const openModal = (helpSection) => {
|
||||
setHelpSectionVisibility({
|
||||
[helpSection]: true,
|
||||
});
|
||||
};
|
||||
|
||||
const closeModal = (helpSection) => {
|
||||
setHelpSectionVisibility({
|
||||
[helpSection]: false,
|
||||
});
|
||||
};
|
||||
|
||||
const {
|
||||
liquidShowing,
|
||||
markdownShowing,
|
||||
frontmatterShowing,
|
||||
} = helpSectionVisibility;
|
||||
|
||||
return (
|
||||
<div className="crayons-article-form__aside">
|
||||
{!previewShowing && (
|
||||
<div
|
||||
data-testid="article-form__help-section"
|
||||
className="sticky"
|
||||
style={{ top: version === 'v1' ? '56px' : helpPosition }}
|
||||
>
|
||||
{helpFor === 'article-form-title' && <ArticleFormTitle />}
|
||||
{helpFor === 'tag-input' && <TagInput />}
|
||||
|
||||
{version === 'v1' && <BasicEditor openModal={openModal} />}
|
||||
|
||||
{(helpFor === 'article_body_markdown' || version === 'v1') && (
|
||||
<EditorFormattingHelp openModal={openModal} />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{liquidShowing &&
|
||||
renderModal(
|
||||
() => closeModal('liquidShowing'),
|
||||
'🌊 Liquid Tags',
|
||||
'editor-liquid-help',
|
||||
)}
|
||||
|
||||
{markdownShowing &&
|
||||
renderModal(
|
||||
() => closeModal('markdownShowing'),
|
||||
'✍️ Markdown',
|
||||
'editor-markdown-help',
|
||||
)}
|
||||
{frontmatterShowing &&
|
||||
renderModal(
|
||||
() => closeModal('frontmatterShowing'),
|
||||
'Jekyll Front Matter',
|
||||
'editor-frontmatter-help',
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Help.propTypes = {
|
||||
previewShowing: PropTypes.bool.isRequired,
|
||||
helpFor: PropTypes.string.isRequired,
|
||||
helpPosition: PropTypes.string.isRequired,
|
||||
version: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
Help.displayName = 'Help';
|
||||
Loading…
Add table
Reference in a new issue