mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-14 20:40:17 -05:00
Merge pull request #21115 from overleaf/ii-bs5-review-panel
[web] BS5 review panel new GitOrigin-RevId: c65d17d0053858bd74984ba746a620b89d900606
This commit is contained in:
parent
f84b205b4b
commit
8bc374c916
29 changed files with 1020 additions and 158 deletions
|
@ -11,4 +11,7 @@ export const bsVersionDecorator: Meta = {
|
|||
options: ['3', '5'],
|
||||
},
|
||||
},
|
||||
args: {
|
||||
[bootstrapVersionArg]: '3',
|
||||
},
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ function ProjectListTable() {
|
|||
selectOrUnselectAllProjects,
|
||||
} = useProjectListContext()
|
||||
const { handleSort } = useSort()
|
||||
const checkAllRef = useRef<HTMLInputElement>()
|
||||
const checkAllRef = useRef<HTMLInputElement>(null)
|
||||
|
||||
const handleAllProjectsCheckboxChange = useCallback(
|
||||
(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
|
|
|
@ -9,12 +9,12 @@ import { useThreadsActionsContext } from '../context/threads-context'
|
|||
import { removeNewCommentRangeEffect } from '@/features/source-editor/extensions/add-comment'
|
||||
import useSubmittableTextInput from '../hooks/use-submittable-text-input'
|
||||
import AutoExpandingTextArea from '@/shared/components/auto-expanding-text-area'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import { ReviewPanelEntry } from './review-panel-entry'
|
||||
import { ThreadId } from '../../../../../types/review-panel/review-panel'
|
||||
import { Decoration } from '@codemirror/view'
|
||||
import { useModalsContext } from '@/features/ide-react/context/modals-context'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
import OLButton from '@/features/ui/components/ol/ol-button'
|
||||
|
||||
export const ReviewPanelAddComment: FC<{
|
||||
docId: string
|
||||
|
@ -148,23 +148,23 @@ export const ReviewPanelAddComment: FC<{
|
|||
disabled={submitting}
|
||||
/>
|
||||
<div className="review-panel-add-comment-buttons">
|
||||
<Button
|
||||
bsSize="sm"
|
||||
bsStyle={null}
|
||||
<OLButton
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="review-panel-add-comment-cancel-button"
|
||||
disabled={submitting}
|
||||
onClick={handleClose}
|
||||
>
|
||||
{t('cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
</OLButton>
|
||||
<OLButton
|
||||
type="submit"
|
||||
bsSize="sm"
|
||||
className="btn-primary"
|
||||
variant="primary"
|
||||
size="sm"
|
||||
disabled={content === '' || submitting}
|
||||
>
|
||||
{t('comment')}
|
||||
</Button>
|
||||
</OLButton>
|
||||
</div>
|
||||
</form>
|
||||
</ReviewPanelEntry>
|
||||
|
|
|
@ -8,8 +8,7 @@ import {
|
|||
import { useTranslation } from 'react-i18next'
|
||||
import classnames from 'classnames'
|
||||
import { usePermissionsContext } from '@/features/ide-react/context/permissions-context'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import Tooltip from '@/shared/components/tooltip'
|
||||
import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
import { formatTimeBasedOnYear } from '@/features/utils/format-date'
|
||||
import { useChangesUsersContext } from '../context/changes-users-context'
|
||||
|
@ -109,29 +108,30 @@ export const ReviewPanelChange = memo<{
|
|||
</div>
|
||||
{editable && permissions.write && (
|
||||
<div className="review-panel-entry-actions">
|
||||
<Tooltip
|
||||
<OLTooltip
|
||||
id="accept-change"
|
||||
overlayProps={{ placement: 'bottom' }}
|
||||
description={t('accept_change')}
|
||||
tooltipProps={{ className: 'review-panel-tooltip' }}
|
||||
>
|
||||
<Button onClick={acceptHandler} bsStyle={null}>
|
||||
<button type="button" className="btn" onClick={acceptHandler}>
|
||||
<MaterialIcon
|
||||
type="check"
|
||||
className="review-panel-entry-actions-icon"
|
||||
accessibilityLabel={t('accept_change')}
|
||||
/>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</button>
|
||||
</OLTooltip>
|
||||
|
||||
<Tooltip
|
||||
<OLTooltip
|
||||
id="reject-change"
|
||||
description={t('reject_change')}
|
||||
overlayProps={{ placement: 'bottom' }}
|
||||
tooltipProps={{ className: 'review-panel-tooltip' }}
|
||||
>
|
||||
<Button
|
||||
bsStyle={null}
|
||||
<button
|
||||
type="button"
|
||||
className="btn"
|
||||
onClick={() =>
|
||||
aggregate
|
||||
? rejectChanges(change.id, aggregate.id)
|
||||
|
@ -143,8 +143,8 @@ export const ReviewPanelChange = memo<{
|
|||
accessibilityLabel={t('reject_change')}
|
||||
type="close"
|
||||
/>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</button>
|
||||
</OLTooltip>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
@ -1,29 +1,80 @@
|
|||
import ControlledDropdown from '@/shared/components/controlled-dropdown'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
import { FC, memo } from 'react'
|
||||
import { Dropdown, MenuItem } from 'react-bootstrap'
|
||||
import { FC, memo, forwardRef } from 'react'
|
||||
import {
|
||||
Dropdown as BS3Dropdown,
|
||||
MenuItem as BS3MenuItem,
|
||||
} from 'react-bootstrap'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
import {
|
||||
Dropdown,
|
||||
DropdownItem,
|
||||
DropdownMenu,
|
||||
DropdownToggle,
|
||||
} from '@/features/ui/components/bootstrap-5/dropdown-menu'
|
||||
import classnames from 'classnames'
|
||||
|
||||
const ReviewPanelCommentDropdownToggleButton = forwardRef<
|
||||
HTMLButtonElement,
|
||||
React.ButtonHTMLAttributes<HTMLButtonElement>
|
||||
>((props, ref) => (
|
||||
<button {...props} ref={ref} className={classnames(props.className, 'btn')} />
|
||||
))
|
||||
ReviewPanelCommentDropdownToggleButton.displayName =
|
||||
'ReviewPanelCommentDropdownToggleButton'
|
||||
|
||||
const ReviewPanelCommentOptions: FC<{
|
||||
onEdit: () => void
|
||||
onDelete: () => void
|
||||
}> = ({ onEdit, onDelete }) => {
|
||||
id: string
|
||||
}> = ({ onEdit, onDelete, id }) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<ControlledDropdown id="review-panel-comment-options" pullRight>
|
||||
<Dropdown.Toggle noCaret bsSize="small" bsStyle={null}>
|
||||
<MaterialIcon
|
||||
type="more_vert"
|
||||
className="review-panel-entry-actions-icon"
|
||||
accessibilityLabel={t('more_options')}
|
||||
/>
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu>
|
||||
<MenuItem onClick={onEdit}>{t('edit')}</MenuItem>
|
||||
<MenuItem onClick={onDelete}>{t('delete')}</MenuItem>
|
||||
</Dropdown.Menu>
|
||||
</ControlledDropdown>
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<ControlledDropdown id={`review-panel-comment-options-${id}`} pullRight>
|
||||
<BS3Dropdown.Toggle noCaret bsSize="small" bsStyle={null}>
|
||||
<MaterialIcon
|
||||
type="more_vert"
|
||||
className="review-panel-entry-actions-icon"
|
||||
accessibilityLabel={t('more_options')}
|
||||
/>
|
||||
</BS3Dropdown.Toggle>
|
||||
<BS3Dropdown.Menu>
|
||||
<BS3MenuItem onClick={onEdit}>{t('edit')}</BS3MenuItem>
|
||||
<BS3MenuItem onClick={onDelete}>{t('delete')}</BS3MenuItem>
|
||||
</BS3Dropdown.Menu>
|
||||
</ControlledDropdown>
|
||||
}
|
||||
bs5={
|
||||
<Dropdown align="end">
|
||||
<DropdownToggle
|
||||
as={ReviewPanelCommentDropdownToggleButton}
|
||||
id={`review-panel-comment-options-btn-${id}`}
|
||||
>
|
||||
<MaterialIcon
|
||||
type="more_vert"
|
||||
className="review-panel-entry-actions-icon"
|
||||
accessibilityLabel={t('more_options')}
|
||||
/>
|
||||
</DropdownToggle>
|
||||
<DropdownMenu flip={false}>
|
||||
<li role="none">
|
||||
<DropdownItem as="button" onClick={onEdit}>
|
||||
{t('edit')}
|
||||
</DropdownItem>
|
||||
</li>
|
||||
<li role="none">
|
||||
<DropdownItem as="button" onClick={onDelete}>
|
||||
{t('delete')}
|
||||
</DropdownItem>
|
||||
</li>
|
||||
</DropdownMenu>
|
||||
</Dropdown>
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
import AccessibleModal from '@/shared/components/accessible-modal'
|
||||
import { FC, memo } from 'react'
|
||||
import { Button, Modal } from 'react-bootstrap'
|
||||
import OLButton from '@/features/ui/components/ol/ol-button'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import OLModal, {
|
||||
OLModalBody,
|
||||
OLModalFooter,
|
||||
OLModalHeader,
|
||||
OLModalTitle,
|
||||
} from '@/features/ui/components/ol/ol-modal'
|
||||
|
||||
const ReviewPanelDeleteCommentModal: FC<{
|
||||
onHide: () => void
|
||||
|
@ -12,20 +17,20 @@ const ReviewPanelDeleteCommentModal: FC<{
|
|||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<AccessibleModal show onHide={onHide}>
|
||||
<Modal.Header>
|
||||
<Modal.Title>{title}</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>{message}</Modal.Body>
|
||||
<Modal.Footer>
|
||||
<Button bsStyle={null} className="btn-secondary" onClick={onHide}>
|
||||
<OLModal show onHide={onHide}>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{title}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody>{message}</OLModalBody>
|
||||
<OLModalFooter>
|
||||
<OLButton variant="secondary" onClick={onHide}>
|
||||
{t('cancel')}
|
||||
</Button>
|
||||
<Button bsStyle="danger" onClick={onDelete}>
|
||||
</OLButton>
|
||||
<OLButton variant="danger" onClick={onDelete}>
|
||||
{t('delete')}
|
||||
</Button>
|
||||
</Modal.Footer>
|
||||
</AccessibleModal>
|
||||
</OLButton>
|
||||
</OLModalFooter>
|
||||
</OLModal>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { FC, useCallback, useEffect, useRef, useState } from 'react'
|
||||
import classNames from 'classnames'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import OLButton from '@/features/ui/components/ol/ol-button'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
export const ExpandableContent: FC<{ className?: string }> = ({
|
||||
|
@ -49,22 +49,22 @@ export const ExpandableContent: FC<{ className?: string }> = ({
|
|||
{children}
|
||||
</div>
|
||||
{isExpanded ? (
|
||||
<Button
|
||||
bsStyle="link"
|
||||
<OLButton
|
||||
variant="link"
|
||||
className="btn-inline-link"
|
||||
onClick={handleShowLess}
|
||||
>
|
||||
{t('show_less')}
|
||||
</Button>
|
||||
</OLButton>
|
||||
) : (
|
||||
isOverflowing && (
|
||||
<Button
|
||||
bsStyle="link"
|
||||
<OLButton
|
||||
variant="link"
|
||||
className="btn-inline-link"
|
||||
onClick={handleShowMore}
|
||||
>
|
||||
{t('show_more')}
|
||||
</Button>
|
||||
</OLButton>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
|
|
|
@ -2,7 +2,6 @@ import { FC, memo, useState } from 'react'
|
|||
import { ReviewPanelResolvedThreadsButton } from './review-panel-resolved-threads-button'
|
||||
import { ReviewPanelTrackChangesMenu } from './review-panel-track-changes-menu'
|
||||
import ReviewPanelTrackChangesMenuButton from './review-panel-track-changes-menu-button'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
import { useLayoutContext } from '@/shared/context/layout-context'
|
||||
import SplitTestBadge from '@/shared/components/split-test-badge'
|
||||
|
@ -26,14 +25,13 @@ const ReviewPanelHeader: FC = () => {
|
|||
/>
|
||||
</span>
|
||||
</div>
|
||||
<Button
|
||||
bsStyle={null}
|
||||
className="review-panel-close-button"
|
||||
<button
|
||||
type="button"
|
||||
className="btn review-panel-close-button"
|
||||
onClick={() => setReviewPanelOpen(false)}
|
||||
>
|
||||
<MaterialIcon type="close" />
|
||||
</Button>
|
||||
</button>
|
||||
</div>
|
||||
<div className="review-panel-tools">
|
||||
<ReviewPanelResolvedThreadsButton />
|
||||
|
|
|
@ -5,8 +5,7 @@ import {
|
|||
} from '../../../../../types/review-panel/review-panel'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { formatTimeBasedOnYear } from '@/features/utils/format-date'
|
||||
import Tooltip from '@/shared/components/tooltip'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
import AutoExpandingTextArea from '@/shared/components/auto-expanding-text-area'
|
||||
import { buildName } from '../utils/build-name'
|
||||
|
@ -90,26 +89,27 @@ export const ReviewPanelMessage: FC<{
|
|||
|
||||
<div className="review-panel-entry-actions">
|
||||
{!isReply && !isThreadResolved && (
|
||||
<Tooltip
|
||||
<OLTooltip
|
||||
id="resolve-thread"
|
||||
overlayProps={{ placement: 'bottom' }}
|
||||
description={t('resolve_comment')}
|
||||
tooltipProps={{ className: 'review-panel-tooltip' }}
|
||||
>
|
||||
<Button onClick={onResolve} bsStyle={null}>
|
||||
<button type="button" className="btn" onClick={onResolve}>
|
||||
<MaterialIcon
|
||||
type="check"
|
||||
className="review-panel-entry-actions-icon"
|
||||
accessibilityLabel={t('resolve_comment')}
|
||||
/>
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</button>
|
||||
</OLTooltip>
|
||||
)}
|
||||
|
||||
{!isThreadResolved && (
|
||||
<ReviewPanelCommentOptions
|
||||
onEdit={handleEditOption}
|
||||
onDelete={showDeleteModal}
|
||||
id={message.id}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import { FC, memo } from 'react'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
import classNames from 'classnames'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import OLButton from '@/features/ui/components/ol/ol-button'
|
||||
import { bsVersion } from '@/features/utils/bootstrap-5'
|
||||
|
||||
const MoreCommentsButton: FC<{
|
||||
onClick: () => void
|
||||
|
@ -17,14 +18,18 @@ const MoreCommentsButton: FC<{
|
|||
upwards: direction === 'upward',
|
||||
})}
|
||||
>
|
||||
<Button
|
||||
bsSize="small"
|
||||
className="btn-secondary review-panel-more-comments-button"
|
||||
<OLButton
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
className={bsVersion({ bs3: 'review-panel-more-comments-button' })}
|
||||
onClick={onClick}
|
||||
bs3Props={{
|
||||
bsSize: 'xsmall',
|
||||
}}
|
||||
>
|
||||
<MaterialIcon type={`arrow_${direction}_alt`} />
|
||||
{t('more_comments')}
|
||||
</Button>
|
||||
</OLButton>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import {
|
|||
} from '../../../../../types/change'
|
||||
import { canAggregate } from '../utils/can-aggregate'
|
||||
|
||||
import { Button } from 'react-bootstrap'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
import useOverviewFileCollapsed from '../hooks/use-overview-file-collapsed'
|
||||
import { useThreadsContext } from '../context/threads-context'
|
||||
|
@ -61,9 +60,9 @@ export const ReviewPanelOverviewFile: FC<{
|
|||
return (
|
||||
<>
|
||||
<div>
|
||||
<Button
|
||||
bsClass="review-panel-overview-file-header"
|
||||
bsStyle={null}
|
||||
<button
|
||||
type="button"
|
||||
className="review-panel-overview-file-header"
|
||||
onClick={toggleCollapsed}
|
||||
>
|
||||
<MaterialIcon
|
||||
|
@ -73,7 +72,7 @@ export const ReviewPanelOverviewFile: FC<{
|
|||
<div className="review-panel-overview-file-entry-count">
|
||||
{numEntries}
|
||||
</div>
|
||||
</Button>
|
||||
</button>
|
||||
|
||||
{!collapsed && (
|
||||
<div className="review-panel-overview-file-entries">
|
||||
|
|
|
@ -2,12 +2,11 @@ import React, { FC, useCallback, useState } from 'react'
|
|||
import { useTranslation, Trans } from 'react-i18next'
|
||||
import { ThreadId } from '../../../../../types/review-panel/review-panel'
|
||||
import { useThreadsActionsContext } from '../context/threads-context'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
import { ExpandableContent } from './review-panel-expandable-content'
|
||||
import { ReviewPanelCommentContent } from './review-panel-comment-content'
|
||||
import { Change, CommentOperation } from '../../../../../types/change'
|
||||
import Tooltip from '@/shared/components/tooltip'
|
||||
import classNames from 'classnames'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
import { useModalsContext } from '@/features/ide-react/context/modals-context'
|
||||
|
@ -73,25 +72,25 @@ export const ReviewPanelResolvedThread: FC<{
|
|||
/>
|
||||
</div>
|
||||
<div className="review-panel-resolved-comment-buttons">
|
||||
<Tooltip
|
||||
<OLTooltip
|
||||
id="reopen-thread"
|
||||
overlayProps={{ placement: 'bottom' }}
|
||||
description={t('reopen')}
|
||||
>
|
||||
<Button onClick={handleReopenThread}>
|
||||
<button type="button" className="btn" onClick={handleReopenThread}>
|
||||
<MaterialIcon type="refresh" accessibilityLabel={t('reopen')} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</button>
|
||||
</OLTooltip>
|
||||
|
||||
<Tooltip
|
||||
<OLTooltip
|
||||
id="delete-thread"
|
||||
overlayProps={{ placement: 'bottom' }}
|
||||
description={t('delete')}
|
||||
>
|
||||
<Button onClick={handleDeleteThread}>
|
||||
<button type="button" className="btn" onClick={handleDeleteThread}>
|
||||
<MaterialIcon type="delete" accessibilityLabel={t('delete')} />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
</button>
|
||||
</OLTooltip>
|
||||
</div>
|
||||
</div>
|
||||
<div className="review-panel-resolved-comment-quoted-text">
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
import React, { FC, useRef, useState } from 'react'
|
||||
import Icon from '@/shared/components/icon'
|
||||
import OLOverlay from '@/features/ui/components/ol/ol-overlay'
|
||||
import OLPopover from '@/features/ui/components/ol/ol-popover'
|
||||
import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
||||
import { ReviewPanelResolvedThreadsMenu } from './review-panel-resolved-threads-menu'
|
||||
import { Overlay, Popover } from 'react-bootstrap'
|
||||
import Tooltip from '@/shared/components/tooltip'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
|
||||
export const ReviewPanelResolvedThreadsButton: FC = () => {
|
||||
const [expanded, setExpanded] = useState(false)
|
||||
|
@ -12,7 +15,7 @@ export const ReviewPanelResolvedThreadsButton: FC = () => {
|
|||
|
||||
return (
|
||||
<>
|
||||
<Tooltip
|
||||
<OLTooltip
|
||||
id="resolved-comments"
|
||||
overlayProps={{ placement: 'bottom' }}
|
||||
description={t('resolved_comments')}
|
||||
|
@ -22,27 +25,30 @@ export const ReviewPanelResolvedThreadsButton: FC = () => {
|
|||
ref={buttonRef}
|
||||
onClick={() => setExpanded(true)}
|
||||
>
|
||||
<Icon type="inbox" fw />
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<Icon type="inbox" fw />}
|
||||
bs5={<MaterialIcon type="inbox" />}
|
||||
/>
|
||||
</button>
|
||||
</Tooltip>
|
||||
</OLTooltip>
|
||||
{expanded && (
|
||||
<Overlay
|
||||
<OLOverlay
|
||||
show
|
||||
onHide={() => setExpanded(false)}
|
||||
animation={false}
|
||||
transition={false}
|
||||
container={this}
|
||||
containerPadding={0}
|
||||
placement="bottom"
|
||||
rootClose
|
||||
target={buttonRef.current ?? undefined}
|
||||
target={buttonRef.current}
|
||||
>
|
||||
<Popover
|
||||
<OLPopover
|
||||
id="popover-resolved-threads"
|
||||
className="review-panel-resolved-comments review-panel-new"
|
||||
>
|
||||
<ReviewPanelResolvedThreadsMenu />
|
||||
</Popover>
|
||||
</Overlay>
|
||||
</OLPopover>
|
||||
</OLOverlay>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
|
|
|
@ -4,9 +4,9 @@ import { useTranslation } from 'react-i18next'
|
|||
import { ReviewPanelResolvedThread } from './review-panel-resolved-thread'
|
||||
import useProjectRanges from '../hooks/use-project-ranges'
|
||||
import { useFileTreeData } from '@/shared/context/file-tree-data-context'
|
||||
import Icon from '@/shared/components/icon'
|
||||
import { Change, CommentOperation } from '../../../../../types/change'
|
||||
import { ThreadId } from '../../../../../types/review-panel/review-panel'
|
||||
import LoadingSpinner from '@/shared/components/loading-spinner'
|
||||
|
||||
export const ReviewPanelResolvedThreadsMenu: FC = () => {
|
||||
const { t } = useTranslation()
|
||||
|
@ -59,11 +59,7 @@ export const ReviewPanelResolvedThreadsMenu: FC = () => {
|
|||
}, [threads])
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="review-panel-resolved-comments-loading">
|
||||
<Icon type="spinner" spin />
|
||||
</div>
|
||||
)
|
||||
return <LoadingSpinner className="ms-auto me-auto" />
|
||||
}
|
||||
|
||||
if (!resolvedThreads.length) {
|
||||
|
|
|
@ -2,6 +2,8 @@ import { FC, memo } from 'react'
|
|||
import { Trans } from 'react-i18next'
|
||||
import { useEditorManagerContext } from '@/features/ide-react/context/editor-manager-context'
|
||||
import Icon from '@/shared/components/icon'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
|
||||
const ReviewPanelTrackChangesMenuButton: FC<{
|
||||
menuExpanded: boolean
|
||||
|
@ -26,7 +28,12 @@ const ReviewPanelTrackChangesMenuButton: FC<{
|
|||
components={{ strong: <strong /> }}
|
||||
/>
|
||||
)}
|
||||
<Icon type={menuExpanded ? 'angle-down' : 'angle-right'} />
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<Icon type={menuExpanded ? 'angle-down' : 'angle-right'} />}
|
||||
bs5={
|
||||
<MaterialIcon type={menuExpanded ? 'expand_more' : 'chevron_right'} />
|
||||
}
|
||||
/>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ const ReviewPanel: FC<{ mini?: boolean }> = ({ mini = false }) => {
|
|||
|
||||
return (
|
||||
<div className={className} style={style}>
|
||||
<div className="review-panel-inner">
|
||||
<div id="review-panel-inner" className="review-panel-inner">
|
||||
{!mini && <ReviewPanelHeader />}
|
||||
|
||||
{activeSubView === 'cur_file' && <ReviewPanelCurrentFile />}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import OLFormSwitch from '@/features/ui/components/ol/ol-form-switch'
|
||||
|
||||
type TrackChangesToggleProps = {
|
||||
id: string
|
||||
description: string
|
||||
|
@ -14,20 +16,13 @@ function TrackChangesToggle({
|
|||
value,
|
||||
}: TrackChangesToggleProps) {
|
||||
return (
|
||||
<div className="input-switch">
|
||||
<input
|
||||
id={`input-switch-${id}`}
|
||||
disabled={disabled}
|
||||
type="checkbox"
|
||||
autoComplete="off"
|
||||
className="input-switch-hidden-input"
|
||||
onChange={handleToggle}
|
||||
checked={value}
|
||||
/>
|
||||
<label htmlFor={`input-switch-${id}`} className="input-switch-btn">
|
||||
<span className="sr-only">{description}</span>
|
||||
</label>
|
||||
</div>
|
||||
<OLFormSwitch
|
||||
id={`input-switch-${id}`}
|
||||
disabled={disabled}
|
||||
onChange={handleToggle}
|
||||
checked={value}
|
||||
label={description}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -103,9 +103,11 @@ const ForwardReferredDropdownItem = fixedForwardRef(DropdownItem, {
|
|||
|
||||
export { ForwardReferredDropdownItem as DropdownItem }
|
||||
|
||||
export function DropdownToggle(props: DropdownToggleProps) {
|
||||
return <BS5DropdownToggle {...props} />
|
||||
}
|
||||
export const DropdownToggle = forwardRef<
|
||||
typeof BS5DropdownToggle,
|
||||
DropdownToggleProps
|
||||
>((props, ref) => <BS5DropdownToggle {...props} ref={ref} />)
|
||||
DropdownToggle.displayName = 'DropdownToggle'
|
||||
|
||||
export const DropdownMenu = forwardRef<
|
||||
typeof BS5DropdownMenu,
|
||||
|
|
|
@ -4,7 +4,7 @@ import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/boots
|
|||
import { getAriaAndDataProps } from '@/features/utils/bootstrap-5'
|
||||
|
||||
type OLFormCheckboxProps = React.ComponentProps<(typeof Form)['Check']> & {
|
||||
inputRef?: React.MutableRefObject<HTMLInputElement | undefined>
|
||||
inputRef?: React.MutableRefObject<HTMLInputElement | null>
|
||||
bs3Props?: Record<string, unknown>
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
import { FormCheck, FormCheckProps, FormLabel } from 'react-bootstrap-5'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
import { getAriaAndDataProps } from '@/features/utils/bootstrap-5'
|
||||
|
||||
type OLFormSwitchProps = FormCheckProps & {
|
||||
inputRef?: React.MutableRefObject<HTMLInputElement | null>
|
||||
bs3Props?: React.InputHTMLAttributes<HTMLInputElement>
|
||||
}
|
||||
|
||||
function OLFormSwitch(props: OLFormSwitchProps) {
|
||||
const { bs3Props, inputRef, label, id, ...rest } = props
|
||||
|
||||
const bs3FormSwitchProps: React.InputHTMLAttributes<HTMLInputElement> = {
|
||||
id,
|
||||
checked: rest.checked,
|
||||
required: rest.required,
|
||||
readOnly: rest.readOnly,
|
||||
disabled: rest.disabled,
|
||||
autoComplete: rest.autoComplete,
|
||||
defaultChecked: rest.defaultChecked,
|
||||
onChange: rest.onChange as (e: React.ChangeEvent<unknown>) => void,
|
||||
...getAriaAndDataProps(rest),
|
||||
...bs3Props,
|
||||
}
|
||||
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<div className="input-switch">
|
||||
<input
|
||||
id={id}
|
||||
type="checkbox"
|
||||
className="input-switch-hidden-input"
|
||||
ref={inputRef}
|
||||
{...bs3FormSwitchProps}
|
||||
/>
|
||||
<label htmlFor={id} className="input-switch-btn">
|
||||
<span className="sr-only">{label}</span>
|
||||
</label>
|
||||
</div>
|
||||
}
|
||||
bs5={
|
||||
<>
|
||||
<FormCheck type="switch" ref={inputRef} id={id} {...rest} />
|
||||
<FormLabel htmlFor={id} visuallyHidden>
|
||||
{label}
|
||||
</FormLabel>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default OLFormSwitch
|
31
services/web/frontend/stories/input-switch.stories.tsx
Normal file
31
services/web/frontend/stories/input-switch.stories.tsx
Normal file
|
@ -0,0 +1,31 @@
|
|||
import OLFormSwitch from '@/features/ui/components/ol/ol-form-switch'
|
||||
import { bsVersionDecorator } from '../../.storybook/utils/with-bootstrap-switcher'
|
||||
import { disableControlsOf } from './utils/arg-types'
|
||||
|
||||
export const Unchecked = () => {
|
||||
return <OLFormSwitch onChange={() => {}} checked={false} />
|
||||
}
|
||||
|
||||
export const UncheckedDisabled = () => {
|
||||
return <OLFormSwitch onChange={() => {}} checked={false} disabled />
|
||||
}
|
||||
|
||||
export const Checked = () => {
|
||||
return <OLFormSwitch onChange={() => {}} checked />
|
||||
}
|
||||
|
||||
export const CheckedDisabled = () => {
|
||||
return <OLFormSwitch onChange={() => {}} checked disabled />
|
||||
}
|
||||
|
||||
export default {
|
||||
title: 'Shared / Components / Input Switch',
|
||||
component: OLFormSwitch,
|
||||
argTypes: {
|
||||
...bsVersionDecorator.argTypes,
|
||||
...disableControlsOf('inputRef', 'bs3Props'),
|
||||
},
|
||||
args: {
|
||||
...bsVersionDecorator.args,
|
||||
},
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
import Switch from '../js/shared/components/switch'
|
||||
|
||||
export const Unchecked = () => {
|
||||
return <Switch onChange={() => {}} checked={false} />
|
||||
}
|
||||
|
||||
export const Checked = () => {
|
||||
return <Switch onChange={() => {}} checked />
|
||||
}
|
||||
|
||||
export default {
|
||||
title: 'Shared / Components / Switch',
|
||||
component: Switch,
|
||||
}
|
|
@ -86,7 +86,7 @@
|
|||
|
||||
.review-panel-entry-actions-icon {
|
||||
padding: @spacing-01;
|
||||
font-size: 20px;
|
||||
font-size: @font-size-05;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -111,7 +111,7 @@
|
|||
.review-panel-entry-icon {
|
||||
border-radius: @border-radius-base-new;
|
||||
padding: @spacing-02;
|
||||
font-size: 16px;
|
||||
font-size: @font-size-03;
|
||||
}
|
||||
|
||||
.review-panel-entry-change-icon {
|
||||
|
@ -138,7 +138,6 @@
|
|||
top: var(--review-panel-top);
|
||||
width: var(--review-panel-width);
|
||||
height: @review-panel-header-height;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
@ -187,7 +186,7 @@
|
|||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 14px;
|
||||
font-size: @font-size-02;
|
||||
|
||||
i {
|
||||
width: 8px;
|
||||
|
@ -202,7 +201,7 @@
|
|||
|
||||
.review-panel-label {
|
||||
font-family: Lato, sans-serif;
|
||||
font-size: 14px;
|
||||
font-size: @font-size-02;
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
}
|
||||
|
@ -245,10 +244,6 @@
|
|||
pointer-events: none;
|
||||
}
|
||||
|
||||
.review-panel-resolved-comments-loading {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.review-panel-resolved-comments-empty {
|
||||
text-align: center;
|
||||
}
|
||||
|
@ -472,7 +467,7 @@
|
|||
width: var(--review-panel-width);
|
||||
z-index: 2;
|
||||
background-color: white;
|
||||
border-top: 1px solid #d9d9d9;
|
||||
border-top: 1px solid @rp-border-grey;
|
||||
display: flex;
|
||||
|
||||
.review-panel-tab {
|
||||
|
@ -507,11 +502,6 @@
|
|||
min-height: 44px;
|
||||
}
|
||||
|
||||
.review-panel-add-comment {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.review-panel-add-comment-buttons {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
@ -545,12 +535,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
// Would not be migrated
|
||||
.review-panel-more-comments-button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 2px 8px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
&.review-panel-subview-overview {
|
||||
|
|
|
@ -6,6 +6,7 @@ $prefix: bs-;
|
|||
// Quickly modify global styling by enabling or disabling optional features.
|
||||
|
||||
$enable-validation-icons: false;
|
||||
$component-active-color: $white;
|
||||
|
||||
// Fonts
|
||||
$font-family-sans-serif: 'Noto Sans', sans-serif;
|
||||
|
@ -115,6 +116,15 @@ $form-check-input-border-radius: $border-radius-base;
|
|||
$form-check-input-focus-border: var(--border-primary);
|
||||
$form-check-input-disabled-opacity: 1;
|
||||
|
||||
// form-switch-variables
|
||||
$form-switch-width: 34px;
|
||||
$form-switch-padding-start: $spacing-03;
|
||||
$form-switch-color: $component-active-color;
|
||||
$form-switch-width: 34px;
|
||||
$form-switch-padding-start: $spacing-03;
|
||||
$form-switch-focus-color: $component-active-color;
|
||||
$form-switch-checked-color: $component-active-color;
|
||||
|
||||
// Form validation
|
||||
|
||||
// form-feedback-variables
|
||||
|
|
|
@ -73,6 +73,32 @@
|
|||
}
|
||||
}
|
||||
|
||||
.form-switch {
|
||||
.form-check-input {
|
||||
--bs-form-check-bg: var(--bg-dark-tertiary);
|
||||
|
||||
height: 20px;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
opacity: 0.32;
|
||||
background-color: var(--bg-dark-tertiary);
|
||||
|
||||
&:checked {
|
||||
background-color: var(--bg-accent-01);
|
||||
background-image: #{escape-svg(
|
||||
url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'><circle r='3' fill='#{$component-active-color}'/></svg>")
|
||||
)};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form-text {
|
||||
display: inline-flex;
|
||||
gap: $spacing-02;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
@import 'editor/publish-modal';
|
||||
@import 'editor/share';
|
||||
@import 'editor/tags-input';
|
||||
@import 'editor/review-panel-new';
|
||||
@import 'website-redesign';
|
||||
@import 'group-settings';
|
||||
@import 'templates-v2';
|
||||
|
|
|
@ -0,0 +1,638 @@
|
|||
.review-panel-new {
|
||||
$review-panel-header-height: 69px;
|
||||
|
||||
&.review-panel-container {
|
||||
height: 100%;
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.review-panel-inner {
|
||||
z-index: 6;
|
||||
flex-shrink: 0;
|
||||
background-color: var(--neutral-10);
|
||||
border-left: solid 0 var(--neutral-20);
|
||||
color: var(--content-primary);
|
||||
font-family: $font-family-base;
|
||||
line-height: $line-height-base;
|
||||
font-size: var(--font-size-01);
|
||||
box-sizing: content-box;
|
||||
width: var(--review-panel-width);
|
||||
min-height: var(--review-panel-height);
|
||||
|
||||
.dropdown-menu {
|
||||
z-index: 1;
|
||||
min-width: var(--bs-dropdown-min-width);
|
||||
}
|
||||
}
|
||||
|
||||
.review-panel-entry {
|
||||
background-color: var(--white);
|
||||
border-radius: var(--border-radius-base);
|
||||
border: 1px solid var(--neutral-20);
|
||||
padding: var(--spacing-04);
|
||||
width: calc(100% - var(--spacing-04));
|
||||
margin-left: var(--spacing-02);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.review-panel-entry.review-panel-entry-disabled {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.review-panel-entry-indicator {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.review-panel-entry-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: var(--font-size-01);
|
||||
gap: var(--spacing-04);
|
||||
}
|
||||
|
||||
.review-panel-entry-focused,
|
||||
.review-panel-entry-highlighted {
|
||||
margin-left: var(--spacing-01);
|
||||
border: 1px solid var(--border-active);
|
||||
}
|
||||
|
||||
.review-panel-entry-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: var(--spacing-01);
|
||||
|
||||
.review-panel-entry-user {
|
||||
color: var(--bg-info-01);
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
.review-panel-entry-time {
|
||||
color: var(--content-secondary);
|
||||
}
|
||||
|
||||
.review-panel-entry-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-03);
|
||||
|
||||
.btn {
|
||||
background-color: transparent;
|
||||
border-width: 0;
|
||||
padding: 0;
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: var(--neutral-20);
|
||||
color: var(--content-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-toggle::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.review-panel-entry-actions-icon {
|
||||
padding: var(--spacing-01);
|
||||
font-size: var(--font-size-05);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.review-panel-change-body {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
color: var(--content-secondary);
|
||||
gap: var(--spacing-02);
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.review-panel-content-highlight {
|
||||
color: var(--content-primary);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
del.review-panel-content-highlight {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.review-panel-entry-icon {
|
||||
border-radius: var(--border-radius-base);
|
||||
padding: var(--spacing-02);
|
||||
font-size: var(--font-size-03);
|
||||
}
|
||||
|
||||
.review-panel-entry-change-icon {
|
||||
margin-top: calc(-1 * var(--spacing-01));
|
||||
}
|
||||
|
||||
.review-panel-entry-icon-accept {
|
||||
background-color: var(--bg-accent-03);
|
||||
color: var(--bg-accent-01);
|
||||
}
|
||||
|
||||
.review-panel-entry-icon-reject {
|
||||
background-color: var(--bg-danger-03);
|
||||
color: var(--bg-danger-01);
|
||||
}
|
||||
|
||||
.review-panel-entry-icon-changed {
|
||||
background-color: var(--neutral-20);
|
||||
color: var(--content-secondary);
|
||||
}
|
||||
|
||||
.review-panel-header {
|
||||
position: fixed;
|
||||
top: var(--review-panel-top);
|
||||
width: var(--review-panel-width);
|
||||
height: $review-panel-header-height;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
border-bottom: 1px solid var(--rp-border-grey);
|
||||
background-color: white;
|
||||
text-align: center;
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
// TODO: Update this when we move the track changes menu to the new design
|
||||
.rp-tc-state {
|
||||
background-color: var(--white);
|
||||
max-height: calc(
|
||||
100vh - var(--review-panel-top) - $review-panel-header-height
|
||||
);
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.review-panel-tools {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-left: var(--spacing-02);
|
||||
padding-right: var(--spacing-05);
|
||||
flex-shrink: 0;
|
||||
flex-basis: 32px;
|
||||
}
|
||||
|
||||
.resolved-comments-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.track-changes-indicator-circle {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 100%;
|
||||
background-color: var(--bg-accent-01);
|
||||
}
|
||||
|
||||
.track-changes-menu-button {
|
||||
border: none;
|
||||
background: none;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-02);
|
||||
font-size: var(--font-size-02);
|
||||
|
||||
i {
|
||||
width: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.review-panel-heading {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: var(--spacing-03) var(--spacing-02);
|
||||
|
||||
.review-panel-label {
|
||||
font-size: var(--font-size-02);
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.review-panel-split-test-badge {
|
||||
margin-left: var(--spacing-02);
|
||||
}
|
||||
|
||||
.review-panel-close-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
color: var(--content-primary);
|
||||
padding: var(--spacing-01);
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: var(--neutral-20);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.review-panel-resolved-comments {
|
||||
--bs-popover-border-width: 1px;
|
||||
--bs-popover-bg: var(--bg-light-secondary);
|
||||
--bs-popover-body-color: var(--content-secondary);
|
||||
|
||||
width: 280px;
|
||||
|
||||
.popover-body {
|
||||
overflow-y: auto;
|
||||
max-height: calc(100vh - 180px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-02);
|
||||
padding: var(--spacing-04) var(--spacing-03);
|
||||
}
|
||||
}
|
||||
|
||||
.review-panel-resolved-disabled {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.review-panel-resolved-comments-empty {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.review-panel-resolved-comments-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: var(--spacing-02) 0;
|
||||
}
|
||||
|
||||
.review-panel-resolved-comments-label {
|
||||
font-weight: bold;
|
||||
font-size: var(--font-size-02);
|
||||
}
|
||||
|
||||
.review-panel-resolved-comments-count {
|
||||
background-color: var(--neutral-20);
|
||||
border-radius: var(--border-radius-base);
|
||||
padding: var(--spacing-01);
|
||||
}
|
||||
|
||||
.review-panel-resolved-comment {
|
||||
background-color: var(--white);
|
||||
border-radius: var(--border-radius-base);
|
||||
padding: var(--spacing-04);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--spacing-04);
|
||||
}
|
||||
|
||||
.review-panel-resolved-comment-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: var(--content-secondary);
|
||||
font-size: var(--font-size-01);
|
||||
}
|
||||
|
||||
.review-panel-resolved-comment-filename {
|
||||
color: var(--content-primary);
|
||||
}
|
||||
|
||||
.review-panel-resolved-comment-buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-03);
|
||||
|
||||
.btn {
|
||||
background-color: transparent;
|
||||
border-width: 0;
|
||||
color: var(--content-primary);
|
||||
padding: var(--spacing-01);
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: var(--neutral-20);
|
||||
}
|
||||
}
|
||||
|
||||
.material-symbols {
|
||||
font-size: var(--font-size-05);
|
||||
}
|
||||
}
|
||||
|
||||
.review-panel-resolved-comment-quoted-text {
|
||||
background-color: var(--neutral-20);
|
||||
border-radius: var(--border-radius-base);
|
||||
padding: var(--spacing-02) var(--spacing-04);
|
||||
}
|
||||
|
||||
.review-panel-resolved-comment-quoted-text-label {
|
||||
color: var(--content-secondary);
|
||||
font-size: var(--font-size-01);
|
||||
}
|
||||
|
||||
.review-panel-resolved-comment-quoted-text-quote {
|
||||
overflow-wrap: anywhere;
|
||||
font-size: var(--font-size-02);
|
||||
}
|
||||
|
||||
.review-panel-comment-wrapper {
|
||||
display: flex;
|
||||
gap: var(--spacing-04);
|
||||
}
|
||||
|
||||
.review-panel-comment {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.review-panel-comment-reply-divider {
|
||||
border-left: 2px solid var(--yellow-20);
|
||||
}
|
||||
|
||||
.review-panel-comment-body {
|
||||
font-size: var(--font-size-02);
|
||||
color: var(--content-primary);
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.review-panel-content-expandable {
|
||||
display: -webkit-box;
|
||||
text-overflow: ellipsis;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 3;
|
||||
line-clamp: 3;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.review-panel-content-expanded {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.review-panel-comment-input {
|
||||
width: 100%;
|
||||
font-size: var(--rp-base-font-size);
|
||||
padding: 2px var(--spacing-03);
|
||||
border-radius: var(--border-radius-base);
|
||||
border: solid 1px var(--neutral-60);
|
||||
resize: vertical;
|
||||
color: var(--rp-type-darkgrey);
|
||||
background-color: var(--white);
|
||||
height: 25px;
|
||||
min-height: 25px;
|
||||
overflow-x: hidden;
|
||||
max-height: 400px;
|
||||
}
|
||||
|
||||
.review-panel-empty-state {
|
||||
position: fixed;
|
||||
width: var(--review-panel-width);
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.review-panel-empty-state-inner {
|
||||
position: sticky;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 100%;
|
||||
padding-left: var(--spacing-06);
|
||||
padding-right: var(--spacing-06);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
|
||||
p {
|
||||
margin-bottom: 0;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.review-panel-empty-state-comment-icon {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
background-color: white;
|
||||
border-radius: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: var(--spacing-06);
|
||||
|
||||
.material-symbols {
|
||||
font-size: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
.review-panel-overview {
|
||||
padding: var(--spacing-02);
|
||||
position: absolute;
|
||||
top: $review-panel-header-height;
|
||||
bottom: 59px;
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
overscroll-behavior-block: none;
|
||||
|
||||
.review-panel-entry {
|
||||
margin-left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.review-panel-overview-file-header {
|
||||
all: unset;
|
||||
padding: var(--spacing-03) var(--spacing-04);
|
||||
font-size: var(--font-size-02);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-04);
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.review-panel-overfile-divider {
|
||||
border-bottom: 1px solid var(--border-divider);
|
||||
margin: var(--spacing-01) 0;
|
||||
}
|
||||
|
||||
.review-panel-overview-file-entries {
|
||||
overflow: hidden;
|
||||
padding-top: var(--spacing-02);
|
||||
padding-bottom: var(--spacing-03);
|
||||
}
|
||||
|
||||
.review-panel-overview-file-entry-count {
|
||||
background-color: var(--neutral-20);
|
||||
padding: var(--spacing-01) var(--spacing-02);
|
||||
margin-left: auto;
|
||||
border-radius: var(--border-radius-base);
|
||||
}
|
||||
|
||||
.review-panel-footer {
|
||||
position: fixed;
|
||||
height: 60px;
|
||||
bottom: 0;
|
||||
width: var(--review-panel-width);
|
||||
z-index: 2;
|
||||
background-color: white;
|
||||
border-top: 1px solid var(--rp-border-grey);
|
||||
display: flex;
|
||||
|
||||
.review-panel-tab {
|
||||
flex: 0 0 50%;
|
||||
padding: var(--spacing-03) 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: var(--spacing-02);
|
||||
border: 0;
|
||||
border-top: solid 3px transparent;
|
||||
background: none;
|
||||
color: var(--content-secondary);
|
||||
font-size: var(--font-size-02);
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
text-decoration: none;
|
||||
color: var(--content-primary);
|
||||
}
|
||||
|
||||
&-active {
|
||||
color: var(--content-primary);
|
||||
border-top: solid 3px var(--bg-accent-01);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.review-panel-add-comment-textarea {
|
||||
padding: var(--spacing-01) var(--spacing-03);
|
||||
resize: vertical;
|
||||
min-height: 44px;
|
||||
}
|
||||
|
||||
.review-panel-add-comment-buttons {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: var(--spacing-04);
|
||||
}
|
||||
|
||||
.review-panel-add-comment-cancel-button {
|
||||
background-color: transparent;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
background-color: var(--neutral-20);
|
||||
color: var(--content-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.review-panel-more-comments-button-container {
|
||||
position: fixed;
|
||||
width: var(--review-panel-width);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
z-index: 3;
|
||||
|
||||
&.downwards {
|
||||
// TODO: fix this to not use a magic number when we have updated the footer ui
|
||||
top: calc(100% - 102px);
|
||||
}
|
||||
|
||||
&.upwards {
|
||||
top: calc(var(--review-panel-top) + $review-panel-header-height + 16px);
|
||||
}
|
||||
}
|
||||
|
||||
&.review-panel-subview-overview {
|
||||
&.review-panel-container {
|
||||
overflow-y: hidden;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.review-panel-inner {
|
||||
min-height: auto;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
&.review-panel-mini {
|
||||
overflow: visible !important;
|
||||
|
||||
.review-panel-inner {
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
.review-panel-entry {
|
||||
margin-left: 0;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.review-panel-entry-indicator {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
display: flex;
|
||||
color: var(--content-secondary);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.review-panel-entry-content {
|
||||
display: none;
|
||||
background: var(--white);
|
||||
border: 1px solid var(--rp-border-grey);
|
||||
border-radius: var(--border-radius-base);
|
||||
width: 200px;
|
||||
padding: var(--spacing-02);
|
||||
}
|
||||
|
||||
.review-panel-entry-hover {
|
||||
.review-panel-entry-content {
|
||||
display: initial;
|
||||
position: absolute;
|
||||
left: -200px;
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.review-panel-more-comments-button-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.review-panel-footer {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.review-tooltip-menu {
|
||||
box-shadow: 0 2px 4px 0 #1e253029;
|
||||
border: none;
|
||||
border-radius: var(--border-radius-base);
|
||||
padding: var(--spacing-02);
|
||||
}
|
||||
|
||||
.review-tooltip-menu-button {
|
||||
background-color: inherit;
|
||||
border: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-01);
|
||||
padding: var(--spacing-01);
|
||||
}
|
||||
|
||||
.review-tooltip-add-comment-button {
|
||||
padding: var(--spacing-01) var(--spacing-04);
|
||||
}
|
||||
|
||||
.review-panel-tooltip {
|
||||
pointer-events: none; // this is to prevent mouseLeave event from firing when hovering over the tooltip
|
||||
}
|
|
@ -1,5 +1,11 @@
|
|||
@use 'sass:color';
|
||||
|
||||
:root {
|
||||
--review-icon: url('../../../../../public/img/ol-icons/review-icon-dark-theme.svg');
|
||||
--rp-base-font-size: var(--font-size-01);
|
||||
--rp-bg-dim-blue: #fafafa;
|
||||
--rp-border-grey: #d9d9d9;
|
||||
--rp-type-darkgrey: #3f3f3f;
|
||||
}
|
||||
|
||||
@include theme('light') {
|
||||
|
@ -15,6 +21,43 @@
|
|||
}
|
||||
}
|
||||
|
||||
$rp-type-blue: #6b7797;
|
||||
|
||||
.rp-tc-state {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
overflow: hidden;
|
||||
list-style: none;
|
||||
padding: 0 var(--spacing-03);
|
||||
margin: 0;
|
||||
border-bottom: 1px solid var(--rp-border-grey);
|
||||
background-color: var(--rp-bg-dim-blue);
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.rp-tc-state-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: var(--spacing-02) 0;
|
||||
|
||||
&:last-of-type {
|
||||
padding-bottom: var(--spacing-03);
|
||||
}
|
||||
}
|
||||
|
||||
.rp-tc-state-item-name {
|
||||
@extend .text-truncate;
|
||||
|
||||
flex-grow: 1;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.rp-tc-state-item-name-disabled {
|
||||
opacity: 0.35;
|
||||
}
|
||||
|
||||
.review-icon {
|
||||
display: inline-block;
|
||||
background-image: var(--review-icon);
|
||||
|
@ -27,3 +70,22 @@
|
|||
content: '\00a0'; // Non-breakable space. A non-breakable character here makes this icon work like font-awesome.
|
||||
}
|
||||
}
|
||||
|
||||
.resolved-comments-toggle {
|
||||
background-color: var(--bg-light-secondary);
|
||||
font-size: var(--font-size-02);
|
||||
color: color.adjust($rp-type-blue, $lightness: 25%);
|
||||
border: solid 1px var(--rp-border-grey);
|
||||
border-radius: var(--border-radius-base);
|
||||
padding: 0 var(--spacing-02);
|
||||
display: block;
|
||||
height: 22px;
|
||||
width: 22px;
|
||||
line-height: 1.4;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
text-decoration: none;
|
||||
color: $rp-type-blue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
.input-switch {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
padding-left: 5px;
|
||||
}
|
||||
.input-switch-hidden-input {
|
||||
|
|
Loading…
Reference in a new issue