feat: updates styling of group field
This commit is contained in:
@@ -1,17 +0,0 @@
|
||||
import React, { createContext, useContext } from 'react';
|
||||
import { useWindowInfo } from '@faceless-ui/window-info';
|
||||
|
||||
const context = createContext(false);
|
||||
const { Provider } = context;
|
||||
|
||||
export const NegativeFieldGutterProvider: React.FC<{allow?: boolean, children?: React.ReactNode}> = ({ children, allow }) => {
|
||||
const { breakpoints: { m: midBreak } } = useWindowInfo();
|
||||
|
||||
return (
|
||||
<Provider value={allow && !midBreak}>
|
||||
{children}
|
||||
</Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useNegativeFieldGutter = (): boolean => useContext(context);
|
||||
@@ -1,89 +0,0 @@
|
||||
@import '../../../scss/styles.scss';
|
||||
|
||||
$controls-top-adjustment: base(.1);
|
||||
|
||||
@mixin nestedStickyOffsets ($loopCount, $currentCount: 0) {
|
||||
.field-type {
|
||||
@if $loopCount >$currentCount {
|
||||
.field-type-gutter--v-align-sticky .field-type-gutter__content {
|
||||
top: calc(#{$top-header-offset} + (#{base(2.75)} * #{$currentCount}));
|
||||
}
|
||||
|
||||
@include nestedStickyOffsets($loopCount, $currentCount + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include nestedStickyOffsets(4);
|
||||
|
||||
.field-type-gutter {
|
||||
&--left {
|
||||
margin-right: base(1.25);
|
||||
}
|
||||
|
||||
&--right {
|
||||
padding-right: 0;
|
||||
padding-left: base(1.25);
|
||||
|
||||
.field-type-gutter__content {
|
||||
margin-bottom: base(1);
|
||||
}
|
||||
|
||||
.field-type-gutter__content-container {
|
||||
padding-right: 0;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
&--v-align-top {
|
||||
.field-type-gutter__content {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
||||
|
||||
&--v-align-sticky {
|
||||
.field-type-gutter__content {
|
||||
position: sticky;
|
||||
top: $top-header-offset;
|
||||
height: unset;
|
||||
}
|
||||
}
|
||||
|
||||
&__content-container {
|
||||
padding-right: $style-stroke-width-s;
|
||||
position: relative;
|
||||
min-height: 100%;
|
||||
box-shadow: #{$style-stroke-width-s} 0px 0px 0px var(--theme-elevation-150);
|
||||
}
|
||||
|
||||
&__content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&--negative-gutter {
|
||||
&.field-type-gutter--left {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 100%;
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@include mid-break {
|
||||
&--left {
|
||||
margin-right: base(1);
|
||||
|
||||
.field-type-gutter__content-container {
|
||||
padding-right: $style-stroke-width-m;
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&--right {
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
import React from 'react';
|
||||
import { useNegativeFieldGutter } from './context';
|
||||
import { Props } from './types';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const baseClass = 'field-type-gutter';
|
||||
|
||||
const FieldTypeGutter: React.FC<Props> = ({
|
||||
children,
|
||||
variant = 'left',
|
||||
verticalAlignment = 'sticky',
|
||||
className,
|
||||
dragHandleProps = {},
|
||||
}) => {
|
||||
const allowNegativeGutter = useNegativeFieldGutter();
|
||||
|
||||
const classes = [
|
||||
baseClass,
|
||||
`${baseClass}--${variant}`,
|
||||
`${baseClass}--v-align-${verticalAlignment}`,
|
||||
allowNegativeGutter && `${baseClass}--negative-gutter`,
|
||||
className && className,
|
||||
].filter(Boolean).join(' ');
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classes}
|
||||
{...dragHandleProps}
|
||||
>
|
||||
<div className={`${baseClass}__content-container`}>
|
||||
<div className={`${baseClass}__content`}>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default FieldTypeGutter;
|
||||
@@ -1,10 +0,0 @@
|
||||
import React from 'react';
|
||||
import { DraggableProvidedDragHandleProps } from 'react-beautiful-dnd';
|
||||
|
||||
export type Props = {
|
||||
variant?: 'left' | 'right'
|
||||
verticalAlignment?: 'top' | 'center' | 'sticky'
|
||||
dragHandleProps?: DraggableProvidedDragHandleProps
|
||||
className?: string
|
||||
children?: React.ReactNode
|
||||
}
|
||||
@@ -1,50 +1,38 @@
|
||||
@import '../../../../scss/styles.scss';
|
||||
|
||||
.group {
|
||||
margin-top: base(2);
|
||||
margin-bottom: base(2);
|
||||
display: flex;
|
||||
position: relative;
|
||||
.group-field {
|
||||
margin: base(2) calc(var(--gutter-h) * -1);
|
||||
padding: base(2) var(--gutter-h);
|
||||
border-top: 1px solid var(--theme-elevation-100);
|
||||
border-bottom: 1px solid var(--theme-elevation-100);
|
||||
|
||||
&--within-collapsible {
|
||||
margin: $baseline calc(#{$baseline} * -1);
|
||||
padding: $baseline;
|
||||
|
||||
&:first-child {
|
||||
border-top: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
padding-bottom: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&__header {
|
||||
margin-bottom: base(1);
|
||||
margin-bottom: base(.75);
|
||||
}
|
||||
|
||||
&__title {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.field-type-gutter__content-container {
|
||||
box-shadow: #{$style-stroke-width-m} 0px 0px 0px var(--theme-elevation-800);
|
||||
}
|
||||
}
|
||||
|
||||
&__content-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&__fields-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.render-fields {
|
||||
width: 100%;
|
||||
|
||||
.row {
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&--no-label {
|
||||
margin-top: 0,
|
||||
}
|
||||
|
||||
@include mid-break {
|
||||
&__fields-wrapper {
|
||||
display: flex;
|
||||
@include small-break {
|
||||
&--within-collapsible {
|
||||
margin-left: calc(var(--gutter-h) * -1);
|
||||
margin-right: calc(var(--gutter-h) * -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,13 @@ import React from 'react';
|
||||
import RenderFields from '../../RenderFields';
|
||||
import withCondition from '../../withCondition';
|
||||
import FieldDescription from '../../FieldDescription';
|
||||
import FieldTypeGutter from '../../FieldTypeGutter';
|
||||
import { NegativeFieldGutterProvider } from '../../FieldTypeGutter/context';
|
||||
import { Props } from './types';
|
||||
import { fieldAffectsData } from '../../../../../fields/config/types';
|
||||
import { useCollapsible } from '../../../elements/Collapsible/provider';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const baseClass = 'group';
|
||||
const baseClass = 'group-field';
|
||||
|
||||
const Group: React.FC<Props> = (props) => {
|
||||
const {
|
||||
@@ -23,12 +22,13 @@ const Group: React.FC<Props> = (props) => {
|
||||
style,
|
||||
className,
|
||||
width,
|
||||
hideGutter,
|
||||
description,
|
||||
},
|
||||
permissions,
|
||||
} = props;
|
||||
|
||||
const isWithinCollapsible = useCollapsible();
|
||||
|
||||
const path = pathFromProps || name;
|
||||
|
||||
return (
|
||||
@@ -37,17 +37,15 @@ const Group: React.FC<Props> = (props) => {
|
||||
className={[
|
||||
'field-type',
|
||||
baseClass,
|
||||
isWithinCollapsible && `${baseClass}--within-collapsible`,
|
||||
className,
|
||||
!label && `${baseClass}--no-label`,
|
||||
].filter(Boolean).join(' ')}
|
||||
style={{
|
||||
...style,
|
||||
width,
|
||||
}}
|
||||
>
|
||||
{!hideGutter && (<FieldTypeGutter />)}
|
||||
|
||||
<div className={`${baseClass}__content-wrapper`}>
|
||||
<div className={`${baseClass}__wrap`}>
|
||||
{(label || description) && (
|
||||
<header className={`${baseClass}__header`}>
|
||||
{label && (
|
||||
@@ -59,19 +57,15 @@ const Group: React.FC<Props> = (props) => {
|
||||
/>
|
||||
</header>
|
||||
)}
|
||||
<div className={`${baseClass}__fields-wrapper`}>
|
||||
<NegativeFieldGutterProvider allow={false}>
|
||||
<RenderFields
|
||||
permissions={permissions?.fields}
|
||||
readOnly={readOnly}
|
||||
fieldTypes={fieldTypes}
|
||||
fieldSchema={fields.map((subField) => ({
|
||||
...subField,
|
||||
path: `${path}${fieldAffectsData(subField) ? `.${subField.name}` : ''}`,
|
||||
}))}
|
||||
/>
|
||||
</NegativeFieldGutterProvider>
|
||||
</div>
|
||||
<RenderFields
|
||||
permissions={permissions?.fields}
|
||||
readOnly={readOnly}
|
||||
fieldTypes={fieldTypes}
|
||||
fieldSchema={fields.map((subField) => ({
|
||||
...subField,
|
||||
path: `${path}${fieldAffectsData(subField) ? `.${subField.name}` : ''}`,
|
||||
}))}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -8,7 +8,6 @@ import Button from '../../../../elements/Button';
|
||||
import RenderFields from '../../../RenderFields';
|
||||
import FormSubmit from '../../../Submit';
|
||||
import Upload from '../../../../views/collections/Edit/Upload';
|
||||
import { NegativeFieldGutterProvider } from '../../../FieldTypeGutter/context';
|
||||
import ViewDescription from '../../../../elements/ViewDescription';
|
||||
import { Props } from './types';
|
||||
|
||||
@@ -82,14 +81,12 @@ const AddUploadModal: React.FC<Props> = (props) => {
|
||||
<Upload
|
||||
collection={collection}
|
||||
/>
|
||||
<NegativeFieldGutterProvider allow>
|
||||
<RenderFields
|
||||
permissions={collectionPermissions}
|
||||
readOnly={false}
|
||||
fieldTypes={fieldTypes}
|
||||
fieldSchema={collection.fields}
|
||||
/>
|
||||
</NegativeFieldGutterProvider>
|
||||
<RenderFields
|
||||
permissions={collectionPermissions}
|
||||
readOnly={false}
|
||||
fieldTypes={fieldTypes}
|
||||
fieldSchema={collection.fields}
|
||||
/>
|
||||
</Form>
|
||||
</MinimalTemplate>
|
||||
</Modal>
|
||||
|
||||
@@ -9,7 +9,6 @@ import { useLocale } from '../../utilities/Locale';
|
||||
import DefaultAccount from './Default';
|
||||
import buildStateFromSchema from '../../forms/Form/buildStateFromSchema';
|
||||
import RenderCustomComponent from '../../utilities/RenderCustomComponent';
|
||||
import { NegativeFieldGutterProvider } from '../../forms/FieldTypeGutter/context';
|
||||
import { useDocumentInfo } from '../../utilities/DocumentInfo';
|
||||
|
||||
const AccountView: React.FC = () => {
|
||||
@@ -73,22 +72,20 @@ const AccountView: React.FC = () => {
|
||||
}, [dataToRender, fields, id, user, locale]);
|
||||
|
||||
return (
|
||||
<NegativeFieldGutterProvider allow>
|
||||
<RenderCustomComponent
|
||||
DefaultComponent={DefaultAccount}
|
||||
CustomComponent={CustomAccount}
|
||||
componentProps={{
|
||||
action,
|
||||
data,
|
||||
collection,
|
||||
permissions: collectionPermissions,
|
||||
hasSavePermission,
|
||||
initialState,
|
||||
apiURL,
|
||||
isLoading: isLoadingDocument || !preferences,
|
||||
}}
|
||||
/>
|
||||
</NegativeFieldGutterProvider>
|
||||
<RenderCustomComponent
|
||||
DefaultComponent={DefaultAccount}
|
||||
CustomComponent={CustomAccount}
|
||||
componentProps={{
|
||||
action,
|
||||
data,
|
||||
collection,
|
||||
permissions: collectionPermissions,
|
||||
hasSavePermission,
|
||||
initialState,
|
||||
apiURL,
|
||||
isLoading: isLoadingDocument || !preferences,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -10,8 +10,6 @@ import FormSubmit from '../../forms/Submit';
|
||||
import { Props } from './types';
|
||||
import { Field } from '../../../../fields/config/types';
|
||||
|
||||
import { NegativeFieldGutterProvider } from '../../forms/FieldTypeGutter/context';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const baseClass = 'create-first-user';
|
||||
@@ -68,15 +66,13 @@ const CreateFirstUser: React.FC<Props> = (props) => {
|
||||
action={`${serverURL}${api}/${userSlug}/first-register`}
|
||||
validationOperation="create"
|
||||
>
|
||||
<NegativeFieldGutterProvider allow>
|
||||
<RenderFields
|
||||
fieldSchema={[
|
||||
...fields,
|
||||
...userConfig.fields,
|
||||
]}
|
||||
fieldTypes={fieldTypes}
|
||||
/>
|
||||
</NegativeFieldGutterProvider>
|
||||
<RenderFields
|
||||
fieldSchema={[
|
||||
...fields,
|
||||
...userConfig.fields,
|
||||
]}
|
||||
fieldTypes={fieldTypes}
|
||||
/>
|
||||
<FormSubmit>Create</FormSubmit>
|
||||
</Form>
|
||||
</MinimalTemplate>
|
||||
|
||||
@@ -10,7 +10,6 @@ import { useLocale } from '../../utilities/Locale';
|
||||
import RenderCustomComponent from '../../utilities/RenderCustomComponent';
|
||||
import DefaultGlobal from './Default';
|
||||
import buildStateFromSchema from '../../forms/Form/buildStateFromSchema';
|
||||
import { NegativeFieldGutterProvider } from '../../forms/FieldTypeGutter/context';
|
||||
import { IndexProps } from './types';
|
||||
import { useDocumentInfo } from '../../utilities/DocumentInfo';
|
||||
|
||||
@@ -77,22 +76,20 @@ const GlobalView: React.FC<IndexProps> = (props) => {
|
||||
const globalPermissions = permissions?.globals?.[slug];
|
||||
|
||||
return (
|
||||
<NegativeFieldGutterProvider allow>
|
||||
<RenderCustomComponent
|
||||
DefaultComponent={DefaultGlobal}
|
||||
CustomComponent={CustomEdit}
|
||||
componentProps={{
|
||||
isLoading: isLoadingDocument || !preferences,
|
||||
data: dataToRender,
|
||||
permissions: globalPermissions,
|
||||
initialState,
|
||||
global,
|
||||
onSave,
|
||||
apiURL: `${serverURL}${api}/globals/${slug}${global.versions?.drafts ? '?draft=true' : ''}`,
|
||||
action: `${serverURL}${api}/globals/${slug}?locale=${locale}&depth=0&fallback-locale=null`,
|
||||
}}
|
||||
/>
|
||||
</NegativeFieldGutterProvider>
|
||||
<RenderCustomComponent
|
||||
DefaultComponent={DefaultGlobal}
|
||||
CustomComponent={CustomEdit}
|
||||
componentProps={{
|
||||
isLoading: isLoadingDocument || !preferences,
|
||||
data: dataToRender,
|
||||
permissions: globalPermissions,
|
||||
initialState,
|
||||
global,
|
||||
onSave,
|
||||
apiURL: `${serverURL}${api}/globals/${slug}${global.versions?.drafts ? '?draft=true' : ''}`,
|
||||
action: `${serverURL}${api}/globals/${slug}?locale=${locale}&depth=0&fallback-locale=null`,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
export default GlobalView;
|
||||
|
||||
@@ -9,7 +9,6 @@ import RenderCustomComponent from '../../../utilities/RenderCustomComponent';
|
||||
import DefaultEdit from './Default';
|
||||
import formatFields from './formatFields';
|
||||
import buildStateFromSchema from '../../../forms/Form/buildStateFromSchema';
|
||||
import { NegativeFieldGutterProvider } from '../../../forms/FieldTypeGutter/context';
|
||||
import { useLocale } from '../../../utilities/Locale';
|
||||
import { IndexProps } from './types';
|
||||
import { StepNavItem } from '../../../elements/StepNav/types';
|
||||
@@ -120,24 +119,22 @@ const EditView: React.FC<IndexProps> = (props) => {
|
||||
const hasSavePermission = (isEditing && collectionPermissions?.update?.permission) || (!isEditing && collectionPermissions?.create?.permission);
|
||||
|
||||
return (
|
||||
<NegativeFieldGutterProvider allow>
|
||||
<RenderCustomComponent
|
||||
DefaultComponent={DefaultEdit}
|
||||
CustomComponent={CustomEdit}
|
||||
componentProps={{
|
||||
isLoading: isLoadingDocument || !preferences,
|
||||
data: dataToRender,
|
||||
collection,
|
||||
permissions: collectionPermissions,
|
||||
isEditing,
|
||||
onSave,
|
||||
initialState,
|
||||
hasSavePermission,
|
||||
apiURL,
|
||||
action,
|
||||
}}
|
||||
/>
|
||||
</NegativeFieldGutterProvider>
|
||||
<RenderCustomComponent
|
||||
DefaultComponent={DefaultEdit}
|
||||
CustomComponent={CustomEdit}
|
||||
componentProps={{
|
||||
isLoading: isLoadingDocument || !preferences,
|
||||
data: dataToRender,
|
||||
collection,
|
||||
permissions: collectionPermissions,
|
||||
isEditing,
|
||||
onSave,
|
||||
initialState,
|
||||
hasSavePermission,
|
||||
apiURL,
|
||||
action,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
export default EditView;
|
||||
|
||||
@@ -203,7 +203,6 @@ export const group = baseField.keys({
|
||||
joi.func(),
|
||||
),
|
||||
admin: baseAdminFields.keys({
|
||||
hideGutter: joi.boolean().default(false),
|
||||
description: joi.string(),
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -160,9 +160,6 @@ export type DateField = FieldBase & {
|
||||
export type GroupField = FieldBase & {
|
||||
type: 'group';
|
||||
fields: Field[];
|
||||
admin?: Admin & {
|
||||
hideGutter?: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export type RowAdmin = Omit<Admin, 'description'>;
|
||||
|
||||
@@ -16,6 +16,16 @@ const CollapsibleFields: CollectionConfig = {
|
||||
type: 'text',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'group',
|
||||
type: 'group',
|
||||
fields: [
|
||||
{
|
||||
name: 'textWithinGroup',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
@@ -23,6 +33,9 @@ const CollapsibleFields: CollectionConfig = {
|
||||
|
||||
export const collapsibleDoc = {
|
||||
text: 'Seeded collapsible doc',
|
||||
group: {
|
||||
textWithinGroup: 'some text within a group',
|
||||
},
|
||||
};
|
||||
|
||||
export default CollapsibleFields;
|
||||
|
||||
@@ -13,6 +13,10 @@ const TabsFields: CollectionConfig = {
|
||||
fields: [
|
||||
{
|
||||
name: 'array',
|
||||
labels: {
|
||||
singular: 'Item',
|
||||
plural: 'Items',
|
||||
},
|
||||
type: 'array',
|
||||
required: true,
|
||||
fields: [
|
||||
|
||||
@@ -16,11 +16,11 @@ export default buildConfig({
|
||||
BlockFields,
|
||||
CollapsibleFields,
|
||||
ConditionalLogic,
|
||||
PointFields,
|
||||
RichTextFields,
|
||||
SelectFields,
|
||||
TabsFields,
|
||||
TextFields,
|
||||
PointFields,
|
||||
],
|
||||
localization: {
|
||||
defaultLocale: 'en',
|
||||
|
||||
Reference in New Issue
Block a user