Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
a8bfe77
Add new tokens with tailwind alias config
RemiBonnet Oct 24, 2025
a3f7236
Add toggle theme and new app console-v5
RemiBonnet Oct 28, 2025
db82634
feat(navigation): add general layout (#2110)
RemiBonnet Dec 15, 2025
cfbf0d8
Update Dockerfile and package.json for console-v5 (#2225)
RemiBonnet Dec 15, 2025
541fc51
fix(new-nav): update router and its layouts (#2227)
rmnbrd Dec 15, 2025
2317bce
feat(organization-overview): add webflow changelog section (#2230)
RemiBonnet Dec 15, 2025
dca100e
feat(new-nav): add authentication (#2232)
rmnbrd Dec 16, 2025
97284a2
impr(new-nav): add logout button and better redirection (#2237)
rmnbrd Dec 17, 2025
6d75591
feat(organization-overview): changelog, links + draft project and pro…
RemiBonnet Dec 17, 2025
26389a9
fix(new-nav): auth context (#2239)
rmnbrd Dec 17, 2025
925f65f
feat(organization-overview): start production health cluster (#2242)
RemiBonnet Dec 18, 2025
cb9c73c
feat(badge): update token (#2245)
RemiBonnet Dec 18, 2025
916e785
feat(cluster): starting views (#2249)
RemiBonnet Dec 19, 2025
696285c
refactor(routes): remove pathname state from links in environment and…
RemiBonnet Dec 23, 2025
cf5c205
feat(cluster): add overview (#2253)
RemiBonnet Dec 24, 2025
4198515
feat(sidebar): add new component for navigation (#2259)
RemiBonnet Dec 24, 2025
04a45b5
feat(cluster-logs): add new view (#2260)
RemiBonnet Dec 26, 2025
54208b2
fix(tokens): update callout & progress-bar components
RemiBonnet Dec 26, 2025
a25e69f
feat(cluster): add general settings (#2264)
RemiBonnet Dec 31, 2025
2b42088
feat(cluster): add credentials settings (#2268)
RemiBonnet Dec 31, 2025
4d9cc74
fix(sticky): ensure dropdown overlays above sticky header (#2269)
RemiBonnet Dec 31, 2025
294fb1d
feat(cluster): add danger-zone settings (#2272)
RemiBonnet Dec 31, 2025
b05902c
feat(cluster): add resources settings (#2271)
RemiBonnet Dec 31, 2025
842bb19
fix(dockerfile): add missing line continuation for environment variables
RemiBonnet Jan 6, 2026
45b125b
feat(cluster): add advanced settings (#2279)
RemiBonnet Jan 6, 2026
9d08de1
feat(cluster): add eks-anywhere settings (#2280)
RemiBonnet Jan 7, 2026
216f0cc
feat(cluster): add image registry and network pages (#2277)
RemiBonnet Jan 7, 2026
f63b23c
feat(new-nav): add onboarding views (#2262)
rmnbrd Jan 9, 2026
9afce6c
feat(header): add user-menu (#2289)
RemiBonnet Jan 9, 2026
5f52dea
feat(cluster): add cluster new page (#2284)
RemiBonnet Jan 9, 2026
d70673b
fix(cluster): terminal new token and overview responsive (#2282)
RemiBonnet Jan 9, 2026
3249faf
fix(new-nav): chargebee imports (#2293)
rmnbrd Jan 9, 2026
7670889
feat(button): Applied new token and style to buttons and action toolb…
TheoGrandin74 Jan 12, 2026
e132ac2
Impr(new-nav): better data fetching (#2298)
rmnbrd Jan 13, 2026
1e3dbe4
feat(cluster): add general step in the creation flow (#2303)
RemiBonnet Jan 15, 2026
a5cadaf
feat(cluster): add resources step in the creation flow (#2308)
RemiBonnet Jan 19, 2026
cb4e751
feat(input): New tokens added (#2313)
TheoGrandin74 Jan 19, 2026
fc6d94b
fix(new-nav): apply correct zIndex value for InputSelect's portal con…
rmnbrd Jan 19, 2026
f22c756
impr(new-nav): improve login UI (#2320)
rmnbrd Jan 22, 2026
ce286b8
fix(new-nav): correct auth redirect issue (#2323)
rmnbrd Jan 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,6 @@ Thumbs.db
.nx/workspace-data
.cursor/rules/nx-rules.mdc
.github/instructions/nx.instructions.md

vite.config.*.timestamp*
vitest.config.*.timestamp*
9 changes: 5 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ ENV NODE_ENV=$NODE_ENV \
NX_PUBLIC_ONBOARDING=$NX_PUBLIC_ONBOARDING \
NX_PUBLIC_CHARGEBEE_PUBLISHABLE_KEY=$NX_PUBLIC_CHARGEBEE_PUBLISHABLE_KEY \
NX_PUBLIC_DEVOPS_COPILOT_API_BASE_URL=$NX_PUBLIC_DEVOPS_COPILOT_API_BASE_URL \
NX_PUBLIC_MINTLIFY_API_KEY=$NX_PUBLIC_MINTLIFY_API_KEY
NX_PUBLIC_MINTLIFY_API_KEY=$NX_PUBLIC_MINTLIFY_API_KEY \
NX_PUBLIC_WEBFLOW_API_KEY=$NX_PUBLIC_WEBFLOW_API_KEY

# Install dependencies with cache mount for faster rebuilds
COPY package.json yarn.lock .yarnrc.yml ./
Expand All @@ -44,14 +45,14 @@ RUN --mount=type=cache,target=/root/.yarn \
# Copy source files (use .dockerignore to exclude unnecessary files)
COPY . .

# Build with NX cache mount for faster rebuilds
# Build console-v5 with NX cache mount for faster rebuilds
RUN --mount=type=cache,target=/app/node_modules/.cache/nx \
yarn build
yarn nx build console-v5 --configuration=production

# Bundle static assets with nginx
FROM nginx:1.25-alpine
# Copy built assets from builder
COPY --from=builder /app/dist/apps/* /usr/share/nginx/html
COPY --from=builder /app/dist/apps/console-v5 /usr/share/nginx/html
# Add your nginx.conf
COPY nginx.conf /etc/nginx/conf.d/default.conf
# Expose port
Expand Down
19 changes: 19 additions & 0 deletions __tests__/mocks.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Auth0ProviderOptions } from '@auth0/auth0-react'
import { ComponentType } from 'react'
import React from 'react'

jest.mock('@auth0/auth0-react', () => ({
Auth0Provider: ({ children }: Auth0ProviderOptions) => children,
Expand All @@ -16,6 +17,24 @@ jest.mock('@auth0/auth0-react', () => ({
},
}))

jest.mock('@tanstack/react-router', () => {
const React = jest.requireActual('react')
return {
...jest.requireActual('@tanstack/react-router'),
useRouter: jest.fn(() => ({
buildLocation: jest.fn(() => ({
href: '/',
})),
})),
Link: React.forwardRef(
(
{ children, ...props }: { children?: React.ReactNode; [key: string]: unknown },
ref: React.Ref<HTMLAnchorElement>
) => React.createElement('a', { ref, ...props }, children)
),
}
})

jest.mock('@uidotdev/usehooks', () => ({
useDocumentTitle: jest.fn(),
useClickAway: jest.fn(),
Expand Down
18 changes: 18 additions & 0 deletions apps/console-v5/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"extends": ["plugin:@nx/react", "../../.eslintrc.json"],
"ignorePatterns": ["!**/*", "**/vite.config.*.timestamp*", "**/vitest.config.*.timestamp*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}
15 changes: 15 additions & 0 deletions apps/console-v5/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Console</title>
<base href="/" />

<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
</head>
<body class="bg-background text-neutral">
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
15 changes: 15 additions & 0 deletions apps/console-v5/postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const { join } = require('path')

// Note: If you use library-specific PostCSS/Tailwind configuration then you should remove the `postcssConfig` build
// option from your application's configuration (i.e. project.json).
//
// See: https://nx.dev/guides/using-tailwind-css-in-react#step-4:-applying-configuration-to-libraries

module.exports = {
plugins: {
tailwindcss: {
config: join(__dirname, 'tailwind.config.js'),
},
autoprefixer: {},
},
}
66 changes: 66 additions & 0 deletions apps/console-v5/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
{
"name": "console-v5",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "/apps/console-v5/src",
"projectType": "application",
"tags": [],
"targets": {
"build": {
"executor": "@nx/vite:build",
"outputs": ["{options.outputPath}"],
"defaultConfiguration": "production",
"options": {
"outputPath": "dist/apps/console-v5"
},
"configurations": {
"development": {
"mode": "development"
},
"production": {
"mode": "production"
}
}
},
"serve": {
"executor": "@nx/vite:dev-server",
"defaultConfiguration": "development",
"options": {
"buildTarget": "console-v5:build"
},
"configurations": {
"development": {
"buildTarget": "console-v5:build:development",
"hmr": true
},
"production": {
"buildTarget": "console-v5:build:production",
"hmr": false
}
}
},
"preview": {
"dependsOn": ["build"],
"executor": "@nx/vite:preview-server",
"defaultConfiguration": "development",
"options": {
"buildTarget": "console-v5:build"
},
"configurations": {
"development": {
"buildTarget": "console-v5:build:development"
},
"production": {
"buildTarget": "console-v5:build:production"
}
}
},
"serve-static": {
"executor": "@nx/web:file-server",
"dependsOn": ["build"],
"options": {
"buildTarget": "console-v5:build",
"spa": true
}
}
}
}
Binary file added apps/console-v5/public/favicon.ico
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
import { Link, useNavigate } from '@tanstack/react-router'
import clsx from 'clsx'
import { type ReactNode, useRef, useState } from 'react'
import { Icon, InputSearch, Popover, dropdownMenuItemVariants } from '@qovery/shared/ui'
import { twMerge } from '@qovery/shared/util-js'

export interface BreadcrumbItemData {
id: string
label: string
path: string
prefix?: ReactNode
logo_url?: string
}

interface BreadcrumbItemProps {
item: BreadcrumbItemData
items?: BreadcrumbItemData[]
}

export function BreadcrumbItem({ item, items }: BreadcrumbItemProps) {
const navigate = useNavigate()
const [searchQuery, setSearchQuery] = useState('')
const [open, setOpen] = useState(false)
const firstItemRef = useRef<HTMLDivElement>(null)
const inputContainerRef = useRef<HTMLDivElement>(null)

const filteredItems = items?.filter((i) => i.label.toLowerCase().includes(searchQuery.toLowerCase())) || []

const handleInputKeyDown = (e: React.KeyboardEvent) => {
if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {
e.preventDefault()
// Transfer focus to the first item in the list
const firstItem = firstItemRef.current?.querySelector('[role="menuitem"]') as HTMLElement
firstItem?.focus()
return
}

// Prevent other keys from interfering with the input, except navigation keys
if (['Home', 'End'].includes(e.key)) {
return
}

e.stopPropagation()
}

const handleListKeyDown = (e: React.KeyboardEvent) => {
if (e.key === 'ArrowUp') {
const items = firstItemRef.current?.querySelectorAll('[role="menuitem"]')
const firstItem = items?.[0]
const activeElement = document.activeElement

// If focus is on the first item, return to input
if (activeElement === firstItem) {
e.preventDefault()
const input = inputContainerRef.current?.querySelector('input') as HTMLInputElement
input?.focus()
}
}
}

if (!items || items.length === 0) {
return <span className="text-sm font-medium text-neutral">{item.label}</span>
}

// XXX: https://github.com/radix-ui/primitives/issues/1342
// We are waiting for radix combobox primitives
// So we are using DropdownMenu.Root in combination of Popover.Root
// to get the flexibility of Popover.Root but keeping the accessibility of
// DropdownMenu.Root for entries.
// So both open state should be sync
return (
<div className="flex items-center justify-between gap-1">
<Link
to={item.path}
className={twMerge(
clsx(
'flex items-center gap-1.5 rounded text-sm font-medium text-neutral-subtle transition-colors hover:text-neutral focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-brand-11',
{
'text-neutral': open,
}
)
)}
>
{item.prefix}
{item.label}
</Link>
<DropdownMenu.Root open={open} onOpenChange={setOpen}>
<Popover.Root open={open} onOpenChange={setOpen}>
<Popover.Trigger>
<button
type="button"
className={twMerge(
clsx(
'relative top-[1px] flex h-6 w-6 items-center justify-center rounded text-neutral-disabled transition-colors hover:text-neutral focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-brand-11',
{
'text-neutral': open,
}
)
)}
>
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 14 14">
<path
fill="currentColor"
fillRule="evenodd"
d="M3.67 8.338a.583.583 0 0 1 .826 0L7 10.842l2.504-2.504a.583.583 0 1 1 .825.824L7.412 12.08a.583.583 0 0 1-.824 0L3.67 9.162a.583.583 0 0 1 0-.824M6.588 1.92a.583.583 0 0 1 .824 0l2.917 2.918a.583.583 0 1 1-.825.824L7 3.158 4.496 5.662a.583.583 0 0 1-.825-.824z"
clipRule="evenodd"
></path>
</svg>
</button>
</Popover.Trigger>
<DropdownMenu.Content asChild>
<Popover.Content className="z-dropdown -ml-2.5 flex w-[340px] flex-col gap-3 p-3 pb-0">
{/*
Transfer focus from input to list when using arrow keys
This enables keyboard navigation while keeping the input functional
https://github.com/radix-ui/primitives/issues/2193#issuecomment-1790564604
*/}
<div className="flex flex-col gap-3" onKeyDown={handleInputKeyDown} ref={inputContainerRef}>
<InputSearch placeholder="Search..." onChange={(value) => setSearchQuery(value)} autofocus />
</div>
<div className="max-h-64 overflow-y-auto" ref={firstItemRef} onKeyDown={handleListKeyDown}>
{filteredItems.length > 0 ? (
<div className="flex flex-col gap-1">
{filteredItems.map((listItem) => (
<DropdownMenu.Item
key={listItem.id}
onSelect={() => {
setOpen(false)
navigate({ to: listItem.path })
}}
className={twMerge(
dropdownMenuItemVariants({ color: 'brand' }),
'justify-between truncate last:mb-3'
)}
>
<div className="flex min-w-0 items-center gap-3">
<Icon
iconName="check"
className={twMerge(
clsx('text-positive opacity-0', {
'opacity-100': item.id === listItem.id,
})
)}
/>
<span className="truncate">{listItem.label}</span>
</div>
</DropdownMenu.Item>
))}
</div>
) : (
<div className="px-3 py-6 text-center">
<Icon iconName="wave-pulse" className="text-neutral-subtle" />
<p className="mt-1 text-xs font-medium text-neutral-subtle">No result for this search</p>
</div>
)}
</div>
</Popover.Content>
</DropdownMenu.Content>
</Popover.Root>
</DropdownMenu.Root>
</div>
)
}

export default BreadcrumbItem
Loading
Loading