[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-content/themes/twentytwentyone/classes/ -> class-twenty-twenty-one-dark-mode.php (source)

   1  <?php
   2  /**
   3   * Dark Mode Class
   4   *
   5   * @package WordPress
   6   * @subpackage Twenty_Twenty_One
   7   * @since Twenty Twenty-One 1.0
   8   */
   9  
  10  /**
  11   * This class is in charge of Dark Mode.
  12   */
  13  class Twenty_Twenty_One_Dark_Mode {
  14  
  15      /**
  16       * Instantiates the object.
  17       *
  18       * @since Twenty Twenty-One 1.0
  19       */
  20  	public function __construct() {
  21  
  22          // Enqueue assets for the block-editor.
  23          if ( is_admin() ) {
  24              add_action( 'enqueue_block_assets', array( $this, 'editor_custom_color_variables' ) );
  25          }
  26  
  27          // Add styles for dark-mode.
  28          add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
  29  
  30          // Add scripts for customizer controls.
  31          add_action( 'customize_controls_enqueue_scripts', array( $this, 'customize_controls_enqueue_scripts' ) );
  32  
  33          // Add customizer controls.
  34          add_action( 'customize_register', array( $this, 'customizer_controls' ) );
  35  
  36          // Add HTML classes.
  37          add_filter( 'twentytwentyone_html_classes', array( $this, 'html_classes' ) );
  38  
  39          // Add classes to <body> in the dashboard.
  40          add_filter( 'admin_body_class', array( $this, 'admin_body_classes' ) );
  41  
  42          // Add the switch on the frontend & customizer.
  43          add_action( 'wp_footer', array( $this, 'the_switch' ) );
  44  
  45          // Add the privacy policy content.
  46          add_action( 'admin_init', array( $this, 'add_privacy_policy_content' ) );
  47      }
  48  
  49      /**
  50       * Enqueues editor custom color variables & scripts.
  51       *
  52       * @since Twenty Twenty-One 1.0
  53       *
  54       * @return void
  55       */
  56  	public function editor_custom_color_variables() {
  57          if ( ! $this->switch_should_render() ) {
  58              return;
  59          }
  60          $background_color            = get_theme_mod( 'background_color', 'D1E4DD' );
  61          $should_respect_color_scheme = get_theme_mod( 'respect_user_color_preference', false );
  62          if ( $should_respect_color_scheme && Twenty_Twenty_One_Custom_Colors::get_relative_luminance_from_hex( $background_color ) > 127 ) {
  63              // Add Dark Mode variable overrides.
  64              wp_add_inline_style(
  65                  'twenty-twenty-one-custom-color-overrides',
  66                  '.is-dark-theme.is-dark-theme .editor-styles-wrapper { --global--color-background: var(--global--color-dark-gray); --global--color-primary: var(--global--color-light-gray); --global--color-secondary: var(--global--color-light-gray); --button--color-text: var(--global--color-background); --button--color-text-hover: var(--global--color-secondary); --button--color-text-active: var(--global--color-secondary); --button--color-background: var(--global--color-secondary); --button--color-background-active: var(--global--color-background); --global--color-border: #9ea1a7; --table--stripes-border-color: rgba(240, 240, 240, 0.15); --table--stripes-background-color: rgba(240, 240, 240, 0.15); }'
  67              );
  68          }
  69          wp_enqueue_script(
  70              'twentytwentyone-dark-mode-support-toggle',
  71              get_template_directory_uri() . '/assets/js/dark-mode-toggler.js',
  72              array(),
  73              '1.0.0',
  74              array( 'in_footer' => true )
  75          );
  76  
  77          wp_enqueue_script(
  78              'twentytwentyone-editor-dark-mode-support',
  79              get_template_directory_uri() . '/assets/js/editor-dark-mode-support.js',
  80              array( 'twentytwentyone-dark-mode-support-toggle' ),
  81              '1.0.0',
  82              array( 'in_footer' => true )
  83          );
  84      }
  85  
  86      /**
  87       * Enqueues scripts and styles.
  88       *
  89       * @since Twenty Twenty-One 1.0
  90       *
  91       * @return void
  92       */
  93  	public function enqueue_scripts() {
  94          if ( ! $this->switch_should_render() ) {
  95              return;
  96          }
  97          $url = get_template_directory_uri() . '/assets/css/style-dark-mode.css';
  98          if ( is_rtl() ) {
  99              $url = get_template_directory_uri() . '/assets/css/style-dark-mode-rtl.css';
 100          }
 101          wp_enqueue_style( 'tt1-dark-mode', $url, array( 'twenty-twenty-one-style' ), wp_get_theme()->get( 'Version' ) ); // @phpstan-ignore-line. Version is always a string.
 102      }
 103  
 104      /**
 105       * Enqueues scripts for the customizer.
 106       *
 107       * @since Twenty Twenty-One 1.0
 108       *
 109       * @return void
 110       */
 111  	public function customize_controls_enqueue_scripts() {
 112          if ( ! $this->switch_should_render() ) {
 113              return;
 114          }
 115          wp_enqueue_script(
 116              'twentytwentyone-customize-controls',
 117              get_template_directory_uri() . '/assets/js/customize.js',
 118              array( 'customize-base', 'customize-controls', 'underscore', 'jquery', 'twentytwentyone-customize-helpers' ),
 119              '1.0.0',
 120              array( 'in_footer' => true )
 121          );
 122      }
 123  
 124      /**
 125       * Registers customizer options.
 126       *
 127       * @since Twenty Twenty-One 1.0
 128       *
 129       * @param WP_Customize_Manager $wp_customize Theme Customizer object.
 130       * @return void
 131       */
 132  	public function customizer_controls( $wp_customize ) {
 133  
 134          $colors_section = $wp_customize->get_section( 'colors' );
 135          if ( is_object( $colors_section ) ) {
 136              $colors_section->title = __( 'Colors & Dark Mode', 'twentytwentyone' );
 137          }
 138  
 139          // Custom notice control.
 140          require_once get_theme_file_path( 'classes/class-twenty-twenty-one-customize-notice-control.php' ); // phpcs:ignore WPThemeReview.CoreFunctionality.FileInclude.FileIncludeFound
 141  
 142          $wp_customize->add_setting(
 143              'respect_user_color_preference_notice',
 144              array(
 145                  'capability'        => 'edit_theme_options',
 146                  'default'           => '',
 147                  'sanitize_callback' => '__return_empty_string',
 148              )
 149          );
 150  
 151          $wp_customize->add_control(
 152              new Twenty_Twenty_One_Customize_Notice_Control(
 153                  $wp_customize,
 154                  'respect_user_color_preference_notice',
 155                  array(
 156                      'section'         => 'colors',
 157                      'priority'        => 100,
 158                      'active_callback' => static function () {
 159                          return 127 >= Twenty_Twenty_One_Custom_Colors::get_relative_luminance_from_hex( get_theme_mod( 'background_color', 'D1E4DD' ) );
 160                      },
 161                  )
 162              )
 163          );
 164  
 165          $wp_customize->add_setting(
 166              'respect_user_color_preference',
 167              array(
 168                  'capability'        => 'edit_theme_options',
 169                  'default'           => false,
 170                  'sanitize_callback' => static function ( $value ) {
 171                      return (bool) $value;
 172                  },
 173              )
 174          );
 175  
 176          $description  = '<p>';
 177          $description .= sprintf(
 178              /* translators: %s: Twenty Twenty-One support article URL. */
 179              __( 'Dark Mode is a device setting. If a visitor to your site requests it, your site will be shown with a dark background and light text. <a href="%s">Learn more about Dark Mode.</a>', 'twentytwentyone' ),
 180              esc_url( __( 'https://wordpress.org/documentation/article/twenty-twenty-one/#dark-mode-support', 'twentytwentyone' ) )
 181          );
 182          $description .= '</p>';
 183          $description .= '<p>' . __( 'Dark Mode can also be turned on and off with a button that you can find in the bottom corner of the page.', 'twentytwentyone' ) . '</p>';
 184  
 185          $wp_customize->add_control(
 186              'respect_user_color_preference',
 187              array(
 188                  'type'            => 'checkbox',
 189                  'section'         => 'colors',
 190                  'label'           => esc_html__( 'Dark Mode support', 'twentytwentyone' ),
 191                  'priority'        => 110,
 192                  'description'     => $description,
 193                  'active_callback' => static function ( $value ) {
 194                      return 127 < Twenty_Twenty_One_Custom_Colors::get_relative_luminance_from_hex( get_theme_mod( 'background_color', 'D1E4DD' ) );
 195                  },
 196              )
 197          );
 198  
 199          // Add partial for background_color.
 200          $wp_customize->selective_refresh->add_partial(
 201              'background_color',
 202              array(
 203                  'selector'            => '#dark-mode-toggler',
 204                  'container_inclusive' => true,
 205                  'render_callback'     => function () {
 206                      $attrs = ( $this->switch_should_render() ) ? array() : array( 'style' => 'display:none;' );
 207                      $this->the_html( $attrs );
 208                  },
 209              )
 210          );
 211      }
 212  
 213      /**
 214       * Calculates classes for the main <html> element.
 215       *
 216       * @since Twenty Twenty-One 1.0
 217       *
 218       * @param string $classes The classes for <html> element.
 219       * @return string
 220       */
 221  	public function html_classes( $classes ) {
 222          if ( ! $this->switch_should_render() ) {
 223              return $classes;
 224          }
 225  
 226          $background_color            = get_theme_mod( 'background_color', 'D1E4DD' );
 227          $should_respect_color_scheme = get_theme_mod( 'respect_user_color_preference', false );
 228          if ( $should_respect_color_scheme && 127 <= Twenty_Twenty_One_Custom_Colors::get_relative_luminance_from_hex( $background_color ) ) {
 229              return ( $classes ) ? ' respect-color-scheme-preference' : 'respect-color-scheme-preference';
 230          }
 231  
 232          return $classes;
 233      }
 234  
 235      /**
 236       * Adds a class to the <body> element in the editor to accommodate dark-mode.
 237       *
 238       * @since Twenty Twenty-One 1.0
 239       *
 240       * @global WP_Screen $current_screen WordPress current screen object.
 241       *
 242       * @param string $classes The admin body-classes.
 243       * @return string
 244       */
 245  	public function admin_body_classes( $classes ) {
 246          if ( ! $this->switch_should_render() ) {
 247              return $classes;
 248          }
 249  
 250          global $current_screen;
 251          if ( empty( $current_screen ) ) {
 252              set_current_screen();
 253          }
 254  
 255          if ( $current_screen->is_block_editor() ) {
 256              $should_respect_color_scheme = get_theme_mod( 'respect_user_color_preference', false );
 257              $background_color            = get_theme_mod( 'background_color', 'D1E4DD' );
 258  
 259              if ( $should_respect_color_scheme && Twenty_Twenty_One_Custom_Colors::get_relative_luminance_from_hex( $background_color ) > 127 ) {
 260                  $classes .= ' twentytwentyone-supports-dark-theme';
 261              }
 262          }
 263  
 264          return $classes;
 265      }
 266  
 267      /**
 268       * Determines if we want to print the dark-mode switch or not.
 269       *
 270       * @since Twenty Twenty-One 1.0
 271       *
 272       * @global bool $is_IE
 273       *
 274       * @return bool
 275       */
 276  	public function switch_should_render() {
 277          global $is_IE;
 278          return (
 279              get_theme_mod( 'respect_user_color_preference', false ) &&
 280              ! $is_IE &&
 281              127 <= Twenty_Twenty_One_Custom_Colors::get_relative_luminance_from_hex( get_theme_mod( 'background_color', 'D1E4DD' ) )
 282          );
 283      }
 284  
 285      /**
 286       * Adds night/day switch.
 287       *
 288       * @since Twenty Twenty-One 1.0
 289       *
 290       * @return void
 291       */
 292  	public function the_switch() {
 293          if ( ! $this->switch_should_render() ) {
 294              return;
 295          }
 296          $this->the_html();
 297          $this->the_script();
 298      }
 299  
 300      /**
 301       * Prints the dark-mode switch HTML.
 302       *
 303       * Inspired from https://codepen.io/aaroniker/pen/KGpXZo (MIT-licensed)
 304       *
 305       * @since Twenty Twenty-One 1.0
 306       *
 307       * @param array $attrs The attributes to add to our <button> element.
 308       * @return void
 309       */
 310  	public function the_html( $attrs = array() ) {
 311          $attrs = wp_parse_args(
 312              $attrs,
 313              array(
 314                  'id'           => 'dark-mode-toggler',
 315                  'class'        => 'fixed-bottom',
 316                  'aria-pressed' => 'false',
 317                  'onClick'      => 'toggleDarkMode()',
 318              )
 319          );
 320          echo '<button';
 321          foreach ( $attrs as $key => $val ) {
 322              echo ' ' . esc_attr( $key ) . '="' . esc_attr( $val ) . '"';
 323          }
 324          echo '>';
 325          printf(
 326              /* translators: %s: On/Off */
 327              esc_html__( 'Dark Mode: %s', 'twentytwentyone' ),
 328              '<span aria-hidden="true"></span>'
 329          );
 330          echo '</button>';
 331          ?>
 332          <style>
 333              #dark-mode-toggler > span {
 334                  margin-<?php echo is_rtl() ? 'right' : 'left'; ?>: 5px;
 335              }
 336              #dark-mode-toggler > span::before {
 337                  content: '<?php esc_attr_e( 'Off', 'twentytwentyone' ); ?>';
 338              }
 339              #dark-mode-toggler[aria-pressed="true"] > span::before {
 340                  content: '<?php esc_attr_e( 'On', 'twentytwentyone' ); ?>';
 341              }
 342              <?php if ( is_admin() || wp_is_json_request() ) : ?>
 343                  .components-editor-notices__pinned ~ .edit-post-visual-editor #dark-mode-toggler {
 344                      z-index: 20;
 345                  }
 346                  .is-dark-theme.is-dark-theme #dark-mode-toggler:not(:hover):not(:focus) {
 347                      color: var(--global--color-primary);
 348                  }
 349                  @media only screen and (max-width: 782px) {
 350                      #dark-mode-toggler {
 351                          margin-top: 32px;
 352                      }
 353                  }
 354              <?php endif; ?>
 355          </style>
 356  
 357          <?php
 358      }
 359  
 360      /**
 361       * Prints the dark-mode switch script.
 362       *
 363       * @since Twenty Twenty-One 1.0
 364       *
 365       * @return void
 366       */
 367  	public function the_script() {
 368          $path = 'assets/js/dark-mode-toggler.js';
 369          $js   = rtrim( file_get_contents( trailingslashit( get_template_directory() ) . $path ) );
 370          $js  .= "\n//# sourceURL=" . esc_url_raw( trailingslashit( get_template_directory_uri() ) . $path );
 371          if ( function_exists( 'wp_print_inline_script_tag' ) ) {
 372              wp_print_inline_script_tag( $js );
 373          } else {
 374              printf( "<script>%s</script>\n", $js );
 375          }
 376      }
 377  
 378      /**
 379       * Adds information to the privacy policy.
 380       *
 381       * @since Twenty Twenty-One 1.0
 382       *
 383       * @return void
 384       */
 385  	public function add_privacy_policy_content() {
 386          if ( ! function_exists( 'wp_add_privacy_policy_content' ) ) {
 387              return;
 388          }
 389          $content = '<p class="privacy-policy-tutorial">' . __( 'Twenty Twenty-One uses LocalStorage when Dark Mode support is enabled.', 'twentytwentyone' ) . '</p>'
 390                  . '<strong class="privacy-policy-tutorial">' . __( 'Suggested text:', 'twentytwentyone' ) . '</strong> '
 391                  . __( 'This website uses LocalStorage to save the setting when Dark Mode support is turned on or off.<br> LocalStorage is necessary for the setting to work and is only used when a user clicks on the Dark Mode button.<br> No data is saved in the database or transferred.', 'twentytwentyone' );
 392          wp_add_privacy_policy_content( __( 'Twenty Twenty-One', 'twentytwentyone' ), wp_kses_post( wpautop( $content, false ) ) );
 393      }
 394  }


Generated : Mon May 25 08:20:05 2026 Cross-referenced by PHPXref