agentsclimarketplace

Customize sidebar

Skill hec-ovi/agentickit/.pilot/skills/customize-sidebar

AI copilot for React apps. Reads your state, fills forms, confirms actions, calls your tools. Multi-agent, AI SDK 6 + AG-UI, markdown skills. MIT.

Install
npx -y skills add hec-ovi/agentickit --skill customize-sidebar

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Theme, relabel, reposition, and customize `<PilotSidebar>`. Covers CSS variables (the sidebar has no Tailwind, no design system), labels for i18n, suggestion chips, position and width. Also covers when to drop the sidebar entirely and build a custom UI from PilotChatContext.

SKILL.md

6.7 KB, as published. Nobody here has run it

Customize Sidebar

Contract

By the end of this skill the consumer has:

  • A <PilotSidebar> styled to match their app (CSS variables overridden on a parent scope).
  • Labels localized or branded via the labels prop.
  • (Optionally) suggestion chips pinned to common prompts.
  • (Optionally) position / width / greeting customized.
  • A clear decision about whether to keep using the bundled sidebar or build a custom one from PilotChatContext.

Iron Law: don't copy-paste the sidebar source, override via CSS variables

The sidebar is ~350 lines split across four sibling files (packages/agentickit/src/components/pilot-sidebar*.tsx + the styles file). It uses CSS variables scoped with --pilot-*. See the exported pilotSidebarStyles injection path in pilot-sidebar.tsx line 41 + 132-134. Overriding via CSS variables on any parent is idempotent and survives package upgrades. Patching the bundled styles via !important or a fork is a maintenance landmine.

Phases

Phase 1: inventory what the consumer wants to change

  • Colors / radius / shadow: CSS variables, Phase 2.
  • Label text / placeholder / buttons: labels prop, Phase 3.
  • Position (left/right) or width: props, Phase 4.
  • Suggestion chips on empty state: suggestions prop, Phase 5.
  • Fundamentally different layout (bottom-anchored, inline, modal): build a custom UI from PilotChatContext, Phase 6.

Phase 2: theme with CSS variables

Anywhere in the app's global CSS:

:root {
  --pilot-bg: #fff;
  --pilot-fg: #0a0a0a;
  --pilot-accent: #7c3aed;          /* send button, toggle pill, focus */
  --pilot-user-bubble-bg: #ede9fe;
  --pilot-radius: 12px;
  --pilot-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
}

Dark mode works automatically via prefers-color-scheme: dark (see pilot-sidebar.tsx line 257 in the header docstring). Consumers who want to force light or dark mode set the variables on an ancestor with data-theme or similar.

Phase 3: override labels

All six labels are optional; omitted keys use the built-in English defaults (see DEFAULT_LABELS in pilot-sidebar.tsx lines 91-98).

<PilotSidebar
  labels={{
    title: "Help",
    inputPlaceholder: "Describe what you want to do…",
    sendButton: "Ask",
    emptyState: "Hi! How can I help?",
    openButton: "Open help panel",
    closeButton: "Close help panel",
  }}
/>

The openButton and closeButton labels are important: they're used as the aria-label on the toggle and close controls (lines 221-224, 258-260). Localize them for accessibility.

Phase 4: position and width

<PilotSidebar
  position="left"        // default "right"
  width={420}            // default "380px"; number → px, string → any CSS unit
  defaultOpen={true}     // default false
/>

width accepts a number (rendered as px) or any CSS length string ("32rem", "50vw", "clamp(320px, 30vw, 540px)"). See lines 213-214.

position renders data-position="left|right" on the outer <aside> (line 246). The bundled styles mirror the slide-in and toggle based on that attribute.

Phase 5: suggestion chips

Only shown when messages.length === 0 (empty state). Clicking a chip calls sendMessage(chipText) and focuses the composer (lines 189-195, 280-294).

<PilotSidebar
  suggestions={[
    "What's still pending?",
    "Add 'buy milk' to my list",
    "Remove the first one",
  ]}
/>

Four to six chips is the practical maximum before they wrap awkwardly. Omit the prop entirely to hide the row.

Phase 6: build a custom UI from PilotChatContext

Drop the bundled sidebar when:

  • The app needs a bottom-anchored bar (ChatGPT-style), modal, inline thread, or slash-command input surface.
  • The design system is strongly opinionated and CSS-variable theming isn't enough.

The chat surface reads from PilotChatContext (exported from packages/agentickit/src/context.ts):

import { useContext } from "react";
import { PilotChatContext } from "@hec-ovi/agentickit";   // still under <Pilot>

function MyComposer() {
  const chat = useContext(PilotChatContext);
  if (!chat) return null;
  return (
    <form onSubmit={(e) => {
      e.preventDefault();
      const text = new FormData(e.currentTarget).get("q");
      if (typeof text === "string" && text.trim()) chat.sendMessage(text.trim());
    }}>
      <input name="q" disabled={chat.isLoading} />
      <button type="submit">Send</button>
    </form>
  );
}

PilotChatContextValue shape (from context.ts / pilot-provider.tsx lines 434-445):

  • messages: UIMessage[]
  • status: "idle" | "submitted" | "streaming" | "ready" | "error"
  • error: Error | undefined
  • isLoading: boolean (derived: status === "submitted" | "streaming")
  • sendMessage(text: string): Promise<void>
  • stop(): void

Render messages however the design calls for. The parts array is documented in the AI SDK's UIMessage type. For tool parts, check part.type === "tool-<name>" and part.state === "output-available".

Anti-Patterns

  • !important overrides in a global stylesheet "because the sidebar's styles are too specific". The sidebar styles are low-specificity by design; if you need !important, you're probably targeting the wrong selector.
  • Passing unstyled JSX into greeting that doesn't match the surrounding empty-state chrome. The greeting slot replaces the default empty text but keeps the parent .pilot-empty container.
  • Building a custom UI that still renders <PilotSidebar> hidden via display: none. Two copies of the message list re-render on every token. Pick one UI.
  • Forgetting to wrap the sidebar (bundled or custom) in a <Pilot> provider. The chat context is a tree context; no provider, no chat.

Output Format

After customization, report:

  • The CSS variables overridden (if any).
  • The labels / position / width / suggestions overridden (if any).
  • Whether the consumer kept <PilotSidebar> or built a custom UI from PilotChatContext.

Tools Used

  • Edit the consumer's global CSS to override --pilot-* variables.
  • Edit the component that renders <PilotSidebar> to pass props.
  • Read packages/agentickit/src/components/pilot-sidebar.tsx to verify the prop shape and available labels.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.