diff --git a/frontend/src/pages/wiki2/editor-component/header-icon.jsx b/frontend/src/pages/wiki2/editor-component/header-icon.jsx deleted file mode 100644 index 3468efe007..0000000000 --- a/frontend/src/pages/wiki2/editor-component/header-icon.jsx +++ /dev/null @@ -1,123 +0,0 @@ -import React, { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react'; -import { Popover, PopoverBody } from 'reactstrap'; -import { init } from 'emoji-mart'; -import Picker from '@emoji-mart/react'; -import classnames from 'classnames'; -import data from '@emoji-mart/data'; -import PropTypes from 'prop-types'; -import { gettext } from '../../../utils/constants'; - -// init data for emoji-mart, used in Picker and `getRandomEmoji` method -init({ data }); - -const HeaderIcon = ({ currentPageConfig, onUpdatePage }, ref) => { - const [isShowIconPanel, setIsShowIconPanel] = useState(false); - const iconPanelPopoverRef = useRef(null); - - - const handleSetIcon = useCallback((emoji, cb) => { - onUpdatePage(currentPageConfig.id, { name: currentPageConfig.name, icon: emoji }); - cb && cb(); - }, [currentPageConfig.id, currentPageConfig.name, onUpdatePage]); - - const setRandomEmoji = useCallback(() => { - const nativeEmojis = Reflect.ownKeys(data.natives); - const emojiCount = nativeEmojis.length; - const emoji = nativeEmojis[Math.floor(Math.random() * emojiCount)]; - handleSetIcon(emoji); - }, [handleSetIcon]); - - const handleIconRemove = () => { - handleSetIcon(''); - handleIconPanelDisplayedChange(false); - }; - - const handleIconPanelDisplayedChange = useCallback((isShowIconPanel) => { - setIsShowIconPanel(isShowIconPanel); - // setIsShowCoverPanel(false); - }, []); - - const handleClickAddIcon = useCallback(() => { - setRandomEmoji(); - handleIconPanelDisplayedChange(false); - }, [handleIconPanelDisplayedChange, setRandomEmoji]); - - useImperativeHandle(ref, () => { - return { handleClickAddIcon }; - }, [handleClickAddIcon]); - - const handleIconPanelListener = useCallback((e) => { - const isClickInPopover = iconPanelPopoverRef.current.contains(e.target); - if (!isClickInPopover) handleIconPanelDisplayedChange(false); - }, [handleIconPanelDisplayedChange]); - - useEffect(() => { - if (isShowIconPanel) { - setTimeout(() => { - // Avoid open behavior closing popover - addEventListener('click', handleIconPanelListener); - }, 0); - } - if (!isShowIconPanel) removeEventListener('click', handleIconPanelListener); - - return () => { - removeEventListener('click', handleIconPanelListener); - }; - }, [handleIconPanelListener, isShowIconPanel]); - - // Update current page favicon - useEffect(() => { - let faviconUrl = ''; - if (currentPageConfig.icon) { - faviconUrl = `data:image/svg+xml,${currentPageConfig.icon}`; - } else { - const { serviceUrl, mediaUrl, faviconPath } = window.seafile; - faviconUrl = `${serviceUrl}${mediaUrl}${faviconPath}`; - } - document.getElementById('favicon').href = faviconUrl; - }, [currentPageConfig.icon]); - - return ( - <> -
-
- {currentPageConfig.icon} -
-
- void 0} - placement="bottom" - isOpen={!!(isShowIconPanel && !!currentPageConfig.icon)} - popperClassName='wiki-icon-popover' - hideArrow={true} - > -
-
- {gettext('Emojis')} - {gettext('Remove')} -
- - handleSetIcon(emoji.native, handleIconPanelDisplayedChange.bind(null, false))} - previewPosition="none" - skinTonePosition="none" - locale={window.seafile.lang.slice(0, 2)} - maxFrequentRows={2} - theme="light" - /> - -
-
- - ); -}; - -HeaderIcon.propTypes = { - currentPageConfig: PropTypes.object.isRequired, - onUpdatePage: PropTypes.func.isRequired, -}; - -export default forwardRef(HeaderIcon); diff --git a/frontend/src/pages/wiki2/editor-component/page-header.jsx b/frontend/src/pages/wiki2/editor-component/page-header.jsx deleted file mode 100644 index 6a2743be40..0000000000 --- a/frontend/src/pages/wiki2/editor-component/page-header.jsx +++ /dev/null @@ -1,166 +0,0 @@ -import React, { useCallback, useEffect, useRef, useState } from 'react'; -import PropTypes from 'prop-types'; -import classnames from 'classnames'; -import { Input, Popover, PopoverBody } from 'reactstrap'; -import { gettext } from '../../../utils/constants'; -import { WIKI_COVER_LIST } from '../constant'; -import HeaderIcon from './header-icon'; - -const propTypes = { - currentPageConfig: PropTypes.object.isRequired, - onUpdatePage: PropTypes.func.isRequired, -}; - -const PageHeader = ({ currentPageConfig, onUpdatePage }) => { - const [isShowController, setIsShowController] = useState(false); - const [isShowCoverController, setIsShowCoverController] = useState(false); - const [isShowCoverPanel, setIsShowCoverPanel] = useState(false); - const coverPanelPopoverRef = useRef(null); - const headerWrapperRef = useRef(null); - const headerIconRef = useRef({ handleClickAddIcon: () => void 0 }); - - const getCoverImgUrl = useCallback((imageName) => { - const { serviceUrl, mediaUrl } = window.seafile; - return `${serviceUrl}${mediaUrl}img/wiki/cover/${imageName}`; - }, []); - - const handleRenameDocument = useCallback((e) => { - const { nativeEvent: { isComposing } } = e; - if (isComposing) return; - - const newName = e.target.value.trim(); - const { id, name, icon } = currentPageConfig; - if (newName === name) return; - const pageConfig = { name: newName, icon }; - onUpdatePage && onUpdatePage(id, pageConfig); - }, [currentPageConfig, onUpdatePage]); - - const changeControllerDisplayed = useCallback((isShowController) => { - if (isShowCoverPanel) return; - setIsShowController(isShowController); - }, [isShowCoverPanel]); - - const handleCoverPanelDisplayedChange = useCallback((isShowCoverPanel) => { - setIsShowCoverPanel(isShowCoverPanel); - }, []); - - const handleCoverPanelListener = useCallback((e) => { - const isClickInPopover = coverPanelPopoverRef.current.contains(e.target); - if (!isClickInPopover) handleCoverPanelDisplayedChange(false); - }, [handleCoverPanelDisplayedChange]); - - useEffect(() => { - if (isShowCoverPanel) { - setTimeout(() => { - // Avoid open behavior closing popover - addEventListener('click', handleCoverPanelListener); - }, 0); - } - if (!isShowCoverPanel) removeEventListener('click', handleCoverPanelListener); - - return () => { - removeEventListener('click', handleCoverPanelListener); - }; - }, [handleCoverPanelListener, isShowCoverPanel]); - - const handleAddCover = useCallback(() => { - const coverName = WIKI_COVER_LIST[Math.floor(Math.random() * WIKI_COVER_LIST.length)]; - const coverImgUrl = `${coverName}`; - onUpdatePage(currentPageConfig.id, { name: currentPageConfig.name, cover_img_url: coverImgUrl }); - }, [currentPageConfig.id, currentPageConfig.name, onUpdatePage]); - - const showCoverController = useCallback(() => { - setIsShowCoverController(true); - }, []); - - const hideCoverController = useCallback((e) => { - if (isShowCoverPanel) return; - setIsShowCoverController(false); - }, [isShowCoverPanel]); - - const handleSetCoverImage = (coverName) => { - const coverImgUrl = `${coverName}`; - onUpdatePage(currentPageConfig.id, { name: currentPageConfig.name, cover_img_url: coverImgUrl }); - handleCoverPanelDisplayedChange(false); - }; - - const handleCoverRemove = () => { - onUpdatePage(currentPageConfig.id, { name: currentPageConfig.name, cover_img_url: '' }); - handleCoverPanelDisplayedChange(false); - }; - - return ( -
- {currentPageConfig.cover_img_url && ( -
- {gettext('Cover')} - {isShowCoverController && ( -
-
{gettext('Change cover')}
- void 0} - placement="bottom" - isOpen={!!(isShowCoverPanel && currentPageConfig.cover_img_url)} - innerClassName='wiki-cover-panel' - hideArrow={true} - popperClassName='wiki-cover-popover' - > -
-
- {gettext('Gallery')} - {gettext('Remove')} -
- - { - WIKI_COVER_LIST.map(imgName => ( - {gettext('Cover')} - )) - } - -
-
-
- )} - -
- )} -
-
- -
- {!currentPageConfig.icon && ( -
- - {gettext('Add icon')} -
- )} - {!currentPageConfig.cover_img_url && ( -
- - {gettext('Add cover')} -
- )} -
- -
- -
-
- ); -}; - -PageHeader.propTypes = propTypes; - -export default PageHeader; diff --git a/frontend/src/pages/wiki2/main-panel.js b/frontend/src/pages/wiki2/main-panel.js index f38f40c675..075b8e279d 100644 --- a/frontend/src/pages/wiki2/main-panel.js +++ b/frontend/src/pages/wiki2/main-panel.js @@ -7,7 +7,7 @@ import { Utils } from '../../utils/utils'; import Account from '../../components/common/account'; import WikiTopNav from './top-nav'; import { getCurrentPageConfig } from './utils'; -import PageHeader from './editor-component/page-header'; +import RightHeader from './wiki-right-header'; const propTypes = { path: PropTypes.string.isRequired, @@ -82,7 +82,7 @@ class MainPanel extends Component { {isViewingFile && Utils.isSdocFile(this.props.path) && (
- + { + const nativeEmojis = Reflect.ownKeys(data.natives); + const emojiCount = nativeEmojis.length; + const emoji = nativeEmojis[Math.floor(Math.random() * emojiCount)]; + return emoji; +}; + +const generateEmojiIcon = (icon) => { + return `data:image/svg+xml,${icon}`; +}; + +export { + data, + generateEmojiIcon, + generateARandomEmoji, +}; diff --git a/frontend/src/pages/wiki2/wiki-right-header/index.js b/frontend/src/pages/wiki2/wiki-right-header/index.js new file mode 100644 index 0000000000..773303daa9 --- /dev/null +++ b/frontend/src/pages/wiki2/wiki-right-header/index.js @@ -0,0 +1,14 @@ +import React from 'react'; +import PageCover from './page-cover'; +import PageTitle from './page-title'; + +export default function RightHeader({ currentPageConfig, onUpdatePage }) { + + const props = { currentPageConfig, onUpdatePage }; + return ( +
+ + +
+ ); +} diff --git a/frontend/src/pages/wiki2/wiki-right-header/page-cover.css b/frontend/src/pages/wiki2/wiki-right-header/page-cover.css new file mode 100644 index 0000000000..403523f119 --- /dev/null +++ b/frontend/src/pages/wiki2/wiki-right-header/page-cover.css @@ -0,0 +1,86 @@ +/* Cover */ +.cur-view-content .wiki-page-cover { + position: relative; + height: 30vh; + width: 100%; +} + +.wiki-page-cover__img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.wiki-page-cover__controller { + display: none; + position: absolute; + top: 15px; + right: 20%; +} + +.wiki-page-cover__controller.show { + display: block; +} + +.wiki-page-cover__controller .wiki-cover-controller-btn { + padding: 4px 6px; + background-color: #fff; + border-radius: 4px; + font-size: 12px; + color: #6a6767b3; + cursor: pointer; +} + +.wiki-page-cover__controller .wiki-cover-controller-btn:hover { + color: #4d5156; +} + +.wiki-page-cover-popover { + max-width: max-content !important; +} + +.wiki-page-cover-panel__header { + background-color: #fff; + display: flex; + justify-content: space-between; + padding: 6px 14px; +} + +.wiki-page-cover-panel__body { + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; + gap: 10px; + background-color: #fff; + overflow-y: auto; +} + +.wiki-page-cover-panel .wiki-cover-gallery-img { + width: 120px; + height: 64px; + cursor: pointer; +} + +.wiki-page-cover-panel .wiki-cover-gallery-img:hover { + filter: brightness(1.1); +} + +/* icon */ + +/* common */ +.wiki-page-panel .popover-header { + background-color: #fff; + display: flex; + justify-content: space-between; + padding: 6px 14px; +} + +.wiki-page-panel .popover-header>span { + border-radius: 4px; + padding: 2px 8px; + user-select: none; +} + +.wiki-page-panel .popover-header>span:last-child:hover { + background-color: #efefef; + cursor: pointer; +} diff --git a/frontend/src/pages/wiki2/wiki-right-header/page-cover.js b/frontend/src/pages/wiki2/wiki-right-header/page-cover.js new file mode 100644 index 0000000000..0b0b8657b9 --- /dev/null +++ b/frontend/src/pages/wiki2/wiki-right-header/page-cover.js @@ -0,0 +1,87 @@ +import React, { useCallback, useRef, useState } from 'react'; +import { UncontrolledPopover } from 'reactstrap'; +import classNames from 'classnames'; +import PropTypes from 'prop-types'; +import { gettext } from '../../../utils/constants'; +import { WIKI_COVER_LIST } from '../constant'; + +import './page-cover.css'; + +function PageCover({ currentPageConfig, onUpdatePage }) { + + const [isShowCoverController, setIsShowCoverController] = useState(false); + const popoverRef = useRef(null); + + const onMouseEnter = useCallback(() => { + setIsShowCoverController(true); + }, []); + + const onMouseLeave = useCallback(() => { + if (popoverRef.current?.state.isOpen) { + return; + } + setIsShowCoverController(false); + }, []); + + const getCoverImgUrl = useCallback((imageName) => { + const { serviceUrl, mediaUrl } = window.seafile; + return `${serviceUrl}${mediaUrl}img/wiki/cover/${imageName}`; + }, []); + + const updatePageCover = useCallback((imageName) => { + onUpdatePage(currentPageConfig.id, { name: currentPageConfig.name, cover_img_url: imageName }); + setTimeout(() => { + popoverRef.current?.toggle(); + }, 300); + }, [currentPageConfig.id, currentPageConfig.name, onUpdatePage]); + + const removeCoverImage = useCallback(() => { + updatePageCover(''); + }, [updatePageCover]); + + const updateCoverImage = useCallback((imageName) => { + updatePageCover(imageName); + }, [updatePageCover]); + + if (!currentPageConfig.cover_img_url) { + return null; + } + + return ( + <> +
+ {gettext('Cover')} +
+
{gettext('Change cover')}
+
+
+ +
+ {gettext('Gallery')} + {gettext('Remove')} +
+
+ {WIKI_COVER_LIST.map(imgName => ( + {gettext('Cover')} + ))} +
+
+ + ); +} + +PageCover.propTypes = { + currentPageConfig: PropTypes.object, + onUpdatePage: PropTypes.func, +}; + +export default PageCover; diff --git a/frontend/src/pages/wiki2/wiki-right-header/page-icon.js b/frontend/src/pages/wiki2/wiki-right-header/page-icon.js new file mode 100644 index 0000000000..fe512a014e --- /dev/null +++ b/frontend/src/pages/wiki2/wiki-right-header/page-icon.js @@ -0,0 +1,65 @@ +import React, { useCallback, useRef } from 'react'; +import { UncontrolledPopover } from 'reactstrap'; +import classNames from 'classnames'; +import Picker from '@emoji-mart/react'; +import PropTypes from 'prop-types'; +import { gettext } from '../../../utils/constants'; +import { data } from './../utils/emoji-utils'; + +const PageIcon = ({ currentPageConfig, onUpdatePage }) => { + const popoverRef = useRef(null); + + const handleSetIcon = useCallback((emoji) => { + onUpdatePage(currentPageConfig.id, { name: currentPageConfig.name, icon: emoji }); + setTimeout(() => { + popoverRef.current?.toggle(); + }, 300); + }, [currentPageConfig.id, currentPageConfig.name, onUpdatePage]); + + const handleIconRemove = useCallback(() => { + handleSetIcon(''); + }, [handleSetIcon]); + + return ( + <> +
+
+ {currentPageConfig.icon} +
+
+ +
+ {gettext('Emojis')} + {gettext('Remove')} +
+
+ handleSetIcon(emoji.native)} + previewPosition="none" + skinTonePosition="none" + locale={window.seafile.lang.slice(0, 2)} + maxFrequentRows={2} + theme="light" + /> +
+
+ + ); +}; + +PageIcon.propTypes = { + currentPageConfig: PropTypes.object.isRequired, + onUpdatePage: PropTypes.func.isRequired, +}; + +export default PageIcon; diff --git a/frontend/src/pages/wiki2/wiki-right-header/page-title.css b/frontend/src/pages/wiki2/wiki-right-header/page-title.css new file mode 100644 index 0000000000..49fc824db2 --- /dev/null +++ b/frontend/src/pages/wiki2/wiki-right-header/page-title.css @@ -0,0 +1,95 @@ +.wiki-page-title-wrapper { + position: relative; + padding: 0 50px 0 142px; +} + +.wiki-page-icon-wrapper { + margin-top: 12px; + margin-bottom: 8px; + line-height: 78px; +} + +.wiki-page-icon-wrapper.no-page-cover { + margin-top: -48px; +} + +.wiki-page-icon-container { + position: relative; + width: 78px; + height: 78px; + font-size: 78px; + z-index: 1; +} + +.wiki-page-icon-container:hover { + cursor: pointer; + background-color: #d3c5c370; +} + +.wiki-page-icon-popover { + max-width: max-content; +} + +.wiki-page-icon-panel__header { + /* height: 337px; */ +} + +.wiki-page-icon-panel__body { + padding: 0; + background-color: #fff; +} + +.wiki-page-icon-panel__body em-emoji-picker { + height: 337px; +} + +.wiki-page-icon-panel__body em-emoji-picker section { + border-radius: 0; +} + +.wiki-page-controller { + display: flex; + margin-top: 10px; + visibility: hidden; +} + +.wiki-page-controller.show { + visibility: visible; +} + +.wiki-page-controller-item { + align-items: center; + border-radius: 4px; + color: #949491; + cursor: pointer; + display: flex; + margin-left: 6px; + padding: 2px 8px; +} + +.wiki-page-controller-item:hover { + background-color: #efefef; + border-radius: 4px; +} + +.wiki-page-controller-item:first-of-type { + margin-left: 0; +} + +.wiki-page-controller-item .text { + font-size: 14px; + margin-left: 4px; +} + +/* sdoc title */ +.main-panel-center .cur-view-content .wiki-sdoc-title { + border: none; + font-size: 26pt; + font-weight: bold; + padding: 0 50px 0 0; + color: #212529; +} + +.main-panel-center .cur-view-content .wiki-sdoc-title:focus { + box-shadow: none; +} diff --git a/frontend/src/pages/wiki2/wiki-right-header/page-title.js b/frontend/src/pages/wiki2/wiki-right-header/page-title.js new file mode 100644 index 0000000000..c072b57855 --- /dev/null +++ b/frontend/src/pages/wiki2/wiki-right-header/page-title.js @@ -0,0 +1,89 @@ +import React, { useCallback, useEffect, useState } from 'react'; +import PropTypes from 'prop-types'; +import classnames from 'classnames'; +import { Input } from 'reactstrap'; +import { gettext } from '../../../utils/constants'; +import { WIKI_COVER_LIST } from '../constant'; +import HeaderIcon from './page-icon'; +import { generateARandomEmoji, generateEmojiIcon } from '../utils/emoji-utils'; + +import './page-title.css'; + +const propTypes = { + currentPageConfig: PropTypes.object.isRequired, + onUpdatePage: PropTypes.func.isRequired, +}; + +const PageTitle = ({ currentPageConfig, onUpdatePage }) => { + const [isShowController, setIsShowController] = useState(false); + + const handleRenameDocument = useCallback((e) => { + const { nativeEvent: { isComposing } } = e; + if (isComposing) return; + + const newName = e.target.value.trim(); + const { id, name, icon } = currentPageConfig; + if (newName === name) return; + const pageConfig = { name: newName, icon }; + onUpdatePage && onUpdatePage(id, pageConfig); + }, [currentPageConfig, onUpdatePage]); + + const onMouseEnter = useCallback(() => { + setIsShowController(true); + }, []); + + const onMouseLeave = useCallback(() => { + setIsShowController(false); + }, []); + + const handleAddIcon = useCallback(() => { + const icon = generateARandomEmoji(); + onUpdatePage(currentPageConfig.id, { name: currentPageConfig.name, icon: icon }); + }, [currentPageConfig.id, currentPageConfig.name, onUpdatePage]); + + const handleAddCover = useCallback(() => { + const coverName = WIKI_COVER_LIST[Math.floor(Math.random() * WIKI_COVER_LIST.length)]; + const coverImgUrl = `${coverName}`; + onUpdatePage(currentPageConfig.id, { name: currentPageConfig.name, cover_img_url: coverImgUrl }); + }, [currentPageConfig.id, currentPageConfig.name, onUpdatePage]); + + // Update current page favicon + useEffect(() => { + let faviconUrl = ''; + if (currentPageConfig.icon) { + faviconUrl = generateEmojiIcon(currentPageConfig.icon); + } else { + const { serviceUrl, mediaUrl, faviconPath } = window.seafile; + faviconUrl = `${serviceUrl}${mediaUrl}${faviconPath}`; + } + document.getElementById('favicon').href = faviconUrl; + }, [currentPageConfig.icon]); + + + return ( +
+ {currentPageConfig.icon && ( + + )} +
+ {!currentPageConfig.icon && ( +
+ + {gettext('Add icon')} +
+ )} + {!currentPageConfig.cover_img_url && ( +
+ + {gettext('Add cover')} +
+ )} +
+ +
+ ); +}; + +PageTitle.propTypes = propTypes; + +export default PageTitle; diff --git a/frontend/src/pages/wiki2/wiki.css b/frontend/src/pages/wiki2/wiki.css index 973e855727..9a8760ab99 100644 --- a/frontend/src/pages/wiki2/wiki.css +++ b/frontend/src/pages/wiki2/wiki.css @@ -23,18 +23,6 @@ body { padding: 0; } -.main-panel-center .cur-view-content .sf-wiki-title { - border: none; - font-size: 26pt; - font-weight: bold; - padding: 0 50px 0 0; - color: #212529; -} - -.main-panel-center .cur-view-content .sf-wiki-title:focus { - box-shadow: none; -} - /* scroll container */ /* wiki editor */ .cur-view-content .sdoc-scroll-container { @@ -109,159 +97,3 @@ body { .sdoc-editor-container .sdoc-article-container .article #sdoc-editor { width: 100%; } - -/* editor layout */ -.main-panel-center .cur-view-content .wiki-page-gap-container { - padding: 0 50px; - padding-left: 142px; -} - -/* wiki page header */ -.wiki-page-controller { - display: flex; - visibility: hidden; - margin-top: 10px; -} - -.wiki-page-controller.show { - visibility: visible; -} - -.wiki-page-controller-item { - display: flex; - align-items: center; - margin-left: 6px; - padding: 2px 8px; - border-radius: 4px; - cursor: pointer; - color: #949491; -} - -.wiki-page-controller-item:first-of-type { - margin-left: 0; -} - -.wiki-page-controller-item:hover { - background-color: #efefef; - border-radius: 4px; -} - -.wiki-page-controller-item .text { - margin-left: 4px; - font-size: 14px; -} - -.wiki-icon-container { - margin-bottom: 8px; - line-height: 78px; -} - -.wiki-icon-container.gap { - margin-top: 60px; -} - -.wiki-icon-wrapper { - display: none; - margin-top: -48px; - position: relative; - width: 78px; - height: 78px; - font-size: 78px; - z-index: 1; -} - -.wiki-icon-wrapper:hover { - cursor: pointer; - background-color: #d3c5c370; -} - -.wiki-icon-wrapper.show { - display: block; -} - -/* Icon */ -.wiki-icon-popover { - max-width: max-content; -} - -.wiki-icon-panel-header { - display: flex; - justify-content: space-between; - padding: 6px 14px; - background-color: #fff; -} - -.wiki-icon-panel-header>span { - padding: 2px 8px; - border-radius: 4px; - user-select: none; -} - -.wiki-icon-panel-header>span:hover { - background-color: #efefef; - cursor: pointer; -} - -.wiki-icon-panel-body { - padding: 0; - background-color: #fff; -} - -.wiki-icon-panel-body em-emoji-picker { - height: 337px; -} - -/* Cover */ -.cur-view-content .wiki-cover { - position: relative; - height: 30vh; - width: 100%; -} - -.cur-view-content .wiki-cover .wiki-cover-img { - width: 100%; - height: 100%; - object-fit: cover; -} - -.wiki-cover .wiki-cover-controller { - position: absolute; - top: 15px; - right: 20%; -} - -.wiki-cover .wiki-cover-controller .wiki-cover-controller-btn { - padding: 4px 6px; - background-color: #fff; - border-radius: 4px; - font-size: 12px; - color: #6a6767b3; - cursor: pointer; -} - -.wiki-cover .wiki-cover-controller .wiki-cover-controller-btn:hover { - color: #4d5156; -} - -.wiki-cover-popover { - max-width: max-content !important; -} - -.wiki-cover-panel-body { - display: grid; - grid-template-columns: 1fr 1fr 1fr 1fr; - gap: 10px; - background-color: #fff; - overflow-y: auto; -} - -.wiki-cover-panel .wiki-cover-gallery-img { - width: 120px; - height: 64px; - cursor: pointer; - -} - -.wiki-cover-panel .wiki-cover-gallery-img:hover { - filter: brightness(1.1); -}