-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Taxonomy: Add UI to Category page to indicate default category #10831
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: trunk
Are you sure you want to change the base?
Conversation
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
|
Test failures appear unrelated — CI tooling tripping. |
Shows the default category first in the list and adds a "Default" label next to its name in the categories admin screen. See https://core.trac.wordpress.org/ticket/26268
829cb2c to
102b5bc
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR updates the Terms list table in the admin to visually surface the default term, particularly for post categories, by pinning it to the top of the list and labeling it as “Default.”
Changes:
- In
display_rows_or_placeholder(), resolves the default category for thecategorytaxonomy and renders it before the rest of the terms, while skipping it later in the non-hierarchical loop. - In
_rows(), introduces logic to detect the default category ID and skip it during hierarchical recursion so it is not duplicated when already rendered first. - In
column_name(), adds a “Default” label (with ataxonomy-default-labelspan) next to the term name when the row’s term matches the configured default term option.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if ( $default_category ) { | ||
| $this->single_row( $default_category ); | ||
| } | ||
|
|
||
| /* | ||
| * Some funky recursion to get the job done (paging & parents mainly) is contained within. | ||
| * Skip it for non-hierarchical taxonomies for performance sake. | ||
| */ | ||
| $this->_rows( $taxonomy, $this->items, $children, $offset, $number, $count ); | ||
| } else { | ||
| if ( $default_category ) { | ||
| $this->single_row( $default_category ); | ||
| } | ||
|
|
||
| foreach ( $this->items as $term ) { | ||
| if ( $default_category && $default_category->term_id === $term->term_id ) { | ||
| continue; | ||
| } | ||
| $this->single_row( $term ); |
Copilot
AI
Feb 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prepending the default category with $this->single_row( $default_category ); here without updating $count or otherwise integrating it into the paging logic means the "per page" limit is effectively exceeded: hierarchical lists will show number rows from _rows() plus this extra row, and in the non‑hierarchical branch the default term can appear on every page even when it is not part of the current slice of $this->items. This changes the semantics of pagination (screen options say N items per page but the table often renders N+1), and duplicates the default term across pages. If the goal is just to surface the default category at the top, consider only rendering it when $offset is 0 (first page) and/or adjusting the paging counters so the extra row is accounted for instead of being "outside" the pagination logic.
| $default_term = get_option( 'default_' . $taxonomy ); | ||
| $default_term_label = ''; | ||
| if ( $tag->term_id == $default_term ) { | ||
| $default_term_label = ' — <span class="taxonomy-default-label">' . __( 'Default' ) . '</span>'; | ||
| } |
Copilot
AI
Feb 1, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using get_option( 'default_' . $taxonomy ) here will work for core taxonomies like category and link_category, but it will not pick up default terms registered via register_taxonomy( ... 'default_term' => ... ), which are stored under default_term_{$taxonomy} (see taxonomy.php:537-557 and post.php:5333-5337). If the intent is for the "Default" label to apply to all taxonomies that support default terms (not only categories/link categories), consider mirroring the pattern in map_meta_cap() by checking both default_{$taxonomy} and default_term_{$taxonomy} so the UI stays consistent with how default terms are modeled elsewhere.
|
One thing seems to be missing in the user interface and that is discovery for how to change the default category. Should there be a link to the Writing Settings screen, linking to the specific field on that screen? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.
I'm open to that. The main intent was to simply explain versus the user needing to infer why that category is acting differently in the list. |
- Only display pinned default category on first page to maintain correct per-page count - Pass default_category_id as parameter to _rows() to avoid repeated get_option() calls during recursion
- Add "Change Default" link to row actions for the default category - Add id attribute to Writing Settings default category row for fragment linking
|
Oh, I like that. I don't think it would be redundant. "The default category can be renamed or changed, but not deleted" or something like that with "renamed" going to the edit category page for that term and "changed" going to the settings page seems lightweight and direct. Going to try that. I'll leave the row action too. Just like us, I thought about the category in the table and you thought about the text at the bottom (which I didn't think about at all), this is an area that I'd rather just help people find what they need no matter where their focus is, especially if it can be done in a relatively "invisible" way if you're thinking about other things. |
Update the help text below the Categories list table to include links for renaming the default category and choosing a different default.
|
Used language similar to elsewhere in Core (src/wp-admin/user-edit.php:63 - |
westonruter
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor point, but I think the $default_category_id variable can be eliminated in favor of just $default_category. And I think it would be slightly better to use null when it isn't WP_Term (but just a personal preference).
Co-authored-by: Weston Ruter <westonruter@gmail.com>
|
This is looking really good. I asked Gemini to provide another review and I think it has some valid points: I have reviewed the changes and identified a functional regression regarding hierarchical display, along with some code style improvements. Review of
|
… check. Use strict comparison with integer casting for consistency with other default term checks in the same file. Also add a description to the $default_category_id parameter in the _rows() method docblock.
Keep the default category in its natural position within the hierarchy rather than pinning it to the top. This avoids complexity with child categories appearing detached from their parent when the default category has subcategories. The default category is still clearly indicated via the "Default" label and "Change Default" row action. The explanatory text below the categories table also describes the default category behavior.
|
Nice find from Gemini on the children issue. If we keep the pinning and iterate through children, we'd have a few options—none great:
Rather than adding complexity to handle this, I've removed the pinning entirely. The default category now stays in its natural position in the hierarchy. The "Default" label and "Change Default" row action still clearly identify it, and the text below the table already explains the default category behavior. I feel like we might be getting into space where if we try to be too clever, we're making things harder. That said, @westonruter—if you think an alternative approach works better here, I'm game to go with that instead. |
|
@kraftbj skipping the pinning of the default category makes sense to me. Does the post list table have any facility for showing sub-posts under a post marked as sticky? I don't believe so, since sticky posts are only relevant to chronological posts not hierarchical ones (e.g. pages). I agree with your conclusion. In any case, the footer has a persistent mention of what the default category is:
So even when it isn't displayed on the first page, it will still be discoverable. |
| '<strong>' . apply_filters( 'the_category', get_cat_name( get_option( 'default_category' ) ), '', '' ) . '</strong>' | ||
| '<strong>' . apply_filters( 'the_category', get_cat_name( $default_category_id ), '', '' ) . '</strong>', | ||
| esc_url( get_edit_term_link( $default_category_id, 'category' ) ), | ||
| esc_url( admin_url( 'options-writing.php#default_category' ) ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, if the user cannot manage_options then this URL won't be accessible. So maybe the but it can be <a href="%2$s">renamed</a> or you can choose a <a href="%3$s">different default category</a> should be conditionally printed after the previous string only if the user can do so. This also goes for whether get_edit_term_link( $default_category_id, 'category' ) returns null, indicating that the user doesn't have the ability to modify a the term. I can imagine this being a common scenario actually, where a site may want to allow Editor role users to create and modify categories, except for the default category, leaving that only for the admin to manage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume for translations, I should either break it into two sentences or have two complete sentences as the options. I don't know but I figure a language might not like assuming a dependent clause being forced to follow the primary clause (not to mention punctuation).
On mobile but I'll update that.
I appreciate your diligence in these reviews! This is a very old issue and was a very old patch that we're pulling out of the time capsule!
This comment was marked as duplicate.
This comment was marked as duplicate.
Sorry, something went wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's right. Having a dependent clause as a separate translation string wouldn't work. So this would be one string:
Deleting a category does not delete the posts in that category. Instead, posts that were only assigned to the deleted category are set to the default category Uncategorized. The default category cannot be deleted.
And then, if the user can manage_options and can edit the term, add another sentence:
It can be renamed or you can choose a different default category.
Or if they just have term editing capability:
It can be renamed.
And then if they just have manage_options (which would surely include the previous capability, but there's no guarantees in WordPress!):
You can choose a different default category.
Might be something to get advice from Polyglots on.
| ); | ||
| } | ||
|
|
||
| if ( 'category' === $taxonomy && (int) get_option( 'default_category' ) === $tag->term_id ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| if ( 'category' === $taxonomy && (int) get_option( 'default_category' ) === $tag->term_id ) { | |
| if ( 'category' === $taxonomy && (int) get_option( 'default_category' ) === $tag->term_id && current_user_can( 'manage_options' ) ) { |



This patch adds UI to the Categories admin page to clearly indicate which category is the default:
This helps users quickly identify and understand the default category behavior, as discussed in the Trac ticket.
Trac ticket: https://core.trac.wordpress.org/ticket/26268
Before:

After:

This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.