feat: updates styling of group field

This commit is contained in:
James
2022-07-15 22:24:52 -07:00
parent 3ae1c26a07
commit 8c4e0fa7b2
16 changed files with 115 additions and 292 deletions

View File

@@ -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);

View File

@@ -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;
}
}
}

View File

@@ -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;

View File

@@ -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
}

View File

@@ -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);
}
}
}

View File

@@ -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>
);

View File

@@ -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>

View File

@@ -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,
}}
/>
);
};

View File

@@ -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>

View File

@@ -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;

View File

@@ -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;

View File

@@ -203,7 +203,6 @@ export const group = baseField.keys({
joi.func(),
),
admin: baseAdminFields.keys({
hideGutter: joi.boolean().default(false),
description: joi.string(),
}),
});

View File

@@ -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'>;

View File

@@ -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;

View File

@@ -13,6 +13,10 @@ const TabsFields: CollectionConfig = {
fields: [
{
name: 'array',
labels: {
singular: 'Item',
plural: 'Items',
},
type: 'array',
required: true,
fields: [

View File

@@ -16,11 +16,11 @@ export default buildConfig({
BlockFields,
CollapsibleFields,
ConditionalLogic,
PointFields,
RichTextFields,
SelectFields,
TabsFields,
TextFields,
PointFields,
],
localization: {
defaultLocale: 'en',