Skip to content
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

feat(core/presentation): allow markdown in ValidationMessage #7510

Conversation

christopherthielen
Copy link
Contributor

@christopherthielen christopherthielen commented Oct 10, 2019

This renders markdown in the ValidationMessage component

const markdown = errorMessage(`A thing happened\n\n[Click here](http://internal.service.com/error?id=12345) for deets`);
return <ValidationMessage message={markdown} type={'error'} />

Screen Shot 2019-10-10 at 3 03 18 PM

private parser: Parser = new Parser();
private renderer: HtmlRenderer = new HtmlRenderer();
export function Markdown(props: IMarkdownProps) {
const { message, tag: tagProp, className: classNameProp, ...rest } = props;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about destructuring with a default value here:
tag = 'div'
or is the concern that tag prop could be null?

@@ -0,0 +1,9 @@
.Markdown {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious if the capitalization here is a convention in deck?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally we apply capitalization like this when a few things are true:

  1. The purpose of the class is to select all instances of a specific component type, and nothing else
  2. The class sits on the root element of that component type
  3. The class name is exactly identical to the name of the component type

The third point kind of goes hand-in-hand with the capitalization.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a convention that has sort of organically appeared. It's a simple way to scope CSS to a specific component.

See also:

or in raw css:

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, thanks for the details.

Copy link
Contributor

@maggieneterval maggieneterval left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🖊️ ⬇️ 🚦 📜

private renderer: HtmlRenderer = new HtmlRenderer();
export function Markdown(props: IMarkdownProps) {
const { message, tag: tagProp, className: classNameProp, ...rest } = props;
const tag = tagProp || 'div';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another option is to use a default prop for tag instead of aliasing then reassigning.

const parsed = this.parser.parse(message.toString());
const rendered = this.renderer.render(parsed);
restProps.dangerouslySetInnerHTML = { __html: DOMPurify.sanitize(rendered) };
const restProps = rest as React.DOMAttributes<any>;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this makes me wish there was a nice way to describe IMarkdownProps as a union of React.DOMAttributes<any> and the other fields in a way where using ...rest would automatically let the type system narrow back down to React.DOMAttributes<any>. Oh well.

@@ -43,7 +46,7 @@ export const ValidationMessage = (props: IValidationMessageProps) => {
return (
<div className={`ValidationMessage ${containerClassName || containerClassNames[type] || ''}`}>
{showIcon && <i className={iconClassName || iconClassNames[type] || ''} />}
<div className="message">{message}</div>
<div className="message">{isString(message) ? <Markdown message={message} /> : { message }}</div>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think something about this syntax got me confused. can you help me figure out what { message } is doing in this case? the way i'm reading it is that if message is anything other than a string, this will take the value of the message variable and make it the value of a message field inside an object, which will then get given to react to render. what am I missing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, this is a whoops... nice catch!

Copy link
Member

@erikmunson erikmunson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🆒 😎

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
6 participants