mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-28 04:24:51 +02:00
[eric] ui: crisp reddit mark + island search polish
This commit is contained in:
@@ -4,7 +4,6 @@ import Typography from '@mui/material/Typography';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import Tooltip from '@mui/material/Tooltip';
|
||||
import Collapse from '@mui/material/Collapse';
|
||||
import SearchIcon from '@mui/icons-material/Search';
|
||||
import StopCircleOutlinedIcon from '@mui/icons-material/StopCircleOutlined';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import CheckIcon from '@mui/icons-material/Check';
|
||||
@@ -239,7 +238,7 @@ const DynamicIsland: React.FC = () => {
|
||||
const [userExpanded, setUserExpanded] = useState(false);
|
||||
const [searchOpen, setSearchOpen] = useState(false);
|
||||
|
||||
// Global Cmd/Ctrl+K opens search palette from anywhere.
|
||||
// Global Cmd/Ctrl+K, or the sidebar search pill, opens the palette from anywhere.
|
||||
useEffect(() => {
|
||||
const handler = (e: KeyboardEvent) => {
|
||||
if ((e.metaKey || e.ctrlKey) && !e.shiftKey && !e.altKey && e.key.toLowerCase() === 'k') {
|
||||
@@ -247,8 +246,13 @@ const DynamicIsland: React.FC = () => {
|
||||
setSearchOpen((prev) => !prev);
|
||||
}
|
||||
};
|
||||
const openFromSidebar = (): void => setSearchOpen(true);
|
||||
window.addEventListener('keydown', handler);
|
||||
return () => window.removeEventListener('keydown', handler);
|
||||
window.addEventListener('openswarm:open-search', openFromSidebar);
|
||||
return () => {
|
||||
window.removeEventListener('keydown', handler);
|
||||
window.removeEventListener('openswarm:open-search', openFromSidebar);
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Cmd/Ctrl+L: clear the chat (focused card > activeSessionId > sole session); same as /clear.
|
||||
@@ -501,6 +505,8 @@ const DynamicIsland: React.FC = () => {
|
||||
return (
|
||||
<>
|
||||
{islandState === 'compact-actionable' && <style>{glowKeyframes}</style>}
|
||||
{/* Search moved to the sidebar, so the island only appears for live agent activity, not idle. */}
|
||||
{islandState !== 'idle' && (
|
||||
<motion.div
|
||||
ref={islandRef}
|
||||
layout
|
||||
@@ -538,9 +544,6 @@ const DynamicIsland: React.FC = () => {
|
||||
}}
|
||||
>
|
||||
<AnimatePresence mode="wait">
|
||||
{islandState === 'idle' && (
|
||||
<IdlePill key="idle" c={c} onClick={() => setSearchOpen(true)} />
|
||||
)}
|
||||
{islandState === 'compact' && (
|
||||
<CompactPill
|
||||
key="compact"
|
||||
@@ -584,65 +587,12 @@ const DynamicIsland: React.FC = () => {
|
||||
</AnimatePresence>
|
||||
</motion.div>
|
||||
</motion.div>
|
||||
)}
|
||||
<GlobalSearchPalette open={searchOpen} onClose={() => setSearchOpen(false)} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const isMac = typeof navigator !== 'undefined' && /Mac|iPod|iPhone|iPad/.test(navigator.platform);
|
||||
const SEARCH_HOTKEY = isMac ? '⌘K' : 'Ctrl+K';
|
||||
|
||||
const IdlePill: React.FC<{ c: ReturnType<typeof useClaudeTokens>; onClick: () => void }> = ({ c, onClick }) => (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, scale: 0.92 }}
|
||||
animate={{ opacity: 1, scale: 1 }}
|
||||
exit={{ opacity: 0, scale: 0.92 }}
|
||||
transition={{ duration: 0.2 }}
|
||||
>
|
||||
<Tooltip title={`Search (${SEARCH_HOTKEY})`} arrow placement="bottom">
|
||||
<Box
|
||||
onClick={(e) => { e.stopPropagation(); onClick(); }}
|
||||
sx={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: 1,
|
||||
px: 1.5,
|
||||
height: 30,
|
||||
userSelect: 'none',
|
||||
cursor: 'pointer',
|
||||
transition: 'background 0.15s',
|
||||
'&:hover': { bgcolor: 'rgba(255,255,255,0.04)' },
|
||||
}}
|
||||
>
|
||||
<SearchIcon sx={{ fontSize: 16, color: c.text.muted, flexShrink: 0 }} />
|
||||
<Typography
|
||||
sx={{
|
||||
color: c.text.muted,
|
||||
fontSize: '0.78rem',
|
||||
fontWeight: 400,
|
||||
lineHeight: 1,
|
||||
whiteSpace: 'nowrap',
|
||||
flex: 1,
|
||||
}}
|
||||
>
|
||||
Search…
|
||||
</Typography>
|
||||
<Typography
|
||||
sx={{
|
||||
color: c.text.ghost,
|
||||
fontSize: '0.7rem',
|
||||
fontFamily: c.font.mono,
|
||||
lineHeight: 1,
|
||||
opacity: 0.7,
|
||||
}}
|
||||
>
|
||||
{SEARCH_HOTKEY}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Tooltip>
|
||||
</motion.div>
|
||||
);
|
||||
|
||||
const CompactPill: React.FC<{
|
||||
c: ReturnType<typeof useClaudeTokens>;
|
||||
text: string;
|
||||
|
||||
@@ -70,8 +70,7 @@ export const INTEGRATIONS: Integration[] = [
|
||||
connectInstructions: 'Uses your own Reddit account: open reddit.com in an OpenSwarm browser card and sign in once. Nothing is stored, the integration borrows your live session per request and paces itself to stay within human limits.',
|
||||
icon: (
|
||||
<svg viewBox="0 0 24 24" width="22" height="22">
|
||||
<circle cx="12" cy="12" r="12" fill="#FF4500"/>
|
||||
<path d="M19.5 12c0-.6-.5-1.1-1.1-1.1-.3 0-.6.1-.8.3-1-.7-2.3-1.1-3.7-1.1l.6-3 2.1.5c0 .6.5 1.1 1.1 1.1.6 0 1.1-.5 1.1-1.1 0-.6-.5-1.1-1.1-1.1-.4 0-.8.3-1 .6l-2.3-.5c-.1 0-.2 0-.2.1l-.7 3.3c-1.4 0-2.7.4-3.7 1.1-.2-.2-.5-.3-.8-.3-.6 0-1.1.5-1.1 1.1 0 .4.2.8.6 1-.1.3-.1.6-.1.9 0 2.3 2.6 4.1 5.8 4.1s5.8-1.8 5.8-4.1c0-.3 0-.6-.1-.9.4-.2.6-.6.6-1zm-9.8 1.1c0-.6.5-1.1 1.1-1.1.6 0 1.1.5 1.1 1.1 0 .6-.5 1.1-1.1 1.1-.6 0-1.1-.5-1.1-1.1zm6.2 2.9c-.8.8-2 .9-2.9.9s-2.1-.1-2.9-.9c-.1-.1-.1-.3 0-.4.1-.1.3-.1.4 0 .6.6 1.6.8 2.5.8s1.9-.2 2.5-.8c.1-.1.3-.1.4 0 .1.1.1.3 0 .4zm-.2-1.8c-.6 0-1.1-.5-1.1-1.1 0-.6.5-1.1 1.1-1.1.6 0 1.1.5 1.1 1.1 0 .6-.5 1.1-1.1 1.1z" fill="#fff"/>
|
||||
<path fill="#FF4500" d="M12 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0zm5.01 4.744c.688 0 1.25.561 1.25 1.249a1.25 1.25 0 0 1-2.498.056l-2.597-.547-.8 3.747c1.824.07 3.48.632 4.674 1.488.308-.309.73-.491 1.207-.491.968 0 1.754.786 1.754 1.754 0 .716-.435 1.333-1.01 1.614a3.111 3.111 0 0 1 .042.52c0 2.694-3.13 4.87-7.004 4.87-3.874 0-7.004-2.176-7.004-4.87 0-.183.015-.366.043-.534A1.748 1.748 0 0 1 4.028 12c0-.968.786-1.754 1.754-1.754.463 0 .898.196 1.207.49 1.207-.883 2.878-1.43 4.744-1.487l.885-4.182a.342.342 0 0 1 .14-.197.35.35 0 0 1 .238-.042l2.906.617a1.214 1.214 0 0 1 1.108-.701zM9.25 12C8.561 12 8 12.562 8 13.25c0 .687.561 1.248 1.25 1.248.687 0 1.248-.561 1.248-1.249 0-.688-.561-1.249-1.249-1.249zm5.5 0c-.687 0-1.248.561-1.248 1.25 0 .687.561 1.248 1.249 1.248.688 0 1.249-.561 1.249-1.249 0-.688-.562-1.249-1.25-1.249zm-5.466 3.99a.327.327 0 0 0-.231.094.33.33 0 0 0 0 .463c.842.842 2.484.91 2.961.91.477 0 2.105-.056 2.961-.91a.361.361 0 0 0 .029-.463.33.33 0 0 0-.464 0c-.547.533-1.684.73-2.512.73-.828 0-1.979-.196-2.512-.73a.326.326 0 0 0-.232-.095z"/>
|
||||
</svg>
|
||||
),
|
||||
},
|
||||
@@ -129,7 +128,10 @@ export const INTEGRATIONS: Integration[] = [
|
||||
website: 'https://www.npmjs.com/package/@softeria/ms-365-mcp-server',
|
||||
icon: (
|
||||
<svg viewBox="0 0 24 24" width="22" height="22">
|
||||
<path d="M11.4 24H0V12.6L11.4 24zM24 24H12.6V12.6L24 24zM11.4 11.4H0V0l11.4 11.4zM24 11.4H12.6V0L24 11.4z" fill="#0078D4"/>
|
||||
<rect x="1" y="1" width="10.4" height="10.4" fill="#F25022"/>
|
||||
<rect x="12.6" y="1" width="10.4" height="10.4" fill="#7FBA00"/>
|
||||
<rect x="1" y="12.6" width="10.4" height="10.4" fill="#00A4EF"/>
|
||||
<rect x="12.6" y="12.6" width="10.4" height="10.4" fill="#FFB900"/>
|
||||
</svg>
|
||||
),
|
||||
authType: 'device_code',
|
||||
|
||||
Reference in New Issue
Block a user