mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-08-28 05:25:33 +00:00
company brain responsiveness (#1239)
## Summary - Improves the Company Brain header and stats cards on mobile without changing the desktop layout intent. - Tightens the mobile Slack banner so the Slack logo is not duplicated and the card stays compact. - Centers the onboarding step flow and card as one stack while keeping the logo independent. before: <img width="388" height="864" alt="image" src="https://github.com/user-attachments/assets/f02890e4-78d1-45cf-a819-97306df20d5c" /> after: <img width="193" height="431" alt="image" src="https://github.com/user-attachments/assets/1b5d6907-1dc1-4d95-9b4f-2b40defecda5" /> <img width="391" height="865" alt="image" src="https://github.com/user-attachments/assets/67fb6009-bace-4c78-9b72-b4dfcdd79b90" /> <img width="385" height="865" alt="image" src="https://github.com/user-attachments/assets/f3c3d785-762e-49c2-92bb-461358eda418" /> <img width="394" height="865" alt="image" src="https://github.com/user-attachments/assets/f5943779-a141-467d-a350-80678f3a2513" />
This commit is contained in:
parent
ef0026a23c
commit
8d926332ab
8 changed files with 156 additions and 99 deletions
|
|
@ -86,8 +86,6 @@ export default function BrainOnboardingPage() {
|
|||
() => workspaceDomainFromEmail(user?.email),
|
||||
[user?.email],
|
||||
)
|
||||
|
||||
// Team (Company Brain) onboarding is gated behind a private-beta flag.
|
||||
const allowTeam = useFeatureFlagEnabled("company-brain-beta") ?? false
|
||||
const [mode, setMode] = useState<BrainMode>(detectedMode)
|
||||
const [about, setAbout] = useState<AboutValues>({
|
||||
|
|
@ -339,8 +337,6 @@ export default function BrainOnboardingPage() {
|
|||
setCreatingOrg(false)
|
||||
}
|
||||
}, [ensureOrg, goNext, forceCreate, organizations, router])
|
||||
|
||||
// Company Brain (team) onboarding is a single research surface, no stepper.
|
||||
const isCompanyBrain = allowTeam && mode === "team"
|
||||
|
||||
const handleBrainConfirm = useCallback(
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ function StatsRow({
|
|||
<button
|
||||
type="button"
|
||||
onClick={onInvite}
|
||||
className="inline-flex items-center gap-1 text-[11px] font-medium text-[#737373] transition-colors hover:text-[#fafafa]"
|
||||
className="hidden items-center gap-1 text-[11px] font-medium text-[#737373] transition-colors hover:text-[#fafafa] sm:inline-flex"
|
||||
>
|
||||
<UserPlus className="size-3" />
|
||||
Invite
|
||||
|
|
@ -235,31 +235,64 @@ function StatsRow({
|
|||
]
|
||||
return (
|
||||
<section
|
||||
className="grid grid-cols-2 divide-white/[0.04] rounded-[16px] bg-[#1B1F24] sm:grid-cols-4 sm:divide-x"
|
||||
className="grid grid-cols-4 divide-x divide-white/[0.04] overflow-hidden rounded-[16px] bg-[#1B1F24]"
|
||||
style={cardStyle}
|
||||
>
|
||||
{tiles.map((t) => (
|
||||
<div key={t.label} className="px-5 py-4">
|
||||
<div className="flex items-start justify-between gap-2">
|
||||
<p className="text-[10px] font-semibold uppercase tracking-[0.12em] text-[#737373]">
|
||||
{t.label}
|
||||
{tiles.map((t, index) => (
|
||||
<div
|
||||
key={t.label}
|
||||
className={cn(
|
||||
"relative min-w-0 px-3 py-3 sm:px-5 sm:py-4",
|
||||
index === 2 && canInvite && "pr-8 sm:pr-5",
|
||||
)}
|
||||
>
|
||||
<div className="flex min-w-0 items-start justify-between gap-2">
|
||||
<p className="min-w-0 truncate text-[8px] font-semibold uppercase leading-tight tracking-[0.08em] text-[#737373] sm:text-[10px] sm:tracking-[0.12em]">
|
||||
<MobileStatLabel label={t.label} />
|
||||
</p>
|
||||
{t.action}
|
||||
</div>
|
||||
<p
|
||||
className={cn(
|
||||
"mt-1.5 text-[22px] font-semibold leading-none tabular-nums text-[#fafafa]",
|
||||
"mt-1 text-[17px] font-semibold leading-none tabular-nums text-[#fafafa] sm:mt-1.5 sm:text-[22px]",
|
||||
dmSans125ClassName(),
|
||||
)}
|
||||
>
|
||||
{t.value}
|
||||
</p>
|
||||
{index === 2 && canInvite && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onInvite}
|
||||
aria-label="Invite teammates"
|
||||
title="Invite teammates"
|
||||
className="absolute right-1.5 bottom-1.5 inline-flex size-6 items-center justify-center rounded-md bg-white/[0.03] text-[#737373] transition-colors hover:bg-white/[0.07] hover:text-[#fafafa] sm:hidden"
|
||||
>
|
||||
<UserPlus className="size-3" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
function MobileStatLabel({ label }: { label: string }) {
|
||||
const mobile =
|
||||
label === "Connected sources"
|
||||
? "Sources"
|
||||
: label === "Active members"
|
||||
? "Members"
|
||||
: label
|
||||
|
||||
return (
|
||||
<>
|
||||
<span className="sm:hidden">{mobile}</span>
|
||||
<span className="hidden sm:inline">{label}</span>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function RecentMemories({
|
||||
docs,
|
||||
loading,
|
||||
|
|
|
|||
|
|
@ -411,7 +411,7 @@ function TileSkeleton({ showDivider = false }: { showDivider?: boolean }) {
|
|||
function SlackBanner() {
|
||||
return (
|
||||
<section
|
||||
className="relative overflow-hidden rounded-[18px] bg-[#1B1F24] p-5"
|
||||
className="relative overflow-hidden rounded-[18px] bg-[#1B1F24] p-3.5 sm:p-5"
|
||||
style={cardStyle}
|
||||
>
|
||||
<div
|
||||
|
|
@ -422,37 +422,45 @@ function SlackBanner() {
|
|||
"linear-gradient(to right, transparent, rgba(75,160,250,0.45), transparent)",
|
||||
}}
|
||||
/>
|
||||
<div className="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between">
|
||||
<div className="flex items-center gap-3.5">
|
||||
<div className="flex items-center justify-between gap-3 sm:gap-4">
|
||||
<div className="flex min-w-0 items-center gap-3 sm:gap-3.5">
|
||||
<div
|
||||
className="flex size-12 shrink-0 items-center justify-center rounded-[12px] border border-[rgba(82,89,102,0.2)] bg-[#080B0F]"
|
||||
className="flex size-10 shrink-0 items-center justify-center rounded-[12px] border border-[rgba(82,89,102,0.2)] bg-[#080B0F] sm:size-12"
|
||||
style={tileStyle}
|
||||
>
|
||||
<SlackMark className="size-7" />
|
||||
<SlackMark className="size-6 sm:size-7" />
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<p
|
||||
className={cn(
|
||||
"text-[16px] font-semibold text-[#fafafa]",
|
||||
"truncate text-[15px] font-semibold leading-tight text-[#fafafa] sm:text-[16px]",
|
||||
dmSans125ClassName(),
|
||||
)}
|
||||
>
|
||||
Company Brain in Slack
|
||||
<span className="sm:hidden">Slack agent</span>
|
||||
<span className="hidden sm:inline">Company Brain in Slack</span>
|
||||
</p>
|
||||
<p className="mt-0.5 text-[13px] font-medium leading-[1.5] text-[#737373]">
|
||||
Install Supermemory so your team can{" "}
|
||||
<span className="text-[#A1A1AA]">@supermemory</span> in any
|
||||
channel.
|
||||
<p className="mt-1 truncate text-[12px] font-medium leading-[1.45] text-[#737373] sm:mt-0.5 sm:text-[13px] sm:leading-[1.5]">
|
||||
<span className="sm:hidden">
|
||||
Ask <span className="text-[#A1A1AA]">@supermemory</span> from
|
||||
any channel.
|
||||
</span>
|
||||
<span className="hidden sm:inline">
|
||||
Install Supermemory so your team can{" "}
|
||||
<span className="text-[#A1A1AA]">@supermemory</span> in any
|
||||
channel.
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a
|
||||
href={`${BACKEND}/brain/slack/oauth/install`}
|
||||
className="inline-flex shrink-0 items-center gap-2 self-start rounded-lg bg-white px-4 py-2.5 text-[14px] font-semibold text-[#1D1C1D] transition-transform hover:scale-[1.02] sm:self-auto"
|
||||
className="inline-flex shrink-0 items-center justify-center rounded-lg bg-white px-3 py-1.5 text-[13px] font-semibold text-[#1D1C1D] transition-transform hover:scale-[1.02] sm:gap-2 sm:px-4 sm:py-2.5 sm:text-[14px]"
|
||||
>
|
||||
<SlackMark className="size-[18px]" />
|
||||
Add to Slack
|
||||
<SlackMark className="hidden sm:block sm:size-[18px]" />
|
||||
<span className="sm:hidden">Add</span>
|
||||
<span className="hidden sm:inline">Add to Slack</span>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -184,16 +184,16 @@ export function CompanyBrainHeader({ onOpenSearch }: CompanyBrainHeaderProps) {
|
|||
}, [setFeedbackOpen])
|
||||
|
||||
return (
|
||||
<div className="relative z-10 flex shrink-0 items-center justify-between gap-1.5 p-2.5 md:gap-2 md:p-3">
|
||||
<div className="z-10! flex min-w-0 shrink items-center justify-center gap-1.5 md:gap-3">
|
||||
<div className="relative z-10 flex shrink-0 items-center justify-between gap-1 px-2 py-2 md:gap-2 md:p-3">
|
||||
<div className="z-10! flex min-w-0 flex-1 shrink items-center justify-start gap-1.5 md:flex-none md:justify-center md:gap-3">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
className="relative flex max-w-[min(52vw,240px)] shrink-0 cursor-pointer items-center rounded-lg px-1.5 py-1 transition-colors hover:bg-white/5 outline-none focus-visible:outline-none md:-ml-2 before:absolute before:-inset-x-2 before:-inset-y-2.5 before:content-['']"
|
||||
className="relative flex min-w-0 max-w-[31vw] shrink cursor-pointer items-center rounded-lg px-1 py-1 transition-colors hover:bg-white/5 outline-none focus-visible:outline-none min-[380px]:max-w-[9rem] sm:max-w-[min(52vw,240px)] md:-ml-2 md:max-w-[min(52vw,240px)] md:shrink-0 md:px-1.5 before:absolute before:-inset-x-1 before:-inset-y-2 before:content-[''] md:before:-inset-x-2 md:before:-inset-y-2.5"
|
||||
>
|
||||
<div
|
||||
className="flex size-8 shrink-0 items-center justify-center overflow-hidden rounded-[8px] border border-[rgba(82,89,102,0.2)] bg-[#14161A]"
|
||||
className="flex size-7 shrink-0 items-center justify-center overflow-hidden rounded-[8px] border border-[rgba(82,89,102,0.2)] bg-[#14161A] sm:size-8"
|
||||
style={{
|
||||
boxShadow:
|
||||
"0px 1px 2px 0px rgba(0,43,87,0.1), inset 0px 0px 0px 1px rgba(43,49,67,0.08)",
|
||||
|
|
@ -205,7 +205,7 @@ export function CompanyBrainHeader({ onOpenSearch }: CompanyBrainHeaderProps) {
|
|||
<Building2 className="size-4 text-[#737373]" />
|
||||
)}
|
||||
</div>
|
||||
<div className="ml-2 min-w-0 flex flex-col items-start justify-center">
|
||||
<div className="ml-1.5 min-w-0 flex flex-col items-start justify-center max-[340px]:hidden sm:ml-2">
|
||||
<p className="max-w-full truncate text-[10px] leading-tight text-[#6B6B6B] sm:text-[11px]">
|
||||
Company Brain
|
||||
</p>
|
||||
|
|
@ -381,7 +381,7 @@ export function CompanyBrainHeader({ onOpenSearch }: CompanyBrainHeaderProps) {
|
|||
</div>
|
||||
)}
|
||||
|
||||
<div className="z-10! flex shrink-0 items-center gap-1.5">
|
||||
<div className="z-10! flex min-w-0 shrink-0 items-center gap-1.5">
|
||||
{isMobile ? (
|
||||
<>
|
||||
<SpaceSelector
|
||||
|
|
@ -389,12 +389,14 @@ export function CompanyBrainHeader({ onOpenSearch }: CompanyBrainHeaderProps) {
|
|||
onValueChange={setSelectedProjects}
|
||||
enableDelete={false}
|
||||
compact
|
||||
triggerClassName="max-w-[34vw] shrink min-[380px]:max-w-[9rem]"
|
||||
/>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
variant="headers"
|
||||
className="rounded-full text-base gap-2 h-10!"
|
||||
aria-label="Open navigation menu"
|
||||
className="size-9! min-h-9 min-w-9 rounded-full px-0! text-base"
|
||||
>
|
||||
<MenuIcon className="size-4" />
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -43,12 +43,21 @@ const BACKEND =
|
|||
type Phase = "confirm" | "research"
|
||||
|
||||
function normalizeDomain(input: string): string {
|
||||
return input
|
||||
const host = input
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replace(/^https?:\/\//, "")
|
||||
.replace(/^www\./, "")
|
||||
.replace(/\/.*$/, "")
|
||||
|
||||
// The confirmation card is often filled with a company name (for example,
|
||||
// "Zomato") even though research needs a hostname. Preserve explicit TLDs,
|
||||
// and make the common single-label case usable without a failed API round trip.
|
||||
if (/^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$/.test(host)) {
|
||||
return `${host}.com`
|
||||
}
|
||||
|
||||
return host
|
||||
}
|
||||
|
||||
export function CompanyBrainOnboarding({
|
||||
|
|
@ -306,30 +315,35 @@ function DockedHeader({
|
|||
}) {
|
||||
const brandName = workspaceNameFromDomain(domain) || domain
|
||||
return (
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex min-w-0 items-center gap-3">
|
||||
<div
|
||||
className="size-8 rounded-[8px] bg-[#14161A] border border-[rgba(82,89,102,0.2)] flex items-center justify-center overflow-hidden shrink-0"
|
||||
style={inputBevelStyle}
|
||||
>
|
||||
<DomainLogo domain={domain} />
|
||||
</div>
|
||||
<span className="text-[14px] font-semibold text-[#fafafa]">
|
||||
{brandName}
|
||||
</span>
|
||||
<span
|
||||
className={cn(
|
||||
"text-[12px] font-medium",
|
||||
done ? "text-[#5CD68A]" : "text-[#737373]",
|
||||
)}
|
||||
>
|
||||
{done ? "Company Brain ready" : "Building your Company Brain…"}
|
||||
</span>
|
||||
<div className="flex min-w-0 flex-1 flex-col md:flex-row md:items-center md:gap-3">
|
||||
<span
|
||||
title={brandName}
|
||||
className="min-w-0 truncate text-[14px] font-semibold text-[#fafafa] md:flex-1"
|
||||
>
|
||||
{brandName}
|
||||
</span>
|
||||
<span
|
||||
className={cn(
|
||||
"shrink-0 whitespace-nowrap text-[12px] font-medium",
|
||||
done ? "text-[#5CD68A]" : "text-[#737373]",
|
||||
)}
|
||||
>
|
||||
{done ? "Company Brain ready" : "Building your Company Brain…"}
|
||||
</span>
|
||||
</div>
|
||||
{done ? (
|
||||
<Button
|
||||
type="button"
|
||||
onClick={onContinue}
|
||||
className={cn(
|
||||
"ml-auto rounded-full bg-white px-4 py-2 text-[13px] font-semibold text-[#1D1C1D] shadow-[0_4px_24px_rgba(75,160,250,0.25)] hover:bg-white/95",
|
||||
"ml-auto shrink-0 rounded-full bg-white px-4 py-2 text-[13px] font-semibold text-[#1D1C1D] shadow-[0_4px_24px_rgba(75,160,250,0.25)] hover:bg-white/95",
|
||||
dmSans125ClassName(),
|
||||
)}
|
||||
>
|
||||
|
|
@ -337,7 +351,7 @@ function DockedHeader({
|
|||
<ArrowRight className="size-3.5" />
|
||||
</Button>
|
||||
) : (
|
||||
<Loader2 className="size-3.5 animate-spin text-[#4BA0FA] ml-auto" />
|
||||
<Loader2 className="ml-auto size-3.5 shrink-0 animate-spin text-[#4BA0FA]" />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ export function BrainShell({ step, steps, children }: ShellProps) {
|
|||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"relative min-h-dvh bg-[#05080D] text-[#FAFAFA] flex flex-col overflow-hidden",
|
||||
"relative min-h-dvh overflow-hidden bg-[#05080D] text-[#FAFAFA]",
|
||||
dmSansClassName(),
|
||||
)}
|
||||
>
|
||||
|
|
@ -46,20 +46,25 @@ export function BrainShell({ step, steps, children }: ShellProps) {
|
|||
}}
|
||||
/>
|
||||
|
||||
<header className="relative z-10 grid grid-cols-[1fr_auto_1fr] items-center px-6 md:px-10 py-4 gap-4">
|
||||
<LogoFull className="h-5 md:h-6 text-[#fafafa] justify-self-start" />
|
||||
<StepIndicator step={step} visibleSteps={visibleSteps} />
|
||||
<header className="pointer-events-none absolute inset-x-0 top-0 z-20 grid grid-cols-[1fr_auto_1fr] items-center gap-4 px-4 py-4 md:px-10">
|
||||
<LogoFull className="h-5 text-[#fafafa] md:h-6" />
|
||||
<div className="hidden justify-center md:flex">
|
||||
<StepIndicator step={step} visibleSteps={visibleSteps} />
|
||||
</div>
|
||||
<span aria-hidden />
|
||||
</header>
|
||||
|
||||
<main
|
||||
className={cn(
|
||||
"relative z-10 flex-1 flex justify-center px-4 md:px-10 py-6 md:py-10",
|
||||
"relative z-10 flex min-h-dvh flex-col items-center px-4 md:px-10",
|
||||
step === "sources"
|
||||
? "items-start overflow-y-auto"
|
||||
: "items-center overflow-hidden",
|
||||
? "justify-start overflow-y-auto pt-20 pb-10"
|
||||
: "justify-center overflow-y-auto py-20 md:overflow-hidden",
|
||||
)}
|
||||
>
|
||||
<div className="mb-5 flex justify-center md:hidden">
|
||||
<StepIndicator step={step} visibleSteps={visibleSteps} />
|
||||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
"w-full",
|
||||
|
|
@ -89,7 +94,7 @@ function StepIndicator({
|
|||
const isLast = i === visibleSteps.length - 1
|
||||
return (
|
||||
<div key={s} className="flex items-start">
|
||||
<div className="flex flex-col items-center gap-1.5 min-w-[58px]">
|
||||
<div className="flex min-w-[44px] flex-col items-center gap-1.5 md:min-w-[58px]">
|
||||
<StepDot done={isDone} current={isCurrent} />
|
||||
<span
|
||||
className={cn(
|
||||
|
|
@ -105,7 +110,7 @@ function StepIndicator({
|
|||
</span>
|
||||
</div>
|
||||
{!isLast && (
|
||||
<div className="flex-1 h-px min-w-[28px] mt-[5px]">
|
||||
<div className="mt-[5px] h-px min-w-[18px] flex-1 md:min-w-[28px]">
|
||||
<motion.div
|
||||
initial={false}
|
||||
animate={{
|
||||
|
|
|
|||
|
|
@ -474,9 +474,9 @@ export function StepSources({
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="mx-auto w-full max-w-[1400px] pb-10">
|
||||
<section className="relative min-h-[calc(100dvh-136px)] py-4">
|
||||
<div className="absolute inset-x-0 top-[46%] -translate-y-1/2">
|
||||
<div className="mx-auto w-full max-w-[1400px] pb-28 md:pb-10">
|
||||
<section className="relative min-h-[calc(100dvh-136px)] py-3 md:py-4">
|
||||
<div className="md:absolute md:inset-x-0 md:top-[46%] md:-translate-y-1/2">
|
||||
<div className="mb-6 px-1">
|
||||
<p
|
||||
className={cn(
|
||||
|
|
@ -494,7 +494,7 @@ export function StepSources({
|
|||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid md:grid-cols-3 gap-4">
|
||||
<div className="grid gap-3 md:grid-cols-3 md:gap-4">
|
||||
{mode === "personal" ? (
|
||||
<>
|
||||
<SourceCard
|
||||
|
|
@ -565,7 +565,7 @@ export function StepSources({
|
|||
)}
|
||||
</div>
|
||||
|
||||
<div className="absolute left-0 right-0 top-full mt-6 px-1">
|
||||
<div className="mt-4 px-1 md:absolute md:left-0 md:right-0 md:top-full md:mt-6">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<button
|
||||
type="button"
|
||||
|
|
@ -579,7 +579,7 @@ export function StepSources({
|
|||
)}
|
||||
/>
|
||||
More integrations
|
||||
<span className="text-[#525D6E]">
|
||||
<span className="hidden text-[#525D6E] sm:inline">
|
||||
(Gmail, GitHub, OneDrive…)
|
||||
</span>
|
||||
</button>
|
||||
|
|
@ -591,7 +591,7 @@ export function StepSources({
|
|||
</div>
|
||||
|
||||
{moreOpen ? (
|
||||
<div className="mt-10 grid md:grid-cols-3 gap-4">
|
||||
<div className="mt-4 grid gap-3 md:mt-10 md:grid-cols-3 md:gap-4">
|
||||
<MoreSourcesGrid
|
||||
mode={mode}
|
||||
values={values}
|
||||
|
|
@ -929,22 +929,21 @@ function SourceActions({
|
|||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"mt-6 flex items-center justify-end gap-[22px] px-1",
|
||||
"mt-4 flex items-center justify-end gap-3 px-1 md:mt-6 md:gap-[22px]",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
onClick={onContinue}
|
||||
className="text-[#737373] font-medium text-[14px] hover:text-[#999] transition-colors"
|
||||
className="hidden text-[#737373] font-medium text-[14px] transition-colors hover:text-[#999] sm:inline"
|
||||
>
|
||||
Skip for now
|
||||
</button>
|
||||
<Button
|
||||
variant="insideOut"
|
||||
onClick={onContinue}
|
||||
disabled={connectedCount === 0}
|
||||
className="rounded-full px-5 py-[10px] text-[13px] font-medium text-[#fafafa]"
|
||||
className="rounded-full px-4 py-2 text-[13px] font-medium text-[#fafafa] md:px-5 md:py-[10px]"
|
||||
>
|
||||
Continue
|
||||
{connectedCount > 0 && (
|
||||
|
|
@ -1276,16 +1275,16 @@ function SourceCard({
|
|||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"min-h-[190px] rounded-[18px] p-5 transition-colors bg-[#1B1F24] flex flex-col",
|
||||
"min-h-[146px] rounded-[18px] bg-[#1B1F24] p-3.5 transition-colors flex flex-col md:min-h-[190px] md:p-5",
|
||||
isDone && "ring-1 ring-[#2261CA33]",
|
||||
)}
|
||||
style={modalCardStyle}
|
||||
>
|
||||
<div className="grid grid-cols-[48px_minmax(0,1fr)_auto] items-start gap-3">
|
||||
<div className="grid grid-cols-[40px_minmax(0,1fr)_auto] items-start gap-2.5 md:grid-cols-[48px_minmax(0,1fr)_auto] md:gap-3">
|
||||
<div className="pt-0.5">
|
||||
<div
|
||||
className={cn(
|
||||
"size-12 rounded-[12px] flex items-center justify-center shrink-0",
|
||||
"size-10 rounded-[12px] flex items-center justify-center shrink-0 md:size-12",
|
||||
bareIconFrame
|
||||
? "bg-transparent border border-transparent"
|
||||
: "bg-[#14161A] border border-[rgba(82,89,102,0.2)]",
|
||||
|
|
@ -1296,10 +1295,10 @@ function SourceCard({
|
|||
</div>
|
||||
</div>
|
||||
<div className="min-w-0 pr-1">
|
||||
<p className="text-[15px] leading-tight font-semibold text-[#fafafa]">
|
||||
<p className="text-[14px] leading-tight font-semibold text-[#fafafa] md:text-[15px]">
|
||||
{title}
|
||||
</p>
|
||||
<p className="text-[12px] text-[#737373] mt-1 leading-[1.35] font-medium">
|
||||
<p className="mt-0.5 text-[11.5px] text-[#737373] leading-[1.3] font-medium md:mt-1 md:text-[12px] md:leading-[1.35]">
|
||||
{blurb}
|
||||
</p>
|
||||
{headerNote}
|
||||
|
|
@ -1320,7 +1319,7 @@ function SourceCard({
|
|||
: undefined
|
||||
}
|
||||
className={cn(
|
||||
"shrink-0 rounded-full h-9 px-4 text-[13px] font-medium text-[#fafafa] gap-1.5",
|
||||
"h-8 shrink-0 rounded-full px-3 text-[12px] font-medium text-[#fafafa] gap-1.5 md:h-9 md:px-4 md:text-[13px]",
|
||||
disabled && "opacity-50",
|
||||
)}
|
||||
>
|
||||
|
|
@ -1336,15 +1335,15 @@ function SourceCard({
|
|||
)}
|
||||
</div>
|
||||
|
||||
<ul className="mt-4 space-y-1.5">
|
||||
<ul className="mt-3 space-y-1 md:mt-4 md:space-y-1.5">
|
||||
{perks.map((p) => (
|
||||
<li
|
||||
key={p}
|
||||
className="flex items-start gap-2.5 text-[12px] text-[#737373] font-medium leading-[1.5]"
|
||||
className="flex items-start gap-2 text-[11px] text-[#737373] font-medium leading-[1.35] md:gap-2.5 md:text-[12px] md:leading-[1.5]"
|
||||
>
|
||||
<span
|
||||
aria-hidden
|
||||
className="size-1 rounded-full bg-[#525D6E] shrink-0 mt-[7px]"
|
||||
className="size-1 rounded-full bg-[#525D6E] shrink-0 mt-[6px] md:mt-[7px]"
|
||||
/>
|
||||
<span>{p}</span>
|
||||
</li>
|
||||
|
|
@ -1352,7 +1351,7 @@ function SourceCard({
|
|||
</ul>
|
||||
|
||||
{(footerLeft || footerRight) && (
|
||||
<div className="mt-auto pt-4 flex items-end justify-between gap-3">
|
||||
<div className="mt-auto flex items-end justify-between gap-3 pt-3 md:pt-4">
|
||||
<div>{footerLeft}</div>
|
||||
<div className="pb-1.5">{footerRight}</div>
|
||||
</div>
|
||||
|
|
@ -1364,10 +1363,10 @@ function SourceCard({
|
|||
function SpaceChip({ name }: { name: string }) {
|
||||
return (
|
||||
<div
|
||||
className="inline-flex items-center gap-1.5 text-[11px] font-medium text-[#737373]"
|
||||
className="inline-flex items-center gap-1 text-[10px] font-medium text-[#737373] md:gap-1.5 md:text-[11px]"
|
||||
title={`This source will save into the "${name}" space.`}
|
||||
>
|
||||
<span className="text-[10px] uppercase tracking-[0.08em] text-[#525D6E]">
|
||||
<span className="text-[9px] uppercase tracking-[0.08em] text-[#525D6E] md:text-[10px]">
|
||||
Saves to
|
||||
</span>
|
||||
<FolderOpen className="size-3 text-[#737373]" />
|
||||
|
|
|
|||
|
|
@ -144,14 +144,14 @@ export function StepTeam({
|
|||
const count = values.invites.length
|
||||
|
||||
return (
|
||||
<div className="max-w-2xl mx-auto">
|
||||
<div className="max-w-2xl mx-auto pb-24 md:pb-0">
|
||||
<section
|
||||
className="rounded-[22px] bg-[#1B1F24] p-7 md:p-8"
|
||||
className="rounded-[22px] bg-[#1B1F24] p-5 md:p-8"
|
||||
style={modalCardStyle}
|
||||
>
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="flex items-start gap-3 md:gap-4">
|
||||
<div
|
||||
className="size-12 rounded-[14px] bg-[#14161A] border border-[rgba(82,89,102,0.2)] flex items-center justify-center shrink-0"
|
||||
className="size-11 rounded-[14px] bg-[#14161A] border border-[rgba(82,89,102,0.2)] flex items-center justify-center shrink-0 md:size-12"
|
||||
style={inputBevelStyle}
|
||||
>
|
||||
<Users className="size-5 text-[#fafafa]" />
|
||||
|
|
@ -159,13 +159,13 @@ export function StepTeam({
|
|||
<div className="min-w-0 flex-1">
|
||||
<p
|
||||
className={cn(
|
||||
"text-[20px] font-semibold text-[#fafafa]",
|
||||
"text-[19px] font-semibold text-[#fafafa] md:text-[20px]",
|
||||
dmSans125ClassName(),
|
||||
)}
|
||||
>
|
||||
Invite your team
|
||||
</p>
|
||||
<p className="text-[14px] text-[#737373] mt-1 leading-[1.5] font-medium">
|
||||
<p className="text-[13px] text-[#737373] mt-1 leading-[1.45] font-medium md:text-[14px] md:leading-[1.5]">
|
||||
A brain gets sharper as more people contribute. You can also do
|
||||
this later.
|
||||
</p>
|
||||
|
|
@ -177,9 +177,9 @@ export function StepTeam({
|
|||
e.preventDefault()
|
||||
addInvites(draft)
|
||||
}}
|
||||
className="mt-6 flex gap-2"
|
||||
className="mt-5 flex min-w-0 gap-2 md:mt-6"
|
||||
>
|
||||
<div className="relative flex-1">
|
||||
<div className="relative min-w-0 flex-1">
|
||||
<Mail className="size-4 absolute left-3.5 top-1/2 -translate-y-1/2 text-[#737373]" />
|
||||
<Input
|
||||
value={draft}
|
||||
|
|
@ -191,8 +191,8 @@ export function StepTeam({
|
|||
addInvites(pasted)
|
||||
}
|
||||
}}
|
||||
placeholder={`alex@${domainOrFallback}, sam@${domainOrFallback}, …`}
|
||||
className={cn(inputClass, "pl-10")}
|
||||
placeholder={`alex@${domainOrFallback}`}
|
||||
className={cn(inputClass, "min-w-0 pl-10")}
|
||||
style={inputBevelStyle}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -200,19 +200,19 @@ export function StepTeam({
|
|||
type="submit"
|
||||
variant="insideOut"
|
||||
disabled={!draft.trim()}
|
||||
className="rounded-full h-12 px-4 text-[13px] font-medium text-[#fafafa]"
|
||||
className="h-12 shrink-0 rounded-full px-3.5 text-[13px] font-medium text-[#fafafa] md:px-4"
|
||||
>
|
||||
<Plus className="size-4" />
|
||||
Add
|
||||
</Button>
|
||||
</form>
|
||||
|
||||
<p className="text-[11px] text-[#525D6E] font-medium mt-2 pl-2">
|
||||
<p className="text-[11px] text-[#525D6E] font-medium mt-2 pl-1 md:pl-2">
|
||||
Paste multiple emails at once — we'll split them for you.
|
||||
</p>
|
||||
|
||||
{count === 0 ? (
|
||||
<div className="mt-6 rounded-[14px] border border-dashed border-[rgba(82,89,102,0.3)] bg-[#14161A]/40 px-5 py-8 text-center">
|
||||
<div className="mt-5 rounded-[14px] border border-dashed border-[rgba(82,89,102,0.3)] bg-[#14161A]/40 px-4 py-7 text-center md:mt-6 md:px-5 md:py-8">
|
||||
<p className="text-[13px] text-[#737373] font-medium">
|
||||
No invites yet.
|
||||
</p>
|
||||
|
|
@ -242,11 +242,11 @@ export function StepTeam({
|
|||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="mt-3 space-y-1.5 max-h-[280px] overflow-y-auto scrollbar-thin pr-1">
|
||||
<div className="mt-3 space-y-1.5 max-h-[240px] overflow-y-auto scrollbar-thin pr-1 md:max-h-[280px]">
|
||||
{values.invites.map((inv) => (
|
||||
<div
|
||||
key={inv.email}
|
||||
className="flex items-center gap-3 rounded-[12px] bg-[#14161A] border border-[rgba(82,89,102,0.2)] px-3 py-2"
|
||||
className="flex flex-wrap items-center gap-2 rounded-[12px] bg-[#14161A] border border-[rgba(82,89,102,0.2)] px-3 py-2 sm:flex-nowrap md:gap-3"
|
||||
style={inputBevelStyle}
|
||||
>
|
||||
<div className="size-7 rounded-full bg-[#0D121A] border border-[rgba(115,115,115,0.15)] flex items-center justify-center shrink-0">
|
||||
|
|
@ -263,7 +263,7 @@ export function StepTeam({
|
|||
setRole(inv.email, r as "admin" | "member")
|
||||
}
|
||||
>
|
||||
<SelectTrigger className="w-24 h-7 bg-transparent border border-[rgba(82,89,102,0.2)] rounded-full text-[#A1A1AA] text-[11px] font-medium px-3 shadow-none focus:ring-0">
|
||||
<SelectTrigger className="h-7 w-24 bg-transparent border border-[rgba(82,89,102,0.2)] rounded-full text-[#A1A1AA] text-[11px] font-medium px-3 shadow-none focus:ring-0">
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
<SelectContent className="bg-[#14161A] border-[rgba(82,89,102,0.2)] rounded-[12px]">
|
||||
|
|
@ -295,12 +295,12 @@ export function StepTeam({
|
|||
</>
|
||||
)}
|
||||
|
||||
<div className="mt-6 flex items-center justify-end gap-[22px] border-t border-white/[0.06] pt-5">
|
||||
<div className="mt-5 flex items-center justify-end gap-3 border-t border-white/[0.06] pt-4 md:mt-6 md:gap-[22px] md:pt-5">
|
||||
<button
|
||||
type="button"
|
||||
onClick={onSkip ?? onContinue}
|
||||
disabled={submitting}
|
||||
className="text-[#737373] font-medium text-[14px] hover:text-[#999] transition-colors disabled:opacity-50"
|
||||
className="text-[#737373] font-medium text-[13px] transition-colors hover:text-[#999] disabled:opacity-50 md:text-[14px]"
|
||||
>
|
||||
Skip for now
|
||||
</button>
|
||||
|
|
@ -308,7 +308,7 @@ export function StepTeam({
|
|||
variant="insideOut"
|
||||
onClick={onContinue}
|
||||
disabled={submitting}
|
||||
className="rounded-full px-5 py-[10px] text-[13px] font-medium text-[#fafafa]"
|
||||
className="rounded-full px-4 py-2 text-[13px] font-medium text-[#fafafa] md:px-5 md:py-[10px]"
|
||||
>
|
||||
{submitting ? (
|
||||
<>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue