style changes to the repeater
This commit is contained in:
46
src/client/components/controls/IconButton/index.js
Normal file
46
src/client/components/controls/IconButton/index.js
Normal file
@@ -0,0 +1,46 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Button from '../Button';
|
||||
import Crosshair from '../../graphics/Crosshair';
|
||||
import Arrow from '../../graphics/Arrow';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const baseClass = 'icon-button';
|
||||
|
||||
const IconButton = ({ iconName, className, ...rest }) => {
|
||||
const classes = [
|
||||
baseClass,
|
||||
className && className,
|
||||
`${baseClass}--${iconName}`,
|
||||
].filter(Boolean).join(' ');
|
||||
|
||||
const icons = {
|
||||
crosshair: Crosshair,
|
||||
crossOut: Crosshair,
|
||||
arrow: Arrow,
|
||||
};
|
||||
|
||||
const Icon = icons[iconName] || icons.arrow;
|
||||
|
||||
return (
|
||||
<Button
|
||||
className={classes}
|
||||
{...rest}
|
||||
>
|
||||
<Icon />
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
IconButton.defaultProps = {
|
||||
className: '',
|
||||
};
|
||||
|
||||
IconButton.propTypes = {
|
||||
iconName: PropTypes.oneOf(['arrow', 'crossOut', 'crosshair']).isRequired,
|
||||
className: PropTypes.string,
|
||||
};
|
||||
|
||||
export default IconButton;
|
||||
27
src/client/components/controls/IconButton/index.scss
Normal file
27
src/client/components/controls/IconButton/index.scss
Normal file
@@ -0,0 +1,27 @@
|
||||
@import '../../../scss/styles.scss';
|
||||
|
||||
.icon-button {
|
||||
line-height: 0;
|
||||
background: transparent;
|
||||
border: 1px solid $black;
|
||||
|
||||
&:hover {
|
||||
background: lighten($black, 50%);
|
||||
border-color: lighten($black, .2%);
|
||||
@include color-svg(lighten($black, 5%));
|
||||
}
|
||||
|
||||
&.btn {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
@include color-svg($black);
|
||||
}
|
||||
|
||||
&--crossOut {
|
||||
svg {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import './index.scss';
|
||||
import Button from '../Button';
|
||||
import Crosshair from '../../graphics/Crosshair';
|
||||
|
||||
const baseClass = 'repeat-field-button';
|
||||
|
||||
const RepeatFieldButton = ({ onClick }) => {
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
<Button
|
||||
onClick={onClick}
|
||||
type="secondary"
|
||||
>
|
||||
<Crosshair />
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
RepeatFieldButton.propTypes = {
|
||||
onClick: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default RepeatFieldButton;
|
||||
@@ -1,28 +0,0 @@
|
||||
@import '../../../scss/styles.scss';
|
||||
|
||||
.repeat-field-button {
|
||||
width: calc(100% + #{base(2)});
|
||||
margin-left: base(-1);
|
||||
padding: base(1.25) 0;
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
background: $light-gray;
|
||||
height: 2px;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
bottom: 50%;
|
||||
}
|
||||
|
||||
.btn {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background: white;
|
||||
margin: 0;
|
||||
padding: base(.25) base(.75);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
@import '../../../scss/styles.scss';
|
||||
|
||||
.form {
|
||||
@include row;
|
||||
|
||||
> * {
|
||||
width: 100%;
|
||||
|
||||
@@ -4,9 +4,8 @@ import PropTypes from 'prop-types';
|
||||
import FormContext from '../../Form/Context';
|
||||
import Section from '../../../layout/Section';
|
||||
import RenderFields from '../../RenderFields';
|
||||
import RepeatFieldButton from '../../../controls/RepeatFieldButton';
|
||||
import Button from '../../../controls/Button';
|
||||
import X from '../../../graphics/X';
|
||||
import IconButton from '../../../controls/IconButton';
|
||||
import Pill from '../../../modules/Pill';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
@@ -24,7 +23,7 @@ const Repeater = (props) => {
|
||||
defaultValue,
|
||||
} = props;
|
||||
|
||||
const addNewRow = (rowIndex) => {
|
||||
const addRow = (rowIndex) => {
|
||||
dispatchFields({
|
||||
type: 'ADD_ROW', rowIndex, name, fields,
|
||||
});
|
||||
@@ -50,37 +49,50 @@ const Repeater = (props) => {
|
||||
heading={label}
|
||||
className="repeater"
|
||||
>
|
||||
|
||||
{rowCount === 0
|
||||
&& (
|
||||
<RepeatFieldButton onClick={() => addNewRow(0)} />
|
||||
)}
|
||||
{Array.from(Array(rowCount).keys()).map((_, rowIndex) => {
|
||||
return (
|
||||
<React.Fragment key={rowIndex}>
|
||||
<div className={`${baseClass}__section-inner`}>
|
||||
<Button
|
||||
className="delete"
|
||||
onClick={() => removeRow(rowIndex)}
|
||||
type="error"
|
||||
>
|
||||
<X />
|
||||
</Button>
|
||||
<h2>{`${label} - Item ${rowIndex}`}</h2>
|
||||
<div className={`${baseClass}__section`}>
|
||||
<div className={`${baseClass}__section-header`}>
|
||||
<Pill>
|
||||
{name}
|
||||
</Pill>
|
||||
<h4 className={`${baseClass}__section-header__heading`}>Title Goes Here</h4>
|
||||
|
||||
<RenderFields
|
||||
fields={fields.map((field) => {
|
||||
const fieldName = `${name}.${rowIndex}.${field.name}`;
|
||||
return ({
|
||||
...field,
|
||||
name: fieldName,
|
||||
defaultValue: fieldState?.[fieldName]?.value,
|
||||
});
|
||||
})}
|
||||
/>
|
||||
<div className={`${baseClass}__section-header__controls`}>
|
||||
<IconButton
|
||||
iconName="crosshair"
|
||||
onClick={() => addRow(rowIndex)}
|
||||
size="small"
|
||||
/>
|
||||
|
||||
<IconButton
|
||||
iconName="crossOut"
|
||||
onClick={() => removeRow(rowIndex)}
|
||||
size="small"
|
||||
/>
|
||||
|
||||
<IconButton
|
||||
iconName="arrow"
|
||||
// onClick={() => removeRow(rowIndex)}
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={`${baseClass}__section-content`}>
|
||||
<RenderFields
|
||||
fields={fields.map((field) => {
|
||||
const fieldName = `${name}.${rowIndex}.${field.name}`;
|
||||
return ({
|
||||
...field,
|
||||
name: fieldName,
|
||||
defaultValue: fieldState?.[fieldName]?.value,
|
||||
});
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<RepeatFieldButton onClick={() => addNewRow(rowIndex)} />
|
||||
</React.Fragment>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -1,16 +1,70 @@
|
||||
@import '../../../../scss/styles.scss';
|
||||
|
||||
.field-repeater {
|
||||
|
||||
.content {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&__section-inner {
|
||||
padding: base(1);
|
||||
&__section {
|
||||
margin-right: base(1);
|
||||
background: $light-gray;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
|
||||
+ .field-repeater__section {
|
||||
margin-top: base(.5);
|
||||
}
|
||||
}
|
||||
|
||||
&__section-header {
|
||||
padding: base(.75) base(1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid white;
|
||||
|
||||
.pill {
|
||||
margin-right: base(.5);
|
||||
}
|
||||
|
||||
&__heading {
|
||||
font-family: $font-body;
|
||||
margin: 0;
|
||||
font-size: base(.65);
|
||||
}
|
||||
|
||||
&__controls {
|
||||
margin-left: auto;
|
||||
|
||||
.btn {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.icon-button--crossOut,
|
||||
.icon-button--crosshair {
|
||||
margin-right: base(.25);
|
||||
}
|
||||
|
||||
.icon-button--crosshair {
|
||||
border-color: $primary;
|
||||
@include color-svg($primary);
|
||||
|
||||
&:hover {
|
||||
background: lighten($primary, 50%);
|
||||
}
|
||||
}
|
||||
|
||||
.icon-button--arrow {
|
||||
svg {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__section-content {
|
||||
padding: base(.75) base(1);
|
||||
}
|
||||
|
||||
.repeat-field-button {
|
||||
@@ -26,10 +80,6 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
&:hover {
|
||||
@include color-svg(white);
|
||||
}
|
||||
|
||||
.crosshair {
|
||||
padding: 3px;
|
||||
}
|
||||
@@ -37,21 +87,13 @@
|
||||
}
|
||||
|
||||
.btn.delete {
|
||||
position: absolute;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
margin: 0;
|
||||
top: base(1);
|
||||
right: base(1);
|
||||
padding: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
line-height: 0;
|
||||
padding: base(.15);
|
||||
|
||||
.x {
|
||||
padding: 1px;
|
||||
@include color-svg($error);
|
||||
height: 100%;
|
||||
padding: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
@import '../../../scss/styles.scss';
|
||||
|
||||
.field-type {
|
||||
@include gutter;
|
||||
margin-bottom: base(.5);
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
@@ -3,12 +3,12 @@ import React from 'react';
|
||||
const Crosshair = () => {
|
||||
return (
|
||||
<svg
|
||||
width="20px"
|
||||
height="20px"
|
||||
viewBox="0 0 20 20"
|
||||
width="10px"
|
||||
height="10px"
|
||||
viewBox="0 0 10 10"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="crosshair"
|
||||
className="icon crosshair"
|
||||
>
|
||||
<g
|
||||
stroke="none"
|
||||
@@ -16,27 +16,20 @@ const Crosshair = () => {
|
||||
fill="none"
|
||||
fillRule="evenodd"
|
||||
strokeLinecap="square"
|
||||
className="stroke"
|
||||
>
|
||||
<g
|
||||
className="stroke"
|
||||
transform="translate(-0.500000, -0.500000)"
|
||||
>
|
||||
<line
|
||||
x1="11"
|
||||
y1="1"
|
||||
x2="11"
|
||||
y2="20"
|
||||
id="Line"
|
||||
/>
|
||||
<line
|
||||
x1="10.5"
|
||||
y1="0.5"
|
||||
x2="10.5"
|
||||
y2="19.5"
|
||||
id="Line"
|
||||
transform="translate(10.500000, 10.000000) rotate(90.000000) translate(-10.500000, -10.000000) "
|
||||
/>
|
||||
</g>
|
||||
<line
|
||||
x1="-1.11022302e-16"
|
||||
y1="5"
|
||||
x2="10"
|
||||
y2="5"
|
||||
/>
|
||||
<line
|
||||
x1="5"
|
||||
y1="0"
|
||||
x2="5"
|
||||
y2="10"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
import React from 'react';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const X = () => {
|
||||
return (
|
||||
<svg
|
||||
width="15px"
|
||||
height="16px"
|
||||
viewBox="0 0 15 16"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="x"
|
||||
>
|
||||
<g
|
||||
stroke="none"
|
||||
strokeWidth="1"
|
||||
fill="none"
|
||||
fillRule="evenodd"
|
||||
strokeLinecap="square"
|
||||
>
|
||||
<g
|
||||
transform="translate(7.000000, 8.000000) rotate(-315.000000) translate(-7.000000, -8.000000) translate(-3.500000, -2.500000)"
|
||||
className="stroke"
|
||||
>
|
||||
<line
|
||||
x1="11"
|
||||
y1="1"
|
||||
x2="11"
|
||||
y2="20"
|
||||
id="Line"
|
||||
/>
|
||||
<line
|
||||
x1="10.5"
|
||||
y1="0.5"
|
||||
x2="10.5"
|
||||
y2="19.5"
|
||||
id="Line"
|
||||
transform="translate(10.500000, 10.000000) rotate(90.000000) translate(-10.500000, -10.000000) "
|
||||
/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default X;
|
||||
@@ -1,3 +0,0 @@
|
||||
.x {
|
||||
|
||||
}
|
||||
31
src/client/components/modules/Pill/index.js
Normal file
31
src/client/components/modules/Pill/index.js
Normal file
@@ -0,0 +1,31 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import './index.scss';
|
||||
|
||||
const baseClass = 'pill';
|
||||
|
||||
const Pill = ({ children, className }) => {
|
||||
const classes = [
|
||||
baseClass,
|
||||
className && className,
|
||||
].filter(Boolean).join(' ');
|
||||
|
||||
return (
|
||||
<div className={classes}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Pill.defaultProps = {
|
||||
children: undefined,
|
||||
className: '',
|
||||
};
|
||||
|
||||
Pill.propTypes = {
|
||||
children: PropTypes.node,
|
||||
className: PropTypes.string,
|
||||
};
|
||||
|
||||
export default Pill;
|
||||
9
src/client/components/modules/Pill/index.scss
Normal file
9
src/client/components/modules/Pill/index.scss
Normal file
@@ -0,0 +1,9 @@
|
||||
@import '../../../scss/styles.scss';
|
||||
|
||||
.pill {
|
||||
@extend %uppercase-label;
|
||||
color: $black;
|
||||
border: 1px solid $gray;
|
||||
border-radius: 3px;
|
||||
padding: 0 base(.25);
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
@import '../../../scss/styles.scss';
|
||||
|
||||
.sticky-header {
|
||||
@include gutter;
|
||||
|
||||
.sticky-header-wrap {
|
||||
display: flex;
|
||||
|
||||
Reference in New Issue
Block a user