UX: update gist toggle styles (#926)
This commit is contained in:
parent
530a795d43
commit
a9afa04329
|
@ -4,35 +4,43 @@ import { action } from "@ember/object";
|
|||
import { service } from "@ember/service";
|
||||
import DButton from "discourse/components/d-button";
|
||||
import DropdownMenu from "discourse/components/dropdown-menu";
|
||||
import bodyClass from "discourse/helpers/body-class";
|
||||
import icon from "discourse-common/helpers/d-icon";
|
||||
import i18n from "discourse-common/helpers/i18n";
|
||||
import DMenu from "float-kit/components/d-menu";
|
||||
import eq from "truth-helpers/helpers/eq";
|
||||
|
||||
export default class AiGistToggle extends Component {
|
||||
@service router;
|
||||
@service gistPreference;
|
||||
|
||||
get shouldShow() {
|
||||
return this.router.currentRoute.attributes?.list?.topics?.some(
|
||||
(topic) => topic.ai_topic_gist
|
||||
);
|
||||
}
|
||||
@service gists;
|
||||
|
||||
get buttons() {
|
||||
return [
|
||||
{
|
||||
id: "gists_enabled",
|
||||
label: "discourse_ai.summarization.gists_enabled_long",
|
||||
icon: "discourse-sparkles",
|
||||
id: "table",
|
||||
label: "discourse_ai.summarization.topic_list_layout.button.compact",
|
||||
icon: "discourse-table",
|
||||
},
|
||||
{
|
||||
id: "gists_disabled",
|
||||
label: "discourse_ai.summarization.gists_disabled",
|
||||
icon: "far-eye-slash",
|
||||
id: "table-ai",
|
||||
label: "discourse_ai.summarization.topic_list_layout.button.expanded",
|
||||
icon: "discourse-table-sparkles",
|
||||
description:
|
||||
"discourse_ai.summarization.topic_list_layout.button.expanded_description",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
get selectedOptionId() {
|
||||
return this.gists.get("preference");
|
||||
}
|
||||
|
||||
get currentButton() {
|
||||
const buttonPreference = this.buttons.find(
|
||||
(button) => button.id === this.selectedOptionId
|
||||
);
|
||||
return buttonPreference || this.buttons[0];
|
||||
}
|
||||
|
||||
@action
|
||||
onRegisterApi(api) {
|
||||
this.dMenu = api;
|
||||
|
@ -40,29 +48,22 @@ export default class AiGistToggle extends Component {
|
|||
|
||||
@action
|
||||
onSelect(optionId) {
|
||||
this.gistPreference.setPreference(optionId);
|
||||
this.gists.setPreference(optionId);
|
||||
this.dMenu.close();
|
||||
}
|
||||
|
||||
<template>
|
||||
{{#if this.shouldShow}}
|
||||
|
||||
{{#if this.gists.shouldShow}}
|
||||
{{bodyClass (concat "topic-list-layout-" this.gists.preference)}}
|
||||
<DMenu
|
||||
@modalForMobile={{true}}
|
||||
@autofocus={{true}}
|
||||
@identifier="ai-gists-dropdown"
|
||||
@identifier="topic-list-layout"
|
||||
@onRegisterApi={{this.onRegisterApi}}
|
||||
@triggerClass="btn-transparent"
|
||||
@triggerClass="btn-default btn-icon"
|
||||
>
|
||||
<:trigger>
|
||||
<span class="d-button-label">
|
||||
{{i18n
|
||||
(concat
|
||||
"discourse_ai.summarization." this.gistPreference.preference
|
||||
)
|
||||
}}
|
||||
</span>
|
||||
{{icon "angle-down"}}
|
||||
{{icon this.currentButton.icon}}
|
||||
</:trigger>
|
||||
<:content>
|
||||
<DropdownMenu as |dropdown|>
|
||||
|
@ -71,9 +72,17 @@ export default class AiGistToggle extends Component {
|
|||
<DButton
|
||||
@label={{button.label}}
|
||||
@icon={{button.icon}}
|
||||
class="btn-transparent"
|
||||
class="btn-transparent
|
||||
{{if button.description '--with-description'}}
|
||||
{{if (eq this.currentButton.id button.id) '--active'}}"
|
||||
@action={{fn this.onSelect button.id}}
|
||||
/>
|
||||
>
|
||||
{{#if button.description}}
|
||||
<div class="btn__description">
|
||||
{{i18n button.description}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</DButton>
|
||||
</dropdown.item>
|
||||
{{/each}}
|
||||
</DropdownMenu>
|
||||
|
|
|
@ -1,31 +1,30 @@
|
|||
import Component from "@glimmer/component";
|
||||
import { service } from "@ember/service";
|
||||
import bodyClass from "discourse/helpers/body-class";
|
||||
import { htmlSafe } from "@ember/template";
|
||||
import { emojiUnescape, sanitize } from "discourse/lib/text";
|
||||
|
||||
export default class AiTopicGist extends Component {
|
||||
@service router;
|
||||
@service gistPreference;
|
||||
@service gists;
|
||||
|
||||
get prefersGist() {
|
||||
return this.gistPreference.preference === "gists_enabled";
|
||||
get shouldShow() {
|
||||
return this.gists.preference === "table-ai" && this.gists.shouldShow;
|
||||
}
|
||||
|
||||
get showGist() {
|
||||
return (
|
||||
this.args.topic?.ai_topic_gist &&
|
||||
this.prefersGist &&
|
||||
!this.args.topic?.excerpt
|
||||
);
|
||||
get gistOrExcerpt() {
|
||||
const topic = this.args.topic;
|
||||
const gist = topic.get("ai_topic_gist");
|
||||
const excerpt = emojiUnescape(sanitize(topic.get("excerpt")));
|
||||
|
||||
return gist || excerpt;
|
||||
}
|
||||
|
||||
<template>
|
||||
{{#if this.showGist}}
|
||||
{{bodyClass "--topic-list-with-gist"}}
|
||||
<div class="ai-topic-gist">
|
||||
<div class="ai-topic-gist__text">
|
||||
{{@topic.ai_topic_gist}}
|
||||
</div>
|
||||
{{#if this.shouldShow}}
|
||||
{{#if this.gistOrExcerpt}}
|
||||
<div class="excerpt">
|
||||
<div>{{htmlSafe this.gistOrExcerpt}}</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</template>
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
import Component from "@glimmer/component";
|
||||
import { service } from "@ember/service";
|
||||
import AiGistToggle from "../../components/ai-gist-toggle";
|
||||
|
||||
export default class AiTopicGist extends Component {
|
||||
@service topicThumbnails; // avoid Topic Thumbnails theme component
|
||||
|
||||
get shouldShow() {
|
||||
return !this.topicThumbnails?.enabledForRoute;
|
||||
}
|
||||
|
||||
<template>
|
||||
<AiGistToggle />
|
||||
</template>
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
import Component from "@glimmer/component";
|
||||
import AiGistToggle from "../../components/ai-gist-toggle";
|
||||
|
||||
export default class AiTopicGistToggle extends Component {
|
||||
static shouldRender(outletArgs, helper) {
|
||||
const isMobileView = helper.site.mobileView;
|
||||
return isMobileView;
|
||||
}
|
||||
|
||||
<template>
|
||||
<AiGistToggle />
|
||||
</template>
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
import Component from "@glimmer/component";
|
||||
import AiGistToggle from "../../components/ai-gist-toggle";
|
||||
|
||||
export default class AiTopicGist extends Component {
|
||||
static shouldRender(outletArgs) {
|
||||
return (
|
||||
// "default" can be removed after the glimmer topic list is rolled out
|
||||
(outletArgs?.name === "default" || outletArgs?.name === "topic.title") &&
|
||||
!outletArgs.bulkSelectEnabled
|
||||
);
|
||||
}
|
||||
|
||||
<template>
|
||||
<AiGistToggle />
|
||||
</template>
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
import { tracked } from "@glimmer/tracking";
|
||||
import Service from "@ember/service";
|
||||
|
||||
export default class GistPreference extends Service {
|
||||
@tracked
|
||||
preference = localStorage.getItem("aiGistPreference") || "gists_disabled";
|
||||
|
||||
setPreference(value) {
|
||||
this.preference = value;
|
||||
localStorage.setItem("aiGistPreference", value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
import { tracked } from "@glimmer/tracking";
|
||||
import Service, { service } from "@ember/service";
|
||||
|
||||
export default class Gists extends Service {
|
||||
@service router;
|
||||
|
||||
@tracked preference = localStorage.getItem("topicListLayout");
|
||||
|
||||
get shouldShow() {
|
||||
const currentRoute = this.router.currentRoute.name;
|
||||
const isDiscovery = currentRoute.includes("discovery");
|
||||
const isNotCategories = !currentRoute.includes("categories");
|
||||
const gistsAvailable =
|
||||
this.router.currentRoute.attributes?.list?.topics?.some(
|
||||
(topic) => topic.ai_topic_gist
|
||||
);
|
||||
|
||||
return isDiscovery && isNotCategories && gistsAvailable;
|
||||
}
|
||||
|
||||
setPreference(value) {
|
||||
this.preference = value;
|
||||
localStorage.setItem("topicListLayout", value);
|
||||
|
||||
if (this.preference === "table-ai") {
|
||||
localStorage.setItem("aiPreferred", true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
.topic-list-layout-content {
|
||||
.btn.--with-description {
|
||||
display: grid;
|
||||
grid-template-areas: "icon title" "icon description";
|
||||
grid-template-columns: auto 1fr;
|
||||
text-align: left;
|
||||
.btn__description {
|
||||
grid-area: description;
|
||||
width: 100%;
|
||||
font-size: var(--font-down-1);
|
||||
color: var(--primary-high);
|
||||
}
|
||||
}
|
||||
|
||||
.btn:focus {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.btn:focus-visible {
|
||||
outline: 2px solid var(--tertiary);
|
||||
background: transparent;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
.btn.--active {
|
||||
background: var(--d-selected);
|
||||
}
|
||||
}
|
||||
|
||||
.topic-list-layout-table-ai {
|
||||
.topic-list-item {
|
||||
.link-bottom-line {
|
||||
font-size: var(--font-down-1);
|
||||
margin-top: 0.25em;
|
||||
line-height: var(--line-height-medium);
|
||||
}
|
||||
.excerpt {
|
||||
width: 100%;
|
||||
line-height: var(--line-height-large);
|
||||
margin-top: 0.15em;
|
||||
margin-bottom: 0.15em;
|
||||
max-width: 70ch;
|
||||
}
|
||||
&:not(.visited) {
|
||||
.excerpt {
|
||||
color: var(--primary-high);
|
||||
}
|
||||
}
|
||||
}
|
||||
.topic-excerpt {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mobile-view & {
|
||||
.topic-list-item .excerpt {
|
||||
margin-top: -0.25em;
|
||||
margin-bottom: 0.25em;
|
||||
}
|
||||
|
||||
.topic-item-stats .num.activity {
|
||||
align-self: end;
|
||||
margin-bottom: -0.15em; // vertical alignment
|
||||
}
|
||||
}
|
||||
}
|
|
@ -215,77 +215,3 @@
|
|||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.ai-topic-gist {
|
||||
width: 100%;
|
||||
.mobile-view & {
|
||||
position: relative;
|
||||
top: -0.33em;
|
||||
line-height: 1.4;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
&__text {
|
||||
color: var(--primary-high);
|
||||
text-wrap: pretty;
|
||||
word-wrap: break-word;
|
||||
font-size: var(--font-down-1);
|
||||
max-width: 65ch;
|
||||
.visited & {
|
||||
color: var(--primary-medium);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.--topic-list-with-gist {
|
||||
.topic-list-item {
|
||||
.main-link {
|
||||
line-height: var(--line-height-medium);
|
||||
}
|
||||
.link-bottom-line {
|
||||
font-size: var(--font-down-1);
|
||||
margin-top: 0.25em;
|
||||
}
|
||||
.ai-topic-gist {
|
||||
font-size: var(--font-up-1);
|
||||
line-height: var(--line-height-large);
|
||||
margin-top: 0.25em;
|
||||
margin-bottom: 0.15em;
|
||||
}
|
||||
.topic-post-badges {
|
||||
font-size: var(--font-down-1);
|
||||
}
|
||||
}
|
||||
|
||||
.mobile-view & {
|
||||
.topic-list {
|
||||
.topic-list-item > .topic-list-data {
|
||||
padding: 1em 0;
|
||||
}
|
||||
.topic-item-stats .num.activity {
|
||||
align-self: end;
|
||||
margin-bottom: -0.15em; // vertical alignment
|
||||
}
|
||||
.pull-left {
|
||||
padding-top: 0.25em;
|
||||
}
|
||||
.right {
|
||||
margin-left: 3.75em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ai-gists-dropdown-trigger {
|
||||
font-size: var(--font-down-1);
|
||||
color: var(--primary-medium);
|
||||
padding-left: 0.25em;
|
||||
.mobile-view & {
|
||||
padding-left: 0;
|
||||
color: var(--primary-high);
|
||||
}
|
||||
.d-icon {
|
||||
color: var(--primary-low-mid);
|
||||
margin-left: 0.15em;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -481,9 +481,11 @@ en:
|
|||
topic:
|
||||
title: "Topic summary"
|
||||
close: "Close summary panel"
|
||||
gists_enabled: "with summary"
|
||||
gists_enabled_long: "with AI-generated summary"
|
||||
gists_disabled: "without summary"
|
||||
topic_list_layout:
|
||||
button:
|
||||
compact: "Compact"
|
||||
expanded: "Expanded"
|
||||
expanded_description: "with AI summaries"
|
||||
review:
|
||||
types:
|
||||
reviewable_ai_post:
|
||||
|
|
|
@ -24,6 +24,8 @@ register_asset "stylesheets/modules/summarization/mobile/ai-summary.scss", :mobi
|
|||
register_asset "stylesheets/modules/summarization/common/ai-summary.scss"
|
||||
register_asset "stylesheets/modules/summarization/desktop/ai-summary.scss", :desktop
|
||||
|
||||
register_asset "stylesheets/modules/summarization/common/ai-gists.scss"
|
||||
|
||||
register_asset "stylesheets/modules/ai-bot/common/bot-replies.scss"
|
||||
register_asset "stylesheets/modules/ai-bot/common/ai-persona.scss"
|
||||
register_asset "stylesheets/modules/ai-bot/mobile/ai-persona.scss", :mobile
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
|
||||
<!-- "Discourse Table" is a Discourse derivative of https://fontawesome.com/v6/icons/table-list?f=classic&s=solid -->
|
||||
<symbol id="discourse-table" viewBox="0 0 512 512">
|
||||
<g>
|
||||
<g id="Layer_1">
|
||||
<path d="M0,96C0,60.7,28.7,32,64,32h384c35.3,0,64,28.7,64,64v320c0,35.3-28.7,64-64,64H64c-35.3,0-64-28.7-64-64V96ZM448,96H64v64h384v-64ZM448,224H64v64h384v-64ZM448,352H64v64h384v-64Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</symbol>
|
||||
|
||||
<!-- "Discourse Table Sparkles" is a Discourse derivative of https://fontawesome.com/v6/icons/table-list?f=classic&s=solid -->
|
||||
<symbol id="discourse-table-sparkles" viewBox="0 0 512 512">
|
||||
<path d="M448 309.64V413H64V290h190c12.23 0 18.46-14.71 9.94-23.48-7.56-7.78-14.48-16.2-20.66-25.16-5.36-7.77-14.24-12.36-23.69-12.36H64V93h130c10.65 0 20.14-6.92 23.18-17.12a193.4 193.4 0 0 1 9.74-25.76c4.56-9.86-2.77-21.12-13.63-21.12H64C28.65 29 0 57.65 0 93v320c0 35.35 28.65 64 64 64h384c35.35 0 64-28.65 64-64V263.8c0-9.16-10.7-14.14-17.7-8.25a194.056 194.056 0 0 1-25.76 18.32c-12.66 7.53-20.53 21.05-20.53 35.77Z"/><path d="M247.46 122.15c-6.45 2.44-10.75 8.6-10.75 15.49s4.3 13.05 10.75 15.49l81.01 30.4 30.4 81.01c2.44 6.45 8.6 10.75 15.49 10.75s13.05-4.3 15.49-10.75l30.4-81.01 81.01-30.4c6.45-2.44 10.75-8.6 10.75-15.49s-4.3-13.05-10.75-15.49l-81.01-30.4-30.4-81.01c-2.44-6.45-8.6-10.75-15.49-10.75s-13.05 4.3-15.49 10.75l-30.4 81.01-81.01 30.4Z"/>
|
||||
</symbol>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
Loading…
Reference in New Issue