diff --git a/docs/manifest.json b/docs/manifest.json index 69d991c65d3da5..b6e4d637640acf 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -911,6 +911,12 @@ "markdown_source": "../packages/components/src/heading/README.md", "parent": "components" }, + { + "title": "HelpText", + "slug": "help-text", + "markdown_source": "../packages/components/src/help-text/README.md", + "parent": "components" + }, { "title": "NavigateRegions", "slug": "navigate-regions", diff --git a/packages/block-editor/src/hooks/anchor.js b/packages/block-editor/src/hooks/anchor.js index 804375da6e2d0c..7cd7a5a8edcbbd 100644 --- a/packages/block-editor/src/hooks/anchor.js +++ b/packages/block-editor/src/hooks/anchor.js @@ -2,7 +2,12 @@ * WordPress dependencies */ import { addFilter } from '@wordpress/hooks'; -import { PanelBody, TextControl, ExternalLink } from '@wordpress/components'; +import { + PanelBody, + TextControl, + HelpText, + ExternalLink, +} from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { hasBlockSupport } from '@wordpress/blocks'; import { createHigherOrderComponent } from '@wordpress/compose'; @@ -70,23 +75,6 @@ export const withInspectorControl = createHigherOrderComponent( - { __( - 'Enter a word or two — without spaces — to make a unique web address just for this block, called an “anchor.” Then, you’ll be able to link directly to this section of your page.' - ) } - - { isWeb && ( - - { __( 'Learn more about anchors' ) } - - ) } - - } value={ props.attributes.anchor || '' } placeholder={ ! isWeb ? __( 'Add an anchor' ) : null } onChange={ ( nextValue ) => { @@ -97,6 +85,23 @@ export const withInspectorControl = createHigherOrderComponent( } } autoCapitalize="none" autoComplete="off" + separatorType="none" + help={ + isWeb && ( + <> + { __( + 'Enter a word or two — without spaces — to make a unique web address just for this block, called an “anchor.” Then, you’ll be able to link directly to this section of your page.' + ) } + + { __( 'Learn more about anchors' ) } + + + ) + } /> ); @@ -118,6 +123,16 @@ export const withInspectorControl = createHigherOrderComponent( { textControl } + + { __( + 'Enter a word or two — without spaces — to make a unique web address just for this block, called an “anchor.” Then, you’ll be able to link directly to this section of your page.' + ) } + ) } diff --git a/packages/block-library/src/embed/embed-link-settings.native.js b/packages/block-library/src/embed/embed-link-settings.native.js index dcacde56aa05ea..4f081572d13692 100644 --- a/packages/block-library/src/embed/embed-link-settings.native.js +++ b/packages/block-library/src/embed/embed-link-settings.native.js @@ -2,10 +2,7 @@ * WordPress dependencies */ import { __, sprintf } from '@wordpress/i18n'; -import { - LinkSettingsNavigation, - FooterMessageLink, -} from '@wordpress/components'; +import { LinkSettingsNavigation } from '@wordpress/components'; import { isURL } from '@wordpress/url'; import { useDispatch } from '@wordpress/data'; import { store as noticesStore } from '@wordpress/notices'; @@ -35,15 +32,9 @@ const EmbedLinkSettings = ( { autoFocus, autoFill: true, }, - footer: { - label: ( - - ), + help: { + url: __( 'https://wordpress.org/support/article/embeds/' ), + moreLinkText: __( 'Learn more about embeds' ), separatorType: 'topFullWidth', }, }; diff --git a/packages/block-library/src/image/edit.native.js b/packages/block-library/src/image/edit.native.js index c06abb7eaf4fca..371043347eeb3c 100644 --- a/packages/block-library/src/image/edit.native.js +++ b/packages/block-library/src/image/edit.native.js @@ -32,8 +32,7 @@ import { BottomSheet, BottomSheetTextControl, BottomSheetSelectControl, - FooterMessageControl, - FooterMessageLink, + HelpText, Badge, } from '@wordpress/components'; import { @@ -574,18 +573,17 @@ export class ImageEdit extends Component { placeholder={ __( 'Add alt text' ) } label={ __( 'Alt Text' ) } icon={ textColor } - footerNote={ - <> + help={ + { __( 'Describe the purpose of the image. Leave empty if the image is purely decorative.' - ) }{ ' ' } - - + ) } + } /> ); @@ -747,14 +745,11 @@ export class ImageEdit extends Component { > { canImageBeFeatured && this.getFeaturedButtonPanel( isFeaturedImage ) } - + { __( 'Changes to featured image will not be affected by the undo/redo buttons.' ) } - cellContainerStyle={ - styles.setFeaturedButtonCellContainer - } - /> + ); diff --git a/packages/block-library/src/social-link/edit.native.js b/packages/block-library/src/social-link/edit.native.js index bc3d2e47db9619..939da55897467d 100644 --- a/packages/block-library/src/social-link/edit.native.js +++ b/packages/block-library/src/social-link/edit.native.js @@ -47,7 +47,7 @@ const linkSettingsOptions = { label: __( 'Link label' ), placeholder: __( 'None' ), }, - footer: { + help: { label: __( 'Briefly describe the link to help screen reader user' ), }, }; diff --git a/packages/components/src/external-link/index.native.js b/packages/components/src/external-link/index.native.js index 84b02b2e92775f..542840a61888d7 100644 --- a/packages/components/src/external-link/index.native.js +++ b/packages/components/src/external-link/index.native.js @@ -2,23 +2,42 @@ * External dependencies */ -import { TouchableOpacity, Text, Linking } from 'react-native'; +import { Text, Linking } from 'react-native'; /** * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { external, Icon } from '@wordpress/icons'; +import { usePreferredColorSchemeStyle } from '@wordpress/compose'; +/** + * Internal dependencies + */ +import style from './style.native.scss'; export function ExternalLink( { href, children } ) { + const externalLink = usePreferredColorSchemeStyle( + style[ 'external-link' ], + style[ 'external-link__dark' ] + ); + + if ( typeof children !== 'string' ) { + throw new Error( + __( + 'The ExternalLink component only accepts a string as a child element. This is to ensure the element can be read by screen readers.' + ) + ); + } + return ( - Linking.openURL( href ) } - accessibilityLabel={ __( 'Open link in a browser' ) } + accessibilityLabel={ children } + accessibilityHint={ __( 'Opens link in a browser' ) } + accessibilityRole={ 'link' } > - { children } - - + { children } + ); } diff --git a/packages/components/src/external-link/style.native.scss b/packages/components/src/external-link/style.native.scss new file mode 100644 index 00000000000000..8bbc5bec3bc51d --- /dev/null +++ b/packages/components/src/external-link/style.native.scss @@ -0,0 +1,7 @@ +.external-link { + color: $blue-50; +} + +.external-link__dark { + color: $blue-30; +} diff --git a/packages/components/src/help-text/README.md b/packages/components/src/help-text/README.md new file mode 100644 index 00000000000000..8a67707375542e --- /dev/null +++ b/packages/components/src/help-text/README.md @@ -0,0 +1,31 @@ +# HelpText + +Renders help text with a `ExternalLink` appended at the end of the text. + +## Usage + +```jsx +import { HelpText } from '@wordpress/components'; + +const HelpfulText = () => ( + WordPress is an easy to use publishing tool +); +``` + +## Props + +The text that's displayed within the component's tags will be "clickable" and extenal link will be added at the end. + +### `url` + +An optional URL to link, opens in a new window when tapped or clicked. + +- Type: `String` +- Required: No + +### `moreLinkText` + +An optional text string to display as the link label for the optional `url` prop. + +- Type: `String` +- Required: No diff --git a/packages/components/src/help-text/index.js b/packages/components/src/help-text/index.js new file mode 100644 index 00000000000000..0a834abfca9aba --- /dev/null +++ b/packages/components/src/help-text/index.js @@ -0,0 +1,24 @@ +/** + * Internal dependencies + */ +import { ExternalLink } from '../external-link'; + +/** + * @param {Object} props + * @param {string} props.moreLinkText + * @param {import('react').ReactNode} props.children + * @param {string} props.url + */ +const HelpText = ( { moreLinkText, children, url } ) => { + return ( +
+ { children } + { children && url && ' ' } + { url && ( + { moreLinkText } + ) } +
+ ); +}; + +export default HelpText; diff --git a/packages/components/src/help-text/index.native.js b/packages/components/src/help-text/index.native.js new file mode 100644 index 00000000000000..bc5c51abe3086a --- /dev/null +++ b/packages/components/src/help-text/index.native.js @@ -0,0 +1,63 @@ +/** + * External dependencies + */ +import { View, Text, AccessibilityInfo, Linking } from 'react-native'; + +/** + * WordPress dependencies + */ +import { ExternalLink } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { usePreferredColorSchemeStyle } from '@wordpress/compose'; + +/** + * Internal dependencies + */ +import styles from './styles.scss'; + +const HelpText = ( { moreLinkText, children, url, separatorType } ) => { + if ( typeof children === 'string' ) { + children = ( + { children } + ); + } + + const separatorStyle = usePreferredColorSchemeStyle( + styles[ 'help-text__separator' ], + styles[ 'help-text__separator--dark' ] + ); + + const hasMoreLink = url && moreLinkText; + + return ( + <> + { separatorType === 'topFullWidth' && ( + + ) } + + { + AccessibilityInfo.isScreenReaderEnabled().then( + ( enabled ) => enabled && Linking.openURL( url ) + ); + } } + style={ styles[ 'help-text__text' ] } + > + { children } + { children && hasMoreLink && ' ' } + { hasMoreLink && ( + + { moreLinkText } + + ) } + + + + ); +}; + +export default HelpText; diff --git a/packages/components/src/help-text/styles.native.scss b/packages/components/src/help-text/styles.native.scss new file mode 100644 index 00000000000000..2f8f3e94340124 --- /dev/null +++ b/packages/components/src/help-text/styles.native.scss @@ -0,0 +1,20 @@ +.help-text { + flex-direction: row; + min-height: 48; + align-items: center; + justify-content: space-between; +} + +.help-text__text { + font-size: 12px; + color: $gray; +} + +.help-text__separator { + background-color: $light-gray-400; + height: 1px; +} + +.help-text__separator--dark { + background-color: $gray-70; +} diff --git a/packages/components/src/help-text/styles.scss b/packages/components/src/help-text/styles.scss new file mode 100644 index 00000000000000..7e86627dc94369 --- /dev/null +++ b/packages/components/src/help-text/styles.scss @@ -0,0 +1,7 @@ +.help-text { + font-size: 12px; +} + +.help-text__text { + color: $gray; +} diff --git a/packages/components/src/index.js b/packages/components/src/index.js index 71d2fb2144f25c..2e3ae757215acc 100644 --- a/packages/components/src/index.js +++ b/packages/components/src/index.js @@ -87,6 +87,7 @@ export { Grid as __experimentalGrid } from './grid'; export { default as Guide } from './guide'; export { default as GuidePage } from './guide/page'; export { Heading as __experimentalHeading } from './heading'; +export { default as HelpText } from './help-text'; export { HStack as __experimentalHStack } from './h-stack'; export { default as Icon } from './icon'; export { default as IconButton } from './button/deprecated'; diff --git a/packages/components/src/index.native.js b/packages/components/src/index.native.js index 140ad940ace6eb..24bb7e9e3033ef 100644 --- a/packages/components/src/index.native.js +++ b/packages/components/src/index.native.js @@ -39,6 +39,7 @@ export { default as PanelActions } from './panel/actions'; export { default as Button } from './button'; export { default as __experimentalText } from './text'; export { default as ExternalLink } from './external-link'; +export { default as HelpText } from './help-text'; export { default as TextControl } from './text-control'; export { default as ToggleControl } from './toggle-control'; export { default as SandBox } from './sandbox'; @@ -98,7 +99,6 @@ export { default as ColorSettings } from './mobile/color-settings'; export { default as SegmentedControls } from './mobile/segmented-control'; export { default as FocalPointSettingsPanel } from './mobile/focal-point-settings-panel'; export { default as BottomSheetTextControl } from './mobile/bottom-sheet-text-control'; -export { default as FooterMessageLink } from './mobile/bottom-sheet/footer-message-link/footer-message-link'; export { LinkPicker } from './mobile/link-picker'; export { default as LinkPickerScreen } from './mobile/link-picker/link-picker-screen'; export { default as LinkSettings } from './mobile/link-settings'; diff --git a/packages/components/src/mobile/bottom-sheet-text-control/README.md b/packages/components/src/mobile/bottom-sheet-text-control/README.md index e23680f5ba2beb..88c8e05da037db 100644 --- a/packages/components/src/mobile/bottom-sheet-text-control/README.md +++ b/packages/components/src/mobile/bottom-sheet-text-control/README.md @@ -10,7 +10,7 @@ // This is a paraphrased example from the image block's edit.native.js file import { BottomSheetSelectControl, - FooterMessageLink, + ExternalLink, } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; @@ -31,13 +31,12 @@ const MyTextControl = () => { placeholder={ __( 'Generic placeholder text' ) } label={ __( 'Generic label' ) } icon={ textColor } - footerNote={ + help={ <> { __( 'A footer note to add to the component! ' ) } - + + { __( 'Visit WordPress.org' ) } + } /> @@ -83,9 +82,9 @@ The icon to display alongside the control. - Type: `String` - Required: No -#### footerNote +#### help An optional note to display in the component's footer area. -- Type: `String` +- Type: `Component` - Required: No diff --git a/packages/components/src/mobile/bottom-sheet-text-control/index.native.js b/packages/components/src/mobile/bottom-sheet-text-control/index.native.js index 820f8e16da2960..bb6773abe137f9 100644 --- a/packages/components/src/mobile/bottom-sheet-text-control/index.native.js +++ b/packages/components/src/mobile/bottom-sheet-text-control/index.native.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { TextInput } from 'react-native'; +import { TextInput, View } from 'react-native'; import { useNavigation } from '@react-navigation/native'; /** @@ -10,11 +10,7 @@ import { useNavigation } from '@react-navigation/native'; import { useState } from '@wordpress/element'; import { Icon, chevronRight } from '@wordpress/icons'; import { usePreferredColorSchemeStyle } from '@wordpress/compose'; -import { - BottomSheet, - PanelBody, - FooterMessageControl, -} from '@wordpress/components'; +import { BottomSheet, PanelBody } from '@wordpress/components'; /** * Internal dependencies @@ -27,7 +23,7 @@ const BottomSheetTextControl = ( { placeholder, label, icon, - footerNote, + help, } ) => { const [ showSubSheet, setShowSubSheet ] = useState( false ); const navigation = useNavigation(); @@ -88,12 +84,9 @@ const BottomSheetTextControl = ( { - { footerNote && ( - - + { !! help && ( + + { help } ) } diff --git a/packages/components/src/mobile/bottom-sheet-text-control/styles.scss b/packages/components/src/mobile/bottom-sheet-text-control/styles.scss index f50712d403a747..b3197411e7286b 100644 --- a/packages/components/src/mobile/bottom-sheet-text-control/styles.scss +++ b/packages/components/src/mobile/bottom-sheet-text-control/styles.scss @@ -8,7 +8,7 @@ } .textFooternote { - padding: 0 16px 24px; + padding: 12px 0; } .horizontalBorder { diff --git a/packages/components/src/mobile/bottom-sheet/footer-message-link/README.md b/packages/components/src/mobile/bottom-sheet/footer-message-link/README.md deleted file mode 100644 index 61df444a200975..00000000000000 --- a/packages/components/src/mobile/bottom-sheet/footer-message-link/README.md +++ /dev/null @@ -1,37 +0,0 @@ -# Footer Message Link - -FooterMessageLink allows for adding a link within a FooterMessageControl component. - -### Usage - -```jsx -return ( - - { __( 'Example footer text. ' ) } - - - } - /> -); -``` - -### Props - -#### href - -The URL that is being linked to and that will open in a browser tab when selected. - -- Type: `String` -- Required: Yes - -#### value - -The "clickable" text that will be displayed to the user. - -- Type: `String` -- Required: Yes diff --git a/packages/components/src/mobile/bottom-sheet/footer-message-link/footer-message-link.native.js b/packages/components/src/mobile/bottom-sheet/footer-message-link/footer-message-link.native.js deleted file mode 100644 index 87a9ae0813fd0d..00000000000000 --- a/packages/components/src/mobile/bottom-sheet/footer-message-link/footer-message-link.native.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * External dependencies - */ -import { Text, Linking } from 'react-native'; -/** - * WordPress dependencies - */ -import { usePreferredColorSchemeStyle } from '@wordpress/compose'; -/** - * Internal dependencies - */ -import styles from './styles.scss'; - -function FooterMessageLink( { href, value } ) { - const textStyle = usePreferredColorSchemeStyle( - styles.footerMessageLink, - styles.footerMessageLinkDark - ); - return ( - Linking.openURL( href ) }> - { value } - - ); -} - -export default FooterMessageLink; diff --git a/packages/components/src/mobile/bottom-sheet/footer-message-link/styles.native.scss b/packages/components/src/mobile/bottom-sheet/footer-message-link/styles.native.scss deleted file mode 100644 index d612defade6294..00000000000000 --- a/packages/components/src/mobile/bottom-sheet/footer-message-link/styles.native.scss +++ /dev/null @@ -1,7 +0,0 @@ -.footerMessageLink { - color: $blue-50; -} - -.footerMessageLinkDark { - color: $blue-30; -} diff --git a/packages/components/src/mobile/link-settings/index.native.js b/packages/components/src/mobile/link-settings/index.native.js index 794650adefdd79..342135f8bef35f 100644 --- a/packages/components/src/mobile/link-settings/index.native.js +++ b/packages/components/src/mobile/link-settings/index.native.js @@ -26,9 +26,9 @@ import { BottomSheetContext } from '../bottom-sheet/bottom-sheet-context'; import PanelBody from '../../panel/body'; import TextControl from '../../text-control'; import ToggleControl from '../../toggle-control'; -import FooterMessageControl from '../../footer-message-control'; import PanelActions from '../../panel/actions'; import LinkRelIcon from './link-rel'; +import HelpText from '../../help-text'; import styles from './style.scss'; @@ -303,12 +303,15 @@ function LinkSettings( { { getSettings() } - { options.footer && ( + { options.help && ( - + + { options.help.label } + ) } { actions && }