Skip to content

Comments

feat: badge design qa#1677

Open
gaspergrom wants to merge 3 commits intomainfrom
fix/badge-design-qa
Open

feat: badge design qa#1677
gaspergrom wants to merge 3 commits intomainfrom
fix/badge-design-qa

Conversation

@gaspergrom
Copy link
Collaborator

No description provided.

Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
@gaspergrom gaspergrom requested a review from emlimlf February 15, 2026 22:10
@gaspergrom gaspergrom self-assigned this Feb 15, 2026
Copilot AI review requested due to automatic review settings February 15, 2026 22:10
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the badges UI to match the “badge design QA” direction by refining badge presentation (grid/layout), share affordances, and adding small visual effects/animations, along with a popover click-outside behavior tweak.

Changes:

  • Adjust popover click-outside handling to use capture-phase document listeners.
  • Improve badges share UI with tooltips and refine rank label presentation.
  • Add badge shine utility styles and apply shine/animation effects to badge imagery and popovers.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
frontend/app/components/uikit/popover/popover.vue Changes document click listener registration to capture phase for click-outside behavior.
frontend/app/components/modules/badges/components/share/badges-share-socials.vue Wraps share icon buttons in tooltips and adds tooltip import.
frontend/app/components/modules/badges/components/share/badges-share-preview.vue Conditionally adds “Rank:” prefix based on computed layout heuristic.
frontend/app/components/modules/badges/components/download/card-download-preview.vue Always displays “Rank: #…” label in download preview.
frontend/app/components/modules/badges/components/badges.vue Switches badges list layout from flex to grid with explicit column sizing.
frontend/app/components/modules/badges/components/badges-popover.vue Adds popover entrance animation and applies badge shine wrapper to the image.
frontend/app/components/modules/badges/components/badges-item.vue Applies badge shine wrapper to badge thumbnails.
frontend/app/assets/styles/utils/index.scss Registers the new badge shine utility stylesheet.
frontend/app/assets/styles/utils/_badge-shine.scss Introduces the .badge-shine animated overlay utility.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 78 to 81
const badgeImage = computed(() => props.badge.config.badgeImages[props.badge.tier]);
const showRankLabel = computed(
() => props.badge.config.title.length + String(props.badge.rank).length <= 22 || props.badge.rank < 1000,
);
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

showRankLabel relies on a hard-coded character-count threshold (22) and string lengths, which is brittle (font differences/localization) and hard to reason about later. Consider extracting the threshold into a named constant with a short comment, or using a layout/CSS-based approach (e.g., nowrap/ellipsis) to decide when to show the "Rank:" prefix.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better to use ellipsis here rather than the fix character length check.

Comment on lines 25 to 49
@@ -43,7 +44,8 @@ SPDX-License-Identifier: MIT
<!-- Badges Grid -->
<div
v-else
class="flex flex-wrap items-start gap-x-4 gap-y-2"
class="grid gap-x-4 gap-y-2 items-start"
style="grid-template-columns: repeat(auto-fill, minmax(52px, 1fr))"
>
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The grid-template-columns: repeat(auto-fill, minmax(52px, 1fr)) inline style is duplicated for loading vs. loaded states. Consider extracting this into a shared class/style binding (or a Tailwind arbitrary value if supported) to avoid divergence and keep the template easier to maintain.

Copilot uses AI. Check for mistakes.
Comment on lines 11 to 17
<div class="badge-shine relative overflow-hidden size-20">
<img
:src="badgeImage"
:alt="badge.config.title"
class="size-20"
/>
</div>
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.badge-shine already sets position: relative and overflow: hidden, so adding relative overflow-hidden here is redundant. Consider removing the extra utility classes so the source of these behaviors stays in one place.

Copilot uses AI. Check for mistakes.
Comment on lines 7 to 16
&::after {
content: '';
top: 0;
transform: translateX(100%);
width: 100%;
height: 100%;
position: absolute;
z-index: 1;
animation: badge-shine 5s infinite;
background: linear-gradient(
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ::after overlay is position: absolute with top: 0 but no left/right (or inset). That can leave its horizontal position dependent on the static position and can misalign the shine overlay. Set left: 0 (or inset: 0) to ensure it consistently covers the badge.

Copilot uses AI. Check for mistakes.
Comment on lines 118 to 129
const openPopover = async () => {
isVisible.value = true;
if (props.triggerEvent === 'click') {
document.addEventListener('click', handleClickOutside);
document.addEventListener('click', handleClickOutside, true);
}
};

const closePopover = () => {
isVisible.value = false;
if (props.triggerEvent === 'click') {
document.removeEventListener('click', handleClickOutside);
document.removeEventListener('click', handleClickOutside, true);
}
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The document click listener is only added/removed via openPopover()/closePopover(). If visibility is controlled externally (v-model / prop updates) or the component unmounts while open, the listener can be left attached and click-outside handling can be out of sync. Consider managing the listener in a watcher/onBeforeUnmount based on isVisible (and always removing it on unmount) so it stays consistent regardless of how visibility changes.

Copilot uses AI. Check for mistakes.
Comment on lines 8 to 13
<lfx-tooltip content="X/Twitter">
<button
type="button"
class="size-9 rounded-full bg-black flex items-center justify-center hover:opacity-80 transition-opacity"
@click="shareToX"
>
Copy link

Copilot AI Feb 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are icon-only buttons. Wrapping them in a tooltip doesn’t provide an accessible name for screen readers; please add an aria-label (or visually hidden text) to each button so the share targets are announced correctly.

Copilot uses AI. Check for mistakes.
Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
Copy link
Collaborator

@emlimlf emlimlf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is one minor feedback from copilot, but it would be better for future maintainability.

Comment on lines 78 to 81
const badgeImage = computed(() => props.badge.config.badgeImages[props.badge.tier]);
const showRankLabel = computed(
() => props.badge.config.title.length + String(props.badge.rank).length <= 22 || props.badge.rank < 1000,
);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is better to use ellipsis here rather than the fix character length check.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants