## What kind of change does this PR introduce? UI update that resolves DEPR-114. Also resolves DEPR-113. ## What is the current behavior? - The breadcrumbs on the file explorer have some rough edges in column view - Fancy hide/show behavior - Hidden tap targets - `FileExplorerHeader` actions can overflow on the x-axis - The Navigate button is only shown on hover - The inline Navigate flow does not work well on smaller screens ## What is the new behavior? - Column view now shows the same in-explorer breadcrumb trail as list view - The active breadcrumb is visually emphasized, while inactive breadcrumbs remain clickable - The back affordance now uses a clearer arrow treatment with a stronger separator from the breadcrumb trail - The Navigate button is permanently visible and moved to the right-side action group before Reload - Navigate now opens a dialog on both desktop and mobile - Added typed telemetry so we can measure `Navigate` usage before deciding whether to keep or remove it - Fixed header overflow by letting the full header contents scroll horizontally together instead of visibly spilling out | Before | After | | --- | --- | | <img width="947" height="997" alt="Buckets Storage AWS Healthy Toolshed Supabase" src="https://github.com/user-attachments/assets/fa53fdd4-954c-4832-bf9b-210b63ae020b" /> | <img width="947" height="997" alt="Buckets Storage AWS Healthy Toolshed Supabase" src="https://github.com/user-attachments/assets/3689a0e5-97d1-4b36-a2dd-7adce23add5d" /> | | <img width="864" height="997" alt="Buckets Storage AWS Healthy Toolshed Supabase" src="https://github.com/user-attachments/assets/ad559118-205f-40e2-b3c5-97cef462d5f5" /> | <img width="864" height="997" alt="Buckets Storage AWS Healthy Toolshed Supabase" src="https://github.com/user-attachments/assets/9c569b29-7c58-4a33-b809-34d6ed919008" /> | ## Additional context Also added a link to the `Buckets` portion of the `PageHeader` breadcrumb: ```text Files > Buckets > MyBucketName ``` It goes to the same place as Files because the root Files page lists buckets, but having both links there feels more ergonomic in practice. --------- Co-authored-by: Ali Waseem <waseema393@gmail.com>
Error Handling
ErrorMatcher displays a typed API error. If the error was classified by handleError (i.e. it is an instance of a known error class), it shows matching troubleshooting steps. Otherwise it shows a generic error card.
Classification happens in the data layer — handleError in data/fetchers.ts matches the error message against patterns and throws the appropriate error subclass (e.g. ConnectionTimeoutError). The component never does regex matching itself.
The title always comes from the caller — the same error type can appear on different pages with different titles.
Usage
import { ErrorMatcher } from 'components/interfaces/ErrorHandling/ErrorMatcher'
{
isError && (
<ErrorMatcher title="Failed to load tables" error={error} supportFormParams={{ projectRef }} />
)
}
Pass the full error object from React Query — not error.message. This lets ErrorMatcher check the error class and show the right troubleshooting steps.
Props
| Prop | Type | Description |
|---|---|---|
title |
string |
Displayed in the error card header. Set by the caller. |
error |
string | { message: string } |
The error from React Query (pass the full object, not .message). |
supportFormParams |
Partial<SupportFormUrlKeys> |
Typed params for the support form URL (projectRef, category…). |
className |
string? |
Extra classes on the card. |
supportFormParams is typed as Partial<SupportFormUrlKeys> — autocomplete shows all available fields (projectRef, orgSlug, category, subject, message, error, sid). The URL is built by createSupportFormUrl() from SupportForm.utils.tsx.
Adding a new error mapping
1. Add the error class to types/api-errors.ts
export type KnownErrorType = 'connection-timeout' | 'your-error'
export class YourError extends ResponseError {
readonly errorType = 'your-error' as const
}
export type ClassifiedError = ConnectionTimeoutError | FailedToRetrieveProjectsError | YourError
2. Add a pattern entry to data/error-patterns.ts
import { YourError } from 'types/api-errors'
export const ERROR_PATTERNS: ErrorPattern[] = [
// existing...
{
pattern: /YOUR_ERROR_PATTERN/i,
ErrorClass: YourError,
},
]
handleError picks this up automatically — any matching API error will be thrown as a YourError instance.
3. Create errorMappings/YourError.tsx
import { SIDEBAR_KEYS } from 'components/layouts/ProjectLayout/LayoutSidebar/LayoutSidebarProvider'
import { useAiAssistantStateSnapshot } from 'state/ai-assistant-state'
import { useSidebarManagerSnapshot } from 'state/sidebar-manager-state'
import { TroubleshootingAccordion } from '../TroubleshootingAccordion'
import {
FixWithAITroubleshootingSection,
TroubleshootingGuideSection,
} from '../TroubleshootingSections'
const ERROR_TYPE = 'your-error'
const BUILD_PROMPT = () => `Describe the issue for the AI assistant.`
export function YourErrorTroubleshooting() {
const { openSidebar } = useSidebarManagerSnapshot()
const aiSnap = useAiAssistantStateSnapshot()
return (
<TroubleshootingAccordion
errorType={ERROR_TYPE}
stepTitles={{ 1: 'Troubleshooting guide', 2: 'Debug with AI' }}
>
<TroubleshootingGuideSection
number={1}
errorType={ERROR_TYPE}
href="https://supabase.com/docs/guides/..."
/>
<FixWithAITroubleshootingSection
number={2}
errorType={ERROR_TYPE}
buildPrompt={BUILD_PROMPT}
onDebugWithAI={(prompt) => {
openSidebar(SIDEBAR_KEYS.AI_ASSISTANT)
aiSnap.newChat({ initialMessage: prompt })
}}
/>
</TroubleshootingAccordion>
)
}
4. Add it to error-mappings.tsx
import { YourErrorTroubleshooting } from './errorMappings/YourError'
export const ERROR_MAPPINGS: Record<KnownErrorType, ErrorMapping> = {
// existing...
'your-error': {
id: 'your-error',
Troubleshooting: YourErrorTroubleshooting,
},
}
That's it. ErrorMatcher picks it up automatically.
Available section components
| Component | Props |
|---|---|
RestartDatabaseTroubleshootingSection |
number, errorType, onRestartProject? |
TroubleshootingGuideSection |
number, errorType, href, title?, description? |
FixWithAITroubleshootingSection |
number, errorType, buildPrompt, onDebugWithAI? |