feat: finishes tabs field

This commit is contained in:
James
2022-07-15 18:40:31 -07:00
parent 735e385537
commit 68e7c41fdc
8 changed files with 157 additions and 21 deletions

4
.vscode/launch.json vendored
View File

@@ -31,7 +31,7 @@
"env": {
"BABEL_ENV": "development"
},
"program": "${workspaceFolder}/test/dev/index.js",
"program": "${workspaceFolder}/test/dev.js",
"skipFiles": [
"<node_internals>/**"
],
@@ -39,7 +39,7 @@
"--nolazy"
],
"args": [
"e2e/fields"
"fields"
]
},
]

View File

@@ -2,8 +2,11 @@ import React from 'react';
import { Props, isComponent } from './types';
import './index.scss';
const baseClass = 'field-description';
const FieldDescription: React.FC<Props> = (props) => {
const {
className,
description,
value,
} = props;
@@ -17,7 +20,10 @@ const FieldDescription: React.FC<Props> = (props) => {
if (description) {
return (
<div
className="field-description"
className={[
baseClass,
className,
].filter(Boolean).join(' ')}
>
{typeof description === 'function' ? description({ value }) : description}
</div>

View File

@@ -9,6 +9,7 @@ export type Description = string | DescriptionFunction | DescriptionComponent
export type Props = {
description?: Description
value?: unknown;
className?: string
}
export function isComponent(description: Description): description is DescriptionComponent {

View File

@@ -0,0 +1,91 @@
@import '../../../../scss/styles.scss';
.tabs-field {
margin-left: calc(var(--gutter-h) * -1);
margin-right: calc(var(--gutter-h) * -1);
margin-bottom: base(2);
&__tabs,
&__content-wrap {
padding-left: var(--gutter-h);
padding-right: var(--gutter-h);
}
&--within-collapsible {
margin-left: calc(#{$baseline} * -1);
margin-right: calc(#{$baseline} * -1);
margin-bottom: 0;
.tabs-field__tabs,
.tabs-field__content-wrap {
padding-left: $baseline;
padding-right: $baseline;
}
}
&__tabs {
border-bottom: 1px solid var(--theme-elevation-100);
margin-bottom: $baseline;
}
&__tab-button {
@extend %btn-reset;
@extend %h4;
padding-bottom: base(.5);
margin: 0 $baseline 0 0;
cursor: pointer;
opacity: .5;
position: relative;
&:last-child {
margin: 0;
}
&:after {
content: ' ';
position: absolute;
right: 0;
bottom: -1px;
left: 0;
height: 1px;
background: var(--theme-elevation-800);
opacity: 0;
}
&:hover {
opacity: .75;
&:after {
opacity: .2;
}
}
}
&__tab-button--active {
opacity: 1 !important;
&:after {
opacity: 1 !important;
height: 2px;
}
}
&__description {
margin-bottom: $baseline;
}
@include small-break {
&--within-collapsible {
margin-left: calc(var(--gutter-h) * -1);
margin-right: calc(var(--gutter-h) * -1);
}
&__tab-button {
margin: 0 base(.75) 0 0;
&:last-child {
margin: 0;
}
}
}
}

View File

@@ -5,6 +5,7 @@ import { Props } from './types';
import { fieldAffectsData } from '../../../../../fields/config/types';
import FieldDescription from '../../FieldDescription';
import toKebabCase from '../../../../../utilities/toKebabCase';
import { useCollapsible } from '../../../elements/Collapsible/provider';
import './index.scss';
@@ -22,6 +23,7 @@ const TabsField: React.FC<Props> = (props) => {
},
} = props;
const isWithinCollapsible = useCollapsible();
const [active, setActive] = useState(0);
const activeTab = tabs[active];
@@ -30,6 +32,7 @@ const TabsField: React.FC<Props> = (props) => {
<div className={[
className,
baseClass,
isWithinCollapsible && `${baseClass}--within-collapsible`,
].filter(Boolean).join(' ')}
>
<div className={`${baseClass}__tabs`}>
@@ -38,7 +41,10 @@ const TabsField: React.FC<Props> = (props) => {
<button
key={i}
type="button"
className={`${baseClass}__tab`}
className={[
`${baseClass}__tab-button`,
active === i && `${baseClass}__tab-button--active`,
].filter(Boolean).join(' ')}
onClick={() => setActive(i)}
>
{tab.label}
@@ -51,9 +57,10 @@ const TabsField: React.FC<Props> = (props) => {
<div className={[
`${baseClass}__tab`,
`${baseClass}__tab-${toKebabCase(activeTab.label)}`,
].join('')}
].join(' ')}
>
<FieldDescription
className={`${baseClass}__description`}
description={activeTab.description}
/>
<RenderFields

View File

@@ -62,6 +62,7 @@
margin: 0 0 $baseline;
font-size: base(.75);
line-height: 1.5;
letter-spacing: -.375px;
}
%h5 {

View File

@@ -304,48 +304,44 @@ const fieldToSchemaMap = {
};
},
row: (field: RowField, fields: SchemaDefinition, config: SanitizedConfig, buildSchemaOptions: BuildSchemaOptions): SchemaDefinition => {
const newFields = { ...fields };
let newFields = { ...fields };
field.fields.forEach((subField: Field) => {
const fieldSchemaMap: FieldSchemaGenerator = fieldToSchemaMap[subField.type];
const fieldSchema: FieldSchemaGenerator = fieldToSchemaMap[subField.type];
if (fieldSchemaMap && fieldAffectsData(subField)) {
const fieldSchema = fieldSchemaMap(subField, fields, config, buildSchemaOptions);
newFields[subField.name] = fieldSchema[subField.name];
if (fieldSchema) {
newFields = fieldSchema(subField, newFields, config, buildSchemaOptions);
}
});
return newFields;
},
collapsible: (field: CollapsibleField, fields: SchemaDefinition, config: SanitizedConfig, buildSchemaOptions: BuildSchemaOptions): SchemaDefinition => {
const newFields = { ...fields };
let newFields = { ...fields };
field.fields.forEach((subField: Field) => {
const fieldSchemaMap: FieldSchemaGenerator = fieldToSchemaMap[subField.type];
const fieldSchema: FieldSchemaGenerator = fieldToSchemaMap[subField.type];
if (fieldSchemaMap && fieldAffectsData(subField)) {
const fieldSchema = fieldSchemaMap(subField, fields, config, buildSchemaOptions);
newFields[subField.name] = fieldSchema[subField.name];
if (fieldSchema) {
newFields = fieldSchema(subField, newFields, config, buildSchemaOptions);
}
});
return newFields;
},
tabs: (field: TabsField, fields: SchemaDefinition, config: SanitizedConfig, buildSchemaOptions: BuildSchemaOptions): SchemaDefinition => {
const newFields = { ...fields };
let newFields = { ...fields };
field.tabs.forEach((tab) => {
tab.fields.forEach((subField: Field) => {
const fieldSchemaMap: FieldSchemaGenerator = fieldToSchemaMap[subField.type];
const fieldSchema: FieldSchemaGenerator = fieldToSchemaMap[subField.type];
if (fieldSchemaMap && fieldAffectsData(subField)) {
const fieldSchema = fieldSchemaMap(subField, fields, config, buildSchemaOptions);
newFields[subField.name] = fieldSchema[subField.name];
if (fieldSchema) {
newFields = fieldSchema(subField, newFields, config, buildSchemaOptions);
}
});
});
return newFields;
},
array: (field: ArrayField, fields: SchemaDefinition, config: SanitizedConfig, buildSchemaOptions: BuildSchemaOptions) => {

View File

@@ -49,6 +49,38 @@ const TabsFields: CollectionConfig = {
},
],
},
{
type: 'collapsible',
label: 'Tabs within Collapsible',
fields: [
{
type: 'tabs',
tabs: [
{
label: 'Nested Tab One',
description: 'Here is a description for a nested tab',
fields: [
{
name: 'textarea',
type: 'textarea',
},
],
},
{
label: 'Nested Tab Two',
description: 'Description for tab two',
fields: [
{
name: 'anotherText',
type: 'text',
required: true,
},
],
},
],
},
],
},
],
};
@@ -66,6 +98,8 @@ export const tabsDoc = {
],
text: 'This text will show up in the second tab input',
number: 12,
textarea: 'Here is some text that goes in a textarea',
anotherText: 'Super tired of writing this text',
};
export default TabsFields;