feat: implements readmore on node description overflow

This commit is contained in:
Mark Mankarious 2023-10-09 13:07:03 +01:00
parent ee3306b691
commit f9536c9cb7
9 changed files with 98 additions and 38 deletions

View file

@ -0,0 +1,18 @@
import React from 'react';
import { Box, SxProps } from '@mui/material';
interface Props {
sx?: SxProps;
}
export const Gradient = ({ sx }: Props) => {
return (
<Box
sx={{
background:
'linear-gradient(0deg, rgba(255,255,255,1) 0%, rgba(255,255,255,1) 5%, rgba(255,255,255,0) 100%)',
...sx
}}
/>
);
};

View file

@ -1,5 +1,5 @@
import React from 'react';
import { Slider, Box } from '@mui/material';
import { Slider, Box, TextField } from '@mui/material';
import { Node } from 'src/types';
import { MarkdownEditor } from 'src/components/MarkdownEditor/MarkdownEditor';
import { DeleteButton } from '../../components/DeleteButton';
@ -15,13 +15,22 @@ export const NodeSettings = ({ node, onUpdate, onDelete }: Props) => {
return (
<>
<Section title="Label">
<MarkdownEditor
<TextField
value={node.label}
onChange={(text) => {
onChange={(e) => {
const text = e.target.value as string;
if (node.label !== text) onUpdate({ label: text });
}}
/>
</Section>
<Section title="Description">
<MarkdownEditor
value={node.description}
onChange={(text) => {
if (node.description !== text) onUpdate({ description: text });
}}
/>
</Section>
{node.label && (
<Section title="Label height">
<Slider

View file

@ -3,7 +3,7 @@ import ReactQuill from 'react-quill';
import { Box } from '@mui/material';
interface Props {
value: string;
value?: string;
onChange?: (value: string) => void;
readOnly?: boolean;
height?: number;
@ -55,7 +55,7 @@ export const MarkdownEditor = ({
>
<ReactQuill
theme="snow"
value={value}
value={value ?? ''}
readOnly={readOnly}
onChange={onChange}
formats={tools}

View file

@ -1,8 +1,12 @@
import React, { useEffect, useRef, useMemo } from 'react';
import { Box } from '@mui/material';
import { Box, Button } from '@mui/material';
import { MoreHoriz as ReadMoreIcon } from '@mui/icons-material';
import { useResizeObserver } from 'src/hooks/useResizeObserver';
import { useUiStateStore } from 'src/stores/uiStateStore';
import { useTileSize } from 'src/hooks/useTileSize';
import { Gradient } from 'src/components/Gradient/Gradient';
const MAX_LABEL_HEIGHT = 125;
interface Props {
labelHeight: number;
@ -66,16 +70,48 @@ export const LabelContainer = ({
position: 'absolute',
bgcolor: 'common.white',
border: '1px solid',
borderColor: 'grey.500',
borderColor: 'grey.400',
borderRadius: 2,
left: -contentSize.width * 0.5,
top: -(contentSize.height + labelHeight + yOffset),
py: 1,
px: 1.5,
overflow: 'hidden'
overflow: 'hidden',
maxHeight: MAX_LABEL_HEIGHT
}}
>
{children}
{contentSize.height >= MAX_LABEL_HEIGHT - 10 && (
<Box
sx={{
position: 'absolute',
height: 50,
width: '100%',
bottom: 0,
left: 0
}}
>
<Gradient
sx={{ position: 'absolute', width: '100%', height: '100%' }}
/>
<Button
sx={{
position: 'absolute',
px: 0.5,
py: 0,
height: 'auto',
minWidth: 0,
fontSize: '0.7em',
bottom: 5,
right: 5,
color: 'common.white'
}}
>
<ReadMoreIcon sx={{ color: 'common.white' }} />
</Button>
</Box>
)}
</Box>
</Box>
);

View file

@ -1,21 +0,0 @@
import React from 'react';
import { Box } from '@mui/material';
import { MarkdownEditor } from 'src/components/MarkdownEditor/MarkdownEditor';
interface Props {
label: string;
}
export const MarkdownLabel = ({ label }: Props) => {
return (
<Box
sx={{
maxWidth: 200,
minWidth: 100,
maxHeight: 150
}}
>
<MarkdownEditor readOnly value={label} />
</Box>
);
};

View file

@ -1,11 +1,11 @@
import React, { useMemo } from 'react';
import { Box } from '@mui/material';
import { Box, Typography, useTheme } from '@mui/material';
import { Node as NodeI, TileOriginEnum } from 'src/types';
import { useTileSize } from 'src/hooks/useTileSize';
import { useGetTilePosition } from 'src/hooks/useGetTilePosition';
import { useIcon } from 'src/hooks/useIcon';
import { MarkdownEditor } from 'src/components/MarkdownEditor/MarkdownEditor';
import { LabelContainer } from './LabelContainer';
import { MarkdownLabel } from './LabelTypes/MarkdownLabel';
interface Props {
node: NodeI;
@ -13,6 +13,7 @@ interface Props {
}
export const Node = ({ node, order }: Props) => {
const theme = useTheme();
const { projectedTileSize } = useTileSize();
const { getTilePosition } = useGetTilePosition();
const { iconComponent } = useIcon(node.icon);
@ -24,11 +25,12 @@ export const Node = ({ node, order }: Props) => {
});
}, [node.tile, getTilePosition]);
const label = useMemo(() => {
if (node.label === undefined || node.label === '<p><br></p>') return null;
const description = useMemo(() => {
if (node.description === undefined || node.description === '<p><br></p>')
return null;
return node.label;
}, [node.label]);
return node.description;
}, [node.description]);
return (
<Box
@ -44,7 +46,7 @@ export const Node = ({ node, order }: Props) => {
top: position.y
}}
>
{label && (
{(node.label || description) && (
<Box
sx={{
position: 'absolute'
@ -57,7 +59,19 @@ export const Node = ({ node, order }: Props) => {
}}
/>
<LabelContainer labelHeight={node.labelHeight} connectorDotSize={3}>
<MarkdownLabel label={label} />
<Typography fontWeight={600}>{node.label}</Typography>
{description && (
<Box sx={{ pt: 0.2, width: 180 }}>
<MarkdownEditor
readOnly
value={node.description}
styles={{
color: theme.palette.text.secondary,
fontSize: '0.8em'
}}
/>
</Box>
)}
</LabelContainer>
</Box>
)}

View file

@ -29,7 +29,8 @@ export interface Node {
id: string;
type: SceneItemTypeEnum.NODE;
icon: string;
label: string;
label?: string;
description?: string;
labelHeight: number;
tile: Coords;
isSelected: boolean;

View file

@ -40,6 +40,7 @@ export const nodeInputToNode = (nodeInput: NodeInput): Node => {
type: SceneItemTypeEnum.NODE,
id: nodeInput.id,
label: nodeInput.label ?? NODE_DEFAULTS.label,
description: nodeInput.description,
labelHeight: nodeInput.labelHeight ?? NODE_DEFAULTS.labelHeight,
icon: nodeInput.icon,
tile: nodeInput.tile,
@ -215,6 +216,7 @@ export const nodeToNodeInput = (node: Node): NodeInput => {
id: node.id,
tile: node.tile,
label: node.label,
description: node.description,
labelHeight: node.labelHeight,
icon: node.icon
};

View file

@ -17,6 +17,7 @@ export const iconInput = z.object({
export const nodeInput = z.object({
id: z.string(),
label: z.string().optional(),
description: z.string().optional(),
labelHeight: z.number().optional(),
icon: z.string(),
tile: coords