diff --git a/packages/block-editor/src/components/border-radius-control/all-input-control.js b/packages/block-editor/src/components/border-radius-control/all-input-control.js
new file mode 100644
index 00000000000000..00073ba297c666
--- /dev/null
+++ b/packages/block-editor/src/components/border-radius-control/all-input-control.js
@@ -0,0 +1,29 @@
+/**
+ * WordPress dependencies
+ */
+import { __experimentalUnitControl as UnitControl } from '@wordpress/components';
+import { __ } from '@wordpress/i18n';
+
+/**
+ * Internal dependencies
+ */
+import { getAllValue, hasMixedValues, hasDefinedValues } from './utils';
+
+export default function AllInputControl( { onChange, values, ...props } ) {
+ const allValue = getAllValue( values );
+ const hasValues = hasDefinedValues( values );
+ const isMixed = hasValues && hasMixedValues( values );
+ const allPlaceholder = isMixed ? __( 'Mixed' ) : null;
+
+ return (
+
+ );
+}
diff --git a/packages/block-editor/src/components/border-radius-control/index.js b/packages/block-editor/src/components/border-radius-control/index.js
new file mode 100644
index 00000000000000..7d5233d5cabe6e
--- /dev/null
+++ b/packages/block-editor/src/components/border-radius-control/index.js
@@ -0,0 +1,102 @@
+/**
+ * WordPress dependencies
+ */
+import {
+ RangeControl,
+ __experimentalParseUnit as parseUnit,
+ __experimentalUseCustomUnits as useCustomUnits,
+} from '@wordpress/components';
+import { useState } from '@wordpress/element';
+import { __ } from '@wordpress/i18n';
+
+/**
+ * Internal dependencies
+ */
+import AllInputControl from './all-input-control';
+import InputControls from './input-controls';
+import LinkedButton from './linked-button';
+import {
+ getAllValue,
+ getAllUnit,
+ hasDefinedValues,
+ hasMixedValues,
+} from './utils';
+
+const DEFAULT_VALUES = {
+ topLeft: null,
+ topRight: null,
+ bottomLeft: null,
+ bottomRight: null,
+};
+const MIN_BORDER_RADIUS_VALUE = 0;
+const MAX_BORDER_RADIUS_VALUES = {
+ px: 100,
+ em: 20,
+ rem: 20,
+};
+
+/**
+ * Control to display border radius options.
+ *
+ * @param {Object} props Component props.
+ * @param {Function} props.onChange Callback to handle onChange.
+ * @param {Object} props.values Border radius values.
+ *
+ * @return {WPElement} Custom border radius control.
+ */
+export default function BorderRadiusControl( { onChange, values } ) {
+ const [ isLinked, setIsLinked ] = useState(
+ ! hasDefinedValues( values ) || ! hasMixedValues( values )
+ );
+
+ const units = useCustomUnits( { availableUnits: [ 'px', 'em', 'rem' ] } );
+ const unit = getAllUnit( values );
+ const unitConfig = units.find( ( item ) => item.value === unit );
+ const step = unitConfig?.step || 1;
+
+ const [ allValue ] = parseUnit( getAllValue( values ) );
+
+ const toggleLinked = () => setIsLinked( ! isLinked );
+
+ const handleSliderChange = ( next ) => {
+ onChange( next !== undefined ? `${ next }${ unit }` : undefined );
+ };
+
+ return (
+
+ );
+}
diff --git a/packages/block-editor/src/components/border-radius-control/input-controls.js b/packages/block-editor/src/components/border-radius-control/input-controls.js
new file mode 100644
index 00000000000000..db294c7f8bd1b6
--- /dev/null
+++ b/packages/block-editor/src/components/border-radius-control/input-controls.js
@@ -0,0 +1,55 @@
+/**
+ * WordPress dependencies
+ */
+import { __experimentalUnitControl as UnitControl } from '@wordpress/components';
+import { __ } from '@wordpress/i18n';
+
+const CORNERS = {
+ topLeft: __( 'Top left' ),
+ topRight: __( 'Top right' ),
+ bottomLeft: __( 'Bottom left' ),
+ bottomRight: __( 'Bottom right' ),
+};
+
+export default function BoxInputControls( {
+ onChange,
+ values: valuesProp,
+ ...props
+} ) {
+ const createHandleOnChange = ( corner ) => ( next ) => {
+ if ( ! onChange ) {
+ return;
+ }
+
+ onChange( {
+ ...values,
+ [ corner ]: next ? next : undefined,
+ } );
+ };
+
+ // For shorthand style & backwards compatibility, handle flat string value.
+ const values =
+ typeof valuesProp !== 'string'
+ ? valuesProp
+ : {
+ topLeft: valuesProp,
+ topRight: valuesProp,
+ bottomLeft: valuesProp,
+ bottomRight: valuesProp,
+ };
+
+ // Controls are wrapped in tooltips as visible labels aren't desired here.
+ return (
+
+ { Object.entries( CORNERS ).map( ( [ key, label ] ) => (
+
+ ) ) }
+
+ );
+}
diff --git a/packages/block-editor/src/components/border-radius-control/linked-button.js b/packages/block-editor/src/components/border-radius-control/linked-button.js
new file mode 100644
index 00000000000000..58fec1012b0651
--- /dev/null
+++ b/packages/block-editor/src/components/border-radius-control/linked-button.js
@@ -0,0 +1,25 @@
+/**
+ * WordPress dependencies
+ */
+import { Button, Tooltip } from '@wordpress/components';
+import { link, linkOff } from '@wordpress/icons';
+import { __ } from '@wordpress/i18n';
+
+export default function LinkedButton( { isLinked, ...props } ) {
+ const label = isLinked ? __( 'Unlink Radii' ) : __( 'Link Radii' );
+
+ return (
+
+
+
+ );
+}
diff --git a/packages/block-editor/src/components/border-radius-control/style.scss b/packages/block-editor/src/components/border-radius-control/style.scss
new file mode 100644
index 00000000000000..4cfeaaeb6fc739
--- /dev/null
+++ b/packages/block-editor/src/components/border-radius-control/style.scss
@@ -0,0 +1,57 @@
+.components-border-radius-control {
+ margin-bottom: $grid-unit-15;
+
+ legend {
+ padding-bottom: $grid-unit-05;
+ }
+
+ .components-border-radius-control__wrapper {
+ display: flex;
+ justify-content: space-between;
+ align-items: flex-start;
+
+ > .components-unit-control-wrapper {
+ width: calc(50% - 26px);
+ margin-bottom: 0;
+ }
+
+ .components-range-control {
+ width: calc(50% - 26px);
+ margin-bottom: 0;
+
+ .components-base-control__field {
+ margin-bottom: 0;
+ height: 30px;
+ }
+
+ .components-range-control__wrapper {
+ margin-right: 10px;
+ }
+ }
+
+ > span {
+ flex: 0 0 auto;
+ }
+ }
+
+ .components-border-radius-control__input-controls-wrapper {
+ display: flex;
+ width: 70%;
+ flex-wrap: wrap;
+
+ .components-unit-control-wrapper {
+ width: calc(50% - #{ $grid-unit-10 });
+ margin-bottom: $grid-unit-10;
+ margin-right: $grid-unit-10;
+ }
+ }
+
+ .component-border-radius-control__linked-button.has-icon {
+ display: flex;
+ justify-content: center;
+
+ svg {
+ margin-right: 0;
+ }
+ }
+}
diff --git a/packages/block-editor/src/components/border-radius-control/utils.js b/packages/block-editor/src/components/border-radius-control/utils.js
new file mode 100644
index 00000000000000..a5bf6e176c92db
--- /dev/null
+++ b/packages/block-editor/src/components/border-radius-control/utils.js
@@ -0,0 +1,112 @@
+/**
+ * WordPress dependencies
+ */
+import { __experimentalParseUnit as parseUnit } from '@wordpress/components';
+
+/**
+ * Gets the item with the highest occurrence within an array
+ * https://stackoverflow.com/a/20762713
+ *
+ * @param {Array} arr Array of items to check.
+ * @return {any} The item with the most occurrences.
+ */
+function mode( arr ) {
+ return arr
+ .sort(
+ ( a, b ) =>
+ arr.filter( ( v ) => v === a ).length -
+ arr.filter( ( v ) => v === b ).length
+ )
+ .pop();
+}
+
+/**
+ * Returns the most common CSS unit in the radius values.
+ *
+ * @param {Object|string} values Radius values.
+ * @return {string} Most common CSS unit in values.
+ */
+export function getAllUnit( values = {} ) {
+ if ( typeof values === 'string' ) {
+ const [ , unit ] = parseUnit( values );
+ return unit || 'px';
+ }
+
+ const allUnits = Object.values( values ).map( ( value ) => {
+ const [ , unit ] = parseUnit( value );
+ return unit;
+ } );
+
+ return mode( allUnits );
+}
+
+/**
+ * Gets the 'all' input value and unit from values data.
+ *
+ * @param {Object|string} values Radius values.
+ * @return {string} A value + unit for the 'all' input.
+ */
+export function getAllValue( values = {} ) {
+ /**
+ * Border radius support was originally a single pixel value.
+ *
+ * To maintain backwards compatibility treat this case as the all value.
+ */
+ if ( typeof values === 'string' ) {
+ return values;
+ }
+
+ const parsedValues = Object.values( values ).map( ( value ) =>
+ parseUnit( value )
+ );
+
+ const allValues = parsedValues.map( ( value ) => value[ 0 ] );
+ const allUnits = parsedValues.map( ( value ) => value[ 1 ] );
+
+ const value = allValues.every( ( v ) => v === allValues[ 0 ] )
+ ? allValues[ 0 ]
+ : '';
+ const unit = mode( allUnits );
+
+ const allValue = value === 0 || value ? `${ value }${ unit }` : null;
+
+ return allValue;
+}
+
+/**
+ * Checks to determine if values are mixed.
+ *
+ * @param {Object} values Radius values.
+ * @return {boolean} Whether values are mixed.
+ */
+export function hasMixedValues( values = {} ) {
+ const allValue = getAllValue( values );
+ const isMixed = isNaN( parseFloat( allValue ) );
+
+ return isMixed;
+}
+
+/**
+ * Checks to determine if values are defined.
+ *
+ * @param {Object} values Radius values.
+ * @return {boolean} Whether values are mixed.
+ */
+export function hasDefinedValues( values ) {
+ if ( ! values ) {
+ return false;
+ }
+
+ // A string value represents a shorthand value.
+ if ( typeof values === 'string' ) {
+ return true;
+ }
+
+ // An object represents longhand border radius values, if any are set
+ // flag values as being defined.
+ const filteredValues = Object.values( values ).filter( ( value ) => {
+ return !! value || value === 0;
+ } );
+
+ return !! filteredValues.length;
+}
diff --git a/packages/block-editor/src/components/border-style-control/index.js b/packages/block-editor/src/components/border-style-control/index.js
index c07e3962438e20..6c44b7bc2fe8ff 100644
--- a/packages/block-editor/src/components/border-style-control/index.js
+++ b/packages/block-editor/src/components/border-style-control/index.js
@@ -1,64 +1,47 @@
/**
* WordPress dependencies
*/
-import { CustomSelectControl } from '@wordpress/components';
+import { Button } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
-
-const DEFAULT_STYLE = {
- key: 'default',
- name: __( 'Default' ),
- style: { borderStyle: undefined },
-};
+import { lineDashed, lineDotted, lineSolid } from '@wordpress/icons';
const BORDER_STYLES = [
- DEFAULT_STYLE,
- {
- key: 'none',
- name: __( 'None' ),
- style: { borderStyle: 'none' },
- },
- {
- key: 'solid',
- name: __( 'Solid' ),
- style: { borderStyle: 'solid' },
- },
- {
- key: 'dashed',
- name: __( 'Dashed' ),
- style: { borderStyle: 'dashed' },
- },
- {
- key: 'dotted',
- name: __( 'Dotted' ),
- style: { borderStyle: 'dotted' },
- },
+ { label: __( 'Solid' ), icon: lineSolid, value: 'solid' },
+ { label: __( 'Dashed' ), icon: lineDashed, value: 'dashed' },
+ { label: __( 'Dotted' ), icon: lineDotted, value: 'dotted' },
];
/**
* Control to display border style options.
*
- * @param {Object} props Component props.
- * @param {Object} props.onChange Handler for changing border style selection.
- * @param {Object} props.value Currently selected border style value.
+ * @param {Object} props Component props.
+ * @param {Function} props.onChange Handler for changing border style selection.
+ * @param {string} props.value Currently selected border style value.
*
- * @return {WPElement} Custom border style select control.
+ * @return {WPElement} Custom border style segmented control.
*/
export default function BorderStyleControl( { onChange, value } ) {
- const style = BORDER_STYLES.find( ( option ) => option.key === value );
-
return (
);
}
diff --git a/packages/block-editor/src/components/border-style-control/style.scss b/packages/block-editor/src/components/border-style-control/style.scss
index 827f31bca718c5..737103be1cd24c 100644
--- a/packages/block-editor/src/components/border-style-control/style.scss
+++ b/packages/block-editor/src/components/border-style-control/style.scss
@@ -1,14 +1,17 @@
-.components-border-style-control__select {
- margin-bottom: 24px;
-
- button {
- width: 100%;
+.components-border-style-control {
+ legend {
+ padding-bottom: $grid-unit-05;
}
- ul {
- li,
- li:last-child {
- margin: 6px;
+ .components-border-style-control__buttons {
+ display: inline-flex;
+ margin-bottom: $grid-unit-30;
+
+ .components-button.has-icon {
+ min-width: 30px;
+ height: 30px;
+ padding: 3px;
+ margin-right: $grid-unit-05;
}
}
}
diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js
index ef4095a17a1d3a..a781b86dc25242 100644
--- a/packages/block-editor/src/components/index.js
+++ b/packages/block-editor/src/components/index.js
@@ -34,6 +34,7 @@ export {
BlockVerticalAlignmentToolbar,
BlockVerticalAlignmentControl,
} from './block-vertical-alignment-control';
+export { default as __experimentalBorderRadiusControl } from './border-radius-control';
export { default as __experimentalBorderStyleControl } from './border-style-control';
export {
// This is a typo, but kept here for back-compat.
diff --git a/packages/block-editor/src/hooks/border-color.js b/packages/block-editor/src/hooks/border-color.js
index 63e1941e17a2d4..036ff345a8ccdd 100644
--- a/packages/block-editor/src/hooks/border-color.js
+++ b/packages/block-editor/src/hooks/border-color.js
@@ -70,7 +70,7 @@ export function BorderColorEdit( props ) {
return (
{
- setStep( newUnit === 'px' ? 1 : 0.25 );
- };
-
const onChange = ( newRadius ) => {
let newStyle = {
...style,
@@ -56,19 +33,10 @@ export function BorderRadiusEdit( props ) {
setAttributes( { style: newStyle } );
};
- const units = useCustomUnits( {
- availableUnits: useSetting( 'layout.units' ) || [ 'px', 'em', 'rem' ],
- } );
-
return (
-
);
}
diff --git a/packages/block-editor/src/hooks/border-width.js b/packages/block-editor/src/hooks/border-width.js
index e5662f5746354e..702877cc800996 100644
--- a/packages/block-editor/src/hooks/border-width.js
+++ b/packages/block-editor/src/hooks/border-width.js
@@ -4,9 +4,7 @@
import {
__experimentalUnitControl as UnitControl,
__experimentalUseCustomUnits as useCustomUnits,
- __experimentalParseUnit as parseUnit,
} from '@wordpress/components';
-import { useState } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
/**
@@ -30,16 +28,6 @@ export const BorderWidthEdit = ( props ) => {
setAttributes,
} = props;
- // Step value is maintained in state so step is appropriate for current unit
- // even when current radius value is undefined.
- const initialStep =
- parseUnit( style?.border?.width )[ 1 ] === 'px' ? 1 : 0.25;
- const [ step, setStep ] = useState( initialStep );
-
- const onUnitChange = ( newUnit ) => {
- setStep( newUnit === 'px' ? 1 : 0.25 );
- };
-
const onChange = ( newWidth ) => {
let newStyle = {
...style,
@@ -63,11 +51,9 @@ export const BorderWidthEdit = ( props ) => {
return (
);
diff --git a/packages/block-editor/src/hooks/border.js b/packages/block-editor/src/hooks/border.js
index d14633975a88a2..64872c5c470f01 100644
--- a/packages/block-editor/src/hooks/border.js
+++ b/packages/block-editor/src/hooks/border.js
@@ -46,13 +46,17 @@ export function BorderPanel( props ) {
- { isStyleSupported && }
- { isWidthSupported && }
- { isRadiusSupported && }
+ { ( isWidthSupported || isStyleSupported ) && (
+
+ { isWidthSupported && }
+ { isStyleSupported && }
+
+ ) }
{ isColorSupported && }
+ { isRadiusSupported && }
);
diff --git a/packages/block-editor/src/hooks/border.scss b/packages/block-editor/src/hooks/border.scss
index 61d75c59454635..6c859252afc34e 100644
--- a/packages/block-editor/src/hooks/border.scss
+++ b/packages/block-editor/src/hooks/border.scss
@@ -1,4 +1,13 @@
.block-editor-hooks__border-controls {
+ .block-editor-hooks__border-controls-row {
+ display: flex;
+ justify-content: space-between;
+
+ > * {
+ width: calc(50% - #{ $grid-unit-10 });
+ }
+ }
+
.components-unit-control-wrapper {
margin-bottom: $grid-unit-30;
diff --git a/packages/block-editor/src/style.scss b/packages/block-editor/src/style.scss
index a3c9a9f055b342..1ec4d59b7bda05 100644
--- a/packages/block-editor/src/style.scss
+++ b/packages/block-editor/src/style.scss
@@ -30,6 +30,7 @@
@import "./components/block-variation-picker/style.scss";
@import "./components/block-pattern-setup/style.scss";
@import "./components/block-variation-transforms/style.scss";
+@import "./components/border-radius-control/style.scss";
@import "./components/border-style-control/style.scss";
@import "./components/button-block-appender/style.scss";
@import "./components/colors-gradients/style.scss";
diff --git a/packages/edit-site/src/components/sidebar/border-panel.js b/packages/edit-site/src/components/sidebar/border-panel.js
index 46e27d6150accb..85f36bc10253e2 100644
--- a/packages/edit-site/src/components/sidebar/border-panel.js
+++ b/packages/edit-site/src/components/sidebar/border-panel.js
@@ -2,10 +2,15 @@
* WordPress dependencies
*/
import {
+ __experimentalBorderRadiusControl as BorderRadiusControl,
__experimentalBorderStyleControl as BorderStyleControl,
__experimentalColorGradientControl as ColorGradientControl,
} from '@wordpress/block-editor';
-import { PanelBody, RangeControl } from '@wordpress/components';
+import {
+ PanelBody,
+ __experimentalUnitControl as UnitControl,
+ __experimentalUseCustomUnits as useCustomUnits,
+} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
/**
@@ -13,10 +18,7 @@ import { __ } from '@wordpress/i18n';
*/
import { useSetting } from '../editor/utils';
-const MIN_BORDER_RADIUS_VALUE = 0;
-const MAX_BORDER_RADIUS_VALUE = 50;
const MIN_BORDER_WIDTH = 0;
-const MAX_BORDER_WIDTH = 50;
// Defining empty array here instead of inline avoids unnecessary re-renders of
// color control.
@@ -66,23 +68,17 @@ export default function BorderPanel( {
getStyle,
setStyle,
} ) {
- // Border style.
- const hasBorderStyle = useHasBorderStyleControl( { supports, name } );
- const borderStyle = getStyle( name, 'borderStyle' );
+ const units = useCustomUnits( {
+ availableUnits: [ 'px', 'em', 'rem' ],
+ } );
// Border width.
const hasBorderWidth = useHasBorderWidthControl( { supports, name } );
- const borderWidthValue = parseInt(
- getStyle( name, 'borderWidth' ) || 0,
- 10
- );
+ const borderWidthValue = getStyle( name, 'borderWidth' );
- // Border radius.
- const hasBorderRadius = useHasBorderRadiusControl( { supports, name } );
- const borderRadiusValue = parseInt(
- getStyle( name, 'borderRadius' ) || 0,
- 10
- );
+ // Border style.
+ const hasBorderStyle = useHasBorderStyleControl( { supports, name } );
+ const borderStyle = getStyle( name, 'borderStyle' );
// Border color.
const colors = useSetting( 'color.palette' ) || EMPTY_ARRAY;
@@ -91,47 +87,42 @@ export default function BorderPanel( {
const hasBorderColor = useHasBorderColorControl( { supports, name } );
const borderColor = getStyle( name, 'borderColor' );
+ // Border radius.
+ const hasBorderRadius = useHasBorderRadiusControl( { supports, name } );
+ const borderRadiusValues = getStyle( name, 'borderRadius' );
+
return (
- { hasBorderStyle && (
-
- setStyle( name, 'borderStyle', value )
- }
- />
- ) }
- { hasBorderWidth && (
- {
- const widthStyle = value ? `${ value }px` : undefined;
- setStyle( name, 'borderWidth', widthStyle );
- } }
- />
- ) }
- { hasBorderRadius && (
- {
- const radiusStyle = value ? `${ value }px` : undefined;
- setStyle( name, 'borderRadius', radiusStyle );
- } }
- />
+ { ( hasBorderWidth || hasBorderStyle ) && (
+
+ { hasBorderWidth && (
+ {
+ setStyle(
+ name,
+ 'borderWidth',
+ value || undefined
+ );
+ } }
+ units={ units }
+ />
+ ) }
+ { hasBorderStyle && (
+
+ setStyle( name, 'borderStyle', value )
+ }
+ />
+ ) }
+
) }
{ hasBorderColor && (
) }
+ { hasBorderRadius && (
+
+ setStyle( name, 'borderRadius', value )
+ }
+ />
+ ) }
);
}
diff --git a/packages/edit-site/src/components/sidebar/style.scss b/packages/edit-site/src/components/sidebar/style.scss
index bc75cfb88ec401..712db7bed14a0a 100644
--- a/packages/edit-site/src/components/sidebar/style.scss
+++ b/packages/edit-site/src/components/sidebar/style.scss
@@ -24,3 +24,17 @@
.edit-site-global-styles-sidebar__reset-button.components-button {
margin-left: auto;
}
+
+.edit-site-global-styles-sidebar__border-controls-row {
+ display: flex;
+ justify-content: space-between;
+ margin-bottom: $grid-unit-15;
+
+ > * {
+ width: calc(50% - #{ $grid-unit-10 });
+ }
+
+ .components-border-style-control__buttons {
+ margin-bottom: 0;
+ }
+}
diff --git a/packages/icons/src/index.js b/packages/icons/src/index.js
index d98147331d0845..e325bddc3fa0ce 100644
--- a/packages/icons/src/index.js
+++ b/packages/icons/src/index.js
@@ -102,6 +102,9 @@ export { default as keyboardClose } from './library/keyboard-close';
export { default as keyboardReturn } from './library/keyboard-return';
export { default as layout } from './library/layout';
export { default as lifesaver } from './library/lifesaver';
+export { default as lineDashed } from './library/line-dashed';
+export { default as lineDotted } from './library/line-dotted';
+export { default as lineSolid } from './library/line-solid';
export { default as link } from './library/link';
export { default as linkOff } from './library/link-off';
export { default as list } from './library/list';
diff --git a/packages/icons/src/library/line-dashed.js b/packages/icons/src/library/line-dashed.js
new file mode 100644
index 00000000000000..2d8ca1f79aef2e
--- /dev/null
+++ b/packages/icons/src/library/line-dashed.js
@@ -0,0 +1,16 @@
+/**
+ * WordPress dependencies
+ */
+import { Path, SVG } from '@wordpress/primitives';
+
+const lineDashed = (
+
+);
+
+export default lineDashed;
diff --git a/packages/icons/src/library/line-dotted.js b/packages/icons/src/library/line-dotted.js
new file mode 100644
index 00000000000000..01d7e9ab671cc2
--- /dev/null
+++ b/packages/icons/src/library/line-dotted.js
@@ -0,0 +1,16 @@
+/**
+ * WordPress dependencies
+ */
+import { Path, SVG } from '@wordpress/primitives';
+
+const lineDotted = (
+
+);
+
+export default lineDotted;
diff --git a/packages/icons/src/library/line-solid.js b/packages/icons/src/library/line-solid.js
new file mode 100644
index 00000000000000..c8dc39c4536691
--- /dev/null
+++ b/packages/icons/src/library/line-solid.js
@@ -0,0 +1,12 @@
+/**
+ * WordPress dependencies
+ */
+import { Path, SVG } from '@wordpress/primitives';
+
+const lineSolid = (
+
+);
+
+export default lineSolid;