Skip to content

Commit

Permalink
Merge pull request #103 from prezly/feature/mt-4618-web-bookmark-menu
Browse files Browse the repository at this point in the history
[MT-4618] Feature - Web Bookmark menu
  • Loading branch information
e1himself authored Feb 16, 2022
2 parents 8f1e1d5 + bb63680 commit ec5e295
Show file tree
Hide file tree
Showing 25 changed files with 229 additions and 116 deletions.
10 changes: 10 additions & 0 deletions packages/slate-editor/src/components/Button/Button.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,20 @@
&:hover,
&:focus-visible {
background: rgba(255, 255, 255, 0.12);
color: inherit;
text-decoration: none;
}

&:visited,
&:focus {
color: inherit;
text-decoration: none;
}

&:active {
background: rgba(255, 255, 255, 0.16);
color: inherit;
text-decoration: none;
}

&:focus-visible {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ export function WithIcon() {
return (
<VStack spacing="2">
<div>
<Button Icon={ExternalLink}>Icon left</Button>
<Button icon={ExternalLink}>Icon left</Button>
</div>
<div>
<Button Icon={ExternalLink} iconPosition="right">
<Button icon={ExternalLink} iconPosition="right">
Icon right
</Button>
</div>
<div>
<Button Icon={ExternalLink} iconPosition="right" />
<Button icon={ExternalLink} iconPosition="right" />
</div>
</VStack>
);
Expand Down
4 changes: 2 additions & 2 deletions packages/slate-editor/src/components/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import styles from './Button.module.scss';

interface ButtonBaseProps {
variant?: 'clear';
Icon?: React.ComponentType<React.SVGProps<SVGSVGElement>>;
icon?: React.ComponentType<React.SVGProps<SVGSVGElement>>;
iconPosition?: 'left' | 'right';
fullWidth?: boolean;
round?: boolean;
Expand All @@ -28,7 +28,7 @@ type ButtonProps = AsButtonProps | AsLinkProps;

export function Button({
variant,
Icon,
icon: Icon,
iconPosition,
fullWidth,
type,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,8 @@
}

.menu {
width: 280px; // FIXME
min-height: 320px; // FIXME

width: 280px;
position: absolute;
border-radius: 12px;
padding: 16px;
background-color: rgba($indigo-900, 0.96);
color: white;
backdrop-filter: blur(6px);
}

Expand Down
13 changes: 8 additions & 5 deletions packages/slate-editor/src/components/EditorBlock/EditorBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { ElementNode } from '@prezly/slate-types';
import classNames from 'classnames';
import type { ReactNode } from 'react';
import React, { forwardRef, useState } from 'react';
import React, { forwardRef, useCallback, useState } from 'react';
import { useSelected } from 'slate-react';
import type { RenderElementProps } from 'slate-react';

Expand All @@ -27,7 +27,7 @@ interface Props extends Omit<RenderElementProps, 'attributes'>, SlateInternalAtt
*/
extendedHitArea?: boolean;
renderBlock: (props: { isSelected: boolean }) => ReactNode;
renderMenu?: () => ReactNode;
renderMenu?: (props: { onClose: () => void }) => ReactNode;
overlay?: OverlayMode;
void?: boolean;
}
Expand All @@ -48,7 +48,10 @@ export const EditorBlock = forwardRef<HTMLDivElement, Props>(function (
) {
const editorElement = useSlateDom();
const isSelected = useSelected();
const [menuOpen, setMenuOpen] = useState(true);
const [container, setContainer] = useState<HTMLDivElement | null>(null);
const openMenu = useCallback(() => setMenuOpen(true), [setMenuOpen]);
const closeMenu = useCallback(() => setMenuOpen(false), [setMenuOpen]);

return (
<div
Expand All @@ -64,11 +67,11 @@ export const EditorBlock = forwardRef<HTMLDivElement, Props>(function (
>
<div className={styles.container} contentEditable={false} ref={setContainer}>
{isSelected && renderMenu && container && editorElement && (
<Menu editorElement={editorElement} reference={container}>
{renderMenu()}
<Menu editorElement={editorElement} open={menuOpen} reference={container}>
{renderMenu({ onClose: closeMenu })}
</Menu>
)}
<Overlay selected={isSelected} mode={overlay} />
<Overlay selected={isSelected} mode={overlay} onClick={openMenu} />
{renderBlock({ isSelected })}
</div>

Expand Down
14 changes: 11 additions & 3 deletions packages/slate-editor/src/components/EditorBlock/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@ import React, { Component } from 'react';
import type { Modifier } from 'react-popper';
import { Popper } from 'react-popper';

import { Toolbox } from '#components';

import styles from './EditorBlock.module.scss';

interface Props {
children: ReactNode;
editorElement: HTMLElement;
open: boolean;
reference: HTMLElement;
}

Expand Down Expand Up @@ -86,15 +89,20 @@ export class Menu extends Component<Props> {
};

render() {
const { children, editorElement } = this.props;
const { children, editorElement, open } = this.props;

if (!open) {
return null;
}

return (
<Popper
referenceElement={this.virtualReferenceElement}
modifiers={[...MODIFIERS, keepPopoverInEditor(editorElement)]}
placement="right-start"
>
{({ ref, style, arrowProps, placement }) => (
<div className={styles.menu} ref={ref} style={style}>
<Toolbox.Panel className={styles.menu} ref={ref} style={style}>
<div
className={classNames(styles.arrow, {
[styles.top]: placement.indexOf('top') >= 0,
Expand All @@ -105,7 +113,7 @@ export class Menu extends Component<Props> {
{...arrowProps}
/>
{children}
</div>
</Toolbox.Panel>
)}
</Popper>
);
Expand Down
4 changes: 3 additions & 1 deletion packages/slate-editor/src/components/EditorBlock/Overlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ export type OverlayMode = 'always' | 'autohide' | false;
interface Props {
selected: boolean;
mode: OverlayMode;
onClick: () => void;
}

export function Overlay({ selected, mode }: Props) {
export function Overlay({ mode, onClick, selected }: Props) {
if (mode === false) {
return null;
}
Expand All @@ -19,6 +20,7 @@ export function Overlay({ selected, mode }: Props) {
className={classNames(styles.overlay, {
[styles.hidden]: selected && mode === 'autohide',
})}
onClick={onClick}
/>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ export default {
export function Base() {
return (
<div style={{ background: 'rgba(27, 27, 54, 0.96)', padding: 20 }}>
<Toggle />
<Toggle name="toggle_base" />
</div>
);
}

export function Disabled() {
return (
<div style={{ background: 'rgba(27, 27, 54, 0.96)', padding: 20 }}>
<Toggle disabled />
<Toggle disabled name="toggle_disabled" />
</div>
);
}
2 changes: 2 additions & 0 deletions packages/slate-editor/src/components/Toggle/Toggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as React from 'react';
import styles from './Toggle.module.scss';

interface ToggleProps {
name: string;
value?: boolean;
onChange?: (value: boolean) => void;
disabled?: boolean;
Expand All @@ -14,6 +15,7 @@ export function Toggle(props: React.PropsWithChildren<ToggleProps>) {
<input
type="checkbox"
checked={props.value}
name={props.name}
onChange={(e) => props.onChange?.(e.target.checked)}
className={styles.input}
disabled={props.disabled}
Expand Down
2 changes: 1 addition & 1 deletion packages/slate-editor/src/components/Toolbox/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function Header(props: React.PropsWithChildren<HeaderProps>) {
<Caption>{props.children}</Caption>

{props.withCloseButton && (
<Button variant="clear" Icon={Cross} onClick={props.onCloseClick} round />
<Button variant="clear" icon={Cross} onClick={props.onCloseClick} round />
)}
</div>
);
Expand Down
23 changes: 20 additions & 3 deletions packages/slate-editor/src/components/Toolbox/Panel.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
import * as React from 'react';
import classNames from 'classnames';
import type { CSSProperties, ReactNode } from 'react';
import React, { forwardRef } from 'react';

import styles from './Toolbox.module.scss';

export function Panel(props: React.PropsWithChildren<Record<string, unknown>>) {
return <span className={styles.panel}>{props.children}</span>;
interface Props {
children: ReactNode;
className?: string;
style?: CSSProperties;
}

export const Panel = forwardRef<HTMLDivElement, Props>(function (
{ children, className, style },
ref,
) {
return (
<div className={classNames(styles.panel, className)} ref={ref} style={style}>
{children}
</div>
);
});

Panel.displayName = 'Panel';
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,18 @@
justify-content: space-between;
align-items: center;
overflow: hidden;
background: rgba($indigo-900, 0.96);
border-top-left-radius: $spacing-1-5;
border-top-right-radius: $spacing-1-5;
padding: $spacing-2;
color: $white;
}

.panel {
backdrop-filter: blur(6px);
background: rgba($indigo-900, 0.96);
border-radius: $border-radius-base * 2;
}

.section {
border-top: 1px solid rgba($white, 0.12);
background: rgba($indigo-900, 0.96);
padding: $spacing-2;
color: white;

Expand All @@ -42,8 +40,5 @@
display: flex;
overflow: hidden;
color: $white;
background: rgba($indigo-900, 0.96);
border-top: 1px solid rgba($white, 0.12);
border-bottom-left-radius: $spacing-1-5;
border-bottom-right-radius: $spacing-1-5;
}
10 changes: 5 additions & 5 deletions packages/slate-editor/src/components/Toolbox/Toolbox.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function Base() {
type="link"
variant="clear"
href="#"
Icon={ExternalLink}
icon={ExternalLink}
iconPosition="right"
fullWidth
>
Expand All @@ -46,24 +46,24 @@ export function Base() {
</Toolbox.Section>

<Toolbox.Section caption="Preview image">
<Toggle>Show preview image</Toggle>
<Toggle name="show_preview">Show preview image</Toggle>
</Toolbox.Section>

<Toolbox.Section caption="Card layout">
<VStack spacing="2-5">
<OptionsGroup
name="card-layout"
name="layout"
options={cardLayoutOptions}
selectedValue={cardLayout}
onChange={setCardLayout}
columns={3}
/>
<Toggle>Open in new tab</Toggle>
<Toggle name="new_tab">Open in new tab</Toggle>
</VStack>
</Toolbox.Section>

<Toolbox.Footer>
<Button variant="clear" Icon={Delete} fullWidth transparent="0-5">
<Button variant="clear" icon={Delete} fullWidth transparent="0-5">
Remove web bookmark
</Button>
</Toolbox.Footer>
Expand Down
4 changes: 2 additions & 2 deletions packages/slate-editor/src/icons/Items-Layout-Horizontal.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions packages/slate-editor/src/icons/Items-Layout-Vertical.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,11 @@ import { BOOKMARK_NODE_TYPE, isBookmarkNode } from '@prezly/slate-types';
import React from 'react';
import type { RenderElementProps } from 'slate-react';

import { WebBookmarkElement, WebBookmarkMenu } from './components';
import { WebBookmarkElement } from './components';
import { WEB_BOOKMARK_EXTENSION_ID } from './constants';
import { normalizeRedundantWebBookmarkAttributes, parseSerializedElement } from './lib';
import type { WebBookmarkParameters } from './types';

export const WebBookmarkExtension = ({
availableWidth,
containerRef,
}: WebBookmarkParameters): Extension => ({
export const WebBookmarkExtension = (): Extension => ({
deserialize: {
element: {
[BOOKMARK_NODE_TYPE]: createDeserializeElement(parseSerializedElement),
Expand All @@ -24,17 +20,7 @@ export const WebBookmarkExtension = ({
if (isBookmarkNode(element)) {
return (
<>
{attributes.ref.current && (
<WebBookmarkMenu
containerRef={containerRef}
element={attributes.ref.current}
/>
)}
<WebBookmarkElement
attributes={attributes}
availableWidth={availableWidth}
element={element}
>
<WebBookmarkElement attributes={attributes} element={element}>
{children}
</WebBookmarkElement>
</>
Expand Down
Loading

0 comments on commit ec5e295

Please sign in to comment.