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
2 changes: 1 addition & 1 deletion src/components/home/features/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const FEATURES = [
title: "Managed Postgres, colocated with your Lakehouse.",
description:
"Provision with the CLI, connect like any Postgres. Instant branching, scales to zero, and change data feed to Unity Catalog.",
href: "/product/data-lakehouse",
href: "/product/lakebase",
visual: "lakebase",
},
{
Expand Down
65 changes: 49 additions & 16 deletions src/components/theme/mobile-nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ import { useLocation } from "@docusaurus/router";
import { DocsSidebarSearch } from "@/components/docs/sidebar-search";

import {
getActiveProductHref,
isHeaderNavItemActive,
PRODUCT_LINKS,
type HeaderNavItem,
} from "@/lib/header-navigation";
import { cn } from "@/lib/utils";
Expand Down Expand Up @@ -126,7 +128,10 @@ function MobileTreeText({
export function MobileNav({ items, open, onOpenChange }: MobileNavProps) {
const menuId = useId();
const { pathname } = useLocation();
const activeProductHref = getActiveProductHref(pathname);
const isHomeActive = pathname === "/";
const productItem = items.find(({ label }) => label === "Product");
const sectionItems = items.filter(({ label }) => label !== "Product");

useEffect(() => {
onOpenChange(false);
Expand Down Expand Up @@ -218,7 +223,7 @@ export function MobileNav({ items, open, onOpenChange }: MobileNavProps) {
};
}, [onOpenChange, open]);

if (items.length === 0) {
if (!productItem || items.length === 0) {
return null;
}

Expand All @@ -245,17 +250,15 @@ export function MobileNav({ items, open, onOpenChange }: MobileNavProps) {
className="relative w-full h-full flex justify-between font-mono text-[20px] leading-none font-normal tracking-[-0.4px]"
aria-label="Main navigation"
>
{/*
Product nav section temporarily removed while product pages are
unpublished. This menu was reflowed (tree-line positions retuned)
for the shorter HOME + Solutions/Templates/Docs list. To restore
Product, revert this file to its pre-PR-114 version and uncomment
the Product entry in header-navigation.ts.
*/}
<MobileTreeLine className="top-[38px] left-[23px] h-[102px] w-px" />
<MobileTreeLine className="top-[72px] left-6 h-px w-[37px] md:w-[39px]" />
<MobileTreeLine className="top-[106px] left-6 h-px w-[37px] md:w-[39px]" />
<MobileTreeLine className="top-[140px] left-6 h-px w-[37px] md:w-[39px]" />
<MobileTreeLine className="top-[38px] left-[23px] h-[226px] w-px" />
<MobileTreeLine className="top-[58px] left-6 h-px w-[37px]" />
<MobileTreeLine className="top-[90px] left-[63px] h-px w-[37px]" />
<MobileTreeLine className="top-[124px] left-[63px] h-px w-[37px]" />
<MobileTreeLine className="top-[158px] left-[63px] h-px w-[37px]" />
<MobileTreeLine className="top-[194px] left-6 h-px w-[37px] md:w-[39px]" />
<MobileTreeLine className="top-[228px] left-6 h-px w-[37px] md:w-[39px]" />
<MobileTreeLine className="top-[264px] left-6 h-px w-[37px] md:w-[39px]" />
<MobileTreeLine className="top-[72px] left-[63px] h-[86px] w-px md:top-[73px] md:h-[85px]" />

<MobileTreeText
active={isHomeActive}
Expand All @@ -268,7 +271,37 @@ export function MobileNav({ items, open, onOpenChange }: MobileNavProps) {
~/HOME
</MobileTreeText>

{items.map((item, index) => {
<span
className="absolute top-[46px] left-[61px] flex h-6 items-center text-grey-80 opacity-60"
data-mobile-menu-product-label="true"
>
{productItem.label.toLowerCase()}
</span>

{PRODUCT_LINKS.map((product, index) => {
const isActive = product.href === activeProductHref;

return (
<MobileTreeText
active={isActive}
activeFill="full"
aria-current={isActive ? "page" : undefined}
className={cn(
"left-[100px] right-5",
index === 0 && "top-[76px]",
index === 1 && "top-[110px]",
index === 2 && "top-36",
)}
data-mobile-menu-product-link="true"
key={product.href}
to={product.href}
>
{product.label.toLowerCase()}
</MobileTreeText>
);
})}

{sectionItems.map((item, index) => {
const isActive = isHeaderNavItemActive(item, pathname);

return (
Expand All @@ -278,9 +311,9 @@ export function MobileNav({ items, open, onOpenChange }: MobileNavProps) {
aria-current={isActive ? "page" : undefined}
className={cn(
"left-[61px] right-5 md:left-[63px] md:right-[22px]",
index === 0 && "top-[58px]",
index === 1 && "top-[92px]",
index === 2 && "top-[126px]",
index === 0 && "top-[180px]",
index === 1 && "top-[214px]",
index === 2 && "top-[248px]",
)}
data-mobile-menu-section-link="true"
key={item.href}
Expand Down
5 changes: 1 addition & 4 deletions src/components/theme/nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -268,10 +268,7 @@ function Nav({ className, items }: HeaderNavProps) {
{items.map((item) => {
const { href, label } = item;

// The "Product" entry is temporarily commented out of HEADER_LINKS,
// so this branch never renders. Kept (with a widened comparison) so
// re-enabling Product is a one-line revert in header-navigation.ts.
if ((label as string) === "Product") {
if (label === "Product") {
const isActive = Boolean(activeProductHref);

return (
Expand Down
5 changes: 2 additions & 3 deletions src/lib/header-navigation.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
export const HEADER_LINKS = [
// Temporarily hidden while product pages are unpublished.
// { label: "Product", href: "/product/data-lakehouse" },
{ label: "Product", href: "/product/lakebase" },
{ label: "Solutions", href: "/solutions" },
{ label: "Templates", href: "/templates" },
{ label: "Docs", href: "/docs/start-here", activePath: "/docs" },
Expand All @@ -9,7 +8,7 @@ export const HEADER_LINKS = [
export type HeaderNavItem = (typeof HEADER_LINKS)[number];

export const PRODUCT_LINKS = [
{ label: "Lakebase", href: "/product/data-lakehouse" },
{ label: "Lakebase", href: "/product/lakebase" },
{ label: "Agent Bricks", href: "/product/agent-bricks" },
{ label: "Databricks Apps", href: "/product/databricks-apps" },
] as const;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/products/lakebase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export const lakebaseProduct: ProductPageContent = {
title: "Lakebase",
description:
"Managed Postgres with branching, autoscaling, and Lakehouse sync for modern operational workloads.",
canonicalPath: "/product/data-lakehouse",
canonicalPath: "/product/lakebase",
hero: {
eyebrow: "Lakebase",
title: "Managed Postgres, built for modern operational workloads.",
Expand Down
2 changes: 1 addition & 1 deletion src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export default function Home(): ReactNode {
<main>
<Hero />
<Templates />
{/* <Features /> */}
<Features />
<div className="bg-linear-to-b from-[#1A2E2F] from-65% to-[#2A4647]">
<LovedByDevelopers />
<CTA
Expand Down
File renamed without changes.
19 changes: 19 additions & 0 deletions src/pages/product/data-lakehouse.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Head from "@docusaurus/Head";
import { Redirect } from "@docusaurus/router";
import useBaseUrl from "@docusaurus/useBaseUrl";
import type { ReactNode } from "react";

export default function LakebaseLegacyProductPage(): ReactNode {
const target = useBaseUrl("/product/lakebase");

return (
<>
<Head>
<meta name="robots" content="noindex, nofollow" />
<meta httpEquiv="refresh" content={`0; url=${target}`} />
<link rel="canonical" href={target} />
</Head>
<Redirect to={target} />
</>
);
}
File renamed without changes.
20 changes: 9 additions & 11 deletions tests/e2e/navigation.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,11 @@ test.describe("navbar navigation", () => {
});
}

// Skipped while the Product nav dropdown is hidden.
test.skip("product dropdown hover state is visible in production CSS", async ({
test("product dropdown hover state is visible in production CSS", async ({
page,
}) => {
await page.setViewportSize({ width: 1440, height: 900 });
await page.goto("/product/data-lakehouse");
await page.goto("/product/lakebase");

await page.getByRole("button", { name: "[Product]" }).hover();
const productMenu = page.locator('[data-slot="navigation-menu-content"]');
Expand Down Expand Up @@ -184,7 +183,7 @@ test.describe.skip("mobile navigation", () => {
width: viewport.width,
height: viewport.height,
});
await page.goto("/product/data-lakehouse");
await page.goto("/product/lakebase");

await page.getByRole("button", { name: "Open menu" }).click();

Expand Down Expand Up @@ -538,19 +537,18 @@ test.describe("home page link navigation", () => {
expect(finalCopiedText).toContain("llms.txt");
});

// Skipped while the home Features pillar cards and product pages are hidden.
test.skip("pillar card Lakebase navigates to /product/data-lakehouse", async ({
test("pillar card Lakebase navigates to /product/lakebase", async ({
page,
}) => {
await page.goto("/");
const link = page.locator('a[href="/product/data-lakehouse"]').first();
const link = page.locator('a[href="/product/lakebase"]').first();
await link.waitFor({ state: "visible" });
await link.click();
await page.waitForURL("**/product/data-lakehouse");
expect(new URL(page.url()).pathname).toBe("/product/data-lakehouse");
await page.waitForURL("**/product/lakebase");
expect(new URL(page.url()).pathname).toBe("/product/lakebase");
});

test.skip("pillar card Agent Bricks navigates to /product/agent-bricks", async ({
test("pillar card Agent Bricks navigates to /product/agent-bricks", async ({
page,
}) => {
await page.goto("/");
Expand All @@ -559,7 +557,7 @@ test.describe("home page link navigation", () => {
expect(new URL(page.url()).pathname).toBe("/product/agent-bricks");
});

test.skip("pillar card Databricks Apps navigates to /product/databricks-apps", async ({
test("pillar card Databricks Apps navigates to /product/databricks-apps", async ({
page,
}) => {
await page.goto("/");
Expand Down
18 changes: 14 additions & 4 deletions tests/e2e/pages.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@ import { test, expect } from "@playwright/test";

const PAGES = [
{ path: "/", title: "Databricks Developer" },
// Product pages temporarily unpublished (hidden via `_` prefix).
// { path: "/product/data-lakehouse", title: "Lakebase" },
// { path: "/product/agent-bricks", title: "Agent Bricks" },
// { path: "/product/databricks-apps", title: "Databricks Apps" },
{ path: "/product/lakebase", title: "Lakebase" },
{ path: "/product/agent-bricks", title: "Agent Bricks" },
{ path: "/product/databricks-apps", title: "Databricks Apps" },
{ path: "/solutions", title: "Solutions" },
{
path: "/solutions/devhub-launch",
Expand Down Expand Up @@ -121,6 +120,17 @@ test.describe("static assets load correctly", () => {
});
});

test.describe("legacy redirects", () => {
test("/product/data-lakehouse redirects to /product/lakebase", async ({
page,
}) => {
await page.goto("/product/data-lakehouse");
await page.waitForURL("**/product/lakebase");
expect(new URL(page.url()).pathname).toBe("/product/lakebase");
await expect(page).toHaveTitle(/Lakebase/);
});
});

test.describe("solutions RSS", () => {
test("RSS action links to the generated feed", async ({ page }) => {
await page.goto("/solutions");
Expand Down