Skip to content

feat: explore btn #4797

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions gui/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,21 +153,20 @@ export const SecondaryButton = styled.button`

export const GhostButton = styled.button`
padding: 6px 8px;
margin: 8px 0;
margin: 6px 0;
border-radius: ${defaultBorderRadius};

border: none;
color: ${vscForeground};
background-color: transparent;

background-color: rgba(255, 255, 255, 0.08);
&:disabled {
color: gray;
pointer-events: none;
}

&:hover:enabled {
cursor: pointer;
background-color: rgba(255, 255, 255, 0.08); /* Subtle hover effect */
filter: brightness(125%);
}
`;

Expand Down
6 changes: 5 additions & 1 deletion gui/src/components/mainInput/Lump/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
vscCommandCenterInactiveBorder,
vscInputBackground,
} from "../..";
import { useAppSelector } from "../../../redux/hooks";
import { LumpToolbar } from "./LumpToolbar";
import { SelectedSection } from "./sections/SelectedSection";

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

useEffect(() => {
if (selectedSection) {
Expand Down Expand Up @@ -67,7 +69,9 @@ export function Lump(props: LumpProps) {
/>

<ContentDiv hasSection={!!selectedSection} isVisible={isVisible}>
<SelectedSection selectedSection={displayedSection} />
{!isStreaming && (
<SelectedSection selectedSection={displayedSection} />
)}
</ContentDiv>
</div>
</LumpDiv>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { PlusIcon } from "@heroicons/react/24/outline";
import {
ArrowTopRightOnSquareIcon,
PlusIcon,
} from "@heroicons/react/24/outline";
import { useContext } from "react";
import { GhostButton } from "../../..";
import { useAuth } from "../../../../context/Auth";
import { IdeMessengerContext } from "../../../../context/IdeMessenger";
import { useAppDispatch } from "../../../../redux/hooks";
Expand All @@ -10,13 +14,22 @@ import {
import { fontSize } from "../../../../util";
import AddDocsDialog from "../../../dialogs/AddDocsDialog";

export function AddBlockButton(props: { blockType: string }) {
export function ExploreBlocksButton(props: { blockType: string }) {
const { selectedProfile } = useAuth();
const ideMessenger = useContext(IdeMessengerContext);
const dispatch = useAppDispatch();

const isLocal = selectedProfile?.profileType === "local";

const Icon = isLocal ? PlusIcon : ArrowTopRightOnSquareIcon;
const text = `${isLocal ? "Add" : "Explore"} ${
props.blockType === "mcpServers"
? "MCP Servers"
: props.blockType.charAt(0).toUpperCase() + props.blockType.slice(1)
}`;

const handleClick = () => {
if (selectedProfile?.profileType === "local") {
if (isLocal) {
switch (props.blockType) {
case "docs":
dispatch(setShowDialog(true));
Expand All @@ -36,8 +49,8 @@ export function AddBlockButton(props: { blockType: string }) {
};

return (
<div
className="cursor-pointer rounded px-2 pb-1 text-center text-gray-400 hover:text-gray-300"
<GhostButton
className="w-full cursor-pointer rounded px-2 text-center text-gray-400 hover:text-gray-300"
style={{
fontSize: fontSize(-3),
}}
Expand All @@ -47,8 +60,8 @@ export function AddBlockButton(props: { blockType: string }) {
}}
>
<div className="flex items-center justify-center gap-1">
<PlusIcon className="h-3 w-3" /> Add
<Icon className="h-3 w-3" /> {text}
</div>
</div>
</GhostButton>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
import { BookmarkIcon as BookmarkSolid } from "@heroicons/react/24/solid";
import { fontSize } from "../../../../util";
import { useBookmarkedSlashCommands } from "../../../ConversationStarters/useBookmarkedSlashCommands";
import { AddBlockButton } from "./AddBlockButton";
import { ExploreBlocksButton } from "./ExploreBlocksButton";

interface PromptRowProps {
command: string;
Expand All @@ -24,7 +24,7 @@ function PromptRow({
}: PromptRowProps) {
return (
<div
className="flex items-center justify-between"
className="flex items-center justify-between gap-3"
style={{
fontSize: fontSize(-3),
}}
Expand All @@ -40,7 +40,7 @@ function PromptRow({
/>
<div
onClick={() => setIsBookmarked(!isBookmarked)}
className="cursor-pointer pt-0.5 text-gray-400"
className="cursor-pointer pt-0.5 text-gray-400 hover:brightness-125"
>
{isBookmarked ? (
<BookmarkSolid className="h-3 w-3" />
Expand Down Expand Up @@ -74,7 +74,7 @@ export function PromptsSection() {
onEdit={() => handleEdit(prompt)}
/>
))}
<AddBlockButton blockType="prompts" />
<ExploreBlocksButton blockType="prompts" />
</div>
);
}
167 changes: 91 additions & 76 deletions gui/src/components/mainInput/Lump/sections/RulesSection.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
import { parseConfigYaml } from "@continuedev/config-yaml";
import { PencilIcon } from "@heroicons/react/24/outline";
import { ArrowsPointingOutIcon, PencilIcon } from "@heroicons/react/24/outline";
import { useContext, useMemo } from "react";
import { useSelector } from "react-redux";
import { defaultBorderRadius, vscCommandCenterActiveBorder } from "../../..";
import { useAuth } from "../../../../context/Auth";
import { IdeMessengerContext } from "../../../../context/IdeMessenger";
import { useAppDispatch } from "../../../../redux/hooks";
import {
setDialogMessage,
setShowDialog,
} from "../../../../redux/slices/uiSlice";
import { RootState } from "../../../../redux/store";
import { fontSize } from "../../../../util";
import HeaderButtonWithToolTip from "../../../gui/HeaderButtonWithToolTip";
import { AddBlockButton } from "./AddBlockButton";
import { ExploreBlocksButton } from "./ExploreBlocksButton";

interface RuleCardProps {
index: number;
Expand All @@ -18,12 +23,19 @@ interface RuleCardProps {
}

const RuleCard: React.FC<RuleCardProps> = ({ index, rule, onClick, title }) => {
const truncateRule = (rule: string) => {
const maxLength = 75;
return rule.length > maxLength
? `${rule.substring(0, maxLength)}...`
: rule;
};
const dispatch = useAppDispatch();

function onClickExpand() {
dispatch(setShowDialog(true));
dispatch(
setDialogMessage(
<div className="p-4 text-center">
<h3>{title}</h3>
<pre className="max-w-full overflow-x-scroll">{rule}</pre>
</div>,
),
);
}

return (
<div
Expand All @@ -33,29 +45,35 @@ const RuleCard: React.FC<RuleCardProps> = ({ index, rule, onClick, title }) => {
}}
className="px-2 py-1 transition-colors"
>
<div className="flex items-start justify-between">
<div className="flex-1">
<div
className="text-vsc-foreground mb-1"
style={{
fontSize: fontSize(-2),
}}
>
{title}
<div className="flex flex-col gap-2">
<div className="flex items-start justify-between">
<div className="flex-1">
<div
className="text-vsc-foreground mb-1"
style={{
fontSize: fontSize(-2),
}}
>
{title}
</div>
<div
style={{
fontSize: fontSize(-3),
}}
className="line-clamp-3 text-gray-400"
>
{rule}
</div>
</div>
<div
style={{
fontSize: fontSize(-3),
whiteSpace: "pre-line",
}}
className="text-gray-400"
>
{truncateRule(rule)}
<div className="flex items-center gap-2">
<HeaderButtonWithToolTip onClick={onClickExpand} text="Expand">
<ArrowsPointingOutIcon className="h-3 w-3 text-gray-400" />
</HeaderButtonWithToolTip>{" "}
<HeaderButtonWithToolTip onClick={onClick} text="Edit">
<PencilIcon className="h-3 w-3 text-gray-400" />
</HeaderButtonWithToolTip>
</div>
</div>
<HeaderButtonWithToolTip onClick={onClick} text="Edit">
<PencilIcon className="h-3 w-3 text-gray-400" />
</HeaderButtonWithToolTip>
</div>
</div>
);
Expand Down Expand Up @@ -86,63 +104,60 @@ export function RulesSection() {
});

return (
<div className="space-y-4">
{mergedRules.length === 0 ? (
<div className="rounded-lg bg-[#1e1e1e] p-6">
<p className="italic text-gray-400">No rules defined yet</p>
</div>
) : (
<div className="space-y-3">
{mergedRules.map((rule, index) => {
if (!rule.ruleFromYaml) {
return (
<RuleCard
key={index}
index={index}
rule={rule.unrolledRule}
onClick={() =>
ideMessenger.post("config/openProfile", {
profileId: undefined,
})
}
title="Locally Defined Rule"
/>
);
}

if (typeof rule.ruleFromYaml === "string") {
const slug = `${selectedProfile?.fullSlug.ownerSlug}/${selectedProfile?.fullSlug.packageSlug}`;

return (
<RuleCard
key={index}
index={index}
rule={rule.unrolledRule}
onClick={() => openUrl(`${slug}/new-version`)}
title="Inline Rule"
/>
);
}

if (!rule.ruleFromYaml?.uses) {
return null;
}
<div>
<div className="space-y-3">
{mergedRules.map((rule, index) => {
if (!rule.ruleFromYaml) {
return (
<RuleCard
key={index}
index={index}
rule={rule.unrolledRule}
onClick={() =>
ideMessenger.post("config/openProfile", {
profileId: undefined,
})
}
title="Locally Defined Rule"
/>
);
}

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

return (
<RuleCard
key={index}
index={index}
rule={rule.unrolledRule}
onClick={() => openUrl(`${ruleSlug}/new-version`)}
title={ruleSlug}
onClick={() => openUrl(`${slug}/new-version`)}
title="Inline Rule"
/>
);
})}
</div>
)}
<AddBlockButton blockType="rules" />
}

if (!rule.ruleFromYaml?.uses) {
return null;
}

const ruleSlug = rule.ruleFromYaml?.uses;

return (
<RuleCard
key={index}
index={index}
rule={rule.unrolledRule}
onClick={() => openUrl(`${ruleSlug}/new-version`)}
title={ruleSlug}
/>
);
})}
</div>
<ExploreBlocksButton blockType="rules" />
</div>
);
}
function useTypedDispatch() {
throw new Error("Function not implemented.");
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ConfigYaml } from "@continuedev/config-yaml";
import {
ArrowPathIcon,
ArrowTopRightOnSquareIcon,
PencilIcon,
StopIcon,
} from "@heroicons/react/24/outline";
Expand Down Expand Up @@ -140,7 +139,6 @@ function DocsIndexingStatus({
>
{docConfig.title ?? docConfig.startUrl}
</p>
<ArrowTopRightOnSquareIcon className="h-2 w-2 text-gray-400" />
</div>

<div className="flex flex-row items-center gap-2">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useMemo } from "react";
import { useDispatch } from "react-redux";
import { useAuth } from "../../../../../context/Auth";
import { useAppSelector } from "../../../../../redux/hooks";
import { AddBlockButton } from "../AddBlockButton";
import { ExploreBlocksButton } from "../ExploreBlocksButton";
import DocsIndexingStatus from "./DocsIndexingStatus";

function DocsIndexingStatuses() {
Expand Down Expand Up @@ -70,7 +70,7 @@ function DocsIndexingStatuses() {
);
})}
</div>
<AddBlockButton blockType="docs" />
<ExploreBlocksButton blockType="docs" />
</div>
);
}
Expand Down
Loading
Loading