Merge pull request 'fix(ui): render user level icon inline beside the name' (#328) from fix/level-icon-inline into main
Reviewed-on: CYL/wordpress-theme-aksrt#328
This commit is contained in:
@@ -162,6 +162,53 @@ main.container,
|
||||
}
|
||||
}
|
||||
|
||||
/* ========== User identity inline icons ==========
|
||||
* Level / medal icons ride inline to the right of a username. Centralized here
|
||||
* so every route (header panel, user center, author hero, single, comments,
|
||||
* widgets) renders the same compact badge instead of the raw intrinsic PNG size.
|
||||
*
|
||||
* Mirrors zibll `.img-icon { height: 1.1em; display: inline-block; vertical-align: -.15em }`
|
||||
* — sizes to the surrounding line height, never dominates the row. Localized
|
||||
* exceptions (UC level hero, admin column) override `height` per context.
|
||||
*/
|
||||
.aksrt-user-level-icon,
|
||||
.aksrt-identity-medal {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
height: 1.1em;
|
||||
max-width: 6em;
|
||||
object-fit: contain;
|
||||
vertical-align: -.15em;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
/* Comment context: a touch smaller to fit the 14px author line. */
|
||||
.aksrt-identity-medal--comment,
|
||||
.aksrt-user-level-icon--comment {
|
||||
height: 1em;
|
||||
vertical-align: -.12em;
|
||||
}
|
||||
|
||||
/* No-wrap inline name rows — keep the level icon on the same line as the name.
|
||||
* The non-standard <name> element (zibll compat) plus .user-name / author-hero /
|
||||
* uc-header name rows must not flex-wrap, or the badge drops to a new line.
|
||||
* The comment header may still wrap (avatar + name + like can overflow on
|
||||
* narrow viewports), so it keeps flex-wrap but the inner <name> never does. */
|
||||
.article-avatar name,
|
||||
.article-avatar .name,
|
||||
.user-name,
|
||||
.aksrt-author-hero__name,
|
||||
.uc-header__name,
|
||||
.aksrt-header-badges {
|
||||
flex-wrap: nowrap;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.aksrt-author-hero__name,
|
||||
.uc-header__name {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
/* ========== 通用空状态 ========== */
|
||||
.no-results {
|
||||
padding: 48px 20px;
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
.comment-header .author-box { display: flex; align-items: center; gap: 8px; width: 100%; }
|
||||
.comment-header .author-box name,
|
||||
.comment-header .author-box .flex1 { flex: 1; min-width: 0; }
|
||||
/* Keep name + level badge on one line; clamp the name so the badge never wraps. */
|
||||
.comment-header .author-box name { flex-wrap: nowrap; }
|
||||
.comment-header .author-box .aksrt-comment__author { max-width: 14em; }
|
||||
.comment-header .aksrt-comment__like,
|
||||
.comment-header .action-comment-like {
|
||||
margin-left: auto; display: inline-flex; align-items: center; gap: 4px;
|
||||
|
||||
@@ -754,15 +754,16 @@ body.dark-theme .comment-login-prompt__inner {
|
||||
.medal-icon.img-icon,
|
||||
.aksrt-identity-medal {
|
||||
display: inline-block;
|
||||
width: 1.35em;
|
||||
height: 1.35em;
|
||||
width: auto;
|
||||
height: 1.1em;
|
||||
max-width: 6em;
|
||||
object-fit: contain;
|
||||
vertical-align: middle;
|
||||
vertical-align: -.15em;
|
||||
margin-left: 4px;
|
||||
}
|
||||
.aksrt-identity-medal--comment {
|
||||
width: 1.15em;
|
||||
height: 1.15em;
|
||||
width: auto;
|
||||
height: 1em;
|
||||
}
|
||||
.aksrt-identity-medal.is-wear {
|
||||
outline: 1px solid rgba(245, 158, 11, 0.45);
|
||||
@@ -782,3 +783,9 @@ body.dark-theme .comment-login-prompt__inner {
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
/* Inline name + level badge stay on one line; only the outer author-box wraps. */
|
||||
.aksrt-comment__header name,
|
||||
.aksrt-comment__header .author-box > name {
|
||||
flex-wrap: nowrap;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@@ -210,6 +210,32 @@
|
||||
flex-wrap: wrap;
|
||||
gap: 4px;
|
||||
}
|
||||
/* Inline name + level badge in the dropdown profile row — one line, no wrap. */
|
||||
.sub-user-box .user-right > .flex1 {
|
||||
min-width: 0;
|
||||
}
|
||||
.sub-user-box .user-right b {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
flex-wrap: nowrap;
|
||||
white-space: nowrap;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
.sub-user-box .user-right b .display-name {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
min-width: 0;
|
||||
max-width: 100%;
|
||||
}
|
||||
.sub-user-box .user-right .aksrt-user-level-icon,
|
||||
.sub-user-box .user-right .aksrt-identity-medal {
|
||||
height: 1em;
|
||||
vertical-align: -.12em;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
/* User dropdown light-theme text contrast */
|
||||
.user-dropdown.sub-user-box,
|
||||
|
||||
@@ -640,7 +640,7 @@ html.dark .post-drop-meta__item:hover {
|
||||
.user-card.author .user-avatar { display: flex; justify-content: center; }
|
||||
.user-card.author .user-avatar .avatar,
|
||||
.user-card.author .user-avatar img { width: 80px; height: 80px; border-radius: 50%; object-fit: cover; }
|
||||
.user-card.author .user-name { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 4px; }
|
||||
.user-card.author .user-name { display: flex; flex-wrap: nowrap; align-items: center; justify-content: center; gap: 4px; }
|
||||
.user-card.author .user-name .display-name { font-weight: 700; color: var(--key-color, inherit); }
|
||||
.user-card.author .user-desc { text-align: center; }
|
||||
.user-card.author .user-btns { text-align: center; }
|
||||
|
||||
@@ -277,7 +277,7 @@
|
||||
}
|
||||
.article-avatar name.flex {
|
||||
gap: 4px;
|
||||
flex-wrap: wrap;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
.article-avatar .aksrt-vip-badge,
|
||||
.article-avatar .aksrt-identity-chip {
|
||||
@@ -286,11 +286,13 @@
|
||||
vertical-align: middle;
|
||||
}
|
||||
.article-avatar .medal-icon.img-icon,
|
||||
.article-avatar .aksrt-identity-medal {
|
||||
width: 1.4em;
|
||||
height: 1.4em;
|
||||
.article-avatar .aksrt-identity-medal,
|
||||
.article-avatar .aksrt-user-level-icon {
|
||||
width: auto;
|
||||
height: 1.2em;
|
||||
max-width: 6em;
|
||||
object-fit: contain;
|
||||
vertical-align: middle;
|
||||
vertical-align: -.15em;
|
||||
margin-left: 4px;
|
||||
}
|
||||
.article-avatar .display-name {
|
||||
|
||||
@@ -535,14 +535,7 @@
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.aksrt-user-level-icon {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
height: 1.15em;
|
||||
max-width: 6em;
|
||||
object-fit: contain;
|
||||
vertical-align: -.18em;
|
||||
}
|
||||
/* Level icon base sizing is centralized in assets/css/frontend/base.css. */
|
||||
|
||||
/* 用户中心 layout 间距;双栏 / sticky 见 user-center/shell.css(body.aksrt-user-center)。 */
|
||||
.aksrt-profile__layout {
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
/* User level — dedicated center panel */
|
||||
.aksrt-user-level-icon {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
height: 1.35em;
|
||||
max-width: 6em;
|
||||
object-fit: contain;
|
||||
vertical-align: -.2em;
|
||||
}
|
||||
/* User level — dedicated center panel.
|
||||
* Base level icon sizing lives in assets/css/frontend/base.css (1.1em, inline).
|
||||
* This file keeps only the UC-level-specific hero/road overrides + admin column. */
|
||||
.aksrt-user-level-icon--admin { height: 22px; }
|
||||
|
||||
.uc-level-page { display: grid; gap: 16px; }
|
||||
|
||||
@@ -91,8 +91,8 @@ if (!function_exists('aksrt_header_user_badges_row')) :
|
||||
if ($user_id <= 0 || !function_exists('aksrt_render_user_identity_chips')) {
|
||||
return '';
|
||||
}
|
||||
// VIP already shown next to display name in the header profile row.
|
||||
$chips = aksrt_render_user_identity_chips($user_id, 'card', ['include_vip' => false]);
|
||||
// VIP + level already shown next to display name in the header profile row.
|
||||
$chips = aksrt_render_user_identity_chips($user_id, 'card', ['include_vip' => false, 'skip_level' => true]);
|
||||
if ($chips === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ if (!function_exists('aksrt_render_user_identity_chips')) {
|
||||
* Optional. Additional options.
|
||||
*
|
||||
* @type bool $include_vip Whether to prepend VIP badge. Default true.
|
||||
* @type bool $skip_level Whether to omit the level chip (rendered inline elsewhere). Default false.
|
||||
* }
|
||||
*/
|
||||
function aksrt_render_user_identity_chips(int $user_id, string $context = 'author', array $args = []): string {
|
||||
@@ -43,6 +44,7 @@ if (!function_exists('aksrt_render_user_identity_chips')) {
|
||||
}
|
||||
$args = wp_parse_args($args, [
|
||||
'include_vip' => true,
|
||||
'skip_level' => false,
|
||||
]);
|
||||
$html = '';
|
||||
if (!empty($args['include_vip']) && function_exists('aksrt_render_vip_badge')) {
|
||||
@@ -63,12 +65,16 @@ if (!function_exists('aksrt_render_user_identity_chips')) {
|
||||
if ($label === '') {
|
||||
continue;
|
||||
}
|
||||
$type = sanitize_html_class((string) ($signal['type'] ?? ''));
|
||||
// Level is rendered inline next to the name by the caller; skip it here.
|
||||
if (!empty($args['skip_level']) && $type === 'level') {
|
||||
continue;
|
||||
}
|
||||
$tone = sanitize_html_class((string) ($signal['tone'] ?? 'info'));
|
||||
$icon = sanitize_html_class((string) ($signal['icon'] ?? 'check'));
|
||||
$icon_url = esc_url((string) ($signal['icon_url'] ?? ''));
|
||||
$title = (string) ($signal['title'] ?? $label);
|
||||
$is_wear = !empty($signal['wear']);
|
||||
$type = sanitize_html_class((string) ($signal['type'] ?? ''));
|
||||
|
||||
// Image medal when dictionary provides icon_url.
|
||||
if ($icon_url !== '') {
|
||||
@@ -162,7 +168,8 @@ if (!function_exists('aksrt_get_user_name')) {
|
||||
if ($icon_url !== '') {
|
||||
$level_html = '<img class="aksrt-user-level-icon img-icon ml3" src="' . $icon_url . '" alt="' . esc_attr($label) . '" title="' . esc_attr($title) . '" loading="lazy" decoding="async" />';
|
||||
} else {
|
||||
$level_html = '<span class="badg badg-sm ml3 aksrt-identity-chip aksrt-identity-chip--info" title="' . esc_attr($title) . '"><i class="fa fa-layer-group" aria-hidden="true"></i> ' . esc_html($label) . '</span>';
|
||||
// Text fallback mirrors zibll LV badge: small pill, never oversized.
|
||||
$level_html = '<span class="badg badg-sm ml3 aksrt-user-level-badge" title="' . esc_attr($title) . '">' . esc_html($label) . '</span>';
|
||||
}
|
||||
} elseif ($type === 'badge' && !empty($args['medal']) && $medal_html === '' && !empty($signal['wear'])) {
|
||||
if ($icon_url !== '') {
|
||||
|
||||
@@ -151,6 +151,10 @@ if (!function_exists('aksrt_header_user_box_html')) :
|
||||
$avatar = get_avatar($user_id, 44, '', esc_attr($display_name), ['loading' => 'lazy']);
|
||||
$desc = (string) ($ctx['user_desc'] ?? '');
|
||||
$vip_badge = function_exists('aksrt_render_vip_badge') ? aksrt_render_vip_badge($user_id, 'sm') : '';
|
||||
// Level icon rides inline to the right of the display name (zibll parity).
|
||||
$level_badge = (class_exists('\AKSRT\User\Level') && method_exists('\AKSRT\User\Level', 'get_badge_html'))
|
||||
? \AKSRT\User\Level::get_badge_html($user_id, 'aksrt-user-level-icon--header')
|
||||
: '';
|
||||
$payvip = function_exists('aksrt_header_payvip_bar') ? aksrt_header_payvip_bar($user_id) : '';
|
||||
// nav_user_pay_vip gate: empty payvip when switch off for non-VIP CTA only — helper already handles VIP status.
|
||||
if (empty($ctx['nav_user_pay_vip']) && $payvip !== '' && strpos($payvip, 'is-vip') === false) {
|
||||
@@ -239,7 +243,7 @@ if (!function_exists('aksrt_header_user_box_html')) :
|
||||
$con .= $avatar;
|
||||
$con .= '<div class="user-right flex flex1 ac jsb ml10">';
|
||||
$con .= '<div class="flex1" style="max-width: calc(100% - 40px);"><b>'
|
||||
. esc_html($display_name) . $vip_badge
|
||||
. '<span class="display-name text-ellipsis">' . esc_html($display_name) . '</span>' . $vip_badge . $level_badge
|
||||
. '</b><div class="px12 muted-2-color text-ellipsis">' . esc_html($desc) . '</div></div>';
|
||||
$con .= '</div>';
|
||||
$con .= $msg_icon;
|
||||
|
||||
@@ -41,6 +41,10 @@ extract($context, EXTR_SKIP); // phpcs:ignore WordPress.PHP.DontExtract.extract_
|
||||
if ($vip_badge) {
|
||||
echo $vip_badge; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
// Level icon inline to the right of the name (zibll parity).
|
||||
if (class_exists('\AKSRT\User\Level') && method_exists('\AKSRT\User\Level', 'get_badge_html')) {
|
||||
echo \AKSRT\User\Level::get_badge_html((int) $user_id); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
?>
|
||||
</h1>
|
||||
<?php if ($target_user->description) : ?>
|
||||
@@ -49,6 +53,12 @@ extract($context, EXTR_SKIP); // phpcs:ignore WordPress.PHP.DontExtract.extract_
|
||||
<?php if (!empty($profile_signals)) : ?>
|
||||
<div class="aksrt-identity-chips">
|
||||
<?php foreach ($profile_signals as $signal) : ?>
|
||||
<?php
|
||||
// Level is rendered inline next to the name above; skip it here.
|
||||
if ((string) ($signal['type'] ?? '') === 'level') {
|
||||
continue;
|
||||
}
|
||||
?>
|
||||
<span class="aksrt-identity-chip aksrt-identity-chip--<?php echo esc_attr($signal['tone']); ?>">
|
||||
<i class="fas fa-<?php echo esc_attr($signal['icon']); ?>" aria-hidden="true"></i>
|
||||
<span><?php echo esc_html($signal['label']); ?></span>
|
||||
|
||||
@@ -98,6 +98,10 @@ $pm_url = ($pm_enabled && $messages_url !== '')
|
||||
if ($vip_badge) {
|
||||
echo $vip_badge; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
// Level icon inline to the right of the name (zibll parity).
|
||||
if (class_exists('\AKSRT\User\Level') && method_exists('\AKSRT\User\Level', 'get_badge_html')) {
|
||||
echo \AKSRT\User\Level::get_badge_html($user_id); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
?>
|
||||
</h1>
|
||||
<?php endif; ?>
|
||||
@@ -124,7 +128,10 @@ $pm_url = ($pm_enabled && $messages_url !== '')
|
||||
<?php echo $city_badge; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
<?php endif; ?>
|
||||
<?php if (function_exists('aksrt_render_user_identity_chips')) : ?>
|
||||
<?php echo aksrt_render_user_identity_chips($user_id, 'author', ['include_vip' => false]); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
|
||||
<?php
|
||||
// Level already rendered inline next to the name above; skip it here.
|
||||
echo aksrt_render_user_identity_chips($user_id, 'author', ['include_vip' => false, 'skip_level' => true]); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
Reference in New Issue
Block a user