Skip to content
Open
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
16 changes: 10 additions & 6 deletions src/app/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { useEffect, useState } from 'react';

import { Box, Toolbar, useMediaQuery, useTheme } from '@mui/material';
import { Box, useMediaQuery, useTheme } from '@mui/material';

import { useShallow } from 'zustand/react/shallow';

import { ReflexContainer, ReflexElement, ReflexSplitter } from 'react-reflex';
import { Outlet } from 'react-router';

import { Toast } from 'src/components/AgentSkills/Toast';
import { Toast as AgentSkillsToast } from 'src/components/AgentSkills/Toast';
import { Navigation } from 'src/components/navigation/Navigation';
import ErrorBoundryWrapper from 'src/components/shared/ErrorBoundryWrapper';
import PageContainer from 'src/components/shared/PageContainer';
Expand Down Expand Up @@ -60,14 +60,19 @@ function AppLayout() {
return (
<Box sx={{ display: 'flex', height: '100vh' }}>
<Navigation />

<Toast docsPanelOpen={displaySidePanel} />
{
// Hide the toast while the docs panel is open so it cannot cover the
// cookie-consent banner that renders inside the docs.
!displaySidePanel ? <AgentSkillsToast /> : null
}

<Box
sx={{
flex: 1,
minWidth: 0,
height: '100%',
overflow: 'hidden',
pt: 2,
}}
>
<ReflexContainer orientation="vertical">
Expand All @@ -81,9 +86,8 @@ function AppLayout() {
: undefined,
}}
>
<Box className="pane-content">
<Box className="pane-content" sx={{ height: '100%' }}>
<ErrorBoundryWrapper>
<Toolbar />
<PageContainer>
<Outlet />
</PageContainer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@ import { Box, Link, Paper, Tooltip, Typography, useTheme } from '@mui/material';

import { usePostHog } from '@posthog/react';
import { NavArrowRight } from 'iconoir-react';
import { useIntl } from 'react-intl';

import {
AGENT_SKILLS_URL,
BG_GRADIENT,
GRADIENT,
LINK_COLOR,
SECONDARY_TEXT_COLOR,
SHIMMER_STYLES,
Expand All @@ -18,7 +15,6 @@ import { SparkleIcon } from 'src/components/AgentSkills/SparkleIcon';
function TooltipContent({ onClick }: { onClick: () => void }) {
const theme = useTheme();
const mode = theme.palette.mode;
const intl = useIntl();

return (
<Paper
Expand Down Expand Up @@ -49,9 +45,7 @@ function TooltipContent({ onClick }: { onClick: () => void }) {
mb: 0.5,
}}
>
{intl.formatMessage({
id: 'agentSkills.title',
})}
Meet Estuary Agent Skills
</Typography>
<Typography
sx={{
Expand All @@ -61,9 +55,9 @@ function TooltipContent({ onClick }: { onClick: () => void }) {
mb: '10px',
}}
>
{intl.formatMessage({
id: 'agentSkills.description',
})}
Give any AI agent the skills to build connectors, debug
pipelines, and check stats on Estuary, from wherever you
work.
</Typography>
<Box
component="span"
Expand All @@ -76,20 +70,15 @@ function TooltipContent({ onClick }: { onClick: () => void }) {
gap: 0.5,
}}
>
{intl.formatMessage({
id: 'agentSkills.cta',
})}
<NavArrowRight width={16} height={16} />
Read the docs
<NavArrowRight style={{ fontSize: 16 }} />
</Box>
</Box>
</Paper>
);
}

export function HeaderPill() {
const theme = useTheme();
const mode = theme.palette.mode;
const intl = useIntl();
export function Pill() {
const postHog = usePostHog();
const toastDismissed = useAgentSkillsStore((s) => s.toastDismissed);

Expand All @@ -113,9 +102,9 @@ export function HeaderPill() {
}}
/>
}
placement="bottom-end"
placement="bottom-start"
enterDelay={200}
leaveDelay={150}
leaveDelay={100}
slotProps={{
tooltip: {
sx: {
Expand All @@ -137,54 +126,49 @@ export function HeaderPill() {
})
}
sx={{
'display': 'inline-flex',
'display': 'flex',
'width': '100%',
'alignItems': 'center',
'justifyContent': 'flex-start',
'gap': 1,
'height': 36,
'px': '14px',
'pl': '10px',
'borderRadius': '999px',
'background': BG_GRADIENT[mode],
'border': '1px solid rgba(46,100,235,0.22)',
'py': '6px',
'px': '10px',
'borderRadius': '8px',
'color': 'text.primary',
'fontSize': 13,
'fontWeight': 600,
'transition': 'transform 200ms ease',
'fontWeight': 400,
'cursor': 'pointer',
'transition':
'background 180ms ease, transform 180ms ease, box-shadow 180ms ease',
'&:hover': {
background:
'linear-gradient(135deg, rgba(46,100,235,0.14) 0%, rgba(54,197,176,0.16) 100%)',
borderColor: 'rgba(46,100,235,0.42)',
boxShadow: '0 6px 16px -6px rgba(46,100,235,0.35)',
transform: 'translateY(-1px)',
},
}}
>
<Box
<SparkleIcon
sx={{
width: 22,
height: 22,
borderRadius: '999px',
background: GRADIENT[mode],
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
boxShadow:
'inset 0 0 0 1px rgba(255,255,255,0.25), 0 2px 6px -2px rgba(46,100,235,0.55)',
fontSize: 21,
color: 'inherit',
flexShrink: 0,
}}
>
<SparkleIcon
sx={{ width: 14, height: 14, color: 'common.white' }}
/>
</Box>
/>
<Typography
component="span"
sx={{
my: 0.5,
flex: '1 1 auto',
minWidth: 0,
overflow: 'hidden',
whiteSpace: 'nowrap',
textOverflow: 'ellipsis',
fontSize: 'inherit',
fontWeight: 'inherit',
color: 'inherit',
}}
>
{intl.formatMessage({ id: 'agentSkills.pill.label' })}
Agent Skills
</Typography>
</Link>
</Tooltip>
Expand Down
59 changes: 24 additions & 35 deletions src/components/AgentSkills/Toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import type { MouseEvent } from 'react';

import {
Box,
Chip,
IconButton,
keyframes,
Link,
Expand All @@ -12,7 +11,6 @@ import {

import { usePostHog } from '@posthog/react';
import { NavArrowRight, Xmark } from 'iconoir-react';
import { useIntl } from 'react-intl';

import {
AGENT_SKILLS_URL,
Expand All @@ -23,28 +21,20 @@ import {
useAgentSkillsStore,
} from 'src/components/AgentSkills/shared';
import { SparkleIcon } from 'src/components/AgentSkills/SparkleIcon';
import { toastIndex } from 'src/context/Theme';

const toastIn = keyframes`
0% { opacity: 0; transform: translateY(16px) scale(0.98); }
100% { opacity: 1; transform: translateY(0) scale(1); }
`;

interface ToastProps {
docsPanelOpen?: boolean;
}

export function Toast({ docsPanelOpen }: ToastProps) {
export function Toast() {
const theme = useTheme();
const mode = theme.palette.mode;
const intl = useIntl();
const postHog = usePostHog();
const toastDismissed = useAgentSkillsStore((s) => s.toastDismissed);
const dismissToast = useAgentSkillsStore((s) => s.dismissToast);

// If the docs panel is open just hide the toast. That way it cannot cover up
// the cookie consent banner in the docs.
if (toastDismissed || docsPanelOpen) {
if (toastDismissed) {
return null;
}

Expand All @@ -71,7 +61,7 @@ export function Toast({ docsPanelOpen }: ToastProps) {
'display': 'block',
'animation': `${toastIn} 750ms cubic-bezier(.2,.9,.25,1) 1s both`,
'transition': 'transform 200ms ease, box-shadow 200ms ease',
'zIndex': toastIndex,
'zIndex': theme.zIndex.snackbar,
'&:hover': {
transform: 'translateY(-2px)',
boxShadow:
Expand Down Expand Up @@ -127,21 +117,22 @@ export function Toast({ docsPanelOpen }: ToastProps) {
mb: 0.5,
}}
>
<Chip
label={intl.formatMessage({
id: 'agentSkills.badge',
})}
size="small"
<Box
component="span"
sx={{
fontSize: 10,
fontWeight: 700,
textTransform: 'uppercase',
color: LINK_COLOR,
bgcolor: '#eaf0ff',
height: 'auto',
background: '#eaf0ff',
px: '7px',
py: '2px',
borderRadius: '999px',
lineHeight: 1.4,
}}
/>
>
New
</Box>
<Typography
component="span"
sx={{
Expand All @@ -150,9 +141,7 @@ export function Toast({ docsPanelOpen }: ToastProps) {
fontWeight: 500,
}}
>
{intl.formatMessage({
id: 'agentSkills.eyebrow',
})}
For Claude, Cursor, Codex and more
</Typography>
</Box>

Expand All @@ -166,7 +155,7 @@ export function Toast({ docsPanelOpen }: ToastProps) {
mb: 0.5,
}}
>
{intl.formatMessage({ id: 'agentSkills.title' })}
Meet Estuary Agent Skills
</Typography>

<Typography
Expand All @@ -177,7 +166,9 @@ export function Toast({ docsPanelOpen }: ToastProps) {
mb: '10px',
}}
>
{intl.formatMessage({ id: 'agentSkills.description' })}
Give any AI agent the skills to build connectors, debug
pipelines, and check stats on Estuary, from wherever you
work.
</Typography>

<Link
Expand All @@ -195,13 +186,13 @@ export function Toast({ docsPanelOpen }: ToastProps) {
gap: 0.25,
}}
>
{intl.formatMessage({ id: 'agentSkills.cta' })}
Read the docs
<NavArrowRight
className="cta-arrow"
width={17}
height={17}
strokeWidth={1.8}
style={{ transition: 'transform 200ms ease' }}
style={{
fontSize: 14,
transition: 'transform 200ms ease',
}}
/>
</Link>
</Box>
Expand All @@ -216,9 +207,7 @@ export function Toast({ docsPanelOpen }: ToastProps) {
});
dismissToast();
}}
aria-label={intl.formatMessage({
id: 'agentSkills.dismiss',
})}
aria-label="Dismiss"
sx={{
'width': 20,
'height': 20,
Expand All @@ -227,7 +216,7 @@ export function Toast({ docsPanelOpen }: ToastProps) {
'&:hover': { color: '#475569', background: 'none' },
}}
>
<Xmark width={20} height={20} />
<Xmark style={{ fontSize: 20 }} />
</IconButton>
</Box>
</Box>
Expand Down
5 changes: 0 additions & 5 deletions src/components/AgentSkills/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,6 @@ export const GRADIENT = {
dark: 'linear-gradient(135deg, #1a4bcb 0%, #3a6fd4 45%, #2a9e8c 100%)',
};

export const BG_GRADIENT = {
light: 'linear-gradient(135deg, rgba(46,100,235,0.08) 0%, rgba(54,197,176,0.10) 100%)',
dark: 'linear-gradient(180deg, rgba(46,100,235,0.12) 0%, rgba(54,197,176,0.16) 100%)',
};

export const SECONDARY_TEXT_COLOR = {
light: '#475569',
dark: '#94a3b8',
Expand Down
Loading
Loading