@@ -384,7 +384,7 @@ function get_search_form( $args = array() ) {
384384 * @type string $id Unique ID for the popover element. Default is a
385385 * generated unique ID.
386386 * @type string $button Existing `button` or `a` markup. Used instead of generated button.
387- * Default standard button HTML .
387+ * Default empty string .
388388 * @type string $label Not used for tooltips.
389389 * @type string $close_label Not used for tooltips.
390390 * @type string $icon Dashicons icon class for the toggle button.
@@ -414,7 +414,7 @@ function wp_get_tooltip( $content, $args = array() ) {
414414 * @type string $id Unique ID for the popover element. Default is a
415415 * generated unique ID.
416416 * @type string $button Existing `button` markup. Used instead of generated button.
417- * Default standard button HTML .
417+ * Default empty string .
418418 * @type string $label Accessible label for the toggle button.
419419 * Default 'Help', matching the default icon.
420420 * Ignored for tooltips.
@@ -449,7 +449,7 @@ function wp_get_toggletip( $content, $args = array() ) {
449449 * @type string $id Unique ID for the popover element. Default is a
450450 * generated unique ID.
451451 * @type string $button Existing `button` or `a` markup. Used instead of generated button.
452- * Default standard button HTML .
452+ * Default empty string .
453453 * @type string $label Accessible label for the toggle button.
454454 * Default 'Help', matching the default icon.
455455 * Ignored for tooltips.
@@ -473,7 +473,7 @@ function wp_get_tooltip_helper( $content, $args = array() ) {
473473
474474 $ defaults = array (
475475 'id ' => wp_unique_id ( 'wp-tooltip- ' ),
476- 'button ' => '<button type="button" aria-label="%3$s"><span class="dashicons %4$s" aria-hidden="true"></span></button> ' ,
476+ 'button ' => '' ,
477477 'label ' => __ ( 'Help ' ),
478478 'close_label ' => __ ( 'Close ' ),
479479 'icon ' => 'dashicons-editor-help ' ,
@@ -488,51 +488,77 @@ function wp_get_tooltip_helper( $content, $args = array() ) {
488488 $ classes .= ' ' . $ args ['class ' ];
489489 }
490490
491- $ icon = ( $ args ['icon ' ] ) ? trim ( $ args ['icon ' ] ) : $ defaults ['icon ' ];
492- $ id = ( $ args ['id ' ] ) ? $ args ['id ' ] : $ defaults ['id ' ];
493- $ button = ( $ args ['button ' ] ) ? $ args ['button ' ] : $ defaults ['button ' ];
494- $ processed = false ;
491+ $ icon = ( $ args ['icon ' ] ) ? trim ( $ args ['icon ' ] ) : $ defaults ['icon ' ];
492+ $ id = ( $ args ['id ' ] ) ? $ args ['id ' ] : $ defaults ['id ' ];
493+
494+ // Tooltips use the content as the accessible name; toggletips use the label.
495+ $ label = ( 'tooltip ' === $ args ['type ' ] ) ? wp_strip_all_tags ( $ content , true ) : $ args ['label ' ];
496+
497+ /*
498+ * The generated button is a plain skeleton. Every dynamic attribute is
499+ * added through the tag processor below, so caller-supplied markup is
500+ * never scanned or substituted and a percent sign in custom markup,
501+ * such as a percent-encoded URL, is never treated as a conversion
502+ * specification.
503+ */
504+ $ default_button = '<button type="button"><span></span></button> ' ;
505+
506+ $ is_default = ! $ args ['button ' ];
507+ $ button = ( $ args ['button ' ] ) ? $ args ['button ' ] : $ default_button ;
508+
509+ // The accepted root element is a `button`, or an `a` for tooltips.
510+ $ tag = false ;
495511 $ processor = new WP_HTML_Tag_Processor ( $ button );
496512 if ( true === $ processor ->next_tag ( 'button ' ) ) {
497- $ processor ->add_class ( 'wp-tooltip__toggle ' );
498- if ( 'tooltip ' !== $ args ['type ' ] ) {
499- $ processor ->set_attribute ( 'popovertarget ' , '%2$s ' );
500- $ processor ->set_attribute ( 'aria-haspopup ' , 'dialog ' );
501- }
502- $ button = $ processor ->get_updated_html ();
503- $ processed = true ;
513+ $ tag = 'button ' ;
504514 } else {
505- // Reset processor.
506515 $ processor = new WP_HTML_Tag_Processor ( $ button );
507- if ( true === $ processor ->next_tag ( 'a ' ) && 'tooltip ' === $ args ['type ' ] ) {
508- $ processor ->add_class ( 'wp-tooltip__toggle ' );
509- $ button = $ processor ->get_updated_html ();
510- $ processed = true ;
516+ if ( 'tooltip ' === $ args ['type ' ] && true === $ processor ->next_tag ( 'a ' ) ) {
517+ $ tag = 'a ' ;
511518 }
512519 }
513- if ( ! $ processed ) {
514- // Button HTML passed was not valid.
515- $ processor = new WP_HTML_Tag_Processor ( $ defaults ['button ' ] );
516- $ processor ->add_class ( 'wp-tooltip__toggle ' );
517- if ( 'tooltip ' !== $ args ['type ' ] ) {
518- $ processor ->set_attribute ( 'popovertarget ' , '%2$s ' );
519- $ processor ->set_attribute ( 'aria-haspopup ' , 'dialog ' );
520- }
521- $ button = $ processor ->get_updated_html ();
520+
521+ if ( false === $ tag ) {
522+ // Button HTML passed was not valid. Reset to default.
523+ $ is_default = true ;
524+ $ button = $ default_button ;
525+ $ processor = new WP_HTML_Tag_Processor ( $ button );
526+ $ processor ->next_tag ( 'button ' );
527+ $ tag = 'button ' ;
522528 }
523529
530+ /*
531+ * Attributes that apply to every accepted button are added in one pass.
532+ * Attributes that name the control are only added when the caller's
533+ * markup did not already provide them.
534+ */
535+ if ( null === $ processor ->get_attribute ( 'aria-label ' ) ) {
536+ $ processor ->set_attribute ( 'aria-label ' , $ label );
537+ }
538+ $ processor ->add_class ( 'wp-tooltip__toggle ' );
539+ if ( 'button ' === $ tag && 'tooltip ' !== $ args ['type ' ] ) {
540+ $ processor ->set_attribute ( 'popovertarget ' , $ id );
541+ $ processor ->set_attribute ( 'aria-haspopup ' , 'dialog ' );
542+ }
543+
544+ // The generated button also carries the dashicon on its inner span.
545+ if ( $ is_default && true === $ processor ->next_tag ( 'span ' ) ) {
546+ $ processor ->set_attribute ( 'class ' , 'dashicons ' . $ icon );
547+ $ processor ->set_attribute ( 'aria-hidden ' , 'true ' );
548+ }
549+
550+ $ button = $ processor ->get_updated_html ();
551+
524552 /*
525553 * The markup only uses phrasing content so it is valid when nested
526554 * in a phrasing context. Sectioning content (e.g. `div`, `dialog`) will
527555 * cause the parser to close an open `p`, creating an empty and breaking
528556 * the layout. See #65660.
529557 */
530558 if ( 'tooltip ' === $ args ['type ' ] ) {
531- // Tooltips are only used to visually display labels.
532- $ label = wp_strip_all_tags ( $ content , true );
533559 $ markup = sprintf (
534560 '<span class="%1$s">
535- ' . $ button . '
561+ %6$s
536562 <span popover="hint" id="%2$s" class="wp-tooltip__bubble" role="tooltip"> ' .
537563 '<span id="%2$s-text" class="wp-tooltip__text">%5$s</span> ' .
538564 '</span> ' .
@@ -542,6 +568,7 @@ function wp_get_tooltip_helper( $content, $args = array() ) {
542568 esc_attr ( $ label ),
543569 esc_attr ( $ icon ),
544570 esc_html ( $ content ),
571+ $ button ,
545572 );
546573 } else {
547574 /*
@@ -551,7 +578,7 @@ function wp_get_tooltip_helper( $content, $args = array() ) {
551578 */
552579 $ markup = sprintf (
553580 '<span class="%1$s">
554- ' . $ button . '
581+ %7$s
555582 <span popover="auto" id="%2$s" class="wp-tooltip__bubble" role="dialog" aria-label="%3$s" tabindex="-1" autofocus> ' .
556583 '<span id="%2$s-text" class="wp-tooltip__text">%5$s</span> ' .
557584 '<button type="button" class="wp-tooltip__close" popovertarget="%2$s" popovertargetaction="hide" aria-label="%6$s"> ' .
@@ -561,10 +588,11 @@ function wp_get_tooltip_helper( $content, $args = array() ) {
561588 '</span> ' ,
562589 esc_attr ( $ classes ),
563590 esc_attr ( $ id ),
564- esc_attr ( $ args [ ' label ' ] ),
591+ esc_attr ( $ label ),
565592 esc_attr ( $ icon ),
566593 esc_html ( $ content ),
567594 esc_attr ( $ args ['close_label ' ] ),
595+ $ button ,
568596 );
569597 }
570598
0 commit comments