-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Make user able to change all color palette origins #36674
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
/** | ||
* External dependencies | ||
*/ | ||
import kebabCase from 'lodash'; | ||
import { kebabCase } from 'lodash'; | ||
|
||
/** | ||
* WordPress dependencies | ||
|
@@ -49,12 +49,14 @@ function ColorNameInput( { value, onChange } ) { | |
} | ||
|
||
function ColorOption( { | ||
canOnlyChangeValues, | ||
color, | ||
onChange, | ||
isEditing, | ||
onStartEditing, | ||
onRemove, | ||
onStopEditing, | ||
slugPrefix, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not very keen on making the ColorEdit component aware of the prefix for custom colors. For components, do we usually expose "hooks" for consumers to tweak the normal behavior? Like, for example, we could have an Not really familiar with how/whether this is a practice we want our components to have, so I'll go with whatever you think is best. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the prefix may end up being used for other things besides custom colors, and it seems we will probably not need other name manipulation than the prefix. So I guess slugPrefix is enough. In the future, I'm not totally sure of the API and the place where this component will be. I guess when we remove experimental from this component or move the component to another package we should audit its API. |
||
} ) { | ||
const focusOutsideProps = useFocusOutside( onStopEditing ); | ||
return ( | ||
|
@@ -68,22 +70,22 @@ function ColorOption( { | |
<ColorIndicatorStyled colorValue={ color.color } /> | ||
</FlexItem> | ||
<FlexItem> | ||
{ isEditing ? ( | ||
{ isEditing && ! canOnlyChangeValues ? ( | ||
<ColorNameInput | ||
value={ color.name } | ||
onChange={ ( nextName ) => | ||
onChange( { | ||
...color, | ||
name: nextName, | ||
slug: kebabCase( nextName ), | ||
slug: slugPrefix + kebabCase( nextName ), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, I see. We need to fix the kebabCase import to |
||
} ) | ||
} | ||
/> | ||
) : ( | ||
<ColorNameContainer>{ color.name }</ColorNameContainer> | ||
) } | ||
</FlexItem> | ||
{ isEditing && ( | ||
{ isEditing && ! canOnlyChangeValues && ( | ||
<FlexItem> | ||
<RemoveButton | ||
isSmall | ||
|
@@ -119,6 +121,8 @@ function ColorPaletteEditListView( { | |
onChange, | ||
editingColor, | ||
setEditingColor, | ||
canOnlyChangeValues, | ||
slugPrefix, | ||
} ) { | ||
// When unmounting the component if there are empty colors (the user did not complete the insertion) clean them. | ||
const colorReference = useRef(); | ||
|
@@ -140,6 +144,7 @@ function ColorPaletteEditListView( { | |
<ItemGroup isBordered isSeparated> | ||
{ colors.map( ( color, index ) => ( | ||
<ColorOption | ||
canOnlyChangeValues={ canOnlyChangeValues } | ||
key={ index } | ||
color={ color } | ||
onStartEditing={ () => { | ||
|
@@ -177,6 +182,7 @@ function ColorPaletteEditListView( { | |
setEditingColor( null ); | ||
} | ||
} } | ||
slugPrefix={ slugPrefix } | ||
/> | ||
) ) } | ||
</ItemGroup> | ||
|
@@ -186,7 +192,15 @@ function ColorPaletteEditListView( { | |
|
||
const EMPTY_ARRAY = []; | ||
|
||
export default function ColorEdit( { colors = EMPTY_ARRAY, onChange } ) { | ||
export default function ColorEdit( { | ||
colors = EMPTY_ARRAY, | ||
onChange, | ||
paletteLabel, | ||
emptyMessage, | ||
canOnlyChangeValues, | ||
canReset, | ||
slugPrefix = '', | ||
} ) { | ||
const [ isEditing, setIsEditing ] = useState( false ); | ||
const [ editingColor, setEditingColor ] = useState( null ); | ||
const isAdding = | ||
|
@@ -200,7 +214,7 @@ export default function ColorEdit( { colors = EMPTY_ARRAY, onChange } ) { | |
return ( | ||
<ColorEditStyles> | ||
<ColorHStackHeader> | ||
<ColorHeading>{ __( 'Custom' ) }</ColorHeading> | ||
<ColorHeading>{ paletteLabel }</ColorHeading> | ||
<ColorActionsContainer> | ||
{ isEditing && ( | ||
<DoneButton | ||
|
@@ -213,24 +227,26 @@ export default function ColorEdit( { colors = EMPTY_ARRAY, onChange } ) { | |
{ __( 'Done' ) } | ||
</DoneButton> | ||
) } | ||
<Button | ||
isSmall | ||
isPressed={ isAdding } | ||
icon={ plus } | ||
label={ __( 'Add custom color' ) } | ||
onClick={ () => { | ||
onChange( [ | ||
...colors, | ||
{ | ||
color: '#000', | ||
name: '', | ||
slug: '', | ||
}, | ||
] ); | ||
setIsEditing( true ); | ||
setEditingColor( colors.length ); | ||
} } | ||
/> | ||
{ ! canOnlyChangeValues && ( | ||
<Button | ||
isSmall | ||
isPressed={ isAdding } | ||
icon={ plus } | ||
label={ __( 'Add color' ) } | ||
onClick={ () => { | ||
onChange( [ | ||
...colors, | ||
{ | ||
color: '#000', | ||
name: '', | ||
slug: '', | ||
}, | ||
] ); | ||
setIsEditing( true ); | ||
setEditingColor( colors.length ); | ||
} } | ||
/> | ||
) } | ||
{ ! isEditing && ( | ||
<Button | ||
disabled={ ! hasColors } | ||
|
@@ -242,28 +258,42 @@ export default function ColorEdit( { colors = EMPTY_ARRAY, onChange } ) { | |
} } | ||
/> | ||
) } | ||
{ isEditing && ( | ||
{ isEditing && ( canReset || ! canOnlyChangeValues ) && ( | ||
<DropdownMenu | ||
icon={ moreVertical } | ||
label={ __( 'Custom color options' ) } | ||
label={ __( 'Color options' ) } | ||
toggleProps={ { | ||
isSmall: true, | ||
} } | ||
> | ||
{ ( { onClose } ) => ( | ||
<> | ||
<NavigableMenu role="menu"> | ||
<Button | ||
variant="tertiary" | ||
onClick={ () => { | ||
setEditingColor( null ); | ||
setIsEditing( false ); | ||
onChange(); | ||
onClose(); | ||
} } | ||
> | ||
{ __( 'Remove all custom colors' ) } | ||
</Button> | ||
{ ! canOnlyChangeValues && ( | ||
<Button | ||
variant="tertiary" | ||
onClick={ () => { | ||
setEditingColor( null ); | ||
setIsEditing( false ); | ||
onChange(); | ||
onClose(); | ||
} } | ||
> | ||
{ __( 'Remove all colors' ) } | ||
</Button> | ||
) } | ||
{ canReset && ( | ||
<Button | ||
variant="tertiary" | ||
onClick={ () => { | ||
setEditingColor( null ); | ||
onChange(); | ||
onClose(); | ||
} } | ||
> | ||
{ __( 'Reset colors' ) } | ||
</Button> | ||
) } | ||
</NavigableMenu> | ||
</> | ||
) } | ||
|
@@ -275,10 +305,12 @@ export default function ColorEdit( { colors = EMPTY_ARRAY, onChange } ) { | |
<> | ||
{ isEditing && ( | ||
<ColorPaletteEditListView | ||
canOnlyChangeValues={ canOnlyChangeValues } | ||
colors={ colors } | ||
onChange={ onChange } | ||
editingColor={ editingColor } | ||
setEditingColor={ setEditingColor } | ||
slugPrefix={ slugPrefix } | ||
/> | ||
) } | ||
{ ! isEditing && ( | ||
|
@@ -291,10 +323,7 @@ export default function ColorEdit( { colors = EMPTY_ARRAY, onChange } ) { | |
) } | ||
</> | ||
) } | ||
{ ! hasColors && | ||
__( | ||
'Custom colors are empty! Add some colors to create your own color palette.' | ||
) } | ||
{ ! hasColors && emptyMessage } | ||
</ColorEditStyles> | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd think we want to rename the
user
origin tocustom
, as we did withcore
todefault
to match the UI, class/css var generation, etc. Perhaps we can do this in a different PR that lands before this one?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the use case
isset( $preset[ 0 ] )
is checking for? My understanding is that we should always skip reorganizing the presets if the origin is the user, as we'll store them already keyed by origin, so this could be simplified to:if ( null != $preset && 'user' !== $origin )
.Additionally, I wonder if we need to keep back compatibility with existing user data in the database. We could add an extra step to normalize the user data by origin for that case (older data that is not keyed by origin).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I see now: the
isset( $preset[ 0 ] )
already does the back-compatibility trick :) Only old user data with no keys by origin would have the0
key.