mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-08-28 05:25:33 +00:00
Fix integrations layout and mobile promo responsiveness (#1481)
## Summary - Reorder Apps & extensions so Import X bookmarks appears in the top row and Apple Shortcuts uses the open space below. - Keep both Apple Shortcut actions inline on larger screens while allowing the card to grow only as much as needed. - Rework the Company Brain promo on phones so its logo, copy, close control, and CTA remain readable and aligned.
This commit is contained in:
parent
5d2b5855fe
commit
e2be9c9edd
3 changed files with 75 additions and 45 deletions
|
|
@ -45,42 +45,44 @@ export function CompanyBrainPromo() {
|
|||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"flex items-center gap-4 rounded-xl bg-surface-card/60 px-4 py-4 backdrop-blur-md",
|
||||
"relative flex items-start gap-3 rounded-xl bg-surface-card/60 px-4 py-4 backdrop-blur-md sm:items-center sm:gap-4",
|
||||
"shadow-[0_12px_40px_rgba(0,0,0,0.22)]",
|
||||
dmSansClassName(),
|
||||
)}
|
||||
>
|
||||
<div className="flex size-10 shrink-0 items-center justify-center rounded-lg bg-[#0562ef]">
|
||||
<div className="mt-1 flex size-10 shrink-0 items-center justify-center rounded-lg bg-[#0562ef] sm:mt-0">
|
||||
<Logo className="h-4 w-5" />
|
||||
</div>
|
||||
<div className="min-w-0 flex-1">
|
||||
<p className="text-[15px] font-semibold text-[#fafafa]">
|
||||
Give your team a Company Brain
|
||||
</p>
|
||||
<p className="text-[13px] text-[#a1a1a1]">
|
||||
Lives in your Slack. Answers from your team's tools, and brings things
|
||||
up before you ask.
|
||||
</p>
|
||||
<div className="flex min-w-0 flex-1 flex-col gap-2 sm:contents">
|
||||
<div className="min-w-0 pt-1 pr-7 sm:flex-1 sm:pt-0 sm:pr-0">
|
||||
<p className="text-[15px] font-semibold text-[#fafafa]">
|
||||
Give your team a Company Brain
|
||||
</p>
|
||||
<p className="text-[11px] leading-snug text-[#a1a1a1] sm:text-[13px] sm:leading-normal">
|
||||
Lives in your Slack. Answers from your team's tools, and brings
|
||||
things up before you ask.
|
||||
</p>
|
||||
</div>
|
||||
<Button
|
||||
className={cn(
|
||||
"h-9! min-h-9 w-fit shrink-0 self-end gap-1.5 rounded-full! px-3 font-medium sm:self-auto",
|
||||
dmSansClassName(),
|
||||
)}
|
||||
onClick={() => {
|
||||
analytics.companyBrainPromoClicked({ source: "dashboard_card" })
|
||||
router.push("/onboarding?new=1&mode=team")
|
||||
}}
|
||||
variant="headers"
|
||||
>
|
||||
Set it up
|
||||
<ArrowRight className="size-4 shrink-0" />
|
||||
</Button>
|
||||
</div>
|
||||
<Button
|
||||
className={cn(
|
||||
"rounded-full! h-9! min-h-9 shrink-0 gap-1.5 px-3 font-medium",
|
||||
dmSansClassName(),
|
||||
)}
|
||||
onClick={() => {
|
||||
analytics.companyBrainPromoClicked({ source: "dashboard_card" })
|
||||
router.push("/onboarding?new=1&mode=team")
|
||||
}}
|
||||
variant="headers"
|
||||
>
|
||||
Set it up
|
||||
<ArrowRight className="size-4 shrink-0" />
|
||||
</Button>
|
||||
<button
|
||||
aria-label="Dismiss"
|
||||
type="button"
|
||||
onClick={dismiss}
|
||||
className="shrink-0 rounded-full p-1.5 text-[#737373] transition-colors hover:text-[#fafafa]"
|
||||
className="absolute right-2.5 top-2.5 shrink-0 rounded-full p-1.5 text-[#737373] transition-colors hover:text-[#fafafa] sm:static"
|
||||
>
|
||||
<XIcon className="size-4" />
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -537,13 +537,13 @@ const SECTIONS: Array<{
|
|||
action: { type: "external", href: POKE_RECIPE_URL },
|
||||
},
|
||||
{
|
||||
kind: "client",
|
||||
id: "shortcuts",
|
||||
name: "Apple Shortcuts",
|
||||
tagline: "Add memories from iPhone, iPad or Mac",
|
||||
simpleTitle: "Save anything from your phone or Mac",
|
||||
icon: <AppleShortcutsIcon />,
|
||||
action: { type: "view", viewMode: "shortcuts" as ViewParamValue },
|
||||
kind: "import",
|
||||
id: "x-bookmarks",
|
||||
name: "Import X bookmarks",
|
||||
tagline: "Turn your X/Twitter bookmarks into memories",
|
||||
simpleTitle: "Turn your X bookmarks into memory",
|
||||
icon: <Image src="/onboarding/x.png" alt="X" width={24} height={24} />,
|
||||
viewMode: "import" as ViewParamValue,
|
||||
},
|
||||
{
|
||||
kind: "client",
|
||||
|
|
@ -556,13 +556,13 @@ const SECTIONS: Array<{
|
|||
dev: true,
|
||||
},
|
||||
{
|
||||
kind: "import",
|
||||
id: "x-bookmarks",
|
||||
name: "Import X bookmarks",
|
||||
tagline: "Turn your X/Twitter bookmarks into memories",
|
||||
simpleTitle: "Turn your X bookmarks into memory",
|
||||
icon: <Image src="/onboarding/x.png" alt="X" width={24} height={24} />,
|
||||
viewMode: "import" as ViewParamValue,
|
||||
kind: "client",
|
||||
id: "shortcuts",
|
||||
name: "Apple Shortcuts",
|
||||
tagline: "Add memories from iPhone, iPad or Mac",
|
||||
simpleTitle: "Save anything from your phone or Mac",
|
||||
icon: <AppleShortcutsIcon />,
|
||||
action: { type: "view", viewMode: "shortcuts" as ViewParamValue },
|
||||
},
|
||||
],
|
||||
},
|
||||
|
|
@ -2068,6 +2068,7 @@ function ItemCard({
|
|||
docsUrl,
|
||||
leftIndicator,
|
||||
statusSlot,
|
||||
layoutClassName,
|
||||
}: {
|
||||
actionSlot: ReactNode
|
||||
infoActionSlot?: ReactNode
|
||||
|
|
@ -2082,6 +2083,7 @@ function ItemCard({
|
|||
docsUrl?: string
|
||||
leftIndicator?: ReactNode
|
||||
statusSlot?: ReactNode
|
||||
layoutClassName?: string
|
||||
}) {
|
||||
const [infoOpen, setInfoOpen] = useState(false)
|
||||
return (
|
||||
|
|
@ -2099,6 +2101,9 @@ function ItemCard({
|
|||
className={cn(
|
||||
"group relative flex h-full cursor-pointer flex-row items-center gap-2.5 rounded-[10px] bg-[#14161A] px-2.5 py-2 transition-colors hover:bg-[#16181D] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#4BA0FA]/45 sm:flex-col sm:items-stretch sm:gap-4 sm:rounded-[12px] sm:p-4",
|
||||
"shadow-[inset_2.42px_2.42px_4.263px_rgba(11,15,21,0.7)]",
|
||||
id === "shortcuts" &&
|
||||
"max-sm:grid max-sm:grid-cols-[auto_minmax(0,1fr)] max-sm:items-center",
|
||||
layoutClassName,
|
||||
)}
|
||||
>
|
||||
<ItemInfoButton name={name} onClick={() => setInfoOpen(true)} />
|
||||
|
|
@ -2116,7 +2121,12 @@ function ItemCard({
|
|||
<div className="flex shrink-0 items-start justify-between gap-2">
|
||||
<IconBox>{icon}</IconBox>
|
||||
</div>
|
||||
<div className="flex min-w-0 flex-1 flex-row items-center justify-between gap-2 sm:flex-col sm:items-stretch sm:justify-end sm:gap-3">
|
||||
<div
|
||||
className={cn(
|
||||
"flex min-w-0 flex-1 flex-row items-center justify-between gap-2 sm:flex-col sm:items-stretch sm:justify-end sm:gap-3",
|
||||
id === "shortcuts" && "max-sm:contents",
|
||||
)}
|
||||
>
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex min-w-0 items-center gap-1">
|
||||
{leftIndicator}
|
||||
|
|
@ -2140,7 +2150,13 @@ function ItemCard({
|
|||
{tagline}
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex w-auto shrink-0 items-center justify-end gap-2 sm:w-full sm:justify-between">
|
||||
<div
|
||||
className={cn(
|
||||
"flex w-auto shrink-0 items-center justify-end gap-2 sm:w-full sm:justify-between",
|
||||
id === "shortcuts" &&
|
||||
"max-sm:col-span-2 max-sm:row-start-2 max-sm:w-full",
|
||||
)}
|
||||
>
|
||||
{/* biome-ignore lint/a11y/noStaticElementInteractions: stop card click from swallowing the status action. */}
|
||||
<div
|
||||
className="hidden min-w-0 flex-1 sm:flex"
|
||||
|
|
@ -2151,7 +2167,11 @@ function ItemCard({
|
|||
</div>
|
||||
{/* biome-ignore lint/a11y/noStaticElementInteractions: stop card click from swallowing the primary action. */}
|
||||
<div
|
||||
className="flex shrink-0 justify-end [&>button]:!h-7 [&>button]:!min-w-[82px] [&>button]:!px-3 [&>button]:!text-[11px] sm:[&>button]:!h-9 sm:[&>button]:!min-w-[116px] sm:[&>button]:!px-5 sm:[&>button]:!text-[14px]"
|
||||
className={cn(
|
||||
"flex shrink-0 justify-end [&>button]:!h-7 [&>button]:!min-w-[82px] [&>button]:!px-3 [&>button]:!text-[11px] sm:[&>button]:!h-9 sm:[&>button]:!min-w-[116px] sm:[&>button]:!px-5 sm:[&>button]:!text-[14px]",
|
||||
id === "shortcuts" &&
|
||||
"max-sm:w-full max-sm:shrink max-sm:[&>div]:w-full",
|
||||
)}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onKeyDown={(e) => e.stopPropagation()}
|
||||
>
|
||||
|
|
@ -3628,7 +3648,7 @@ export function IntegrationsView({
|
|||
}
|
||||
}
|
||||
|
||||
const renderItemCard = (item: Item) => (
|
||||
const renderItemCard = (item: Item, layoutClassName?: string) => (
|
||||
<ItemCard
|
||||
key={item.id}
|
||||
actionSlot={renderRight(item)}
|
||||
|
|
@ -3644,6 +3664,7 @@ export function IntegrationsView({
|
|||
docsUrl={item.docsUrl}
|
||||
leftIndicator={renderLeftIndicator(item)}
|
||||
statusSlot={renderStatus(item)}
|
||||
layoutClassName={layoutClassName}
|
||||
/>
|
||||
)
|
||||
|
||||
|
|
@ -3753,7 +3774,14 @@ export function IntegrationsView({
|
|||
</p>
|
||||
) : q || category !== "all" ? (
|
||||
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2 lg:grid-cols-3">
|
||||
{visibleItems.map((item) => renderItemCard(item))}
|
||||
{visibleItems.map((item) =>
|
||||
renderItemCard(
|
||||
item,
|
||||
item.id === "shortcuts"
|
||||
? "sm:w-max sm:min-w-full"
|
||||
: undefined,
|
||||
),
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col gap-6">
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ export function ShortcutsConnectButtons({
|
|||
}) {
|
||||
const { connect, isPending, pendingType } = controller
|
||||
return (
|
||||
<div className="flex flex-col gap-2 sm:flex-row">
|
||||
<div className="flex flex-col items-stretch gap-2 sm:flex-row sm:items-center">
|
||||
<PillButton
|
||||
className="h-9 flex-none"
|
||||
onClick={(e) => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue