feat: finishes tabs field
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
margin: 0 0 $baseline;
|
||||
font-size: base(.75);
|
||||
line-height: 1.5;
|
||||
letter-spacing: -.375px;
|
||||
}
|
||||
|
||||
%h5 {
|
||||
|
||||
Reference in New Issue
Block a user