-
Notifications
You must be signed in to change notification settings - Fork 162
feat: Add formatting buttons to new Markdown editor #2073 #2456
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
93664e3
to
5f1f774
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #2456 +/- ##
=======================================
Coverage 94.64% 94.65%
=======================================
Files 1187 1189 +2
Lines 26220 26306 +86
Branches 5839 5854 +15
=======================================
+ Hits 24817 24901 +84
- Misses 1333 1335 +2
Partials 70 70 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work! it looks good in general, just a few comments.
|
||
const EditorToolbar = ({ editorRef }) => { | ||
const intl = useIntl(); | ||
const cm = editorRef; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would appreciate a better self described name for this variable, or maybe we can use the prop variable instead of this new one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes
const view = new EditorView({ state: newState, parent: ref.current }); | ||
// eslint-disable-next-line no-param-reassign | ||
upstreamRef.current = view; | ||
if (onReady) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can be simplified with the optional chaining operator like this: onReady?.(view)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah that make sense
@@ -0,0 +1,79 @@ | |||
import React from 'react'; | |||
import { Button, Icon } from '@openedx/paragon'; | |||
import PropTypes from 'prop-types'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not mandatory but it would be nice to start using typescript for new components, that way we can get rid of the PropTypes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure
align-items: center; | ||
gap: 4px; | ||
padding: 6px; | ||
background: #D1DAE5; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just wondering if we can use design tokens here instead of the raw values on this file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not get it. can you please give me example?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here is the pr on which design tokens were added to the repo #2187, it is basically to use predefined variables instead of hardcoded values, but is just a nice to have.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
5f1f774
to
e8754a6
Compare
Sandbox deployment failed 💥 |
The main thing that concerns me about this PR is the amount of custom CSS being used. The more custom CSS in an MFE, the harder it is for theme authors to verify their theme works throughout the platform. Custom CSS also concerns me from an a11y stand point. Paragon components and styles have been reviewed for accessibility, so anything custom outside of that would need to be reviewed for a11y as well. I pulled this down locally to try to get a sense of how possible it would be to reduce the amount of custom CSS needed to accomplish this. My first attempt was using a Paragon ![]() <ButtonToolbar>
<ButtonGroup size='sm'>
[...]
<Button variant="light" iconBefore={CheckBoxIcon} onClick={() => insertAtCursor(CHECKBOXES)}>
{intl.formatMessage(messages.editorToolbarCheckboxButtonLabel)}
</Button>
[...]
</ButtonGroup>
</ButtonGroup>
[...]
</ButtonToolbar> I ran into issues with it being too big (either the buttons overflowed to the next line, or if I prevented overflowing to the next line some of the buttons had 2 lines of text so everything looked really tall. Looking for something smaller, I tried using Paragon <Stack direction="horizontal" className="bg-primary-300">
<Chip variant="dark" onClick={() => insertAtCursor(HEADING)}>
<span>{'<H>'}</span>{' '}{intl.formatMessage(messages.editorToolbarHeadingButtonLabel)}
</Chip>
<Chip variant="dark" iconBefore={ViewList} onClick={() => insertAtCursor(MULTIPLE_CHOICE)}>
{intl.formatMessage(messages.editorToolbarMultipleChoiceButtonLabel)}
</Chip>
<Chip variant="dark" iconBefore={CheckBoxIcon} onClick={() => insertAtCursor(CHECKBOXES)}>
{intl.formatMessage(messages.editorToolbarCheckboxButtonLabel)}
</Chip>
<Chip variant="dark" iconBefore={Abc} onClick={() => insertAtCursor(TEXT_INPUT)}>
{intl.formatMessage(messages.editorToolbarTextButtonLabel)}
</Chip>
<Chip variant="dark" iconBefore={Pgn123} onClick={() => insertAtCursor(TEXT_INPUT)}>
{intl.formatMessage(messages.editorToolbarNumericalButtonLabel)}
</Chip>
<Chip variant="dark" iconBefore={ArrowDropDown} onClick={() => insertAtCursor(DROPDOWN)}>
{intl.formatMessage(messages.editorToolbarDropdownButtonLabel)}
</Chip>
<Chip variant="dark" iconBefore={Lightbulb} onClick={() => insertAtCursor(EXPLANATION)}>
{intl.formatMessage(messages.editorToolbarExplanationButtonLabel)}
</Chip>
</Stack> but even that didn't fit everything ![]() The next thing I tried was just minimizing the amount of custom CSS, and only referencing CSS vars instead of any hardcoded values. I was able to get to this ![]() with
<ButtonToolbar className="editor-toolbar">
<ButtonGroup size="sm">
<Button variant="light" onClick={() => insertAtCursor(HEADING)}>
<span className="btn-icon-before font-weight-bold">{'<H>'}</span>
{intl.formatMessage(messages.editorToolbarHeadingButtonLabel)}
</Button>
<Button variant="light" iconBefore={ViewList} onClick={() => insertAtCursor(MULTIPLE_CHOICE)}>
{intl.formatMessage(messages.editorToolbarMultipleChoiceButtonLabel)}
</Button>
<Button variant="light" iconBefore={CheckBoxIcon} onClick={() => insertAtCursor(CHECKBOXES)}>
{intl.formatMessage(messages.editorToolbarCheckboxButtonLabel)}
</Button>
</ButtonGroup>
<ButtonGroup size="sm">
<Button variant="light" iconBefore={Abc} onClick={() => insertAtCursor(TEXT_INPUT)}>
{intl.formatMessage(messages.editorToolbarTextButtonLabel)}
</Button>
<Button variant="light" iconBefore={Pgn123} onClick={() => insertAtCursor(NUMERICAL_INPUT)}>
{intl.formatMessage(messages.editorToolbarNumericalButtonLabel)}
</Button>
<Button
variant="light"
iconBefore={ArrowDropDown}
onClick={() => insertAtCursor(DROPDOWN)}
>
{intl.formatMessage(messages.editorToolbarDropdownButtonLabel)}
</Button>
</ButtonGroup>
<ButtonGroup size="sm">
<Button variant="light" iconBefore={Lightbulb} onClick={() => insertAtCursor(EXPLANATION)}>
{intl.formatMessage(messages.editorToolbarExplanationButtonLabel)}
</Button>
</ButtonGroup>
</ButtonToolbar>
.editor-toolbar {
background-color: var(--pgn-color-btn-bg-light);
.btn {
font-size: var(--pgn-typography-font-size-micro);
.btn-icon-before {
width: var(--pgn-size-icon-xs);
height: var(--pgn-size-icon-xs);
}
}
} Which doesn't match the implementation in this PR 1:1 but is the closest of the things I tried. Also, since the goal of this was just to get a proof-of-concept implementation that looks similar to what's in this PR, I am still concerned about the a11y implications of it. Before this lands, I'd like to see if @kblemel has thoughts about this from an a11y perspective. Then those a11y requirements can be used to inform the final design, and I'll be able to provide suggestions and another review to ensure the implementation utilizes Paragon components, utility classes, and CSS variables. |
Thanks for that feedback @brian-smith-tcril ! @kblemel and @sdaitzman , any feedback you provide is also appreciated. I want to make sure that we land this before the Ulmo cutoff (Oct 9)--if there are still improvements to be made after that, we can certainly fix forward and/or backport. @ahtesham-quraish Would you be able to factor in Brian's feedback? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ahtesham-quraish , could you factor in Brian's feedback?
Description
Add formatting buttons to new Markdown editor #2073
Supporting information