Maintaining a Beautiful
WordPress Admin UI
Helen Hou-Sandí
WordCamp Phoenix 2012
Helen Hou-Sandí
WordCamp Phoenix 2012
Web Design Engineer with 10up, LLC
@helenhousandi on Twitter
WordPress Core Contributor *
This dashed border tells us … that I am a developer, not a designer.mdawaffe, WCSF 2011
// Admin menu icon register_post_type( 'event', array( ... 'menu_icon' => get_template_directory_uri() . '/images/icon-16.png'; )); // Screen icon add_action( 'admin_head', 'hhs_event_screen_icon' ); function hhs_event_screen_icon() { $post_type = get_current_screen()->post_type; if ( 'event' != $post_type ) return; ?> <style type="text/css"> .icon32.icon32-posts-event { background: url(<?php echo get_template_directory_uri(); ?>/images/icon-32.png) !important; } </style> <?php }
// Don't set anything for the menu_icon arg in register_post_type() add_action( 'admin_head', 'hhs_event_admin_menu_icon' ); function hhs_event_admin_menu_icon() { ?> <style type="text/css"> #adminmenu #menu-posts-event div.wp-menu-image{ background: transparent url(<?php echo get_template_directory_uri(); ?>/images/icon-16.png) no-repeat 6px -17px; } #adminmenu #menu-posts-event:hover div.wp-menu-image, #adminmenu #menu-posts-event.wp-has-current-submenu div.wp-menu-image { background-position: 6px 7px; </style> <?php }
register_post_type( 'slide', array( ... 'show_in_menu' => 'themes.php', 'show_in_nav_menus' => false, 'supports' => array( 'thumbnail' ) ) );
add_action( 'add_meta_boxes_slide', 'hhs_slide_add_meta_boxes' ); add_filter( 'admin_post_thumbnail_html', 'hhs_slide_post_thumbnail_html' ); function hhs_slide_add_meta_boxes() { remove_meta_box( 'postimagediv', 'slide', 'side' ); add_meta_box( 'postimagediv', 'Slide Image', 'post_thumbnail_meta_box', 'slide', 'normal', 'high' ); } function hhs_slide_post_thumbnail_html( $output ) { global $post_type; // beware of translated admin if ( ! empty ( $post_type ) && 'slide' == $post_type ) { $output = str_replace( 'Set featured image', 'Select / Upload a slide image', $output ); } return $output; }
add_filter( 'manage_edit-slide_columns', 'hhs_slide_edit_columns' ); add_action( 'manage_slide_posts_custom_column', 'hhs_slide_custom_columns' ); function hhs_slide_edit_columns( $columns ) { $columns = array( 'cb' => '<input type="checkbox" />', 'thumbnail' => 'Slide', ); return $columns; } function hhs_slide_custom_columns( $column ) { global $post; switch ($column) { case 'thumbnail' : if ( has_post_thumbnail( $post->ID ) ) { // the current post has a thumbnail the_post_thumbnail( $post->ID ); } else { // the current post lacks a thumbnail ?> No image <?php } // add row_action links for Edit and Trash because there's no title column $post_type_object = get_post_type_object( $post->post_type ); $can_edit_post = current_user_can( $post_type_object->cap->edit_post, $post->ID ); $always_visible = false; // change to true to make it always show instead of on hover $actions = array(); if ( $can_edit_post && 'trash' != $post->post_status ) { $actions['edit'] = '<a href="' . get_edit_post_link( $post->ID, true ) . '" title="' . esc_attr( __( 'Edit this item' ) ) . '">' . __( 'Edit' ) . '</a>'; } if ( current_user_can( $post_type_object->cap->delete_post, $post->ID ) ) { if ( 'trash' == $post->post_status ) $actions['untrash'] = "<a title='" . esc_attr( __( 'Restore this item from the Trash' ) ) . "' href='" . wp_nonce_url( admin_url( sprintf( $post_type_object->_edit_link . '&action=untrash', $post->ID ) ), 'untrash-' . $post->post_type . '_' . $post->ID ) . "'>" . __( 'Restore' ) . "</a>"; elseif ( EMPTY_TRASH_DAYS ) $actions['trash'] = "<a class='submitdelete' title='" . esc_attr( __( 'Move this item to the Trash' ) ) . "' href='" . get_delete_post_link( $post->ID ) . "'>" . __( 'Trash' ) . "</a>"; if ( 'trash' == $post->post_status || !EMPTY_TRASH_DAYS ) $actions['delete'] = "<a class='submitdelete' title='" . esc_attr( __( 'Delete this item permanently' ) ) . "' href='" . get_delete_post_link( $post->ID, '', true ) . "'>" . __( 'Delete Permanently' ) . "</a>"; } $action_count = count( $actions ); $i = 0; $out = '<div class="' . ( $always_visible ? 'row-actions-visible' : 'row-actions' ) . '">'; foreach ( $actions as $action => $link ) { ++$i; ( $i == $action_count ) ? $sep = '' : $sep = ' | '; $out .= "<span class='$action'>$link$sep</span>"; } $out .= '</div>'; echo $out; break; } }
// can also use callback in register_post_type() instead register_post_type( 'event', array( ... 'register_meta_box_cb' => 'hhs_event_add_meta_boxes' ), ) ); function hhs_event_add_meta_boxes( $post ) { add_meta_box( 'hhs-event-date', 'Event Information', 'hhs_event_datepicker_meta_box', 'event', 'side', 'default' ); } function hhs_event_datepicker_meta_box( $post ) { $event_date = get_post_meta( $post->ID, 'hhs_event_date', true ); // mid-page enqueueing came in 3.3 wp_enqueue_script( 'jquery-ui-datepicker' ); wp_nonce_field( plugin_basename(__FILE__), 'hhs_eventmeta_nonce' ); ?> <script type="text/javascript"> jQuery(document).ready(function($) { $('.datepicker').datepicker({ dateFormat : 'yy-mm-dd' }); }); </script> <p><label for="hhs_event_date">Event Date</label><br /> <input type="text" class="datepicker" name="hhs_event_date" id="hhs_event_date"<?php if( $event_date ) echo ' value="' . esc_attr( $event_date) . '"'; ?> /></p> <?php }
add_filter( 'manage_edit-events_columns', 'hhs_event_edit_columns' ); add_action( 'manage_event_posts_custom_column', 'hhs_event_custom_columns' ); function hhs_event_edit_columns( $columns ) { // relabel title column $columns['title'] = 'Event Title'; // remove published date column unset( $columns['date'] ); // append new columns $columns['event-date'] = 'Event Date'; return $columns; } function hhs_event_custom_columns( $column ) { global $post; $event_date = get_post_meta( $post->ID, 'hhs_event_date', true ); switch ( $column ) { case 'event-date' : // escape as appropriate // the date shouldn't contain HTML echo esc_html( $event_date ); break; } }
add_filter( 'manage_edit-event_sortable_columns', 'hhs_event_sortable_columns' ); add_action( 'load-edit.php', 'hhs_event_edit_load' ); function hhs_event_sortable_columns( $columns ) { $columns['event-date'] = 'event-date'; return $columns; } function hhs_event_edit_load() { add_filter( 'request', 'hhs_event_sort' ); } function hhs_event_sort( $vars ) { // Check post type and for the orderby request if ( isset( $vars['post_type'] ) && 'event' == $vars['post_type'] && isset( $vars['orderby'] ) && 'event-date' == $vars['orderby'] ) { // Merge in with the rest of the query vars $vars = array_merge( $vars, array( 'meta_key' => 'hhs_event_date', 'orderby' => 'meta_value' ) ); } return $vars; }
Note: Only appears when a front page has already been selected.
add_action( 'add_meta_boxes', 'hhs_add_meta_boxes', 10, 2 ); function hhs_add_meta_boxes( $post_type, $post ) { $front_page = get_option( 'page_on_front' ); if ( $post->ID === $front_page ) { add_meta_box( 'hhs_front_page_meta', 'Home Page Content', 'hhs_front_page_meta', 'page', 'normal', 'high' ); // remove the editor remove_post_type_support( 'page', 'editor' ); } }
<?php add_action( 'post_submitbox_misc_actions', 'hhs_post_submitbox_misc_actions' ); function hhs_post_submitbox_misc_actions() { // restrict post type if needed if ( 'post' != get_post_type() ) return; wp_nonce_field( 'hhs_post_submitbox_nonce', plugin_basename(__FILE__) ); // the following inline styles may not be needed in 3.4 // see http://core.trac.wordpress.org/ticket/19604 ?> <div style="border-top: 1px solid #dfdfdf;"> <div class="misc-pub-section misc-pub-section-last" style="border-top: 1px solid #fff;"> <input type="checkbox" name="remove_claim_link" id="remove_claim_link" value="1" <?php checked( get_post_meta( get_the_ID(), 'remove_claim_link', true ) ); ?> /> <label for="remove_claim_link">Claimed</label> </div> </div> <div style="border-top: 1px solid #dfdfdf;"> <div class="misc-pub-section misc-pub-section-last" style="border-top: 1px solid #fff;"> <input type="checkbox" name="is_featured" id="is_featured" value="1" <?php checked( get_post_meta( get_the_ID(), 'is_featured', true ) ); ?> /> <label for="is_featured">Featured</label> </div> </div> <div style="border-top: 1px solid #dfdfdf;"> <div class="misc-pub-section misc-pub-section-last" style="border-top: 1px solid #fff;"> <input type="checkbox" name="is_premium" id="is_premium" value="1" <?php checked( get_post_meta( get_the_ID(), 'is_premium', true ) ); ?> /> <label for="is_premium">Premium</label> </div> </div> <?php }
// These are actual text, not placeholders - will save if not removed // Also: default_excerpt add_filter( 'default_title', 'hhs_event_default_title', 10, 2 ); function hhs_event_default_title( $title, $post ) { if ( 'event' == $post->post_type ) $title = 'Event Title'; return $title; } add_filter( 'default_content', 'hhs_event_default_content', 10, 2 ); function hhs_event_default_content( $content, $post ) { if ( 'event' == $post->post_type ) $content = 'Event description'; return $content; } // This is a placeholder add_filter( 'enter_title_here', 'hhs_event_enter_title_here', 10, 2 ); function hhs_event_enter_title_here( $placeholder, $post ) { if ( 'event' == $post->post_type ) $placeholder = 'Event Title'; return $placeholder; }
Slides online at
http://slides.helenhousandi.com/wcphx2012.html