Skip to content

Commit

Permalink
Draft combined border controls component
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronrobertshaw committed Jan 7, 2022
1 parent 90c1e7d commit 776891f
Show file tree
Hide file tree
Showing 52 changed files with 1,545 additions and 25 deletions.
42 changes: 42 additions & 0 deletions docs/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,48 @@
"markdown_source": "../packages/components/src/base-field/README.md",
"parent": "components"
},
{
"title": "BorderBoxControl",
"slug": "border-box-control",
"markdown_source": "../packages/components/src/border-box-control/border-box-control/README.md",
"parent": "components"
},
{
"title": "BorderVisualizer",
"slug": "border-visualizer",
"markdown_source": "../packages/components/src/border-box-control/border-visualizer/README.md",
"parent": "components"
},
{
"title": "LinkedButton",
"slug": "linked-button",
"markdown_source": "../packages/components/src/border-box-control/linked-button/README.md",
"parent": "components"
},
{
"title": "SplitBorderControl",
"slug": "split-border-control",
"markdown_source": "../packages/components/src/border-box-control/split-border-control/README.md",
"parent": "components"
},
{
"title": "BorderControl",
"slug": "border-control",
"markdown_source": "../packages/components/src/border-control/border-control/README.md",
"parent": "components"
},
{
"title": "BorderDropdown",
"slug": "border-dropdown",
"markdown_source": "../packages/components/src/border-control/border-dropdown/README.md",
"parent": "components"
},
{
"title": "BorderStyleControl",
"slug": "border-style-control",
"markdown_source": "../packages/components/src/border-control/border-style-control/README.md",
"parent": "components"
},
{
"title": "BoxControl",
"slug": "box-control",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# BorderBoxControl

<div class="callout callout-alert">
This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes.
</div>
<br />

## Development guidelines
## Usage
## Props
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import LinkedButton from '../linked-button';
import SplitBorderControl from '../split-border-control';
import { BorderControl } from '../../border-control';
import { HStack } from '../../h-stack';
import { View } from '../../view';
import { contextConnect, WordPressComponentProps } from '../../ui/context';
import { useBorderBoxControl } from './hook';

import type { BorderBoxControlProps } from '../types';

const BorderBoxControl = (
props: WordPressComponentProps< BorderBoxControlProps, 'div' >,
forwardedRef: React.Ref< any >
) => {
const {
className,
colors,
hasMixedBorders,
isLinked,
linkedControlClassName,
onLinkedChange,
onSplitChange,
toggleLinked,
value,
__experimentalHasMultipleOrigins,
__experimentalIsRenderedInSidebar,
...otherProps
} = useBorderBoxControl( props );

return (
<View className={ className } { ...otherProps } ref={ forwardedRef }>
<HStack alignment={ 'start' } expanded={ true } spacing={ 3 }>
{ isLinked ? (
<BorderControl
className={ linkedControlClassName }
colors={ colors }
onChange={ onLinkedChange }
placeholder={
hasMixedBorders ? __( 'Mixed' ) : undefined
}
value={ hasMixedBorders ? undefined : value?.top }
withSlider={ true }
width={ '110px' }
__experimentalHasMultipleOrigins={
__experimentalHasMultipleOrigins
}
__experimentalIsRenderedInSidebar={
__experimentalIsRenderedInSidebar
}
/>
) : (
<SplitBorderControl
colors={ colors }
onChange={ onSplitChange }
value={ value }
__experimentalHasMultipleOrigins={
__experimentalHasMultipleOrigins
}
__experimentalIsRenderedInSidebar={
__experimentalIsRenderedInSidebar
}
/>
) }
<LinkedButton onClick={ toggleLinked } isLinked={ isLinked } />
</HStack>
</View>
);
};

const ConnectedBorderBoxControl = contextConnect(
BorderBoxControl,
'BorderBoxControl'
);

export default ConnectedBorderBoxControl;
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/**
* WordPress dependencies
*/
import { useMemo, useState } from '@wordpress/element';

/**
* Internal dependencies
*/
import * as styles from '../styles';
import { hasMixedBorders } from '../utils';
import { useContextSystem, WordPressComponentProps } from '../../ui/context';
import { useCx } from '../../utils/hooks/use-cx';

import type { Border } from '../../border-control/types';
import type { BordersKey, BorderBoxControlProps } from '../types';

export function useBorderBoxControl(
props: WordPressComponentProps< BorderBoxControlProps, 'div' >
) {
const { className, onChange, value, ...otherProps } = useContextSystem(
props,
'BorderBoxControl'
);

const mixedBorders = hasMixedBorders( value );
const [ isLinked, setIsLinked ] = useState( ! mixedBorders );
const toggleLinked = () => setIsLinked( ! isLinked );

const onLinkedChange = ( newBorder: Border | undefined ) => {
if ( ! newBorder ) {
onChange( undefined );
}

onChange( {
top: newBorder,
right: newBorder,
bottom: newBorder,
left: newBorder,
} );
};

const onSplitChange = (
newBorder: Border | undefined,
side: BordersKey
) => {
onChange?.( {
...value,
[ side ]: newBorder,
} );
};

const cx = useCx();
const classes = useMemo( () => {
return cx( styles.BorderBoxControl, className );
}, [ className ] );

const linkedControlClassName = useMemo( () => {
return cx( styles.LinkedBorderControl );
}, [] );

return {
...otherProps,
className: classes,
hasMixedBorders: mixedBorders,
isLinked,
linkedControlClassName,
onLinkedChange,
onSplitChange,
toggleLinked,
value,
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as BorderBoxControl } from './component';
export { useBorderBoxControl } from './hook';
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# BorderVisualizer

<div class="callout callout-alert">
This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes.
</div>
<br />

## Development guidelines
## Usage
## Props
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import { View } from '../../view';
import { contextConnect, WordPressComponentProps } from '../../ui/context';
import { getClampedWidthBorderStyle } from '../utils';
import { useBorderVisualizer } from './hook';

import type { BorderVisualizerProps } from '../types';

const BorderVisualizer = (
props: WordPressComponentProps< BorderVisualizerProps, 'div' >,
forwardedRef: React.Ref< any >
) => {
const { value, ...otherProps } = useBorderVisualizer( props );
const styles = {
borderTop: getClampedWidthBorderStyle( value?.top ),
borderRight: getClampedWidthBorderStyle( value?.right ),
borderBottom: getClampedWidthBorderStyle( value?.bottom ),
borderLeft: getClampedWidthBorderStyle( value?.left ),
};

return <View { ...otherProps } ref={ forwardedRef } style={ styles } />;
};

const ConnectedBorderVisualizer = contextConnect(
BorderVisualizer,
'BorderVisualizer'
);
export default ConnectedBorderVisualizer;
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* WordPress dependencies
*/
import { useMemo } from '@wordpress/element';

/**
* Internal dependencies
*/
import * as styles from '../styles';
import { useContextSystem, WordPressComponentProps } from '../../ui/context';
import { useCx } from '../../utils/hooks/use-cx';

import type { BorderVisualizerProps } from '../types';

export function useBorderVisualizer(
props: WordPressComponentProps< BorderVisualizerProps, 'div' >
) {
const { className, ...otherProps } = useContextSystem(
props,
'BorderVisualizer'
);

// Generate class names.
const cx = useCx();
const classes = useMemo( () => {
return cx( styles.BorderVisualizer, className );
}, [ className ] );

return { ...otherProps, className: classes };
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './component';
2 changes: 2 additions & 0 deletions packages/components/src/border-box-control/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as BorderBoxControl } from './border-box-control/component';
export { useBorderBoxControl } from './border-box-control/hook';
10 changes: 10 additions & 0 deletions packages/components/src/border-box-control/linked-button/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# LinkedButton

<div class="callout callout-alert">
This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes.
</div>
<br />

## Development guidelines
## Usage
## Props
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/**
* WordPress dependencies
*/
import { link, linkOff } from '@wordpress/icons';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import Button from '../../button';
import Tooltip from '../../tooltip';
import { contextConnect, WordPressComponentProps } from '../../ui/context';
import { useLinkedButton } from './hook';

import type { LinkedButtonProps } from '../types';

const LinkedButton = (
props: WordPressComponentProps< LinkedButtonProps, 'div' >,
forwardedRef: React.Ref< any >
) => {
const { className, isLinked, ...buttonProps } = useLinkedButton( props );
const label = isLinked ? __( 'Unlink Sides' ) : __( 'Link Sides' );

return (
<Tooltip text={ label }>
<div className={ className }>
<Button
{ ...buttonProps }
variant={ isLinked ? 'primary' : 'secondary' }
isSmall
icon={ isLinked ? link : linkOff }
iconSize={ 16 }
aria-label={ label }
ref={ forwardedRef }
/>
</div>
</Tooltip>
);
};

const ConnectedLinkedButton = contextConnect( LinkedButton, 'LinkedButton' );
export default ConnectedLinkedButton;
30 changes: 30 additions & 0 deletions packages/components/src/border-box-control/linked-button/hook.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* WordPress dependencies
*/
import { useMemo } from '@wordpress/element';

/**
* Internal dependencies
*/
import * as styles from '../styles';
import { useContextSystem, WordPressComponentProps } from '../../ui/context';
import { useCx } from '../../utils/hooks/use-cx';

import type { LinkedButtonProps } from '../types';

export function useLinkedButton(
props: WordPressComponentProps< LinkedButtonProps, 'div' >
) {
const { className, ...otherProps } = useContextSystem(
props,
'LinkedButton'
);

// Generate class names.
const cx = useCx();
const classes = useMemo( () => {
return cx( styles.LinkedButton, className );
}, [ className ] );

return { ...otherProps, className: classes };
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './component';
Loading

0 comments on commit 776891f

Please sign in to comment.