From e32fc09fea124ef77eb516beba8c743d7293741b Mon Sep 17 00:00:00 2001 From: Guillaume Grossetie Date: Tue, 4 Feb 2025 13:42:34 +0100 Subject: [PATCH] wip: sidebar --- front/package-lock.json | 10 ++ front/package.json | 3 +- front/src/components/Sidebar.jsx | 32 +++++ front/src/components/Sidebar.module.scss | 51 ++++++++ .../Write/ArticleEditorMetadata.jsx | 118 +++++++----------- .../Write/articleEditorMetadata.module.scss | 7 +- front/src/stories/Sidebar.story.jsx | 71 +++++++++++ front/src/stories/Sidebar.story.module.scss | 4 + front/src/stories/Story.jsx | 5 + 9 files changed, 229 insertions(+), 72 deletions(-) create mode 100644 front/src/components/Sidebar.jsx create mode 100644 front/src/components/Sidebar.module.scss create mode 100644 front/src/stories/Sidebar.story.jsx create mode 100644 front/src/stories/Sidebar.story.module.scss diff --git a/front/package-lock.json b/front/package-lock.json index 1af993700..0dfd9847c 100644 --- a/front/package-lock.json +++ b/front/package-lock.json @@ -34,6 +34,7 @@ "js-yaml": "^4.1.0", "lodash.debounce": "^4.0.8", "lodash.throttle": "^4.1.1", + "lucide-react": "^0.474.0", "monaco-editor": "^0.52.0", "object-path-immutable": "^4.1.0", "pagedjs": "^0.4.0", @@ -7397,6 +7398,15 @@ "integrity": "sha512-AI2r85+4MquTw9ZYqabu4nMwy9Oftlfa/e/52t9IjtfG+mGBbTNdAoZ3RQKLHR6r0wQnwZnPIEh/Ya6XTWAKNA==", "optional": true }, + "node_modules/lucide-react": { + "version": "0.474.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.474.0.tgz", + "integrity": "sha512-CmghgHkh0OJNmxGKWc0qfPJCYHASPMVSyGY8fj3xgk4v84ItqDg64JNKFZn5hC6E0vHi6gxnbCgwhyVB09wQtA==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/lz-string": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", diff --git a/front/package.json b/front/package.json index 1db3e9d52..78253ed3d 100644 --- a/front/package.json +++ b/front/package.json @@ -52,6 +52,7 @@ "js-yaml": "^4.1.0", "lodash.debounce": "^4.0.8", "lodash.throttle": "^4.1.1", + "lucide-react": "^0.474.0", "monaco-editor": "^0.52.0", "object-path-immutable": "^4.1.0", "pagedjs": "^0.4.0", @@ -113,4 +114,4 @@ "node": "18.20.4", "npm": "10.9.0" } -} \ No newline at end of file +} diff --git a/front/src/components/Sidebar.jsx b/front/src/components/Sidebar.jsx new file mode 100644 index 000000000..a7544360f --- /dev/null +++ b/front/src/components/Sidebar.jsx @@ -0,0 +1,32 @@ +import clsx from 'clsx' +import { PanelRightClose, PanelRightOpen } from 'lucide-react' + +import styles from './Sidebar.module.scss' + +export default function Sidebar({ + opened, + setOpened, + labelOpened, + labelClosed, + children, +}) { + const button = opened ? ( + + ) : ( + + ) + + const label = opened ? labelOpened ?? 'Close' : labelClosed ?? 'Open' + + return ( +
+
setOpened(!opened)}> +
{button}
+
{label}
+
+ {opened &&
{children}
} +
+ ) +} diff --git a/front/src/components/Sidebar.module.scss b/front/src/components/Sidebar.module.scss new file mode 100644 index 000000000..90111c30f --- /dev/null +++ b/front/src/components/Sidebar.module.scss @@ -0,0 +1,51 @@ +.sidebar { + border-left: 1px solid #DCDCDC; + margin-left: 2rem; + max-width: 33vw; + position: relative; +} + +.opened { + margin-left: 6rem; + .action { + left: -4.5rem; + } +} + +.closed { + margin-left: 6rem; + padding-left: 3rem; + + .action { + right: 0.5rem; + } +} + +.action { + display: flex; + background-color: #F9F9F9; + border: 1px solid #DCDCDC; + padding: 0.5rem 1rem; + align-items: center; + gap: 0.25rem; + position: absolute; + top: 1rem; + max-width: fit-content; + cursor: pointer; +} + +.icon { + display: flex; + align-items: center; +} + +.label { + font-weight: 500; +} + +.content { + margin-top: 4rem; + padding-top: 1rem; + padding-left: 1rem; +} + diff --git a/front/src/components/Write/ArticleEditorMetadata.jsx b/front/src/components/Write/ArticleEditorMetadata.jsx index a035f662d..1948e17d2 100644 --- a/front/src/components/Write/ArticleEditorMetadata.jsx +++ b/front/src/components/Write/ArticleEditorMetadata.jsx @@ -4,7 +4,7 @@ import { useDispatch, useSelector } from 'react-redux' import PropTypes from 'prop-types' import { useTranslation } from 'react-i18next' import YAML from 'js-yaml' -import { Sidebar } from 'react-feather' +import Sidebar from '../Sidebar.jsx' import { toYaml } from './metadata/yaml.js' import ArticleEditorMetadataForm from './yamleditor/ArticleEditorMetadataForm.jsx' @@ -74,77 +74,55 @@ export default function ArticleEditorMetadata({ ) return ( - + + + + {selector === 'raw' && ( + <> + {error !== '' &&

{error}

} + + + )} + {selector !== 'raw' && ( + { + setError(reason) + if (reason !== '') { + setSelector('raw') + } + }} + onChange={handleFormUpdate} + /> + )} + + ) } diff --git a/front/src/components/Write/articleEditorMetadata.module.scss b/front/src/components/Write/articleEditorMetadata.module.scss index 31d3335d5..568754591 100644 --- a/front/src/components/Write/articleEditorMetadata.module.scss +++ b/front/src/components/Write/articleEditorMetadata.module.scss @@ -92,9 +92,14 @@ margin-bottom: 1.25rem; } -.yamlEditor { +.metadata { display: flex; flex-direction: column; + min-width: 375px; + max-width: 375px; + max-height: calc(100vh - 180px); + overflow-y: scroll; + padding-right: 0.5rem; > section { :global { diff --git a/front/src/stories/Sidebar.story.jsx b/front/src/stories/Sidebar.story.jsx new file mode 100644 index 000000000..49e2d6e06 --- /dev/null +++ b/front/src/stories/Sidebar.story.jsx @@ -0,0 +1,71 @@ +import React, { useState } from 'react' +import Sidebar from '../components/Sidebar.jsx' + +import styles from './Sidebar.story.module.scss' + +export default function SidebarStory() { + const [opened, setOpened] = useState(false) + return ( +
+
+

+ Proin pulvinar felis vitae commodo volutpat. Ut ut purus felis. Donec + blandit faucibus odio, a pulvinar turpis pharetra quis. Aenean + ultricies venenatis arcu, nec malesuada libero ornare nec. Sed + faucibus quam eget placerat accumsan. Aenean ut elementum arcu. Nulla + tortor dolor, scelerisque at porta placerat, tincidunt nec enim. + Phasellus dictum lacinia vestibulum. Aenean vestibulum arcu a ex + molestie, sit amet mattis magna ultrices. Nulla quam nibh, cursus ut + neque eget, imperdiet mattis ipsum. +

+ +

+ Curabitur viverra, lorem hendrerit fringilla ornare, ex libero + tincidunt sapien, in malesuada eros eros sit amet urna. Sed porta eu + quam sit amet rhoncus. Sed imperdiet, nulla eu venenatis congue, orci + mi fermentum magna, in cursus eros lectus quis ex. Nullam interdum + bibendum congue. Donec sit amet mattis libero. Vivamus suscipit risus + at diam hendrerit pulvinar. Curabitur tristique arcu vel tincidunt + rutrum. Integer placerat, metus vitae vestibulum eleifend, felis mi + fringilla tellus, a efficitur erat risus vitae augue. Nunc tincidunt, + lectus eu volutpat suscipit, augue est vestibulum tortor, sed sodales + quam elit at enim. Integer ut felis id justo pretium condimentum. + Phasellus lobortis vel ipsum sit amet pulvinar. Donec vehicula + molestie lorem sed lobortis. Proin suscipit pharetra arcu, varius + scelerisque enim porta pellentesque. +

+
+ +
+

+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce + rutrum velit nisl, sit amet iaculis tortor scelerisque in. Nam sed + tellus tincidunt, efficitur nunc quis, consequat metus. Maecenas + vestibulum mauris ut tristique aliquam. Quisque at sodales nisi, eu + molestie arcu. Vivamus lobortis, risus eu ultrices viverra, libero + ligula fringilla elit, ac pellentesque augue neque in nibh. Sed + lacinia pharetra ipsum eget iaculis. Aenean a pulvinar tortor. Sed + ut porttitor libero. Sed vitae dui non libero venenatis vulputate id + eget erat. Vivamus lorem ex, fringilla quis efficitur et, venenatis + tristique nunc. Ut blandit tempor turpis, nec dignissim sem + pellentesque vitae. Aliquam malesuada, orci ac semper cursus, turpis + dolor imperdiet tortor, id interdum velit nibh sit amet diam. + Interdum et malesuada fames ac ante ipsum primis in faucibus. +

+ +

+ Duis sodales massa a iaculis vehicula. Aenean porttitor, eros vel + auctor semper, nunc augue feugiat lectus, sit amet sagittis orci + turpis sed leo. Duis vestibulum pulvinar quam, nec fermentum nisi + interdum eget. Nam nec augue nec odio tempor rhoncus sit amet ut + magna. Suspendisse potenti. Sed ut urna ac nulla commodo volutpat. + Nulla efficitur mollis venenatis. Vestibulum vehicula nulla sed + vulputate sagittis. Suspendisse potenti. Pellentesque arcu massa, + cursus et maximus nec, auctor vel sapien. Nulla facilisi. Ut ac + laoreet ex. +

+
+
+
+ ) +} diff --git a/front/src/stories/Sidebar.story.module.scss b/front/src/stories/Sidebar.story.module.scss new file mode 100644 index 000000000..54423ad8c --- /dev/null +++ b/front/src/stories/Sidebar.story.module.scss @@ -0,0 +1,4 @@ +.container { + display: flex; + gap: 1rem; +} diff --git a/front/src/stories/Story.jsx b/front/src/stories/Story.jsx index db6305f69..365eba40f 100644 --- a/front/src/stories/Story.jsx +++ b/front/src/stories/Story.jsx @@ -4,8 +4,10 @@ import { Search } from 'react-feather' import buttonStyles from '../components/button.module.scss' import Field from '../components/Field.jsx' import Select from '../components/Select.jsx' +import Sidebar from '../components/Sidebar.jsx' import ButtonStory from './Button.story.jsx' import FormStory from './Form.story.jsx' +import SidebarStory from './Sidebar.story.jsx' import styles from './story.module.scss' @@ -36,6 +38,9 @@ export default function Story() { + + + )