discourse/app/assets/javascripts/admin/addon/components/admin-section-landing-item.gjs
Kris 42b3148f7b
UX: don't highlight admin content on hover if it isn't clickable (#34332)
This resolves a number of cases where we were highlighting content on
hover that isn't clickable.


Common table example

Before:
<img width="1726" height="548" alt="image"
src="https://github.com/user-attachments/assets/24635052-0efd-4c02-b75b-dc3901acd799"
/>


After:
<img width="1744" height="550" alt="image"
src="https://github.com/user-attachments/assets/73837bff-532b-48ec-99de-2e579221eccb"
/>




Reports are a case where the box *should* be clickable, so I kept the
hover effect and made the box clickable via changes to
`admin-section-landing-item`...

Before: 
<img width="1710" height="838" alt="image"
src="https://github.com/user-attachments/assets/a8bc8f67-5f1f-44c1-8de7-e64c1a60fd49"
/>


After (removed the blue because the headings aren't actually links
anymore, the whole box is):
<img width="1732" height="922" alt="image"
src="https://github.com/user-attachments/assets/2fb5b63a-1cdc-4fc9-906a-c343c26cd025"
/>

In cases where these boxes have buttons, the inner title (if linked) and
buttons are clickable, not the box...

<img width="400" alt="image"
src="https://github.com/user-attachments/assets/3bf04522-179b-49e6-ae0a-f5d3714b94ec"
/>
2025-08-14 15:59:29 -04:00

105 lines
3.2 KiB
Text
Vendored

import Component from "@glimmer/component";
import { hash } from "@ember/helper";
import { LinkTo } from "@ember/routing";
import { and } from "truth-helpers";
import {
DangerButton,
DefaultButton,
PrimaryButton,
} from "discourse/components/d-page-action-button";
import concatClass from "discourse/helpers/concat-class";
import icon from "discourse/helpers/d-icon";
import element from "discourse/helpers/element";
import { i18n } from "discourse-i18n";
export default class AdminSectionLandingItem extends Component {
wrapperElement = (hasButtons) => {
const makeClickable = this.args.titleRoute && !hasButtons;
return makeClickable ? LinkTo : element("div");
};
get title() {
if (this.args.titleLabelTranslated) {
return this.args.titleLabelTranslated;
} else if (this.args.titleLabel) {
return i18n(this.args.titleLabel);
}
}
get description() {
if (this.args.descriptionLabelTranslated) {
return this.args.descriptionLabelTranslated;
} else if (this.args.descriptionLabel) {
return i18n(this.args.descriptionLabel);
}
}
get tagline() {
if (this.args.taglineLabelTranslated) {
return this.args.taglineLabelTranslated;
} else if (this.args.taglineLabel) {
return i18n(this.args.taglineLabel);
}
}
<template>
{{#let (has-block "buttons") as |hasButtons|}}
{{! When there are no nested buttons, the entire component is a link }}
{{#let (this.wrapperElement hasButtons) as |WrapperComponent|}}
<WrapperComponent
@route={{@titleRoute}}
@model={{@titleRouteModel}}
class={{concatClass
"admin-section-landing-item"
(if @icon "--has-icon")
}}
...attributes
>
{{#if @imageUrl}}
<img class="admin-section-landing-item__image" src={{@imageUrl}} />
{{/if}}
{{#if @icon}}
<div class="admin-section-landing-item__icon">
{{icon @icon}}
</div>
{{/if}}
<div class="admin-section-landing-item__content">
{{#if this.tagline}}
<h4
class="admin-section-landing-item__tagline"
>{{this.tagline}}</h4>
{{/if}}
{{#if (and @titleRoute hasButtons)}}
{{! Individual title is a link when buttons exist}}
<LinkTo @route={{@titleRoute}} @model={{@titleRouteModel}}>
<h3
class="admin-section-landing-item__title"
>{{this.title}}</h3>
</LinkTo>
{{else}}
<h3 class="admin-section-landing-item__title">{{this.title}}</h3>
{{/if}}
<p class="admin-section-landing-item__description">
{{this.description}}
</p>
</div>
{{#if hasButtons}}
<div class="admin-section-landing-item__buttons">
{{yield
(hash
Primary=PrimaryButton
Default=DefaultButton
Danger=DangerButton
)
to="buttons"
}}
</div>
{{/if}}
</WrapperComponent>
{{/let}}
{{/let}}
</template>
}