From 8b2f047bb459c908392692b74ee7c2ec26860780 Mon Sep 17 00:00:00 2001 From: Matias Benedetto Date: Thu, 11 Jul 2024 17:24:24 +0400 Subject: [PATCH] Adding Font size presets UI (#63057) * adding ui for size presets * add disable prop * removes font size custom ordering * use origins * fix spelling * fixing font size presets count button size * size of font size preset item * edit wording * style on font size preset item * focus on input on the rename preset modal * redirect to font sizes * Add confirm dialog to reset font size presets * update wording * remove size prop for ItemGroup * remove number in font size presets drilldown * improve item look * update label Co-authored-by: Aki Hamano <54422211+t-hamano@users.noreply.github.com> * make markup more consistent with other rename dialogs Co-authored-by: Aki Hamano <54422211+t-hamano@users.noreply.github.com> * update label Co-authored-by: Aki Hamano <54422211+t-hamano@users.noreply.github.com> * disalow rename and delete of default font size presets * add missing imports * disable font main size component when custom fluid is set * use getComputedFluidTypographyValue to compute the size of the preview * remove not needed prop Co-authored-by: Aki Hamano <54422211+t-hamano@users.noreply.github.com> * remove not needed prop Co-authored-by: Aki Hamano <54422211+t-hamano@users.noreply.github.com> * allow to rename and delete only custom font size presets * improve styles * remove not needed classes * revert unwated changes * removing not needed navigation * removing not needed condition * improve array comparison --------- Co-authored-by: matiasbenedetto Co-authored-by: t-hamano Co-authored-by: tyxla Co-authored-by: jasmussen Co-authored-by: mirka <0mirka00@git.wordpress.org> Co-authored-by: ciampo Co-authored-by: beafialho Co-authored-by: markhowellsmead Co-authored-by: youknowriad Co-authored-by: annezazu Co-authored-by: carolinan Co-authored-by: luminuu Co-authored-by: mikachan Co-authored-by: BenjaminZekavica --- .../confirm-delete-font-size-dialog.js | 43 +++ .../confirm-reset-font-sizes-dialog.js | 37 +++ .../font-sizes/font-size-preview.js | 43 +++ .../global-styles/font-sizes/font-size.js | 250 +++++++++++++++++ .../font-sizes/font-sizes-count.js | 40 +++ .../global-styles/font-sizes/font-sizes.js | 263 ++++++++++++++++++ .../font-sizes/rename-font-size-dialog.js | 70 +++++ .../global-styles/screen-typography.js | 2 + .../global-styles/size-control/index.js | 86 ++++++ .../src/components/global-styles/style.scss | 11 + .../src/components/global-styles/ui.js | 10 + 11 files changed, 855 insertions(+) create mode 100644 packages/edit-site/src/components/global-styles/font-sizes/confirm-delete-font-size-dialog.js create mode 100644 packages/edit-site/src/components/global-styles/font-sizes/confirm-reset-font-sizes-dialog.js create mode 100644 packages/edit-site/src/components/global-styles/font-sizes/font-size-preview.js create mode 100644 packages/edit-site/src/components/global-styles/font-sizes/font-size.js create mode 100644 packages/edit-site/src/components/global-styles/font-sizes/font-sizes-count.js create mode 100644 packages/edit-site/src/components/global-styles/font-sizes/font-sizes.js create mode 100644 packages/edit-site/src/components/global-styles/font-sizes/rename-font-size-dialog.js create mode 100644 packages/edit-site/src/components/global-styles/size-control/index.js diff --git a/packages/edit-site/src/components/global-styles/font-sizes/confirm-delete-font-size-dialog.js b/packages/edit-site/src/components/global-styles/font-sizes/confirm-delete-font-size-dialog.js new file mode 100644 index 00000000000000..69d561ee0232a8 --- /dev/null +++ b/packages/edit-site/src/components/global-styles/font-sizes/confirm-delete-font-size-dialog.js @@ -0,0 +1,43 @@ +/** + * WordPress dependencies + */ +import { __experimentalConfirmDialog as ConfirmDialog } from '@wordpress/components'; +import { __, sprintf } from '@wordpress/i18n'; + +function ConfirmDeleteFontSizeDialog( { + fontSize, + isOpen, + toggleOpen, + handleRemoveFontSize, +} ) { + const handleConfirm = async () => { + toggleOpen(); + handleRemoveFontSize( fontSize ); + }; + + const handleCancel = () => { + toggleOpen(); + }; + + return ( + + { fontSize && + sprintf( + /* translators: %s: Name of the font size preset. */ + __( + 'Are you sure you want to delete "%s" font size preset?' + ), + fontSize.name + ) } + + ); +} + +export default ConfirmDeleteFontSizeDialog; diff --git a/packages/edit-site/src/components/global-styles/font-sizes/confirm-reset-font-sizes-dialog.js b/packages/edit-site/src/components/global-styles/font-sizes/confirm-reset-font-sizes-dialog.js new file mode 100644 index 00000000000000..fb1bd51ba1479a --- /dev/null +++ b/packages/edit-site/src/components/global-styles/font-sizes/confirm-reset-font-sizes-dialog.js @@ -0,0 +1,37 @@ +/** + * WordPress dependencies + */ +import { __experimentalConfirmDialog as ConfirmDialog } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; + +function ConfirmResetFontSizesDialog( { + text, + confirmButtonText, + isOpen, + toggleOpen, + onConfirm, +} ) { + const handleConfirm = async () => { + toggleOpen(); + onConfirm(); + }; + + const handleCancel = () => { + toggleOpen(); + }; + + return ( + + { text } + + ); +} + +export default ConfirmResetFontSizesDialog; diff --git a/packages/edit-site/src/components/global-styles/font-sizes/font-size-preview.js b/packages/edit-site/src/components/global-styles/font-sizes/font-size-preview.js new file mode 100644 index 00000000000000..e49ed0249e65a4 --- /dev/null +++ b/packages/edit-site/src/components/global-styles/font-sizes/font-size-preview.js @@ -0,0 +1,43 @@ +/** + * WordPress dependencies + */ +import { + getComputedFluidTypographyValue, + privateApis as blockEditorPrivateApis, +} from '@wordpress/block-editor'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { unlock } from '../../../lock-unlock'; +const { useGlobalStyle } = unlock( blockEditorPrivateApis ); + +function FontSizePreview( { fontSize } ) { + const [ font ] = useGlobalStyle( 'typography' ); + + const input = + fontSize?.fluid?.min && fontSize?.fluid?.max + ? { + minimumFontSize: fontSize.fluid.min, + maximumFontSize: fontSize.fluid.max, + } + : { + fontSize: fontSize.size, + }; + + const computedFontSize = getComputedFluidTypographyValue( input ); + return ( +
+ { __( 'Aa' ) } +
+ ); +} + +export default FontSizePreview; diff --git a/packages/edit-site/src/components/global-styles/font-sizes/font-size.js b/packages/edit-site/src/components/global-styles/font-sizes/font-size.js new file mode 100644 index 00000000000000..8eb6bc20bd407d --- /dev/null +++ b/packages/edit-site/src/components/global-styles/font-sizes/font-size.js @@ -0,0 +1,250 @@ +/** + * WordPress dependencies + */ +import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; +import { __, sprintf } from '@wordpress/i18n'; +import { + __experimentalSpacer as Spacer, + __experimentalUseNavigator as useNavigator, + __experimentalView as View, + __experimentalHStack as HStack, + __experimentalVStack as VStack, + privateApis as componentsPrivateApis, + Button, + FlexItem, + ToggleControl, +} from '@wordpress/components'; +import { moreVertical } from '@wordpress/icons'; +import { useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { unlock } from '../../../lock-unlock'; +const { + DropdownMenuV2: DropdownMenu, + DropdownMenuItemV2: DropdownMenuItem, + DropdownMenuItemLabelV2: DropdownMenuItemLabel, +} = unlock( componentsPrivateApis ); +const { useGlobalSetting } = unlock( blockEditorPrivateApis ); +import ScreenHeader from '../header'; +import FontSizePreview from './font-size-preview'; +import ConfirmDeleteFontSizeDialog from './confirm-delete-font-size-dialog'; +import RenameFontSizeDialog from './rename-font-size-dialog'; +import SizeControl from '../size-control'; + +function FontSize() { + const [ isDeleteConfirmOpen, setIsDeleteConfirmOpen ] = useState( false ); + const [ isRenameDialogOpen, setIsRenameDialogOpen ] = useState( false ); + + const { + params: { origin, slug }, + goBack, + goTo, + } = useNavigator(); + + const [ fontSizes, setFontSizes ] = useGlobalSetting( + 'typography.fontSizes' + ); + + // Get the font sizes from the origin, default to empty array. + const sizes = fontSizes[ origin ] ?? []; + + // Get the font size by slug. + const fontSize = sizes.find( ( size ) => size.slug === slug ); + + // Whether fluid is true or an object, set it to true, otherwise false. + const isFluid = !! fontSize.fluid ?? false; + + // Whether custom fluid values are used. + const isCustomFluid = typeof fontSize.fluid === 'object'; + + const handleNameChange = ( value ) => { + updateFontSize( 'name', value ); + }; + + const handleFontSizeChange = ( value ) => { + updateFontSize( 'size', value ); + }; + + const handleFluidChange = ( value ) => { + updateFontSize( 'fluid', value ); + }; + + const handleCustomFluidValues = ( value ) => { + if ( value ) { + // If custom values are used, init the values with the current ones. + updateFontSize( 'fluid', { + min: fontSize.size, + max: fontSize.size, + } ); + } else { + // If custom fluid values are disabled, set fluid to true. + updateFontSize( 'fluid', true ); + } + }; + + const handleMinChange = ( value ) => { + updateFontSize( 'fluid', { ...fontSize.fluid, min: value } ); + }; + + const handleMaxChange = ( value ) => { + updateFontSize( 'fluid', { ...fontSize.fluid, max: value } ); + }; + + const updateFontSize = ( key, value ) => { + const newFontSizes = sizes.map( ( size ) => { + if ( size.slug === slug ) { + return { ...size, [ key ]: value }; // Create a new object with updated key + } + return size; + } ); + + setFontSizes( { + ...fontSizes, + [ origin ]: newFontSizes, + } ); + }; + + const handleRemoveFontSize = () => { + // Navigate to the font sizes list. + goBack(); + + const newFontSizes = sizes.filter( ( size ) => size.slug !== slug ); + setFontSizes( { + ...fontSizes, + [ origin ]: newFontSizes, + } ); + }; + + const toggleDeleteConfirm = () => { + setIsDeleteConfirmOpen( ! isDeleteConfirmOpen ); + }; + + const toggleRenameDialog = () => { + setIsRenameDialogOpen( ! isRenameDialogOpen ); + }; + + return ( + <> + + + { isRenameDialogOpen && ( + + ) } + + + + goTo( '/typography/font-sizes/' ) } + /> + { origin === 'custom' && ( + + + + } + > + + + { __( 'Rename' ) } + + + + + { __( 'Delete' ) } + + + + + + ) } + + + + + + + + + + + + + + { isFluid && ( + + ) } + + { isCustomFluid && ( + <> + + + + ) } + + + + + + ); +} + +export default FontSize; diff --git a/packages/edit-site/src/components/global-styles/font-sizes/font-sizes-count.js b/packages/edit-site/src/components/global-styles/font-sizes/font-sizes-count.js new file mode 100644 index 00000000000000..8c8c79772ecbf3 --- /dev/null +++ b/packages/edit-site/src/components/global-styles/font-sizes/font-sizes-count.js @@ -0,0 +1,40 @@ +/** + * WordPress dependencies + */ +import { __, isRTL } from '@wordpress/i18n'; +import { + __experimentalItemGroup as ItemGroup, + __experimentalVStack as VStack, + __experimentalHStack as HStack, + FlexItem, +} from '@wordpress/components'; +import { Icon, chevronLeft, chevronRight } from '@wordpress/icons'; + +/** + * Internal dependencies + */ +import Subtitle from '../subtitle'; +import { NavigationButtonAsItem } from '../navigation-button'; + +function FontSizes() { + return ( + + + { __( 'Font Sizes' ) } + + + + + { __( 'Font size presets' ) } + + + + + + ); +} + +export default FontSizes; diff --git a/packages/edit-site/src/components/global-styles/font-sizes/font-sizes.js b/packages/edit-site/src/components/global-styles/font-sizes/font-sizes.js new file mode 100644 index 00000000000000..450d0797139f85 --- /dev/null +++ b/packages/edit-site/src/components/global-styles/font-sizes/font-sizes.js @@ -0,0 +1,263 @@ +/** + * WordPress dependencies + */ +import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; +import { __, sprintf, isRTL } from '@wordpress/i18n'; +import { + privateApis as componentsPrivateApis, + __experimentalSpacer as Spacer, + __experimentalView as View, + __experimentalItemGroup as ItemGroup, + __experimentalVStack as VStack, + __experimentalHStack as HStack, + FlexItem, + FlexBlock, + Button, +} from '@wordpress/components'; +import { + Icon, + plus, + moreVertical, + chevronLeft, + chevronRight, +} from '@wordpress/icons'; +import { useState } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { unlock } from '../../../lock-unlock'; +const { + DropdownMenuV2: DropdownMenu, + DropdownMenuItemV2: DropdownMenuItem, + DropdownMenuItemLabelV2: DropdownMenuItemLabel, +} = unlock( componentsPrivateApis ); +const { useGlobalSetting } = unlock( blockEditorPrivateApis ); +import Subtitle from '../subtitle'; +import { NavigationButtonAsItem } from '../navigation-button'; +import { getNewIndexFromPresets } from '../utils'; +import ScreenHeader from '../header'; +import ConfirmResetFontSizesDialog from './confirm-reset-font-sizes-dialog'; + +function FontSizeGroup( { + label, + origin, + sizes, + handleAddFontSize, + handleResetFontSizes, +} ) { + const [ isResetDialogOpen, setIsResetDialogOpen ] = useState( false ); + + const toggleResetDialog = () => setIsResetDialogOpen( ! isResetDialogOpen ); + + const resetDialogText = + origin === 'custom' + ? __( + 'Are you sure you want to remove all custom font size presets?' + ) + : __( + 'Are you sure you want to reset all font size presets to their default values?' + ); + + return ( + <> + { isResetDialogOpen && ( + + ) } + + + { label } + + { origin === 'custom' && ( + + + + + + + ); +} + +export default RenameFontSizeDialog; diff --git a/packages/edit-site/src/components/global-styles/screen-typography.js b/packages/edit-site/src/components/global-styles/screen-typography.js index 08472325ebc1f8..6d1b69f0ddb5e5 100644 --- a/packages/edit-site/src/components/global-styles/screen-typography.js +++ b/packages/edit-site/src/components/global-styles/screen-typography.js @@ -13,6 +13,7 @@ import TypographyElements from './typography-elements'; import TypographyVariations from './variations/variations-typography'; import FontFamilies from './font-families'; import ScreenHeader from './header'; +import FontSizesCount from './font-sizes/font-sizes-count'; function ScreenTypography() { const fontLibraryEnabled = useSelect( @@ -35,6 +36,7 @@ function ScreenTypography() { fontLibraryEnabled && } + diff --git a/packages/edit-site/src/components/global-styles/size-control/index.js b/packages/edit-site/src/components/global-styles/size-control/index.js new file mode 100644 index 00000000000000..a7e7bd6127a5fb --- /dev/null +++ b/packages/edit-site/src/components/global-styles/size-control/index.js @@ -0,0 +1,86 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { + BaseControl, + RangeControl, + Flex, + FlexItem, + useBaseControlProps, + __experimentalUseCustomUnits as useCustomUnits, + __experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue, + __experimentalUnitControl as UnitControl, + __experimentalSpacer as Spacer, +} from '@wordpress/components'; + +const DEFAULT_UNITS = [ 'px', 'em', 'rem', 'vw', 'vh' ]; + +function SizeControl( props ) { + const { baseControlProps } = useBaseControlProps( props ); + const { value, onChange, fallbackValue, disabled } = props; + + const units = useCustomUnits( { + availableUnits: DEFAULT_UNITS, + } ); + + const [ valueQuantity, valueUnit = 'px' ] = + parseQuantityAndUnitFromRawValue( value, units ); + + const isValueUnitRelative = + !! valueUnit && [ 'em', 'rem', 'vw', 'vh' ].includes( valueUnit ); + + // Receives the new value from the UnitControl component as a string containing the value and unit. + const handleUnitControlChange = ( newValue ) => { + onChange( newValue ); + }; + + // Receives the new value from the RangeControl component as a number. + const handleRangeControlChange = ( newValue ) => { + onChange?.( newValue + valueUnit ); + }; + + return ( + + + + + + + + + + + + + ); +} + +export default SizeControl; diff --git a/packages/edit-site/src/components/global-styles/style.scss b/packages/edit-site/src/components/global-styles/style.scss index 51e83f33c03eee..8fa66b6d1b7947 100644 --- a/packages/edit-site/src/components/global-styles/style.scss +++ b/packages/edit-site/src/components/global-styles/style.scss @@ -23,6 +23,17 @@ overflow: hidden; } +.edit-site-font-size__item { + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; + line-break: anywhere; +} + +.edit-site-font-size__item-value { + color: $gray-700; +} + .edit-site-global-styles-screen { margin: $grid-unit-15 $grid-unit-20 $grid-unit-20; } diff --git a/packages/edit-site/src/components/global-styles/ui.js b/packages/edit-site/src/components/global-styles/ui.js index 08cd20e9aac6a8..40d20bc1ec86f8 100644 --- a/packages/edit-site/src/components/global-styles/ui.js +++ b/packages/edit-site/src/components/global-styles/ui.js @@ -33,6 +33,8 @@ import { import ScreenBlock from './screen-block'; import ScreenTypography from './screen-typography'; import ScreenTypographyElement from './screen-typography-element'; +import FontSize from './font-sizes/font-size'; +import FontSizes from './font-sizes/font-sizes'; import ScreenColors from './screen-colors'; import ScreenColorPalette from './screen-color-palette'; import { ScreenShadows, ScreenShadowsEdit } from './screen-shadows'; @@ -313,6 +315,14 @@ function GlobalStylesUI() { + + + + + + + +