Skip to content

Commit 30bfc4f

Browse files
authored
Merge pull request #4797 from continuedev/pe/assistant-polish
feat: explore btn
2 parents 0015200 + 14c9528 commit 30bfc4f

File tree

8 files changed

+128
-100
lines changed

8 files changed

+128
-100
lines changed

gui/src/components/index.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -153,21 +153,20 @@ export const SecondaryButton = styled.button`
153153

154154
export const GhostButton = styled.button`
155155
padding: 6px 8px;
156-
margin: 8px 0;
156+
margin: 6px 0;
157157
border-radius: ${defaultBorderRadius};
158158
159159
border: none;
160160
color: ${vscForeground};
161-
background-color: transparent;
162-
161+
background-color: rgba(255, 255, 255, 0.08);
163162
&:disabled {
164163
color: gray;
165164
pointer-events: none;
166165
}
167166
168167
&:hover:enabled {
169168
cursor: pointer;
170-
background-color: rgba(255, 255, 255, 0.08); /* Subtle hover effect */
169+
filter: brightness(125%);
171170
}
172171
`;
173172

gui/src/components/mainInput/Lump/index.tsx

+5-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
vscCommandCenterInactiveBorder,
66
vscInputBackground,
77
} from "../..";
8+
import { useAppSelector } from "../../../redux/hooks";
89
import { LumpToolbar } from "./LumpToolbar";
910
import { SelectedSection } from "./sections/SelectedSection";
1011

@@ -39,6 +40,7 @@ export function Lump(props: LumpProps) {
3940
const [selectedSection, setSelectedSection] = useState<string | null>(null);
4041
const [displayedSection, setDisplayedSection] = useState<string | null>(null);
4142
const [isVisible, setIsVisible] = useState(false);
43+
const isStreaming = useAppSelector((state) => state.session.isStreaming);
4244

4345
useEffect(() => {
4446
if (selectedSection) {
@@ -67,7 +69,9 @@ export function Lump(props: LumpProps) {
6769
/>
6870

6971
<ContentDiv hasSection={!!selectedSection} isVisible={isVisible}>
70-
<SelectedSection selectedSection={displayedSection} />
72+
{!isStreaming && (
73+
<SelectedSection selectedSection={displayedSection} />
74+
)}
7175
</ContentDiv>
7276
</div>
7377
</LumpDiv>

gui/src/components/mainInput/Lump/sections/AddBlockButton.tsx renamed to gui/src/components/mainInput/Lump/sections/ExploreBlocksButton.tsx

+20-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
import { PlusIcon } from "@heroicons/react/24/outline";
1+
import {
2+
ArrowTopRightOnSquareIcon,
3+
PlusIcon,
4+
} from "@heroicons/react/24/outline";
25
import { useContext } from "react";
6+
import { GhostButton } from "../../..";
37
import { useAuth } from "../../../../context/Auth";
48
import { IdeMessengerContext } from "../../../../context/IdeMessenger";
59
import { useAppDispatch } from "../../../../redux/hooks";
@@ -10,13 +14,22 @@ import {
1014
import { fontSize } from "../../../../util";
1115
import AddDocsDialog from "../../../dialogs/AddDocsDialog";
1216

13-
export function AddBlockButton(props: { blockType: string }) {
17+
export function ExploreBlocksButton(props: { blockType: string }) {
1418
const { selectedProfile } = useAuth();
1519
const ideMessenger = useContext(IdeMessengerContext);
1620
const dispatch = useAppDispatch();
1721

22+
const isLocal = selectedProfile?.profileType === "local";
23+
24+
const Icon = isLocal ? PlusIcon : ArrowTopRightOnSquareIcon;
25+
const text = `${isLocal ? "Add" : "Explore"} ${
26+
props.blockType === "mcpServers"
27+
? "MCP Servers"
28+
: props.blockType.charAt(0).toUpperCase() + props.blockType.slice(1)
29+
}`;
30+
1831
const handleClick = () => {
19-
if (selectedProfile?.profileType === "local") {
32+
if (isLocal) {
2033
switch (props.blockType) {
2134
case "docs":
2235
dispatch(setShowDialog(true));
@@ -36,8 +49,8 @@ export function AddBlockButton(props: { blockType: string }) {
3649
};
3750

3851
return (
39-
<div
40-
className="cursor-pointer rounded px-2 pb-1 text-center text-gray-400 hover:text-gray-300"
52+
<GhostButton
53+
className="w-full cursor-pointer rounded px-2 text-center text-gray-400 hover:text-gray-300"
4154
style={{
4255
fontSize: fontSize(-3),
4356
}}
@@ -47,8 +60,8 @@ export function AddBlockButton(props: { blockType: string }) {
4760
}}
4861
>
4962
<div className="flex items-center justify-center gap-1">
50-
<PlusIcon className="h-3 w-3" /> Add
63+
<Icon className="h-3 w-3" /> {text}
5164
</div>
52-
</div>
65+
</GhostButton>
5366
);
5467
}

gui/src/components/mainInput/Lump/sections/PromptsSection.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
import { BookmarkIcon as BookmarkSolid } from "@heroicons/react/24/solid";
66
import { fontSize } from "../../../../util";
77
import { useBookmarkedSlashCommands } from "../../../ConversationStarters/useBookmarkedSlashCommands";
8-
import { AddBlockButton } from "./AddBlockButton";
8+
import { ExploreBlocksButton } from "./ExploreBlocksButton";
99

1010
interface PromptRowProps {
1111
command: string;
@@ -24,7 +24,7 @@ function PromptRow({
2424
}: PromptRowProps) {
2525
return (
2626
<div
27-
className="flex items-center justify-between"
27+
className="flex items-center justify-between gap-3"
2828
style={{
2929
fontSize: fontSize(-3),
3030
}}
@@ -40,7 +40,7 @@ function PromptRow({
4040
/>
4141
<div
4242
onClick={() => setIsBookmarked(!isBookmarked)}
43-
className="cursor-pointer pt-0.5 text-gray-400"
43+
className="cursor-pointer pt-0.5 text-gray-400 hover:brightness-125"
4444
>
4545
{isBookmarked ? (
4646
<BookmarkSolid className="h-3 w-3" />
@@ -74,7 +74,7 @@ export function PromptsSection() {
7474
onEdit={() => handleEdit(prompt)}
7575
/>
7676
))}
77-
<AddBlockButton blockType="prompts" />
77+
<ExploreBlocksButton blockType="prompts" />
7878
</div>
7979
);
8080
}
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
import { parseConfigYaml } from "@continuedev/config-yaml";
2-
import { PencilIcon } from "@heroicons/react/24/outline";
2+
import { ArrowsPointingOutIcon, PencilIcon } from "@heroicons/react/24/outline";
33
import { useContext, useMemo } from "react";
44
import { useSelector } from "react-redux";
55
import { defaultBorderRadius, vscCommandCenterActiveBorder } from "../../..";
66
import { useAuth } from "../../../../context/Auth";
77
import { IdeMessengerContext } from "../../../../context/IdeMessenger";
8+
import { useAppDispatch } from "../../../../redux/hooks";
9+
import {
10+
setDialogMessage,
11+
setShowDialog,
12+
} from "../../../../redux/slices/uiSlice";
813
import { RootState } from "../../../../redux/store";
914
import { fontSize } from "../../../../util";
1015
import HeaderButtonWithToolTip from "../../../gui/HeaderButtonWithToolTip";
11-
import { AddBlockButton } from "./AddBlockButton";
16+
import { ExploreBlocksButton } from "./ExploreBlocksButton";
1217

1318
interface RuleCardProps {
1419
index: number;
@@ -18,12 +23,19 @@ interface RuleCardProps {
1823
}
1924

2025
const RuleCard: React.FC<RuleCardProps> = ({ index, rule, onClick, title }) => {
21-
const truncateRule = (rule: string) => {
22-
const maxLength = 75;
23-
return rule.length > maxLength
24-
? `${rule.substring(0, maxLength)}...`
25-
: rule;
26-
};
26+
const dispatch = useAppDispatch();
27+
28+
function onClickExpand() {
29+
dispatch(setShowDialog(true));
30+
dispatch(
31+
setDialogMessage(
32+
<div className="p-4 text-center">
33+
<h3>{title}</h3>
34+
<pre className="max-w-full overflow-x-scroll">{rule}</pre>
35+
</div>,
36+
),
37+
);
38+
}
2739

2840
return (
2941
<div
@@ -33,29 +45,35 @@ const RuleCard: React.FC<RuleCardProps> = ({ index, rule, onClick, title }) => {
3345
}}
3446
className="px-2 py-1 transition-colors"
3547
>
36-
<div className="flex items-start justify-between">
37-
<div className="flex-1">
38-
<div
39-
className="text-vsc-foreground mb-1"
40-
style={{
41-
fontSize: fontSize(-2),
42-
}}
43-
>
44-
{title}
48+
<div className="flex flex-col gap-2">
49+
<div className="flex items-start justify-between">
50+
<div className="flex-1">
51+
<div
52+
className="text-vsc-foreground mb-1"
53+
style={{
54+
fontSize: fontSize(-2),
55+
}}
56+
>
57+
{title}
58+
</div>
59+
<div
60+
style={{
61+
fontSize: fontSize(-3),
62+
}}
63+
className="line-clamp-3 text-gray-400"
64+
>
65+
{rule}
66+
</div>
4567
</div>
46-
<div
47-
style={{
48-
fontSize: fontSize(-3),
49-
whiteSpace: "pre-line",
50-
}}
51-
className="text-gray-400"
52-
>
53-
{truncateRule(rule)}
68+
<div className="flex items-center gap-2">
69+
<HeaderButtonWithToolTip onClick={onClickExpand} text="Expand">
70+
<ArrowsPointingOutIcon className="h-3 w-3 text-gray-400" />
71+
</HeaderButtonWithToolTip>{" "}
72+
<HeaderButtonWithToolTip onClick={onClick} text="Edit">
73+
<PencilIcon className="h-3 w-3 text-gray-400" />
74+
</HeaderButtonWithToolTip>
5475
</div>
5576
</div>
56-
<HeaderButtonWithToolTip onClick={onClick} text="Edit">
57-
<PencilIcon className="h-3 w-3 text-gray-400" />
58-
</HeaderButtonWithToolTip>
5977
</div>
6078
</div>
6179
);
@@ -86,63 +104,60 @@ export function RulesSection() {
86104
});
87105

88106
return (
89-
<div className="space-y-4">
90-
{mergedRules.length === 0 ? (
91-
<div className="rounded-lg bg-[#1e1e1e] p-6">
92-
<p className="italic text-gray-400">No rules defined yet</p>
93-
</div>
94-
) : (
95-
<div className="space-y-3">
96-
{mergedRules.map((rule, index) => {
97-
if (!rule.ruleFromYaml) {
98-
return (
99-
<RuleCard
100-
key={index}
101-
index={index}
102-
rule={rule.unrolledRule}
103-
onClick={() =>
104-
ideMessenger.post("config/openProfile", {
105-
profileId: undefined,
106-
})
107-
}
108-
title="Locally Defined Rule"
109-
/>
110-
);
111-
}
112-
113-
if (typeof rule.ruleFromYaml === "string") {
114-
const slug = `${selectedProfile?.fullSlug.ownerSlug}/${selectedProfile?.fullSlug.packageSlug}`;
115-
116-
return (
117-
<RuleCard
118-
key={index}
119-
index={index}
120-
rule={rule.unrolledRule}
121-
onClick={() => openUrl(`${slug}/new-version`)}
122-
title="Inline Rule"
123-
/>
124-
);
125-
}
126-
127-
if (!rule.ruleFromYaml?.uses) {
128-
return null;
129-
}
107+
<div>
108+
<div className="space-y-3">
109+
{mergedRules.map((rule, index) => {
110+
if (!rule.ruleFromYaml) {
111+
return (
112+
<RuleCard
113+
key={index}
114+
index={index}
115+
rule={rule.unrolledRule}
116+
onClick={() =>
117+
ideMessenger.post("config/openProfile", {
118+
profileId: undefined,
119+
})
120+
}
121+
title="Locally Defined Rule"
122+
/>
123+
);
124+
}
130125

131-
const ruleSlug = rule.ruleFromYaml?.uses;
126+
if (typeof rule.ruleFromYaml === "string") {
127+
const slug = `${selectedProfile?.fullSlug.ownerSlug}/${selectedProfile?.fullSlug.packageSlug}`;
132128

133129
return (
134130
<RuleCard
135131
key={index}
136132
index={index}
137133
rule={rule.unrolledRule}
138-
onClick={() => openUrl(`${ruleSlug}/new-version`)}
139-
title={ruleSlug}
134+
onClick={() => openUrl(`${slug}/new-version`)}
135+
title="Inline Rule"
140136
/>
141137
);
142-
})}
143-
</div>
144-
)}
145-
<AddBlockButton blockType="rules" />
138+
}
139+
140+
if (!rule.ruleFromYaml?.uses) {
141+
return null;
142+
}
143+
144+
const ruleSlug = rule.ruleFromYaml?.uses;
145+
146+
return (
147+
<RuleCard
148+
key={index}
149+
index={index}
150+
rule={rule.unrolledRule}
151+
onClick={() => openUrl(`${ruleSlug}/new-version`)}
152+
title={ruleSlug}
153+
/>
154+
);
155+
})}
156+
</div>
157+
<ExploreBlocksButton blockType="rules" />
146158
</div>
147159
);
148160
}
161+
function useTypedDispatch() {
162+
throw new Error("Function not implemented.");
163+
}

gui/src/components/mainInput/Lump/sections/docs/DocsIndexingStatus.tsx

-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { ConfigYaml } from "@continuedev/config-yaml";
22
import {
33
ArrowPathIcon,
4-
ArrowTopRightOnSquareIcon,
54
PencilIcon,
65
StopIcon,
76
} from "@heroicons/react/24/outline";
@@ -140,7 +139,6 @@ function DocsIndexingStatus({
140139
>
141140
{docConfig.title ?? docConfig.startUrl}
142141
</p>
143-
<ArrowTopRightOnSquareIcon className="h-2 w-2 text-gray-400" />
144142
</div>
145143

146144
<div className="flex flex-row items-center gap-2">

gui/src/components/mainInput/Lump/sections/docs/DocsSection.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { useMemo } from "react";
44
import { useDispatch } from "react-redux";
55
import { useAuth } from "../../../../../context/Auth";
66
import { useAppSelector } from "../../../../../redux/hooks";
7-
import { AddBlockButton } from "../AddBlockButton";
7+
import { ExploreBlocksButton } from "../ExploreBlocksButton";
88
import DocsIndexingStatus from "./DocsIndexingStatus";
99

1010
function DocsIndexingStatuses() {
@@ -70,7 +70,7 @@ function DocsIndexingStatuses() {
7070
);
7171
})}
7272
</div>
73-
<AddBlockButton blockType="docs" />
73+
<ExploreBlocksButton blockType="docs" />
7474
</div>
7575
);
7676
}

0 commit comments

Comments
 (0)