' . esc_html__( 'Color Studio', 'dashpalette' ) . ''; array_unshift( $links, $settings_link ); return $links; } public function register_admin_menu() { add_menu_page( __( 'DashPalette Studio', 'dashpalette' ), __( 'DashPalette', 'dashpalette' ), 'read', 'dashpalette', array( $this, 'render_admin_page' ), 'dashicons-art', 66 ); } public function enqueue_admin_assets( $hook_suffix ) { if ( 'toplevel_page_dashpalette' !== $hook_suffix ) { return; } wp_enqueue_style( 'wp-color-picker' ); wp_enqueue_style( 'dashpalette-admin-css', DASHPALETTE_URL . 'assets/css/admin-style.css', array( 'wp-color-picker' ), DASHPALETTE_VERSION ); wp_enqueue_script( 'wp-color-picker' ); wp_enqueue_script( 'dashpalette-admin-js', DASHPALETTE_URL . 'assets/js/admin-script.js', array( 'jquery', 'wp-color-picker' ), DASHPALETTE_VERSION, true ); $current_palette = $this->get_user_palette(); wp_localize_script( 'dashpalette-admin-js', 'dashpaletteData', array( 'ajaxUrl' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'dashpalette_nonce' ), 'currentPalette' => $current_palette, 'strings' => array( 'saved' => __( 'Palette & icon styles applied!', 'dashpalette' ), 'reset' => __( 'Dashboard reset to default colors.', 'dashpalette' ), 'saving' => __( 'Saving preferences...', 'dashpalette' ), 'error' => __( 'Something went wrong. Please try again.', 'dashpalette' ), 'copied' => __( 'Color copied to clipboard!', 'dashpalette' ), ), ) ); } public function get_user_palette() { $user_id = get_current_user_id(); $palette = get_user_meta( $user_id, '_dashpalette_colors', true ); if ( empty( $palette ) || ! is_array( $palette ) ) { $palette = get_option( 'dashpalette_site_default', array() ); } $defaults = array( 'admin_bar' => '', 'sidebar' => '', 'active_hover' => '', 'accent' => '', 'palette_name' => '', 'icon_style' => 'default', 'is_active' => false, ); return wp_parse_args( $palette, $defaults ); } /** * Properly enqueue custom admin colors via standard wp_add_inline_style. */ public function enqueue_custom_admin_colors() { $palette = $this->get_user_palette(); if ( empty( $palette['is_active'] ) && empty( $palette['icon_style'] ) ) { return; } $admin_bar = sanitize_hex_color( $palette['admin_bar'] ); $sidebar = sanitize_hex_color( $palette['sidebar'] ); $active_hover = sanitize_hex_color( $palette['active_hover'] ); $accent = sanitize_hex_color( $palette['accent'] ); $icon_style = sanitize_key( $palette['icon_style'] ?? 'default' ); // Text contrast $sidebar_text = $sidebar ? $this->get_contrast_color( $sidebar ) : '#ffffff'; $admin_bar_text = $admin_bar ? $this->get_contrast_color( $admin_bar ) : '#ffffff'; $accent_text = $accent ? $this->get_contrast_color( $accent ) : '#ffffff'; $active_text = $active_hover ? $this->get_contrast_color( $active_hover ) : '#ffffff'; $custom_css = ''; if ( ! empty( $palette['is_active'] ) && $admin_bar && $sidebar && $active_hover && $accent ) { $custom_css .= ' :root { --dp-admin-bar: ' . esc_attr( $admin_bar ) . '; --dp-admin-bar-text: ' . esc_attr( $admin_bar_text ) . '; --dp-sidebar: ' . esc_attr( $sidebar ) . '; --dp-sidebar-text: ' . esc_attr( $sidebar_text ) . '; --dp-active-hover: ' . esc_attr( $active_hover ) . '; --dp-active-text: ' . esc_attr( $active_text ) . '; --dp-accent: ' . esc_attr( $accent ) . '; --dp-accent-text: ' . esc_attr( $accent_text ) . '; } #wpadminbar { background: var(--dp-admin-bar) !important; color: var(--dp-admin-bar-text) !important; border-bottom: 1px solid rgba(0, 0, 0, 0.1); } #wpadminbar .ab-item, #wpadminbar a.ab-item, #wpadminbar > #wp-toolbar span.ab-label, #wpadminbar > #wp-toolbar span.noticon { color: var(--dp-admin-bar-text) !important; } #wpadminbar .ab-icon:before, #wpadminbar .ab-item:before { color: var(--dp-admin-bar-text) !important; opacity: 0.9; } #wpadminbar:not(.mobile) .ab-top-menu > li:hover > .ab-item, #wpadminbar:not(.mobile) .ab-top-menu > li.hover > .ab-item, #wpadminbar:not(.mobile) .ab-top-menu > li > .ab-item:focus { background: var(--dp-active-hover) !important; color: var(--dp-active-text) !important; } #wpadminbar .menupop .ab-sub-wrapper { background: var(--dp-sidebar) !important; } #adminmenuback, #adminmenuwrap, #adminmenu { background: var(--dp-sidebar) !important; } #adminmenu a { color: var(--dp-sidebar-text) !important; opacity: 0.88; transition: all 0.15s ease-in-out; } #adminmenu .wp-menu-image:before { color: var(--dp-sidebar-text) !important; opacity: 0.85; } #adminmenu li.menu-top:hover, #adminmenu li.opensub > a.menu-top, #adminmenu li > a.menu-top:focus { background: var(--dp-active-hover) !important; color: var(--dp-active-text) !important; } #adminmenu li.wp-has-current-submenu a.wp-has-current-submenu, #adminmenu li.current a.menu-top, .folded #adminmenu li.wp-has-current-submenu, .folded #adminmenu li.current.menu-top { background: var(--dp-accent) !important; color: var(--dp-accent-text) !important; font-weight: 600; } #adminmenu .wp-submenu { background: var(--dp-sidebar) !important; box-shadow: 0 4px 15px rgba(0, 0, 0, 0.15); } #adminmenu .wp-submenu a { color: var(--dp-sidebar-text) !important; opacity: 0.85; } #adminmenu .wp-submenu a:hover, #adminmenu .wp-submenu a:focus { background: var(--dp-active-hover) !important; color: var(--dp-active-text) !important; opacity: 1; } #adminmenu .wp-submenu li.current a { color: var(--dp-accent) !important; font-weight: 600; } .wp-core-ui .button-primary { background: var(--dp-accent) !important; border-color: var(--dp-accent) !important; color: var(--dp-accent-text) !important; box-shadow: 0 2px 4px rgba(0,0,0,0.12); } .wp-core-ui .button-primary:hover, .wp-core-ui .button-primary:focus { background: var(--dp-active-hover) !important; border-color: var(--dp-active-hover) !important; color: var(--dp-active-text) !important; } #adminmenu .awaiting-mod, #adminmenu .update-plugins { background-color: var(--dp-accent) !important; color: var(--dp-accent-text) !important; } '; } if ( 'vibrant' === $icon_style || 'material_3d' === $icon_style ) { $custom_css .= ' #adminmenu div.wp-menu-image { display: flex !important; align-items: center !important; justify-content: center !important; } #adminmenu div.wp-menu-image img, #adminmenu div.wp-menu-image svg { padding: 0 !important; max-width: 20px !important; max-height: 20px !important; transition: all 0.2s ease !important; } #adminmenu div.wp-menu-image:before { transition: all 0.2s ease !important; } #adminmenu > li:nth-child(1) .wp-menu-image:before { color: #38bdf8 !important; } #adminmenu > li:nth-child(2) .wp-menu-image:before { color: #ec4899 !important; } #adminmenu > li:nth-child(3) .wp-menu-image:before { color: #fb923c !important; } #adminmenu > li:nth-child(4) .wp-menu-image:before { color: #c084fc !important; } #adminmenu > li:nth-child(5) .wp-menu-image:before { color: #60a5fa !important; } #adminmenu > li:nth-child(6) .wp-menu-image:before { color: #34d399 !important; } #adminmenu > li:nth-child(7) .wp-menu-image:before { color: #f43f5e !important; } #adminmenu > li:nth-child(8) .wp-menu-image:before { color: #facc15 !important; } #adminmenu > li:nth-child(9) .wp-menu-image:before { color: #2dd4bf !important; } #adminmenu > li:nth-child(10) .wp-menu-image:before { color: #a78bfa !important; } #adminmenu > li:nth-child(11) .wp-menu-image:before { color: #f97316 !important; } #adminmenu > li:nth-child(12) .wp-menu-image:before { color: #06b6d4 !important; } #adminmenu > li:nth-child(13) .wp-menu-image:before { color: #84cc16 !important; } #adminmenu > li:nth-child(14) .wp-menu-image:before { color: #e11d48 !important; } #adminmenu > li:nth-child(15) .wp-menu-image:before { color: #6366f1 !important; } #adminmenu > li:nth-child(16) .wp-menu-image:before { color: #10b981 !important; } #adminmenu > li:nth-child(17) .wp-menu-image:before { color: #d946ef !important; } #adminmenu > li:nth-child(18) .wp-menu-image:before { color: #eab308 !important; } #adminmenu > li:nth-child(19) .wp-menu-image:before { color: #14b8a6 !important; } #adminmenu > li:nth-child(20) .wp-menu-image:before { color: #8b5cf6 !important; } #adminmenu > li:nth-child(1) .wp-menu-image img, #adminmenu > li:nth-child(1) .wp-menu-image svg { filter: hue-rotate(190deg) saturate(3) brightness(1.2) !important; } #adminmenu > li:nth-child(2) .wp-menu-image img, #adminmenu > li:nth-child(2) .wp-menu-image svg { filter: hue-rotate(300deg) saturate(3) brightness(1.2) !important; } #adminmenu > li:nth-child(3) .wp-menu-image img, #adminmenu > li:nth-child(3) .wp-menu-image svg { filter: hue-rotate(30deg) saturate(3) brightness(1.2) !important; } #adminmenu > li:nth-child(4) .wp-menu-image img, #adminmenu > li:nth-child(4) .wp-menu-image svg { filter: hue-rotate(260deg) saturate(3) brightness(1.2) !important; } #adminmenu > li:nth-child(5) .wp-menu-image img, #adminmenu > li:nth-child(5) .wp-menu-image svg { filter: hue-rotate(210deg) saturate(3) brightness(1.2) !important; } #adminmenu > li:nth-child(6) .wp-menu-image img, #adminmenu > li:nth-child(6) .wp-menu-image svg { filter: hue-rotate(140deg) saturate(3) brightness(1.2) !important; } #adminmenu > li:nth-child(7) .wp-menu-image img, #adminmenu > li:nth-child(7) .wp-menu-image svg { filter: hue-rotate(340deg) saturate(3) brightness(1.2) !important; } #adminmenu > li:nth-child(8) .wp-menu-image img, #adminmenu > li:nth-child(8) .wp-menu-image svg { filter: hue-rotate(50deg) saturate(3) brightness(1.2) !important; } #adminmenu > li:nth-child(9) .wp-menu-image img, #adminmenu > li:nth-child(9) .wp-menu-image svg { filter: hue-rotate(170deg) saturate(3) brightness(1.2) !important; } #adminmenu > li:nth-child(10) .wp-menu-image img, #adminmenu > li:nth-child(10) .wp-menu-image svg { filter: hue-rotate(250deg) saturate(3) brightness(1.2) !important; } '; } if ( 'material_3d' === $icon_style ) { $custom_css .= ' #adminmenu div.wp-menu-image:before, #adminmenu div.wp-menu-image img, #adminmenu div.wp-menu-image svg { filter: drop-shadow(0 3px 5px rgba(0, 0, 0, 0.55)) drop-shadow(0 0 6px rgba(255, 255, 255, 0.25)) !important; transform: scale(1.12) !important; } #adminmenu li.menu-top:hover div.wp-menu-image:before, #adminmenu li.menu-top:hover div.wp-menu-image img, #adminmenu li.menu-top:hover div.wp-menu-image svg { transform: scale(1.28) translateY(-1px) !important; filter: drop-shadow(0 5px 9px rgba(0, 0, 0, 0.7)) drop-shadow(0 0 12px rgba(56, 189, 248, 0.6)) !important; } '; } if ( ! empty( $custom_css ) ) { // Register a virtual style handle and attach inline style using standard WP API wp_register_style( 'dashpalette-custom-admin', false, array(), DASHPALETTE_VERSION ); wp_enqueue_style( 'dashpalette-custom-admin' ); wp_add_inline_style( 'dashpalette-custom-admin', $custom_css ); } } private function get_contrast_color( $hex ) { $hex = ltrim( $hex, '#' ); if ( strlen( $hex ) === 3 ) { $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2]; } $r = hexdec( substr( $hex, 0, 2 ) ); $g = hexdec( substr( $hex, 2, 2 ) ); $b = hexdec( substr( $hex, 4, 2 ) ); $yiq = ( ( $r * 299 ) + ( $g * 587 ) + ( $b * 114 ) ) / 1000; return ( $yiq >= 150 ) ? '#1e293b' : '#ffffff'; } public function ajax_save_palette() { check_ajax_referer( 'dashpalette_nonce', 'nonce' ); if ( ! current_user_can( 'read' ) ) { wp_send_json_error( array( 'message' => __( 'Permission denied.', 'dashpalette' ) ) ); } $admin_bar = isset( $_POST['admin_bar'] ) ? sanitize_hex_color( wp_unslash( $_POST['admin_bar'] ) ) : ''; $sidebar = isset( $_POST['sidebar'] ) ? sanitize_hex_color( wp_unslash( $_POST['sidebar'] ) ) : ''; $active_hover = isset( $_POST['active_hover'] ) ? sanitize_hex_color( wp_unslash( $_POST['active_hover'] ) ) : ''; $accent = isset( $_POST['accent'] ) ? sanitize_hex_color( wp_unslash( $_POST['accent'] ) ) : ''; $name = isset( $_POST['palette_name'] ) ? sanitize_text_field( wp_unslash( $_POST['palette_name'] ) ) : 'Custom'; $icon_style = isset( $_POST['icon_style'] ) ? sanitize_key( wp_unslash( $_POST['icon_style'] ) ) : 'default'; $is_global = ! empty( $_POST['apply_globally'] ) && current_user_can( 'manage_options' ); if ( ! $admin_bar || ! $sidebar || ! $active_hover || ! $accent ) { wp_send_json_error( array( 'message' => __( 'Invalid color values provided.', 'dashpalette' ) ) ); } $palette_data = array( 'admin_bar' => $admin_bar, 'sidebar' => $sidebar, 'active_hover' => $active_hover, 'accent' => $accent, 'palette_name' => $name, 'icon_style' => in_array( $icon_style, array( 'default', 'vibrant', 'material_3d' ), true ) ? $icon_style : 'default', 'is_active' => true, ); update_user_meta( get_current_user_id(), '_dashpalette_colors', $palette_data ); if ( $is_global ) { update_option( 'dashpalette_site_default', $palette_data ); } wp_send_json_success( array( 'message' => __( 'Palette & universal icon styles applied successfully!', 'dashpalette' ), 'palette' => $palette_data, ) ); } public function ajax_reset_palette() { check_ajax_referer( 'dashpalette_nonce', 'nonce' ); if ( ! current_user_can( 'read' ) ) { wp_send_json_error( array( 'message' => __( 'Permission denied.', 'dashpalette' ) ) ); } delete_user_meta( get_current_user_id(), '_dashpalette_colors' ); if ( ! empty( $_POST['reset_globally'] ) && current_user_can( 'manage_options' ) ) { delete_option( 'dashpalette_site_default' ); } wp_send_json_success( array( 'message' => __( 'Dashboard reset to default colors.', 'dashpalette' ) ) ); } public function render_admin_page() { $current = $this->get_user_palette(); ?>

🎨 DashPalette v

Admin Bar
Sidebar
Hover / Active
Accent
✨

All Palettes

Loading palettes...