From 372b9b149c26047a1d077e4e6f77571e37316dac Mon Sep 17 00:00:00 2001 From: Gerardo Pacheco Date: Mon, 17 Jul 2023 12:44:40 +0200 Subject: [PATCH] [Mobile] Update toolbar icons and colors (#52336) * Update toolbar icons and colors * Update colors to add $app-safe-area-background * Button component - Update icon colors * SVG component - Update colors to support dark/light themes * ToolbarGroup - Update border colors * HeaderToolbar - Update colors * Layout - Update safe area color * TextColor Format - Update toolbar icon styles * Update changelog * Add missing file extension * Update styleMock * Update BlockMover snapshot * Restores the Fill/Slot logic for the BlockSettingsButton * Adds initial Block Toolbar integration tests related to the block settings button * Add missing style to the styleMock file * Update usage of Platform * Rename $app-safe-area-background to $app-safe-area-background-dark --- packages/base-styles/_colors.native.scss | 1 + .../test/__snapshots__/index.native.js.snap | 5 +- .../block-settings/button.native.js | 41 ++++++++---- .../components/block-toolbar/index.native.js | 14 +++-- .../block-toolbar/test/index.native.js | 42 +++++++++++++ .../inspector-controls/fill.native.js | 3 + .../components/src/button/index.native.js | 10 ++- .../components/src/button/style.native.scss | 9 +++ .../toolbar/toolbar-group/style.native.scss | 5 +- .../toolbar-group-container.native.js | 29 ++++----- .../header/header-toolbar/index.native.js | 63 +++++++++++-------- .../header/header-toolbar/style.native.scss | 27 ++++++-- .../src/components/layout/style.native.scss | 2 +- .../src/text-color/index.native.js | 25 +++++--- .../src/text-color/style.native.scss | 5 +- packages/primitives/src/svg/index.native.js | 5 +- packages/primitives/src/svg/style.native.scss | 17 +++-- packages/react-native-editor/CHANGELOG.md | 1 + test/native/__mocks__/styleMock.js | 6 ++ 19 files changed, 222 insertions(+), 88 deletions(-) create mode 100644 packages/block-editor/src/components/block-toolbar/test/index.native.js create mode 100644 packages/components/src/button/style.native.scss diff --git a/packages/base-styles/_colors.native.scss b/packages/base-styles/_colors.native.scss index c21de46e6a4595..ef4443c38c0e22 100644 --- a/packages/base-styles/_colors.native.scss +++ b/packages/base-styles/_colors.native.scss @@ -102,6 +102,7 @@ $dark-ultra-dim: #ffffff14; //rgba(255, 255, 255, 0.08); $app-background: $white; $app-background-dark: $black; $app-background-dark-alt: $background-dark-elevated; +$app-safe-area-background-dark: #141414; $modal-background: $white; $modal-background-dark: $background-dark-elevated; diff --git a/packages/block-editor/src/components/block-mover/test/__snapshots__/index.native.js.snap b/packages/block-editor/src/components/block-mover/test/__snapshots__/index.native.js.snap index db322ec2af8406..21445e691f4289 100644 --- a/packages/block-editor/src/components/block-mover/test/__snapshots__/index.native.js.snap +++ b/packages/block-editor/src/components/block-mover/test/__snapshots__/index.native.js.snap @@ -49,6 +49,9 @@ exports[`Block Mover Picker should render without crashing and match snapshot 1` { "height": 44, }, + { + "borderLeftWidth": 0.5, + }, undefined, ] } @@ -108,7 +111,6 @@ exports[`Block Mover Picker should render without crashing and match snapshot 1` } > { - return ( - - - - ); -}; +const { Fill, Slot } = createSlotFill( 'SettingsToolbarButton' ); -export default SettingsButton; +const SettingsButton = ( { openGeneralSidebar } ) => ( + +); + +const SettingsButtonFill = ( props ) => ( + + + +); + +const SettingsToolbarButton = withDispatch( ( dispatch ) => { + const { openGeneralSidebar } = dispatch( 'core/edit-post' ); + + return { + openGeneralSidebar: () => openGeneralSidebar( 'edit-post/block' ), + }; +} )( SettingsButtonFill ); + +SettingsToolbarButton.Slot = Slot; + +export default SettingsToolbarButton; diff --git a/packages/block-editor/src/components/block-toolbar/index.native.js b/packages/block-editor/src/components/block-toolbar/index.native.js index 32233fa54a1c15..bdf4c778ebc151 100644 --- a/packages/block-editor/src/components/block-toolbar/index.native.js +++ b/packages/block-editor/src/components/block-toolbar/index.native.js @@ -20,7 +20,7 @@ const REMOVE_EMPY_PARENT_BLOCKS = [ 'core/social-links', ]; -export default function BlockToolbar( { anchorNodeRef, onOpenBlockSettings } ) { +export default function BlockToolbar( { anchorNodeRef } ) { const { rootClientId, blockClientId, @@ -93,9 +93,15 @@ export default function BlockToolbar( { anchorNodeRef, onOpenBlockSettings } ) { <> { isValidAndVisual && ( <> - + + { /* Render only one settings icon even if we have more than one fill - need for hooks with controls. */ } + { ( fills = [ null ] ) => { + if ( ! fills?.length > 0 ) { + return null; + } + return fills[ 0 ]; + } } + diff --git a/packages/block-editor/src/components/block-toolbar/test/index.native.js b/packages/block-editor/src/components/block-toolbar/test/index.native.js new file mode 100644 index 00000000000000..473e1a40bb966a --- /dev/null +++ b/packages/block-editor/src/components/block-toolbar/test/index.native.js @@ -0,0 +1,42 @@ +/** + * External dependencies + */ +import { + addBlock, + fireEvent, + getBlock, + initializeEditor, + setupCoreBlocks, +} from 'test/helpers'; + +setupCoreBlocks(); + +describe( 'Block Toolbar', () => { + it( "doesn't render the block settings button if there aren't any settings for the current selected block", async () => { + // Arrange + const screen = await initializeEditor(); + await addBlock( screen, 'Image' ); + + // Act + fireEvent( + screen.getByTestId( 'media-options-picker' ), + 'backdropPress' + ); + + // Assert + expect( screen.queryByLabelText( 'Open Settings' ) ).toBeNull(); + } ); + + it( 'renders the block settings button for the current selected block', async () => { + // Arrange + const screen = await initializeEditor(); + await addBlock( screen, 'Paragraph' ); + + // Act + const paragraphBlock = await getBlock( screen, 'Paragraph' ); + fireEvent.press( paragraphBlock ); + + // Assert + expect( screen.queryByLabelText( 'Open Settings' ) ).toBeVisible(); + } ); +} ); diff --git a/packages/block-editor/src/components/inspector-controls/fill.native.js b/packages/block-editor/src/components/inspector-controls/fill.native.js index f4cd288c6913cf..d38d865cd15cc0 100644 --- a/packages/block-editor/src/components/inspector-controls/fill.native.js +++ b/packages/block-editor/src/components/inspector-controls/fill.native.js @@ -6,6 +6,7 @@ import { View } from 'react-native'; /** * WordPress dependencies */ +import { Children } from '@wordpress/element'; import { BottomSheetConsumer } from '@wordpress/components'; import warning from '@wordpress/warning'; import deprecated from '@wordpress/deprecated'; @@ -15,6 +16,7 @@ import deprecated from '@wordpress/deprecated'; */ import groups from './groups'; import useDisplayBlockControls from '../use-display-block-controls'; +import { BlockSettingsButton } from '../block-settings'; export default function InspectorControlsFill( { children, @@ -53,6 +55,7 @@ export default function InspectorControlsFill( { } + { Children.count( children ) > 0 && } ); } diff --git a/packages/components/src/button/index.native.js b/packages/components/src/button/index.native.js index 9643f442d28c6a..95ca9d36b3791b 100644 --- a/packages/components/src/button/index.native.js +++ b/packages/components/src/button/index.native.js @@ -24,6 +24,7 @@ import { */ import Tooltip from '../tooltip'; import Icon from '../icon'; +import style from './style.scss'; const isAndroid = Platform.OS === 'android'; const marginBottom = isAndroid ? -0.5 : 0; @@ -51,8 +52,6 @@ const styles = StyleSheet.create( { justifyContent: 'center', alignItems: 'center', borderRadius: 6, - borderColor: '#2e4453', - backgroundColor: '#2e4453', }, subscriptInactive: { color: '#7b9ab1', // $toolbar-button. @@ -106,10 +105,16 @@ export function Button( props ) { customContainerStyles && { ...customContainerStyles }, ]; + const buttonActiveColorStyles = usePreferredColorSchemeStyle( + style[ 'components-button-light--active' ], + style[ 'components-button-dark--active' ] + ); + const buttonViewStyle = { opacity: isDisabled ? 0.3 : 1, ...( fixedRatio && styles.fixedRatio ), ...( isPressed ? styles.buttonActive : styles.buttonInactive ), + ...( isPressed ? buttonActiveColorStyles : {} ), ...( isPressed && isActiveStyle?.borderRadius && { borderRadius: isActiveStyle.borderRadius, @@ -159,7 +164,6 @@ export function Button( props ) { const newIcon = icon ? cloneElement( , { - colorScheme: preferredColorScheme, isPressed, } ) : null; diff --git a/packages/components/src/button/style.native.scss b/packages/components/src/button/style.native.scss new file mode 100644 index 00000000000000..ab90f8ec64e82c --- /dev/null +++ b/packages/components/src/button/style.native.scss @@ -0,0 +1,9 @@ +.components-button-light--active { + border-color: $light-dim; + background-color: $light-dim; +} + +.components-button-dark--active { + border-color: $dark-quaternary; + background-color: $dark-quaternary; +} diff --git a/packages/components/src/toolbar/toolbar-group/style.native.scss b/packages/components/src/toolbar/toolbar-group/style.native.scss index e218aa37363e37..f45797de3a625a 100644 --- a/packages/components/src/toolbar/toolbar-group/style.native.scss +++ b/packages/components/src/toolbar/toolbar-group/style.native.scss @@ -1,11 +1,10 @@ .container { flex-direction: row; - border-left-width: 1px; - border-color: #e9eff3; + border-color: $light-quaternary; padding-left: 5px; padding-right: 5px; } .containerDark { - border-color: #525354; + border-color: $dark-quaternary; } diff --git a/packages/components/src/toolbar/toolbar-group/toolbar-group-container.native.js b/packages/components/src/toolbar/toolbar-group/toolbar-group-container.native.js index 6eaf0dc0c3c74a..53c2c59bda9548 100644 --- a/packages/components/src/toolbar/toolbar-group/toolbar-group-container.native.js +++ b/packages/components/src/toolbar/toolbar-group/toolbar-group-container.native.js @@ -1,31 +1,26 @@ /** * External dependencies */ -import { View } from 'react-native'; +import { StyleSheet, View } from 'react-native'; /** * WordPress dependencies */ -import { withPreferredColorScheme } from '@wordpress/compose'; +import { usePreferredColorSchemeStyle } from '@wordpress/compose'; /** * Internal dependencies */ import styles from './style.scss'; -const ToolbarGroupContainer = ( { - getStylesFromColorScheme, - passedStyle, - children, -} ) => ( - - { children } - -); +const ToolbarGroupContainer = ( { passedStyle, children } ) => { + const groupStyles = [ + usePreferredColorSchemeStyle( styles.container, styles.containerDark ), + { borderLeftWidth: StyleSheet.hairlineWidth }, + passedStyle, + ]; -export default withPreferredColorScheme( ToolbarGroupContainer ); + return { children }; +}; + +export default ToolbarGroupContainer; diff --git a/packages/edit-post/src/components/header/header-toolbar/index.native.js b/packages/edit-post/src/components/header/header-toolbar/index.native.js index 55854ffc995f68..692136b2c3c204 100644 --- a/packages/edit-post/src/components/header/header-toolbar/index.native.js +++ b/packages/edit-post/src/components/header/header-toolbar/index.native.js @@ -1,13 +1,13 @@ /** * External dependencies */ -import { Platform, ScrollView, View } from 'react-native'; +import { ScrollView, StyleSheet, View } from 'react-native'; /** * WordPress dependencies */ -import { useCallback, useRef, useEffect } from '@wordpress/element'; -import { compose, withPreferredColorScheme } from '@wordpress/compose'; +import { useCallback, useRef, useEffect, Platform } from '@wordpress/element'; +import { compose, usePreferredColorSchemeStyle } from '@wordpress/compose'; import { withSelect, withDispatch } from '@wordpress/data'; import { withViewportMatch } from '@wordpress/viewport'; import { __ } from '@wordpress/i18n'; @@ -39,6 +39,13 @@ import { import styles from './style.scss'; import { store as editPostStore } from '../../../store'; +const shadowStyle = { + shadowOffset: { width: 2, height: 2 }, + shadowOpacity: 1, + shadowRadius: 6, + elevation: 18, +}; + function HeaderToolbar( { hasRedo, hasUndo, @@ -46,18 +53,20 @@ function HeaderToolbar( { undo, showInserter, showKeyboardHideButton, - getStylesFromColorScheme, insertBlock, onHideKeyboard, - onOpenBlockSettings, isRTL, noContentSelected, } ) { const anchorNodeRef = useRef(); - const containerStyle = getStylesFromColorScheme( - styles[ 'header-toolbar__container' ], - styles[ 'header-toolbar__container--dark' ] - ); + + const containerStyle = [ + usePreferredColorSchemeStyle( + styles[ 'header-toolbar__container' ], + styles[ 'header-toolbar__container--dark' ] + ), + { borderTopWidth: StyleSheet.hairlineWidth }, + ]; useEffect( () => { const onUndoSubscription = subscribeOnUndoPressed( undo ); @@ -80,8 +89,7 @@ function HeaderToolbar( { const scrollViewRef = useRef( null ); const scrollToStart = () => { // scrollview doesn't seem to automatically adjust to RTL on Android so, scroll to end when Android - const isAndroid = Platform.OS === 'android'; - if ( isAndroid && isRTL ) { + if ( Platform.isAndroid && isRTL ) { scrollViewRef.current.scrollToEnd(); } else { scrollViewRef.current.scrollTo( { x: 0 } ); @@ -145,6 +153,23 @@ function HeaderToolbar( { /* translators: accessibility text for the editor toolbar */ const toolbarAriaLabel = __( 'Document tools' ); + const shadowColor = usePreferredColorSchemeStyle( + styles[ 'header-toolbar__keyboard-hide-shadow--light' ], + styles[ 'header-toolbar__keyboard-hide-shadow--dark' ] + ); + const showKeyboardButtonStyles = [ + usePreferredColorSchemeStyle( + styles[ 'header-toolbar__keyboard-hide-container' ], + styles[ 'header-toolbar__keyboard-hide-container--dark' ] + ), + shadowStyle, + { + shadowColor: Platform.isAndroid + ? styles[ 'header-toolbar__keyboard-hide-shadow--solid' ].color + : shadowColor.color, + }, + ]; + return ( { noContentSelected && renderMediaButtons } - + { showKeyboardHideButton && ( - + { const { clearSelectedBlock, insertBlock } = dispatch( blockEditorStore ); - const { openGeneralSidebar } = dispatch( editPostStore ); const { togglePostTitleSelection } = dispatch( editorStore ); return { @@ -231,11 +248,7 @@ export default compose( [ togglePostTitleSelection( false ); }, insertBlock, - onOpenBlockSettings() { - openGeneralSidebar( 'edit-post/block' ); - }, }; } ), withViewportMatch( { isLargeViewport: 'medium' } ), - withPreferredColorScheme, ] )( HeaderToolbar ); diff --git a/packages/edit-post/src/components/header/header-toolbar/style.native.scss b/packages/edit-post/src/components/header/header-toolbar/style.native.scss index 031d082706656a..751f83d3dc63e6 100644 --- a/packages/edit-post/src/components/header/header-toolbar/style.native.scss +++ b/packages/edit-post/src/components/header/header-toolbar/style.native.scss @@ -3,13 +3,13 @@ height: $mobile-header-toolbar-height; flex-direction: row; background-color: $app-background; - border-top-color: #e9eff3; - border-top-width: 1px; + border-top-color: $light-quaternary; + overflow: hidden; } .header-toolbar__container--dark { - background-color: $app-background-dark-alt; - border-top-color: $background-dark-elevated; + background-color: $app-safe-area-background-dark; + border-top-color: $dark-quaternary; } .header-toolbar__container--expanded { @@ -18,6 +18,7 @@ .header-toolbar__scrollable-content { flex-grow: 1; // Fixes RTL issue on Android. + padding-right: 8px; } .header-toolbar__keyboard-hide-container { @@ -27,4 +28,22 @@ width: 44px; justify-content: center; align-items: center; + border-color: transparent; + background-color: $app-background; +} + +.header-toolbar__keyboard-hide-container--dark { + background-color: $app-background-dark-alt; +} + +.header-toolbar__keyboard-hide-shadow--solid { + color: $black; +} + +.header-toolbar__keyboard-hide-shadow--light { + color: $light-quaternary; +} + +.header-toolbar__keyboard-hide-shadow--dark { + color: $light-primary; } diff --git a/packages/edit-post/src/components/layout/style.native.scss b/packages/edit-post/src/components/layout/style.native.scss index faee2799e54eb8..765314bf15955c 100644 --- a/packages/edit-post/src/components/layout/style.native.scss +++ b/packages/edit-post/src/components/layout/style.native.scss @@ -6,7 +6,7 @@ } .containerDark { - background-color: $app-background-dark-alt; + background-color: $app-safe-area-background-dark; } .background { diff --git a/packages/format-library/src/text-color/index.native.js b/packages/format-library/src/text-color/index.native.js index 5003dee86d3a5b..5f133383ae1d1d 100644 --- a/packages/format-library/src/text-color/index.native.js +++ b/packages/format-library/src/text-color/index.native.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { View } from 'react-native'; +import { StyleSheet, View } from 'react-native'; /** * WordPress dependencies @@ -14,7 +14,11 @@ import { ToolbarButton, useMobileGlobalStylesColors, } from '@wordpress/components'; -import { Icon, textColor as textColorIcon } from '@wordpress/icons'; +import { + Icon, + color as colorIcon, + textColor as textColorIcon, +} from '@wordpress/icons'; import { removeFormat } from '@wordpress/rich-text'; import { usePreferredColorSchemeStyle } from '@wordpress/compose'; @@ -98,10 +102,13 @@ function TextColorEdit( { } }, [ hasColorsToChoose, value ] ); - const outlineStyle = usePreferredColorSchemeStyle( - styles[ 'components-inline-color__outline' ], - styles[ 'components-inline-color__outline--dark' ] - ); + const outlineStyle = [ + usePreferredColorSchemeStyle( + styles[ 'components-inline-color__outline' ], + styles[ 'components-inline-color__outline--dark' ] + ), + { borderWidth: StyleSheet.hairlineWidth }, + ]; if ( ! hasColorsToChoose && ! isActive ) { return null; @@ -131,7 +138,11 @@ function TextColorEdit( { isActive={ isActive } icon={ { - const colorScheme = props.colorScheme || 'light'; + const colorScheme = usePreferredColorScheme(); const stylesFromClasses = className .split( ' ' ) .map( ( element ) => styles[ element ] ) .filter( Boolean ); const defaultStyle = isPressed - ? styles[ 'is-pressed' ] + ? styles[ `is-pressed--${ colorScheme }` ] : styles[ 'components-toolbar__control-' + colorScheme ]; const propStyle = Array.isArray( props.style ) ? props.style.reduce( ( acc, el ) => { diff --git a/packages/primitives/src/svg/style.native.scss b/packages/primitives/src/svg/style.native.scss index ea8e7845174aaa..2e7dfdbfaff7a6 100644 --- a/packages/primitives/src/svg/style.native.scss +++ b/packages/primitives/src/svg/style.native.scss @@ -1,21 +1,30 @@ .dashicon-light, .components-toolbar__control-light { - color: $toolbar-button; + color: $light-primary; fill: currentColor; } .dashicon-dark, .components-toolbar__control-dark { - color: $gray_20; + color: $dark-primary; fill: currentColor; } -.dashicon-active, -.is-pressed { +.dashicon-active { color: #fff; fill: currentColor; } +.is-pressed--light { + color: $light-primary; + fill: currentColor; +} + +.is-pressed--dark { + color: $dark-primary; + fill: currentColor; +} + .dashicons-insert { color: #87a6bc; fill: currentColor; diff --git a/packages/react-native-editor/CHANGELOG.md b/packages/react-native-editor/CHANGELOG.md index d8a7a2e0f2b970..b7bd28a9926c96 100644 --- a/packages/react-native-editor/CHANGELOG.md +++ b/packages/react-native-editor/CHANGELOG.md @@ -14,6 +14,7 @@ For each user feature we should also add a importance categorization label to i - [**] Update native BlockOutline component styles to remove blue border from blocks [#51222] - [**] Move the undo/redo buttons to the navigation bar [#51766] - [**] Update Editor block inserter button styles and default text input placeholder/selection styles [#52269] +- [**] Update Editor toolbar icons and colors [#52336] ## 1.99.1 - [**] Fix crash related to removing a block under certain conditions [#52595] diff --git a/test/native/__mocks__/styleMock.js b/test/native/__mocks__/styleMock.js index a3707d71e3d3bc..7aae4fd6f8941f 100644 --- a/test/native/__mocks__/styleMock.js +++ b/test/native/__mocks__/styleMock.js @@ -190,4 +190,10 @@ module.exports = { 'rich-text-selection': { color: 'black', }, + 'header-toolbar__keyboard-hide-shadow--light': { + color: 'black', + }, + 'header-toolbar__keyboard-hide-shadow--solid': { + color: 'black', + }, };