feat: 2.0 popover style updates (#3404)
This commit is contained in:
@@ -11,16 +11,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.popup--active .array-actions__button {
|
||||
background: var(--theme-elevation-0);
|
||||
}
|
||||
|
||||
&__button,
|
||||
&__action {
|
||||
@extend %btn-reset;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&__actions {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
@@ -28,9 +18,6 @@
|
||||
}
|
||||
|
||||
&__action {
|
||||
@extend %btn-reset;
|
||||
display: block;
|
||||
|
||||
svg {
|
||||
position: relative;
|
||||
top: -1px;
|
||||
@@ -40,10 +27,6 @@
|
||||
stroke-width: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
|
||||
&__move-up {
|
||||
|
||||
@@ -9,6 +9,7 @@ import More from '../../icons/More'
|
||||
import Plus from '../../icons/Plus'
|
||||
import X from '../../icons/X'
|
||||
import Popup from '../Popup'
|
||||
import * as PopupList from '../Popup/PopupButtonList'
|
||||
import './index.scss'
|
||||
|
||||
const baseClass = 'array-actions'
|
||||
@@ -31,73 +32,69 @@ export const ArrayAction: React.FC<Props> = ({
|
||||
horizontalAlign="center"
|
||||
render={({ close }) => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<PopupList.ButtonGroup buttonSize="small">
|
||||
{index !== 0 && (
|
||||
<button
|
||||
<PopupList.Button
|
||||
className={`${baseClass}__action ${baseClass}__move-up`}
|
||||
onClick={() => {
|
||||
moveRow(index, index - 1)
|
||||
close()
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
<Chevron />
|
||||
{t('moveUp')}
|
||||
</button>
|
||||
</PopupList.Button>
|
||||
)}
|
||||
{index < rowCount - 1 && (
|
||||
<button
|
||||
className={`${baseClass}__action ${baseClass}__move-down`}
|
||||
<PopupList.Button
|
||||
className={`${baseClass}__action`}
|
||||
onClick={() => {
|
||||
moveRow(index, index + 1)
|
||||
close()
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
<Chevron />
|
||||
{t('moveDown')}
|
||||
</button>
|
||||
</PopupList.Button>
|
||||
)}
|
||||
{!hasMaxRows && (
|
||||
<React.Fragment>
|
||||
<button
|
||||
<PopupList.Button
|
||||
className={`${baseClass}__action ${baseClass}__add`}
|
||||
onClick={() => {
|
||||
addRow(index + 1)
|
||||
close()
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
<Plus />
|
||||
{t('addBelow')}
|
||||
</button>
|
||||
<button
|
||||
</PopupList.Button>
|
||||
<PopupList.Button
|
||||
className={`${baseClass}__action ${baseClass}__duplicate`}
|
||||
onClick={() => {
|
||||
duplicateRow(index)
|
||||
close()
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
<Copy />
|
||||
{t('duplicate')}
|
||||
</button>
|
||||
</PopupList.Button>
|
||||
</React.Fragment>
|
||||
)}
|
||||
<button
|
||||
<PopupList.Button
|
||||
className={`${baseClass}__action ${baseClass}__remove`}
|
||||
onClick={() => {
|
||||
removeRow(index)
|
||||
close()
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
<X />
|
||||
{t('remove')}
|
||||
</button>
|
||||
</React.Fragment>
|
||||
</PopupList.Button>
|
||||
</PopupList.ButtonGroup>
|
||||
)
|
||||
}}
|
||||
size="medium"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -73,13 +73,14 @@
|
||||
}
|
||||
|
||||
&__controls-wrapper {
|
||||
--controls-gap: calc(var(--base) / 2);
|
||||
--dot-button-width: calc(var(--base) * 2);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0;
|
||||
// move to the right to account for the padding on the dots
|
||||
// this will make sure the alignment is correct
|
||||
// while still keeping a large button hitbox
|
||||
transform: translate3d(var(--base), 0, 0);
|
||||
gap: var(--controls-gap);
|
||||
padding-right: calc(var(--controls-gap) + var(--dot-button-width));
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&__controls {
|
||||
@@ -94,27 +95,20 @@
|
||||
}
|
||||
}
|
||||
|
||||
&__popup {
|
||||
.popup-button {
|
||||
padding: var(--base);
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
color: var(--theme-elevation-500);
|
||||
|
||||
&:hover {
|
||||
color: var(--theme-text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__dots {
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
|
||||
> div {
|
||||
.btn__label {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
> span > span > div {
|
||||
width: 3px;
|
||||
height: 3px;
|
||||
border-radius: 100%;
|
||||
@@ -122,49 +116,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
&__popup-actions {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: calc(var(--base) / 4);
|
||||
&__popup {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: var(--dot-button-width);
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
li {
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border-radius: 1px;
|
||||
background: var(--theme-elevation-100);
|
||||
width: calc(100% + (var(--base) / 2));
|
||||
left: calc(var(--base) / -4);
|
||||
top: 0;
|
||||
opacity: 0;
|
||||
transition: opacity 50ms linear;
|
||||
}
|
||||
|
||||
&:hover::before {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
> * {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: left;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
font-family: inherit;
|
||||
}
|
||||
.popup__trigger-wrap {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import React, { Fragment } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
import type { CollectionPermission, GlobalPermission } from '../../../../auth'
|
||||
import type { SanitizedCollectionConfig, SanitizedGlobalConfig } from '../../../../exports/types'
|
||||
@@ -9,10 +8,12 @@ import { formatDate } from '../../../utilities/formatDate'
|
||||
import { useConfig } from '../../utilities/Config'
|
||||
import { useDocumentInfo } from '../../utilities/DocumentInfo'
|
||||
import Autosave from '../Autosave'
|
||||
import Button from '../Button'
|
||||
import DeleteDocument from '../DeleteDocument'
|
||||
import DuplicateDocument from '../DuplicateDocument'
|
||||
import { Gutter } from '../Gutter'
|
||||
import Popup from '../Popup'
|
||||
import * as PopupList from '../Popup/PopupButtonList'
|
||||
import PreviewButton from '../PreviewButton'
|
||||
import { Publish } from '../Publish'
|
||||
import { Save } from '../Save'
|
||||
@@ -30,9 +31,9 @@ export const DocumentControls: React.FC<{
|
||||
global?: SanitizedGlobalConfig
|
||||
hasSavePermission?: boolean
|
||||
id?: string
|
||||
isAccountView?: boolean
|
||||
isEditing?: boolean
|
||||
permissions?: CollectionPermission | GlobalPermission
|
||||
isAccountView?: boolean
|
||||
}> = (props) => {
|
||||
const {
|
||||
id,
|
||||
@@ -41,9 +42,9 @@ export const DocumentControls: React.FC<{
|
||||
disableActions,
|
||||
global,
|
||||
hasSavePermission,
|
||||
isAccountView,
|
||||
isEditing,
|
||||
permissions,
|
||||
isAccountView,
|
||||
} = props
|
||||
|
||||
const { publishedDoc } = useDocumentInfo()
|
||||
@@ -73,6 +74,8 @@ export const DocumentControls: React.FC<{
|
||||
!global?.versions?.drafts?.autosave
|
||||
}
|
||||
|
||||
const showDotMenu = Boolean(collection && !disableActions)
|
||||
|
||||
return (
|
||||
<Gutter className={baseClass}>
|
||||
<div className={`${baseClass}__wrapper`}>
|
||||
@@ -187,49 +190,47 @@ export const DocumentControls: React.FC<{
|
||||
</React.Fragment>
|
||||
)}
|
||||
</div>
|
||||
{Boolean(collection && !disableActions) && (
|
||||
{showDotMenu && (
|
||||
<Popup
|
||||
button={
|
||||
<div className={`${baseClass}__dots`}>
|
||||
<Button buttonStyle="secondary" className={`${baseClass}__dots`} el="div">
|
||||
<div />
|
||||
<div />
|
||||
<div />
|
||||
</div>
|
||||
</Button>
|
||||
}
|
||||
caret={false}
|
||||
className={`${baseClass}__popup`}
|
||||
horizontalAlign="center"
|
||||
horizontalAlign="right"
|
||||
size="large"
|
||||
verticalAlign="bottom"
|
||||
>
|
||||
<ul className={`${baseClass}__popup-actions`}>
|
||||
<PopupList.ButtonGroup>
|
||||
{'create' in permissions && permissions?.create?.permission && (
|
||||
<React.Fragment>
|
||||
<li>
|
||||
<Link
|
||||
id="action-create"
|
||||
to={`${adminRoute}/collections/${collection?.slug}/create`}
|
||||
>
|
||||
{t('createNew')}
|
||||
</Link>
|
||||
</li>
|
||||
<PopupList.Button
|
||||
id="action-create"
|
||||
to={`${adminRoute}/collections/${collection?.slug}/create`}
|
||||
>
|
||||
{t('createNew')}
|
||||
</PopupList.Button>
|
||||
|
||||
{!collection?.admin?.disableDuplicate && isEditing && (
|
||||
<li>
|
||||
<PopupList.Button>
|
||||
<DuplicateDocument
|
||||
collection={collection}
|
||||
id={id}
|
||||
slug={collection?.slug}
|
||||
/>
|
||||
</li>
|
||||
</PopupList.Button>
|
||||
)}
|
||||
</React.Fragment>
|
||||
)}
|
||||
{'delete' in permissions && permissions?.delete?.permission && id && (
|
||||
<li>
|
||||
<PopupList.Button>
|
||||
<DeleteDocument buttonId="action-delete" collection={collection} id={id} />
|
||||
</li>
|
||||
</PopupList.Button>
|
||||
)}
|
||||
</ul>
|
||||
</PopupList.ButtonGroup>
|
||||
</Popup>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
button {
|
||||
color: currentColor;
|
||||
padding: base(0.25) 0;
|
||||
padding: 0;
|
||||
font-size: 1rem;
|
||||
line-height: base(1);
|
||||
background: transparent;
|
||||
@@ -39,33 +39,10 @@
|
||||
|
||||
&__button {
|
||||
white-space: nowrap;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
span {
|
||||
color: var(--theme-elevation-400);
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
max-height: base(8);
|
||||
margin: 0;
|
||||
|
||||
li a {
|
||||
all: unset;
|
||||
cursor: pointer;
|
||||
padding-right: 0;
|
||||
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include mid-break {
|
||||
.popup__content {
|
||||
width: calc(100vw - calc(var(--gutter-h) * 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import qs from 'qs'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
import { Chevron } from '../..'
|
||||
import { useConfig } from '../../utilities/Config'
|
||||
import { useLocale } from '../../utilities/Locale'
|
||||
import { useSearchParams } from '../../utilities/SearchParams'
|
||||
import Popup from '../Popup'
|
||||
import * as PopupList from '../Popup/PopupButtonList'
|
||||
import './index.scss'
|
||||
|
||||
const baseClass = 'localizer'
|
||||
@@ -37,20 +37,10 @@ const Localizer: React.FC<{
|
||||
<Chevron className={`${baseClass}__chevron`} />
|
||||
</div>
|
||||
}
|
||||
caret={false}
|
||||
horizontalAlign="left"
|
||||
horizontalAlign="right"
|
||||
render={({ close }) => (
|
||||
<ul>
|
||||
<PopupList.ButtonGroup>
|
||||
{locales.map((localeOption) => {
|
||||
const baseLocaleClass = `${baseClass}__locale`
|
||||
|
||||
const localeClasses = [
|
||||
baseLocaleClass,
|
||||
locale.code === localeOption.code && `${baseLocaleClass}--active`,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join('')
|
||||
|
||||
const newParams = {
|
||||
...searchParams,
|
||||
locale: localeOption.code,
|
||||
@@ -60,20 +50,19 @@ const Localizer: React.FC<{
|
||||
|
||||
if (localeOption.code !== locale.code) {
|
||||
return (
|
||||
<li className={localeClasses} key={localeOption.code}>
|
||||
<Link onClick={close} to={{ search }}>
|
||||
{localeOption.label}
|
||||
{localeOption.label !== localeOption.code && ` (${localeOption.code})`}
|
||||
</Link>
|
||||
</li>
|
||||
<PopupList.Button key={localeOption.code} onClick={close} to={{ search }}>
|
||||
{localeOption.label}
|
||||
{localeOption.label !== localeOption.code && ` (${localeOption.code})`}
|
||||
</PopupList.Button>
|
||||
)
|
||||
}
|
||||
|
||||
return null
|
||||
})}
|
||||
</ul>
|
||||
</PopupList.ButtonGroup>
|
||||
)}
|
||||
showScrollbar
|
||||
size="large"
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -7,12 +7,6 @@
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.popup-button--default {
|
||||
@extend %btn-reset;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&__button {
|
||||
@extend %btn-reset;
|
||||
cursor: pointer;
|
||||
|
||||
@@ -7,6 +7,7 @@ import { defaults } from '../../../../collections/config/defaults'
|
||||
import Chevron from '../../icons/Chevron'
|
||||
import { useSearchParams } from '../../utilities/SearchParams'
|
||||
import Popup from '../Popup'
|
||||
import * as PopupList from '../Popup/PopupButtonList'
|
||||
import './index.scss'
|
||||
|
||||
const baseClass = 'per-page'
|
||||
@@ -43,43 +44,37 @@ const PerPage: React.FC<Props> = ({
|
||||
}
|
||||
horizontalAlign="right"
|
||||
render={({ close }) => (
|
||||
<div>
|
||||
<ul>
|
||||
{limits.map((limitNumber, i) => (
|
||||
<li className={`${baseClass}-item`} key={i}>
|
||||
<button
|
||||
className={[
|
||||
`${baseClass}__button`,
|
||||
limitNumber === Number(limit) && `${baseClass}__button-active`,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' ')}
|
||||
onClick={() => {
|
||||
close()
|
||||
if (handleChange) handleChange(limitNumber)
|
||||
if (modifySearchParams) {
|
||||
history.replace({
|
||||
search: qs.stringify(
|
||||
{
|
||||
...params,
|
||||
limit: limitNumber,
|
||||
page: resetPage ? 1 : params.page,
|
||||
},
|
||||
{ addQueryPrefix: true },
|
||||
),
|
||||
})
|
||||
}
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
{limitNumber === Number(limit) && <Chevron />}
|
||||
{limitNumber}
|
||||
</button>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<PopupList.ButtonGroup>
|
||||
{limits.map((limitNumber, i) => (
|
||||
<PopupList.Button
|
||||
className={[limitNumber === Number(limit) && `${baseClass}__button-active`]
|
||||
.filter(Boolean)
|
||||
.join(' ')}
|
||||
key={i}
|
||||
onClick={() => {
|
||||
close()
|
||||
if (handleChange) handleChange(limitNumber)
|
||||
if (modifySearchParams) {
|
||||
history.replace({
|
||||
search: qs.stringify(
|
||||
{
|
||||
...params,
|
||||
limit: limitNumber,
|
||||
page: resetPage ? 1 : params.page,
|
||||
},
|
||||
{ addQueryPrefix: true },
|
||||
),
|
||||
})
|
||||
}
|
||||
}}
|
||||
>
|
||||
{limitNumber === Number(limit) && <Chevron />}
|
||||
{limitNumber}
|
||||
</PopupList.Button>
|
||||
))}
|
||||
</PopupList.ButtonGroup>
|
||||
)}
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
@import '../../../../scss/styles.scss';
|
||||
|
||||
.popup-button {
|
||||
display: inline-flex;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
@import '../../../../scss/styles.scss';
|
||||
|
||||
.popup-button-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
text-align: left;
|
||||
--list-button-padding: calc(var(--base) * 0.5);
|
||||
|
||||
&__text-align--left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
&__text-align--center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
&__text-align--right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
&__button {
|
||||
@extend %btn-reset;
|
||||
padding-left: var(--list-button-padding);
|
||||
padding-right: var(--list-button-padding);
|
||||
padding-top: 2px;
|
||||
padding-bottom: 2px;
|
||||
cursor: pointer;
|
||||
text-align: inherit;
|
||||
line-height: var(--base);
|
||||
text-decoration: none;
|
||||
border-radius: 3px;
|
||||
|
||||
button {
|
||||
@extend %btn-reset;
|
||||
|
||||
&:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover,
|
||||
&:focus-visible,
|
||||
&:focus-within {
|
||||
background-color: var(--popup-button-highlight);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
import type { LinkProps } from 'react-router-dom'
|
||||
|
||||
import * as React from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
|
||||
import './index.scss'
|
||||
|
||||
const baseClass = 'popup-button-list'
|
||||
export const ButtonGroup: React.FC<{
|
||||
buttonSize?: 'default' | 'small'
|
||||
children: React.ReactNode
|
||||
className?: string
|
||||
textAlign?: 'center' | 'left' | 'right'
|
||||
}> = ({ buttonSize = 'default', children, className, textAlign = 'left' }) => {
|
||||
const classes = [
|
||||
baseClass,
|
||||
className,
|
||||
`${baseClass}__text-align--${textAlign}`,
|
||||
`${baseClass}__button-size--${buttonSize}`,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(' ')
|
||||
return <div className={classes}>{children}</div>
|
||||
}
|
||||
|
||||
type MenuButtonProps = {
|
||||
children: React.ReactNode
|
||||
className?: string
|
||||
id?: string
|
||||
onClick?: () => void
|
||||
to?: LinkProps['to']
|
||||
}
|
||||
export const Button: React.FC<MenuButtonProps> = ({ id, children, className, onClick, to }) => {
|
||||
const classes = [`${baseClass}__button`, className].filter(Boolean).join(' ')
|
||||
|
||||
if (to) {
|
||||
return (
|
||||
<Link
|
||||
className={classes}
|
||||
id={id}
|
||||
onClick={() => {
|
||||
if (onClick) {
|
||||
onClick()
|
||||
}
|
||||
}}
|
||||
to={to}
|
||||
>
|
||||
{children}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
if (onClick) {
|
||||
return (
|
||||
<button
|
||||
className={classes}
|
||||
id={id}
|
||||
onClick={() => {
|
||||
if (onClick) {
|
||||
onClick()
|
||||
}
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classes} id={id}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
@import '../../../../scss/styles.scss';
|
||||
|
||||
.popup-button {
|
||||
height: 100%;
|
||||
color: currentColor;
|
||||
padding: 0;
|
||||
font-size: 1rem;
|
||||
line-height: base(1);
|
||||
background: transparent;
|
||||
border: 0;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
display: inline-flex;
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import './index.scss'
|
||||
|
||||
const baseClass = 'popup-button'
|
||||
|
||||
const PopupButton: React.FC<Props> = (props) => {
|
||||
export const PopupTrigger: React.FC<Props> = (props) => {
|
||||
const { active, button, buttonType, className, setActive } = props
|
||||
|
||||
const classes = [baseClass, className, `${baseClass}--${buttonType}`].filter(Boolean).join(' ')
|
||||
@@ -41,5 +41,3 @@ const PopupButton: React.FC<Props> = (props) => {
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
export default PopupButton
|
||||
@@ -1,43 +1,48 @@
|
||||
@import '../../../scss/styles.scss';
|
||||
|
||||
.popup {
|
||||
--popup-button-highlight: var(--theme-elevation-200);
|
||||
--popup-bg: var(--theme-input-bg);
|
||||
--popup-text: var(--theme-text);
|
||||
--popup-caret-size: 10px;
|
||||
--popup-x-padding: calc(var(--base) * 0.33);
|
||||
--popup-padding: calc(var(--base) * 0.5);
|
||||
position: relative;
|
||||
|
||||
&__content {
|
||||
position: absolute;
|
||||
background: var(--theme-input-bg);
|
||||
background: var(--popup-bg);
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
pointer-events: none;
|
||||
z-index: var(--z-popup);
|
||||
max-width: calc(100vw - #{$baseline});
|
||||
|
||||
&--caret {
|
||||
&:after {
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
top: calc(100% - 1px);
|
||||
border: 12px solid transparent;
|
||||
border-top-color: var(--theme-input-bg);
|
||||
}
|
||||
}
|
||||
color: var(--popup-text);
|
||||
border-radius: 4px;
|
||||
padding-left: var(--popup-padding);
|
||||
padding-right: var(--popup-padding);
|
||||
min-width: var(--popup-width, auto);
|
||||
}
|
||||
|
||||
&__wrap {
|
||||
&__hide-scrollbar {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.popup__scroll {
|
||||
padding: $baseline;
|
||||
&__scroll-container {
|
||||
overflow-y: auto;
|
||||
white-space: nowrap;
|
||||
padding-right: calc(var(--scrollbar-width) + #{$baseline});
|
||||
width: calc(100% + var(--scrollbar-width));
|
||||
padding-top: var(--popup-padding);
|
||||
padding-bottom: var(--popup-padding);
|
||||
}
|
||||
|
||||
&__scroll-content {
|
||||
width: calc(100% - var(--scrollbar-width));
|
||||
}
|
||||
|
||||
&--show-scrollbar {
|
||||
.popup__scroll {
|
||||
padding-right: 0;
|
||||
.popup__scroll-container,
|
||||
.popup__scroll-content {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
@@ -52,63 +57,24 @@
|
||||
////////////////////////////////
|
||||
|
||||
&--size-small {
|
||||
.popup__scroll {
|
||||
[dir='ltr'] & {
|
||||
padding: base(0.75) calc(var(--scrollbar-width) + #{base(0.75)}) base(0.75) base(0.75);
|
||||
}
|
||||
[dir='rtl'] & {
|
||||
padding: base(0.75) base(0.75) base(0.75) calc(var(--scrollbar-width) + #{base(0.75)});
|
||||
}
|
||||
}
|
||||
|
||||
--popup-width: 100px;
|
||||
.popup__content {
|
||||
@include shadow-m;
|
||||
}
|
||||
}
|
||||
|
||||
&.popup--h-align-left {
|
||||
.popup__content {
|
||||
left: - base(0.5);
|
||||
|
||||
&:after {
|
||||
left: base(0.425);
|
||||
}
|
||||
}
|
||||
&--size-medium {
|
||||
--popup-width: 150px;
|
||||
.popup__content {
|
||||
@include shadow-lg;
|
||||
}
|
||||
}
|
||||
|
||||
&--size-large {
|
||||
--popup-width: 200px;
|
||||
.popup__content {
|
||||
@include shadow-lg;
|
||||
}
|
||||
|
||||
.popup__scroll {
|
||||
padding: base(1) calc(var(--scrollbar-width) + #{base(1.5)}) base(1) base(1.5);
|
||||
}
|
||||
}
|
||||
|
||||
&--size-wide {
|
||||
.popup__content {
|
||||
@include shadow-m;
|
||||
|
||||
&:after {
|
||||
border: 12px solid transparent;
|
||||
border-top-color: var(--theme-input-bg);
|
||||
}
|
||||
}
|
||||
|
||||
.popup__scroll {
|
||||
padding: base(0.25) base(0.5);
|
||||
}
|
||||
|
||||
&.popup--align-left {
|
||||
.popup__content {
|
||||
left: - base(0.5);
|
||||
|
||||
&:after {
|
||||
left: base(0.425);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
@@ -116,12 +82,8 @@
|
||||
////////////////////////////////
|
||||
|
||||
&--h-align-left {
|
||||
.popup__content {
|
||||
left: - base(1.75);
|
||||
|
||||
&:after {
|
||||
left: base(1.75);
|
||||
}
|
||||
.popup__caret {
|
||||
left: var(--popup-padding);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,26 +91,21 @@
|
||||
.popup__content {
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
&:after {
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
.popup__caret {
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
&--h-align-right {
|
||||
.popup__content {
|
||||
right: - base(1.75);
|
||||
[dir='rtl'] & {
|
||||
right: - base(0.75);
|
||||
}
|
||||
&:after {
|
||||
right: base(1.75);
|
||||
[dir='rtl'] & {
|
||||
right: base(0.75);
|
||||
}
|
||||
}
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.popup__caret {
|
||||
right: var(--popup-padding);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,46 +113,32 @@
|
||||
// VERTICAL ALIGNMENT
|
||||
////////////////////////////////
|
||||
|
||||
&__caret {
|
||||
position: absolute;
|
||||
border: var(--popup-caret-size) solid transparent;
|
||||
}
|
||||
|
||||
&--v-align-top {
|
||||
.popup__content {
|
||||
bottom: calc(100% + #{$baseline});
|
||||
@include shadow-lg;
|
||||
bottom: calc(100% + var(--popup-caret-size));
|
||||
}
|
||||
|
||||
.popup__caret {
|
||||
top: calc(100% - 1px);
|
||||
border-top-color: var(--popup-bg);
|
||||
}
|
||||
}
|
||||
|
||||
&--v-align-bottom {
|
||||
.popup__content {
|
||||
@include shadow-lg-top;
|
||||
top: calc(100% + #{base(0.5)});
|
||||
|
||||
&:after {
|
||||
top: unset;
|
||||
bottom: calc(100% - 1px);
|
||||
border-top-color: transparent !important;
|
||||
border-bottom-color: var(--theme-input-bg);
|
||||
}
|
||||
top: calc(100% + var(--popup-caret-size));
|
||||
}
|
||||
|
||||
&.popup--color-dark {
|
||||
.popup__content {
|
||||
&:after {
|
||||
border-bottom-color: var(--theme-elevation-800);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
// COLOR
|
||||
////////////////////////////////
|
||||
|
||||
&--color-dark {
|
||||
.popup__content {
|
||||
background: var(--theme-elevation-800);
|
||||
color: var(--theme-input-bg);
|
||||
|
||||
&:after {
|
||||
border-top-color: var(--theme-elevation-800);
|
||||
}
|
||||
.popup__caret {
|
||||
bottom: calc(100% - 1px);
|
||||
border-bottom-color: var(--popup-bg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,69 +155,55 @@
|
||||
}
|
||||
|
||||
@include mid-break {
|
||||
&__scroll,
|
||||
&--size-large .popup__scroll {
|
||||
padding: base(0.75);
|
||||
padding-right: calc(var(--scrollbar-width) + #{base(0.75)});
|
||||
}
|
||||
|
||||
&--h-align-left {
|
||||
.popup__content {
|
||||
left: - base(0.5);
|
||||
|
||||
&:after {
|
||||
left: base(0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
--popup-padding: calc(var(--base) * 0.25);
|
||||
|
||||
&--h-align-center {
|
||||
.popup__content {
|
||||
left: 50%;
|
||||
transform: translateX(-0%);
|
||||
}
|
||||
|
||||
&:after {
|
||||
left: 50%;
|
||||
transform: translateX(-0%);
|
||||
}
|
||||
.popup__caret {
|
||||
left: 50%;
|
||||
transform: translateX(-0%);
|
||||
}
|
||||
}
|
||||
|
||||
&--h-align-right {
|
||||
.popup__content {
|
||||
right: - base(0.5);
|
||||
right: 0;
|
||||
}
|
||||
|
||||
&:after {
|
||||
right: base(0.5);
|
||||
}
|
||||
.popup__caret {
|
||||
right: var(--popup-padding);
|
||||
}
|
||||
}
|
||||
|
||||
&--force-h-align-left {
|
||||
.popup__content {
|
||||
left: - base(0.5);
|
||||
left: 0;
|
||||
right: unset;
|
||||
transform: unset;
|
||||
}
|
||||
|
||||
&:after {
|
||||
left: base(0.5);
|
||||
right: unset;
|
||||
transform: unset;
|
||||
}
|
||||
.popup__caret {
|
||||
left: var(--popup-padding);
|
||||
right: unset;
|
||||
transform: unset;
|
||||
}
|
||||
}
|
||||
|
||||
&--force-h-align-right {
|
||||
.popup__content {
|
||||
right: - base(0.5);
|
||||
right: 0;
|
||||
left: unset;
|
||||
transform: unset;
|
||||
}
|
||||
|
||||
&:after {
|
||||
right: base(0.5);
|
||||
left: unset;
|
||||
transform: unset;
|
||||
}
|
||||
.popup__caret {
|
||||
right: var(--popup-padding);
|
||||
left: unset;
|
||||
transform: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import type { Props } from './types'
|
||||
|
||||
import useIntersect from '../../../hooks/useIntersect'
|
||||
import PopupButton from './PopupButton'
|
||||
import { PopupTrigger } from './PopupTrigger'
|
||||
import './index.scss'
|
||||
|
||||
const baseClass = 'popup'
|
||||
@@ -18,16 +18,14 @@ const Popup: React.FC<Props> = (props) => {
|
||||
caret = true,
|
||||
children,
|
||||
className,
|
||||
color = 'light',
|
||||
forceOpen,
|
||||
horizontalAlign: horizontalAlignFromProps = 'left',
|
||||
initActive = false,
|
||||
onToggleOpen,
|
||||
padding,
|
||||
render,
|
||||
showOnHover = false,
|
||||
showScrollbar = false,
|
||||
size = 'small',
|
||||
size = 'medium',
|
||||
verticalAlign: verticalAlignFromProps = 'top',
|
||||
} = props
|
||||
|
||||
@@ -38,7 +36,6 @@ const Popup: React.FC<Props> = (props) => {
|
||||
threshold: 1,
|
||||
})
|
||||
|
||||
const buttonRef = useRef(null)
|
||||
const contentRef = useRef(null)
|
||||
const [active, setActive] = useState(initActive)
|
||||
const [verticalAlign, setVerticalAlign] = useState(verticalAlignFromProps)
|
||||
@@ -57,8 +54,8 @@ const Popup: React.FC<Props> = (props) => {
|
||||
} = bounds
|
||||
|
||||
let boundingTopPos = 100
|
||||
let boundingRightPos = window.innerWidth
|
||||
let boundingBottomPos = window.innerHeight
|
||||
let boundingRightPos = document.documentElement.clientWidth
|
||||
let boundingBottomPos = document.documentElement.clientHeight
|
||||
let boundingLeftPos = 0
|
||||
|
||||
if (boundingRef?.current) {
|
||||
@@ -131,7 +128,6 @@ const Popup: React.FC<Props> = (props) => {
|
||||
baseClass,
|
||||
className,
|
||||
`${baseClass}--size-${size}`,
|
||||
`${baseClass}--color-${color}`,
|
||||
`${baseClass}--v-align-${verticalAlign}`,
|
||||
`${baseClass}--h-align-${horizontalAlign}`,
|
||||
active && `${baseClass}--active`,
|
||||
@@ -142,39 +138,35 @@ const Popup: React.FC<Props> = (props) => {
|
||||
|
||||
return (
|
||||
<div className={classes}>
|
||||
<div className={`${baseClass}__wrapper`} ref={buttonRef}>
|
||||
<div className={`${baseClass}__trigger-wrap`}>
|
||||
{showOnHover ? (
|
||||
<div
|
||||
className={`${baseClass}__on-hover-watch`}
|
||||
onMouseEnter={() => setActive(true)}
|
||||
onMouseLeave={() => setActive(false)}
|
||||
>
|
||||
<PopupButton
|
||||
<PopupTrigger
|
||||
{...{ active, button, buttonType, className: buttonClassName, setActive }}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<PopupButton {...{ active, button, buttonType, className: buttonClassName, setActive }} />
|
||||
<PopupTrigger
|
||||
{...{ active, button, buttonType, className: buttonClassName, setActive }}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div
|
||||
className={[`${baseClass}__content`, caret && `${baseClass}__content--caret`]
|
||||
.filter(Boolean)
|
||||
.join(' ')}
|
||||
ref={contentRef}
|
||||
>
|
||||
<div className={`${baseClass}__wrap`} ref={intersectionRef}>
|
||||
<div
|
||||
className={`${baseClass}__scroll`}
|
||||
style={{
|
||||
padding,
|
||||
}}
|
||||
>
|
||||
{render && render({ close: () => setActive(false) })}
|
||||
{children && children}
|
||||
<div className={`${baseClass}__content`} ref={contentRef}>
|
||||
<div className={`${baseClass}__hide-scrollbar`} ref={intersectionRef}>
|
||||
<div className={`${baseClass}__scroll-container`}>
|
||||
<div className={`${baseClass}__scroll-content`}>
|
||||
{render && render({ close: () => setActive(false) })}
|
||||
{children && children}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{caret && <div className={`${baseClass}__caret`} />}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -9,15 +9,13 @@ export type Props = {
|
||||
caret?: boolean
|
||||
children?: React.ReactNode
|
||||
className?: string
|
||||
color?: 'dark' | 'light'
|
||||
forceOpen?: boolean
|
||||
horizontalAlign?: 'center' | 'left' | 'right'
|
||||
initActive?: boolean
|
||||
onToggleOpen?: (active: boolean) => void
|
||||
padding?: CSSProperties['padding']
|
||||
render?: (any) => React.ReactNode
|
||||
showOnHover?: boolean
|
||||
showScrollbar?: boolean
|
||||
size?: 'large' | 'small' | 'wide'
|
||||
size?: 'fit-content' | 'large' | 'medium' | 'small'
|
||||
verticalAlign?: 'bottom' | 'top'
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
|
||||
.popup__wrapper {
|
||||
.popup__trigger-wrap {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
height: 100%;
|
||||
@@ -22,27 +22,4 @@
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&__relations {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
|
||||
li:not(:last-child) {
|
||||
margin-bottom: base(0.375);
|
||||
}
|
||||
}
|
||||
|
||||
&__relation-button {
|
||||
@extend %btn-reset;
|
||||
cursor: pointer;
|
||||
display: block;
|
||||
padding: base(0.125) 0;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import React, { Fragment, useCallback, useEffect, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import type { SanitizedCollectionConfig } from '../../../../../../collections/config/types'
|
||||
import type { EditViewProps } from '../../../../views/types'
|
||||
import type { Value } from '../types'
|
||||
import type { Props } from './types'
|
||||
|
||||
@@ -9,13 +10,13 @@ import { getTranslation } from '../../../../../../utilities/getTranslation'
|
||||
import Button from '../../../../elements/Button'
|
||||
import { useDocumentDrawer } from '../../../../elements/DocumentDrawer'
|
||||
import Popup from '../../../../elements/Popup'
|
||||
import * as PopupList from '../../../../elements/Popup/PopupButtonList'
|
||||
import Tooltip from '../../../../elements/Tooltip'
|
||||
import Plus from '../../../../icons/Plus'
|
||||
import { useAuth } from '../../../../utilities/Auth'
|
||||
import { useConfig } from '../../../../utilities/Config'
|
||||
import './index.scss'
|
||||
import { useRelatedCollections } from './useRelatedCollections'
|
||||
import { EditViewProps } from '../../../../views/types'
|
||||
|
||||
const baseClass = 'relationship-add-new'
|
||||
|
||||
@@ -85,7 +86,7 @@ export const AddNewRelation: React.FC<Props> = ({
|
||||
[relationTo, collectionConfig, dispatchOptions, i18n, hasMany, setValue, value, config],
|
||||
)
|
||||
|
||||
const onPopopToggle = useCallback((state) => {
|
||||
const onPopupToggle = useCallback((state) => {
|
||||
setPopupOpen(state)
|
||||
}, [])
|
||||
|
||||
@@ -161,31 +162,30 @@ export const AddNewRelation: React.FC<Props> = ({
|
||||
}
|
||||
buttonType="custom"
|
||||
horizontalAlign="center"
|
||||
onToggleOpen={onPopopToggle}
|
||||
onToggleOpen={onPopupToggle}
|
||||
render={({ close: closePopup }) => (
|
||||
<ul className={`${baseClass}__relations`}>
|
||||
<PopupList.ButtonGroup>
|
||||
{relatedCollections.map((relatedCollection) => {
|
||||
if (permissions.collections[relatedCollection.slug].create.permission) {
|
||||
return (
|
||||
<li key={relatedCollection.slug}>
|
||||
<button
|
||||
className={`${baseClass}__relation-button ${baseClass}__relation-button--${relatedCollection.slug}`}
|
||||
onClick={() => {
|
||||
closePopup()
|
||||
setSelectedCollection(relatedCollection.slug)
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
{getTranslation(relatedCollection.labels.singular, i18n)}
|
||||
</button>
|
||||
</li>
|
||||
<PopupList.Button
|
||||
className={`${baseClass}__relation-button--${relatedCollection.slug}`}
|
||||
key={relatedCollection.slug}
|
||||
onClick={() => {
|
||||
closePopup()
|
||||
setSelectedCollection(relatedCollection.slug)
|
||||
}}
|
||||
>
|
||||
{getTranslation(relatedCollection.labels.singular, i18n)}
|
||||
</PopupList.Button>
|
||||
)
|
||||
}
|
||||
|
||||
return null
|
||||
})}
|
||||
</ul>
|
||||
</PopupList.ButtonGroup>
|
||||
)}
|
||||
size="medium"
|
||||
/>
|
||||
{collectionConfig &&
|
||||
permissions.collections[collectionConfig.slug].create.permission && (
|
||||
|
||||
@@ -85,8 +85,8 @@ $focus-box-shadow: 0 0 0 $style-stroke-width-m var(--theme-success-500);
|
||||
|
||||
@mixin shadow-lg-top {
|
||||
box-shadow:
|
||||
0 -2px 20px 7px rgba(0, 2, 4, 0.1),
|
||||
0 6px 4px -4px rgba(0, 2, 4, 0.02);
|
||||
0 -20px 35px -10px rgba(0, 2, 4, 0.2),
|
||||
0 -6px 4px -4px rgba(0, 2, 4, 0.02);
|
||||
}
|
||||
|
||||
@mixin shadow {
|
||||
|
||||
@@ -11,14 +11,13 @@
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
|
||||
.popup__scroll,
|
||||
.popup__wrap {
|
||||
.popup__hide-scrollbar,
|
||||
.popup__scroll-container {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.popup__scroll {
|
||||
.popup__scroll-content {
|
||||
white-space: pre;
|
||||
padding-right: base(0.5);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +34,7 @@
|
||||
@extend %btn-reset;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
margin: 0 0 0 base(0.25);
|
||||
margin: 0;
|
||||
|
||||
&:hover,
|
||||
&:focus-visible {
|
||||
@@ -48,7 +47,29 @@
|
||||
max-width: base(8);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin-right: base(0.25);
|
||||
border-radius: 2px;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--popup-button-highlight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.rich-text-link__popup {
|
||||
display: flex;
|
||||
gap: calc(var(--base) * 0.25);
|
||||
button {
|
||||
&:hover {
|
||||
.btn__icon {
|
||||
background-color: var(--popup-button-highlight);
|
||||
.fill {
|
||||
fill: var(--theme-text);
|
||||
}
|
||||
.stroke {
|
||||
stroke: var(--theme-text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -159,6 +159,7 @@ export const LinkElement: React.FC<{
|
||||
href={`${config.routes.admin}/collections/${element.doc.relationTo}/${element.doc.value}`}
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
title={`${config.routes.admin}/collections/${element.doc.relationTo}/${element.doc.value}`}
|
||||
>
|
||||
label
|
||||
</a>
|
||||
@@ -170,6 +171,7 @@ export const LinkElement: React.FC<{
|
||||
href={element.url}
|
||||
rel="noreferrer"
|
||||
target="_blank"
|
||||
title={element.url}
|
||||
>
|
||||
{element.url}
|
||||
</a>
|
||||
@@ -200,7 +202,7 @@ export const LinkElement: React.FC<{
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
size="small"
|
||||
size="fit-content"
|
||||
verticalAlign="bottom"
|
||||
/>
|
||||
</span>
|
||||
|
||||
@@ -321,13 +321,13 @@ describe('fields', () => {
|
||||
const firstBlockSelector = blocksDrawer
|
||||
.locator('.blocks-drawer__blocks .blocks-drawer__block')
|
||||
.first()
|
||||
await expect(firstBlockSelector).toContainText('Text')
|
||||
await expect(firstBlockSelector).toContainText('Content')
|
||||
await firstBlockSelector.click()
|
||||
|
||||
// ensure the block was appended to the rows
|
||||
const addedRow = page.locator('#field-blocks .blocks-field__row').last()
|
||||
await expect(addedRow).toBeVisible()
|
||||
await expect(addedRow.locator('.blocks-field__block-pill-text')).toContainText('Text')
|
||||
await expect(addedRow.locator('.blocks-field__block-pill-content')).toContainText('Content')
|
||||
})
|
||||
|
||||
test('should open blocks drawer from block row and add below', async () => {
|
||||
@@ -348,13 +348,13 @@ describe('fields', () => {
|
||||
const firstBlockSelector = blocksDrawer
|
||||
.locator('.blocks-drawer__blocks .blocks-drawer__block')
|
||||
.first()
|
||||
await expect(firstBlockSelector).toContainText('Text')
|
||||
await expect(firstBlockSelector).toContainText('Content')
|
||||
await firstBlockSelector.click()
|
||||
|
||||
// ensure the block was inserted beneath the first in the rows
|
||||
const addedRow = page.locator('#field-blocks #blocks-row-1')
|
||||
await expect(addedRow).toBeVisible()
|
||||
await expect(addedRow.locator('.blocks-field__block-pill-text')).toContainText('Text') // went from `Number` to `Text`
|
||||
await expect(addedRow.locator('.blocks-field__block-pill-content')).toContainText('Content') // went from `Number` to `Content`
|
||||
})
|
||||
|
||||
test('should use i18n block labels', async () => {
|
||||
@@ -488,18 +488,16 @@ describe('fields', () => {
|
||||
|
||||
await page.locator('#potentiallyEmptyArray-row-1 .array-actions__button').click()
|
||||
await page
|
||||
.locator('#potentiallyEmptyArray-row-1 .popup__scroll .array-actions__remove')
|
||||
.locator('#potentiallyEmptyArray-row-1 .popup__scroll-container .array-actions__remove')
|
||||
.click()
|
||||
await page.locator('#potentiallyEmptyArray-row-0 .array-actions__button').click()
|
||||
await page
|
||||
.locator('#potentiallyEmptyArray-row-0 .popup__scroll .array-actions__remove')
|
||||
.locator('#potentiallyEmptyArray-row-0 .popup__scroll-container .array-actions__remove')
|
||||
.click()
|
||||
|
||||
const rows = await page.locator(
|
||||
'#field-potentiallyEmptyArray > .array-field__draggable-rows',
|
||||
)
|
||||
const rows = page.locator('#field-potentiallyEmptyArray > .array-field__draggable-rows')
|
||||
|
||||
expect(rows).not.toBeVisible()
|
||||
await expect(rows).toBeHidden()
|
||||
})
|
||||
|
||||
test('should remove existing row', async () => {
|
||||
@@ -513,15 +511,13 @@ describe('fields', () => {
|
||||
await page.locator('#potentiallyEmptyArray-row-0 .array-actions__button').click()
|
||||
await page
|
||||
.locator(
|
||||
'#potentiallyEmptyArray-row-0 .popup__scroll .array-actions__action.array-actions__remove',
|
||||
'#potentiallyEmptyArray-row-0 .popup__scroll-container .array-actions__action.array-actions__remove',
|
||||
)
|
||||
.click()
|
||||
|
||||
const rows = await page.locator(
|
||||
'#field-potentiallyEmptyArray > .array-field__draggable-rows',
|
||||
)
|
||||
const rows = page.locator('#field-potentiallyEmptyArray > .array-field__draggable-rows')
|
||||
|
||||
expect(rows).not.toBeVisible()
|
||||
await expect(rows).toBeHidden()
|
||||
})
|
||||
|
||||
test('should add row after removing existing row', async () => {
|
||||
@@ -537,7 +533,7 @@ describe('fields', () => {
|
||||
await page.locator('#potentiallyEmptyArray-row-1 .array-actions__button').click()
|
||||
await page
|
||||
.locator(
|
||||
'#potentiallyEmptyArray-row-1 .popup__scroll .array-actions__action.array-actions__remove',
|
||||
'#potentiallyEmptyArray-row-1 .popup__scroll-container .array-actions__action.array-actions__remove',
|
||||
)
|
||||
.click()
|
||||
await page.locator('#field-potentiallyEmptyArray > .array-field__add-row').click()
|
||||
|
||||
Reference in New Issue
Block a user