From 49d09a349fe6cdc45c429b77e9d60943b7db851f Mon Sep 17 00:00:00 2001 From: James Date: Thu, 14 Jul 2022 14:00:14 -0700 Subject: [PATCH] feat: updates block field to use new collapsible --- docs/admin/customizing-css.mdx | 44 ++-- scss/index.scss | 7 - .../components/elements/ArrayAction/types.ts | 2 +- .../elements/Collapsible/index.scss | 4 + .../components/elements/DatePicker/index.scss | 2 +- .../components/elements/Popup/index.scss | 4 + src/admin/components/elements/Popup/index.tsx | 8 +- .../elements/ReactSelect/index.scss | 4 +- .../DraggableSection/SectionTitle/index.scss | 2 +- .../forms/field-types/Array/Array.tsx | 113 +++++----- .../forms/field-types/Blocks/Blocks.tsx | 203 ++++++++++++++---- .../forms/field-types/Blocks/index.scss | 63 +++--- src/admin/scss/app.scss | 10 +- src/admin/scss/overrides.scss | 1 - src/admin/scss/styles.scss | 2 - src/admin/scss/type.scss | 2 +- src/admin/scss/vars.scss | 27 +-- src/admin/utilities/getOffsetTop.ts | 2 +- src/config/defaults.ts | 1 - src/config/schema.ts | 1 - src/config/types.ts | 1 - src/webpack/getBaseConfig.ts | 1 - 22 files changed, 299 insertions(+), 205 deletions(-) delete mode 100644 src/admin/scss/overrides.scss diff --git a/docs/admin/customizing-css.mdx b/docs/admin/customizing-css.mdx index 45a1397566..a370d7da51 100644 --- a/docs/admin/customizing-css.mdx +++ b/docs/admin/customizing-css.mdx @@ -24,38 +24,26 @@ const config = buildConfig({ }) ``` -### Overriding SCSS variables +### Overriding built-in styles -You can specify your own SCSS variable stylesheet that will allow for the override of Payload's base theme. This unlocks a ton of powerful theming and design options such as: +To make it as easy as possible for you to override our styles, Payload uses [BEM naming conventions](http://getbem.com/) for all CSS within the Admin UI. If you provide your own CSS, you can override any built-in styles easily. -- Changing dashboard font families -- Modifying color palette -- Creating a dark theme -- Etc. +In addition to adding your own style definitions, you can also override Payload's built-in CSS variables. We use as much as possible behind the scenes, and you can override any of them that you'd like to. -To do so, provide your base Payload config with a path to your own SCSS variable sheet. +You can find the built-in Payload CSS variables within [`./src/admin/scss/app.scss`](https://github.com/payloadcms/payload/blob/master/src/admin/scss/app.scss). The following variables are defined and can be overridden: -**Example in payload.config.js:** -```js -import { buildConfig } from 'payload/config'; -import path from 'path'; +- Breakpoints +- Base color shades (white to black by default) +- Success / warning / error color shades +- Theme-specific colors (background, input background, text color, etc.) +- Elevation colors (used to determine how "bright" something should be when compared to the background) +- Fonts +- Horizontal gutter -const config = buildConfig({ - admin: { - scss: path.resolve(__dirname, 'relative/path/to/vars.scss'), - }, -}) -``` +#### Dark mode -**Example stylesheet override:** -```scss -$font-body: 'Papyrus'; -$style-radius-m: 10px; -``` - -To reference all Sass variables that you can override, look at the default [SCSS variable stylesheet](https://github.com/payloadcms/payload/blob/master/src/admin/scss/vars.scss) within the Payload source code. - - - Warning:
- Only SCSS variables, mixins, functions, and extends are allowed in your SCSS overrides. Do not attempt to add any CSS declarations to this file, as this variable stylesheet is imported by many components throughout the Payload Admin panel and will result in your CSS definition(s) being duplicated many times. If you need to add real CSS definitions, see "Adding your own CSS / SCSS" the top of this page. + + If you're overriding colors or theme elevations, make sure to consider how your changes will affect dark mode. + +By default, Payload automatically overrides all `--theme-elevation`s and inverts all success / warning / error shades to suit dark mode. We also update some base theme variables like `--theme-bg`, `--theme-text`, etc. diff --git a/scss/index.scss b/scss/index.scss index e3fad15b30..86943bb14c 100644 --- a/scss/index.scss +++ b/scss/index.scss @@ -1,12 +1,5 @@ @import '../dist/admin/scss/vars'; @import '../dist/admin/scss/z-index'; - -////////////////////////////// -// IMPORT OVERRIDES -////////////////////////////// - -@import '~payload-scss-overrides'; - @import '../dist/admin/scss/type'; @import '../dist/admin/scss/queries'; @import '../dist/admin/scss/resets'; diff --git a/src/admin/components/elements/ArrayAction/types.ts b/src/admin/components/elements/ArrayAction/types.ts index 540cc9b8de..958cdd96a9 100644 --- a/src/admin/components/elements/ArrayAction/types.ts +++ b/src/admin/components/elements/ArrayAction/types.ts @@ -1,5 +1,5 @@ export type Props = { - addRow: (current: number) => void + addRow: (current: number, blockType?: string) => void duplicateRow: (current: number) => void removeRow: (index: number) => void moveRow: (from: number, to: number) => void diff --git a/src/admin/components/elements/Collapsible/index.scss b/src/admin/components/elements/Collapsible/index.scss index cd150286cc..2badfadf27 100644 --- a/src/admin/components/elements/Collapsible/index.scss +++ b/src/admin/components/elements/Collapsible/index.scss @@ -87,5 +87,9 @@ header { padding: base(.75) var(--gutter-h); } + + &__content { + padding: var(--gutter-h); + } } } diff --git a/src/admin/components/elements/DatePicker/index.scss b/src/admin/components/elements/DatePicker/index.scss index 17a410eeb3..e11ecbecff 100644 --- a/src/admin/components/elements/DatePicker/index.scss +++ b/src/admin/components/elements/DatePicker/index.scss @@ -102,7 +102,7 @@ $cal-icon-width: 18px; background: var(--theme-input-bg); display: inline-flex; border: none; - font-family: $font-body; + font-family: var(--font-body); font-weight: 100; border-radius: 0; color: var(--theme-elevation-800); diff --git a/src/admin/components/elements/Popup/index.scss b/src/admin/components/elements/Popup/index.scss index 7b56a7e105..69b42f4308 100644 --- a/src/admin/components/elements/Popup/index.scss +++ b/src/admin/components/elements/Popup/index.scss @@ -42,6 +42,10 @@ //////////////////////////////// &--size-small { + .popup__scroll { + padding: base(.75); + } + .popup__content { @include shadow-m; } diff --git a/src/admin/components/elements/Popup/index.tsx b/src/admin/components/elements/Popup/index.tsx index e7aaa503cc..da1ee4c644 100644 --- a/src/admin/components/elements/Popup/index.tsx +++ b/src/admin/components/elements/Popup/index.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useRef, useState } from 'react'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; import { useWindowInfo } from '@faceless-ui/window-info'; import { useScrollInfo } from '@faceless-ui/scroll-info'; import { Props } from './types'; @@ -40,13 +40,13 @@ const Popup: React.FC = (props) => { const { y: scrollY } = useScrollInfo(); const { height: windowHeight, width: windowWidth } = useWindowInfo(); - const handleClickOutside = (e) => { + const handleClickOutside = useCallback((e) => { if (contentRef.current.contains(e.target)) { return; } setActive(false); - }; + }, []); useThrottledEffect(() => { if (contentRef.current && buttonRef.current) { @@ -99,7 +99,7 @@ const Popup: React.FC = (props) => { return () => { document.removeEventListener('mousedown', handleClickOutside); }; - }, [active, onToggleOpen]); + }, [active, handleClickOutside, onToggleOpen]); useEffect(() => { setActive(forceOpen); diff --git a/src/admin/components/elements/ReactSelect/index.scss b/src/admin/components/elements/ReactSelect/index.scss index a729906dfd..06e1199542 100644 --- a/src/admin/components/elements/ReactSelect/index.scss +++ b/src/admin/components/elements/ReactSelect/index.scss @@ -46,7 +46,7 @@ div.react-select { color: var(--theme-elevation-1000); input { - font-family: $font-body; + font-family: var(--font-body); width: 100% !important; } } @@ -65,7 +65,7 @@ div.react-select { } .rs__option { - font-family: $font-body; + font-family: var(--font-body); font-size: $baseline-body-size; padding: base(.375) base(.75); color: var(--theme-elevation-800); diff --git a/src/admin/components/forms/DraggableSection/SectionTitle/index.scss b/src/admin/components/forms/DraggableSection/SectionTitle/index.scss index 32301870da..ffbe50fa46 100644 --- a/src/admin/components/forms/DraggableSection/SectionTitle/index.scss +++ b/src/admin/components/forms/DraggableSection/SectionTitle/index.scss @@ -9,7 +9,7 @@ flex-grow: 1; color: var(--theme-elevation-800); background-color: transparent; - font-family: $font-body; + font-family: var(--font-body); font-weight: 600; font-size: base(.75); padding: base(.1) base(.2); diff --git a/src/admin/components/forms/field-types/Array/Array.tsx b/src/admin/components/forms/field-types/Array/Array.tsx index 032be7a7f0..a9c30f9fd3 100644 --- a/src/admin/components/forms/field-types/Array/Array.tsx +++ b/src/admin/components/forms/field-types/Array/Array.tsx @@ -44,6 +44,8 @@ const ArrayFieldType: React.FC = (props) => { }, } = props; + const path = pathFromProps || name; + // Handle labeling for Arrays, Global Arrays, and Blocks const getLabels = (p: Props) => { if (p?.labels) return p.labels; @@ -66,8 +68,6 @@ const ArrayFieldType: React.FC = (props) => { const { dispatchFields } = formContext; - const path = pathFromProps || name; - const memoizedValidate = useCallback((value, options) => { return validate(value, { ...options, minRows, maxRows, required }); }, [maxRows, minRows, required, validate]); @@ -91,6 +91,18 @@ const ArrayFieldType: React.FC = (props) => { dispatchFields({ type: 'ADD_ROW', rowIndex, subFieldState, path }); dispatchRows({ type: 'ADD', rowIndex }); setValue(value as number + 1); + + setTimeout(() => { + const newRow = document.getElementById(`${path}-row-${rowIndex + 1}`); + + if (newRow) { + const bounds = newRow.getBoundingClientRect(); + window.scrollBy({ + top: bounds.top - 100, + behavior: 'smooth', + }); + } + }, 0); }, [dispatchRows, dispatchFields, fields, path, setValue, value, operation, id, user, locale]); const duplicateRow = useCallback(async (rowIndex: number) => { @@ -233,52 +245,57 @@ const ArrayFieldType: React.FC = (props) => { ref={provided.innerRef} {...provided.droppableProps} > - {rows.length > 0 && rows.map((row, i) => ( - - {(providedDrag) => ( -
- setCollapse(row.id, collapsed)} - className={`${baseClass}__row`} - key={row.id} - dragHandleProps={providedDrag.dragHandleProps} - header={`${labels.singular} ${i + 1}`} - actions={!readOnly ? ( - - ) : undefined} - > - ({ - ...field, - path: `${path}.${i}${fieldAffectsData(field) ? `.${field.name}` : ''}`, - }))} - /> + {rows.length > 0 && rows.map((row, i) => { + const rowNumber = i + 1; - -
- )} -
- ))} + return ( + + {(providedDrag) => ( +
+ setCollapse(row.id, collapsed)} + className={`${baseClass}__row`} + key={row.id} + dragHandleProps={providedDrag.dragHandleProps} + header={`${labels.singular} ${rowNumber >= 10 ? rowNumber : `0${rowNumber}`}`} + actions={!readOnly ? ( + + ) : undefined} + > + ({ + ...field, + path: `${path}.${i}${fieldAffectsData(field) ? `.${field.name}` : ''}`, + }))} + /> + + +
+ )} +
+ ); + })} {(rows.length < minRows || (required && rows.length === 0)) && ( This field requires at least @@ -300,7 +317,7 @@ const ArrayFieldType: React.FC = (props) => { )} - {(!readOnly && (!hasMaxRows)) && ( + {(!readOnly && !hasMaxRows) && (
-

{label}

+
+

{label}

+
    +
  • + +
  • +
  • + +
  • +
+
= (props) => { const { blockType } = row; const blockToRender = blocks.find((block) => block.slug === blockType); + const rowNumber = i + 1; + if (blockToRender) { return ( - + draggableId={row.id} + index={i} + isDragDisabled={readOnly} + > + {(providedDrag) => ( +
+ setCollapse(row.id, collapsed)} + className={`${baseClass}__row`} + key={row.id} + dragHandleProps={providedDrag.dragHandleProps} + header={( +
+ + {rowNumber >= 10 ? rowNumber : `0${rowNumber}`} + + + {blockToRender.labels.singular} + +
+ )} + actions={!readOnly ? ( + + ( + + )} + /> + duplicateRow(i, blockType)} + addRow={() => setSelectorIndexOpen(i)} + moveRow={moveRow} + removeRow={removeRow} + index={i} + /> + + ) : undefined} + > + ({ + ...field, + path: `${path}.${i}${fieldAffectsData(field) ? `.${field.name}` : ''}`, + }))} + /> + +
+
+ )} + ); } @@ -251,7 +362,7 @@ const Blocks: React.FC = (props) => { )} - {(!readOnly && (rows.length < maxRows || maxRows === undefined)) && ( + {(!readOnly && !hasMaxRows) && (
div>div { - width: 100%; - } - } - - @include mid-break { - min-width: calc(100vw - #{base(2)}); - } -} - -.field-type.group, -.field-type.array, -.field-type.blocks { - .field-type.blocks { - .field-type.blocks__add-button-wrap { - margin-left: base(3); - } + .field-type:last-child { + margin-bottom: 0; } } diff --git a/src/admin/scss/app.scss b/src/admin/scss/app.scss index 78db38d0c8..5738e7ff17 100644 --- a/src/admin/scss/app.scss +++ b/src/admin/scss/app.scss @@ -133,7 +133,7 @@ } @include small-break { - --gutter-h: #{base(.75)}; + --gutter-h: #{base(.5)}; } } @@ -250,14 +250,8 @@ html { } } -html, -body, -#app { - height: 100%; -} - body { - font-family: $font-body; + font-family: var(--font-body); font-weight: 400; color: var(--theme-text); margin: 0; diff --git a/src/admin/scss/overrides.scss b/src/admin/scss/overrides.scss deleted file mode 100644 index 0b6a709cf2..0000000000 --- a/src/admin/scss/overrides.scss +++ /dev/null @@ -1 +0,0 @@ -/* Used as a placeholder for when the Payload app does not have custom SCSS */ diff --git a/src/admin/scss/styles.scss b/src/admin/scss/styles.scss index 1930011bcf..65aa3d3e95 100644 --- a/src/admin/scss/styles.scss +++ b/src/admin/scss/styles.scss @@ -5,8 +5,6 @@ // IMPORT OVERRIDES ////////////////////////////// -@import '~payload-scss-overrides'; - @import 'type'; @import 'queries'; @import 'resets'; diff --git a/src/admin/scss/type.scss b/src/admin/scss/type.scss index 4f341ded62..18bd0dd423 100644 --- a/src/admin/scss/type.scss +++ b/src/admin/scss/type.scss @@ -11,7 +11,7 @@ %h4, %h5, %h6 { - font-family: $font-body; + font-family: var(--font-body); font-weight: 500; } diff --git a/src/admin/scss/vars.scss b/src/admin/scss/vars.scss index 1526d71b17..1f20d8a675 100644 --- a/src/admin/scss/vars.scss +++ b/src/admin/scss/vars.scss @@ -1,10 +1,5 @@ @use 'sass:math'; -/////////////////////////////////////////////////////////////////////////////////////// -// All variables and mixins within this file are able to be overridden by -// developers using Payload. No CSS definitions should be placed in this file. -/////////////////////////////////////////////////////////////////////////////////////// - ///////////////////////////// // BREAKPOINTS ///////////////////////////// @@ -26,26 +21,6 @@ $baseline : math.div($baseline-px, $baseline-body-size)+rem; @return math.div($baseline-px, $baseline-body-size) * $multiplier +rem; } -////////////////////////////// -// FONTS -////////////////////////////// - -$font-body : 'Suisse Intl' !default; -$font-mono : monospace !default; - -////////////////////////////// -// COLORS (LEGACY - DO NOT USE. PREFER CSS VARIABLES) -////////////////////////////// - -$color-dark-gray : #333333 !default; -$color-gray : #9A9A9A !default; -$color-light-gray : #DADADA !default; -$color-background-gray : #F3F3F3 !default; -$color-red : #ff6f76 !default; -$color-yellow : #FDFFA4 !default; -$color-green : #B2FFD6 !default; -$color-purple : #F3DDF3 !default; - ////////////////////////////// // STYLES ////////////////////////////// @@ -144,7 +119,7 @@ $focus-box-shadow: 0 0 0 $style-stroke-width-m var(--color-success-500); @mixin formInput () { @include inputShadow; - font-family: $font-body; + font-family: var(--font-body); width: 100%; border: 1px solid var(--theme-elevation-150); background: var(--theme-input-bg); diff --git a/src/admin/utilities/getOffsetTop.ts b/src/admin/utilities/getOffsetTop.ts index 3b09b269f8..b0b6924f24 100644 --- a/src/admin/utilities/getOffsetTop.ts +++ b/src/admin/utilities/getOffsetTop.ts @@ -1,4 +1,4 @@ -export default (element: HTMLElement): number => { +export const getOffsetTop = (element: HTMLElement): number => { let el = element; // Set our distance placeholder let distance = 0; diff --git a/src/config/defaults.ts b/src/config/defaults.ts index b5b75ff6e9..ff232e5ace 100644 --- a/src/config/defaults.ts +++ b/src/config/defaults.ts @@ -18,7 +18,6 @@ export const defaults: Config = { indexHTML: path.resolve(__dirname, '../admin/index.html'), components: {}, css: path.resolve(__dirname, '../admin/scss/custom.css'), - scss: path.resolve(__dirname, '../admin/scss/overrides.scss'), dateFormat: 'MMMM do yyyy, h:mm a', }, typescript: { diff --git a/src/config/schema.ts b/src/config/schema.ts index 1f71e84d3a..76d3a6a5c9 100644 --- a/src/config/schema.ts +++ b/src/config/schema.ts @@ -45,7 +45,6 @@ export default joi.object({ disable: joi.bool(), indexHTML: joi.string(), css: joi.string(), - scss: joi.string(), dateFormat: joi.string(), components: joi.object() .keys({ diff --git a/src/config/types.ts b/src/config/types.ts index 450b87fb8e..c62fa04636 100644 --- a/src/config/types.ts +++ b/src/config/types.ts @@ -112,7 +112,6 @@ export type Config = { disable?: boolean; indexHTML?: string; css?: string - scss?: string dateFormat?: string components?: { routes?: AdminRoute[] diff --git a/src/webpack/getBaseConfig.ts b/src/webpack/getBaseConfig.ts index def6a2fa97..01a1e373ea 100644 --- a/src/webpack/getBaseConfig.ts +++ b/src/webpack/getBaseConfig.ts @@ -54,7 +54,6 @@ export default (config: SanitizedConfig): Configuration => ({ 'payload-config': config.paths.config, payload$: mockModulePath, 'payload-user-css': config.admin.css, - 'payload-scss-overrides': config.admin.scss, dotenv: mockDotENVPath, }, extensions: ['.ts', '.tsx', '.js', '.json'],