PluginProbe
Extendify / trunk
Extendify vtrunk
3.2.1 3.2.0 3.1.6 3.1.5 3.1.4 3.1.3 3.1.2 3.1.1 3.1.0 3.0.6 3.0.5 3.0.4 trunk 0.1.0 0.10.0 0.10.1 0.10.2 0.11.0 0.11.1 0.2.0 0.3.0 0.3.1 0.4.0 0.5.0 0.6.0 All 127 releases
← All changes | src/Agent/components/ChatSuggestions.jsx +56 -11 3.0.5 → trunk View file →
@@ -1,7 +1,9 @@
1 1 import { sparkle } from '@agent/icons';
2 +import { useDomainActivities } from '@agent/state/domain-activities';
2 3 import { useSuggestionsStore } from '@agent/state/suggestions';
3 -import { useState } from '@wordpress/element';
4 +import { track } from '@shared/lib/track';
5 +import { useEffect, useState } from '@wordpress/element';
4 6 import { __ } from '@wordpress/i18n';
5 7 import {
6 8 chevronRight,
7 9 drafts,
@@ -30,17 +32,26 @@
30 32 };
31 33
32 34 export const ChatSuggestions = ({ suggestions }) => {
33 35 const { markAsClicked, isAvailable, getSuggestions } = useSuggestionsStore();
36 + const { setDomainActivity } = useDomainActivities();
34 37 const [allSuggestions, setAllSuggestions] = useState(suggestions);
35 38
36 - const handleSubmit = (suggestion) => {
39 + const handleSelect = (suggestion) => {
40 + markAsClicked(suggestion);
41 + if (suggestion.telemetry) {
42 + track(suggestion.telemetry.key, suggestion.telemetry.payload);
43 + } else if (suggestion.tracking) {
44 + setDomainActivity({ ...suggestion.tracking, action: 'clicked' });
45 + }
46 + // External-link suggestions are plain links: the anchor opens the new tab.
47 + // They don't trigger a workflow or post a message in the chat.
48 + if (suggestion.type === 'external-link') return;
37 49 window.dispatchEvent(
38 50 new CustomEvent('extendify-agent:chat-submit', {
39 51 detail: { message: suggestion.message },
40 52 }),
41 53 );
42 - markAsClicked(suggestion);
43 54 };
44 55
45 56 const handleShowMore = () => {
46 57 const next = getSuggestions({ slice: 6, exclude: allSuggestions });
@@ -57,9 +68,9 @@
57 68 return (
58 69 <SuggestionButton
59 70 key={suggestion.message}
60 71 suggestion={suggestion}
61 - handleSubmit={handleSubmit}
72 + onSelect={handleSelect}
62 73 />
63 74 );
64 75 })}
65 76 <ShowMoreButton handleShowMore={handleShowMore} />
@@ -66,16 +77,25 @@
66 77 </>
67 78 );
68 79 };
69 80
70 -const SuggestionButton = ({ suggestion, handleSubmit }) => {
81 +const SuggestionButton = ({ suggestion, onSelect }) => {
82 + const { setDomainActivity } = useDomainActivities();
71 83 const icon = icons[suggestion?.icon] ?? icons.sparkle;
72 - return (
73 - <button
74 - type="button"
75 - className="group flex items-center justify-between rounded-sm bg-transparent px-1 py-1 text-left text-sm not-italic text-gray-900 transition-colors duration-100 hover:bg-gray-100 focus:outline-hidden focus:ring-2 focus:ring-design-main"
76 - onClick={() => handleSubmit(suggestion)}
77 - >
84 +
85 + useEffect(() => {
86 + if (suggestion.viewTelemetry) {
87 + track(suggestion.viewTelemetry.key, suggestion.viewTelemetry.payload);
88 + }
89 + if (suggestion.tracking) {
90 + setDomainActivity({ ...suggestion.tracking, action: 'viewed' });
91 + }
92 + }, [suggestion, setDomainActivity]);
93 +
94 + const className =
95 + 'group flex items-center justify-between rounded-sm bg-transparent px-1 py-1 text-left text-sm not-italic text-gray-900 transition-colors duration-100 hover:bg-gray-100 focus:outline-hidden focus:ring-2 focus:ring-design-main';
96 + const content = (
97 + <>
78 98 <div className="flex items-center gap-1.5 leading-none">
79 99 <span className="h-5 w-5 shrink-0 self-start fill-gray-700">
80 100 {icon}
81 101 </span>
@@ -83,8 +103,33 @@
83 103 </div>
84 104 <span className="inline-block h-5 w-5 fill-gray-700 leading-none opacity-0 transition-opacity duration-100 group-hover:opacity-100 rtl:scale-x-[-1]">
85 105 {chevronRight}
86 106 </span>
107 + </>
108 + );
109 +
110 + // External-link suggestions render as a real anchor that opens in a new tab.
111 + if (suggestion.type === 'external-link') {
112 + return (
113 + <a
114 + href={suggestion.url}
115 + target="_blank"
116 + rel="noopener noreferrer"
117 + className={`${className} no-underline`}
118 + onClick={() => onSelect(suggestion)}
119 + >
120 + {content}
121 + </a>
122 + );
123 + }
124 +
125 + return (
126 + <button
127 + type="button"
128 + className={className}
129 + onClick={() => onSelect(suggestion)}
130 + >
131 + {content}
87 132 </button>
88 133 );
89 134 };
90 135