Skip to content

Commit

Permalink
Merge pull request #84 from prezly/feature/dev-13006-theme-support-fo…
Browse files Browse the repository at this point in the history
…r-the-new-node-type

[DEV-13006] Feature - Callout & text highlights
  • Loading branch information
e1himself authored Jun 19, 2024
2 parents 7247bdb + 5c18ea1 commit eff26ea
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 4 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@
},
"dependencies": {
"@prezly/linear-partition": "^1.0.2",
"@prezly/sdk": "^21.0.0",
"@prezly/story-content-format": "^0.64.0",
"@prezly/sdk": "^21.6.0",
"@prezly/story-content-format": "^0.65.1",
"@prezly/uploadcare": "^2.4.4",
"@react-hookz/web": "^12.0.0",
"classnames": "^2.2.6",
Expand Down
2 changes: 2 additions & 0 deletions src/Renderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
AttachmentNode,
BookmarkNode,
ButtonBlockNode,
CalloutNode,
ContactNode,
DividerNode,
DocumentNode,
Expand Down Expand Up @@ -69,6 +70,7 @@ export function Renderer<N extends Node | Node[]>({
component={Elements.ButtonBlock}
/>
<Component match={BookmarkNode.isBookmarkNode} component={Elements.Bookmark} />
<Component match={CalloutNode.isCalloutNode} component={Elements.Callout} />
<Component match={ContactNode.isContactNode} component={Elements.Contact} />
<Component match={DividerNode.isDividerNode} component={Elements.Divider} />
<Component match={DocumentNode.isDocumentNode} component={Elements.Document} />
Expand Down
44 changes: 44 additions & 0 deletions src/elements/Callout/Callout.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
@import "styles/variables";

.prezly-slate-callout {
margin: $spacing-2 0;

color: $color-text;
font-weight: 500;
font-size: $font-size-m;
line-height: $line-height;

display: flex;
flex-direction: row;

padding: $spacing-3;
gap: $spacing-1-5;

background: rgba($color-link, 0.08);
border: 1px solid rgba($color-link, 0.6);
border-radius: $spacing-half;

&[data-icon]::before {
content: attr(data-icon);
display: block;
}

&--align-left {
text-align: left;
flex-direction: row;
}

&--align-center {
text-align: center;
flex-direction: column;
}

&--align-right {
text-align: right;
flex-direction: row-reverse;
}

> p {
margin: 0;
}
}
61 changes: 61 additions & 0 deletions src/elements/Callout/Callout.slate.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import type { Meta, Story } from '@storybook/react';

import { StoryNameDecorator } from '../../dev/StoryNameDecorator';
import { Renderer } from '../../Renderer';

export default {
title: 'Elements/Callout',
decorators: [StoryNameDecorator],
} as Meta;

const TEXT = {
text: 'I love how Prezly has been created by people who really understand the needs of PR professionals. Its features and functionality are just right for our business.',
};

export const Callout: Story = () => (
<Renderer
nodes={[
{
type: 'callout',
icon: '💡',
children: [TEXT],
},
]}
/>
);

export const CenterAligned: Story = () => (
<Renderer
nodes={[
{
type: 'callout',
icon: '⚠️',
align: 'center',
children: [TEXT],
},
]}
/>
);
export const RightAligned: Story = () => (
<Renderer
nodes={[
{
type: 'callout',
icon: '❌',
align: 'right',
children: [TEXT],
},
]}
/>
);

export const NoIcon: Story = () => (
<Renderer
nodes={[
{
type: 'callout',
children: [TEXT],
},
]}
/>
);
34 changes: 34 additions & 0 deletions src/elements/Callout/Callout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { CalloutNode } from '@prezly/story-content-format';
import classNames from 'classnames';
import type { HTMLAttributes } from 'react';

import { stringifyNode } from '../../lib';

import './Callout.scss';

interface Props extends HTMLAttributes<HTMLDivElement> {
node: CalloutNode;
}

export function Callout({ children, className, node, ...props }: Props) {
const isEmpty = stringifyNode(node).trim() === '';

if (isEmpty) {
return null;
}

return (
<div
className={classNames('prezly-slate-callout', className, {
'prezly-slate-callout--align-inherit': node.align === undefined,
'prezly-slate-callout--align-left': node.align === CalloutNode.Alignment.LEFT,
'prezly-slate-callout--align-center': node.align === CalloutNode.Alignment.CENTER,
'prezly-slate-callout--align-right': node.align === CalloutNode.Alignment.RIGHT,
})}
data-icon={node.icon || undefined}
{...props}
>
<p>{children}</p>
</div>
);
}
1 change: 1 addition & 0 deletions src/elements/Callout/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Callout } from './Callout';
8 changes: 6 additions & 2 deletions src/elements/Text.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ interface Props {
}

export function Text({ node }: Props) {
const { bold, italic, subscript, superscript, text, underlined } = node;
const { bold, italic, subscript, superscript, text, underlined, highlighted } = node;
let children: ReactNode = Text.preserveSoftBreaks(text);

if (bold) {
Expand All @@ -33,10 +33,14 @@ export function Text({ node }: Props) {
children = <u>{children}</u>;
}

if (highlighted) {
children = <mark>{children}</mark>;
}

return <>{children}</>;
}

Text.preserveSoftBreaks = function (text: string): ReactNode {
Text.preserveSoftBreaks = (text: string): ReactNode => {
const nodes = text.split(LINE_BREAKS).reduce<ReactNode[]>(
(result, part, index) =>
result.length === 0
Expand Down
1 change: 1 addition & 0 deletions src/elements/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export { Passthru } from './Passthru';
export { Attachment } from './Attachment';
export { Bookmark } from './Bookmark';
export { ButtonBlock } from './ButtonBlock';
export { Callout } from './Callout';
export { Contact } from './Contact';
export { Divider } from './Divider';
export { Embed } from './Embed';
Expand Down

0 comments on commit eff26ea

Please sign in to comment.