refactor: migrate to the new format

Signed-off-by: Antony Bouyon <antony.bouyon@believe.com>
This commit is contained in:
Antony Bouyon
2026-01-16 17:56:30 +01:00
parent 1cf2972f45
commit d61a795383
9 changed files with 67 additions and 88 deletions
-23
View File
@@ -1,23 +0,0 @@
import { hooks } from '@/utils/data';
export default async function Page({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
const { default: Component } = await import(`@/content/hooks/${slug}.mdx`);
return <Component />;
}
export function generateStaticParams() {
const list = [...hooks];
return list.map(hook => ({
slug: hook.slug,
}));
}
export const dynamicParams = false;
@@ -0,0 +1,28 @@
'use client';
import { useBreakpoint } from '@backstage/ui';
import { useEffect, useState } from 'react';
export function UseBreakpointExample() {
const { breakpoint, up, down } = useBreakpoint();
const [isMounted, setIsMounted] = useState(false);
// prevent hydration mismatch by rendering only on the client
useEffect(() => {
setIsMounted(true);
}, []);
if (!isMounted) {
return null;
}
return (
<div>
<p>Current Breakpoint: {breakpoint}</p>
{(up('md') && <p>The viewport is larger than 1024px.</p>) ||
(down('sm') && <p>The viewport is smaller than 768px.</p>) || (
<p>The viewport is between 768px and 1024px.</p>
)}
</div>
);
}
@@ -0,0 +1,46 @@
import { ChangelogComponent } from '@/components/ChangelogComponent';
import { CodeBlock } from '@/components/CodeBlock';
import { PageTitle } from '@/components/PageTitle';
import { PropsTable } from '@/components/PropsTable';
import { Snippet } from '@/components/Snippet';
import { UseBreakpointExample } from './components';
import {
useBreakpointReturnDefs,
} from './props-definition';
import {
useBreakpointExampleSnippet
} from './snippets';
<PageTitle
title="useBreakpoint"
description="A hook to detect responsive breakpoints and manage responsive layouts."
/>
## Usage
The `useBreakpoint` hook returns the active breakpoint and two functions, `up` and `down`, to check if the viewport is above, or below a given breakpoint, letting you adjust your UI responsively.
<Snippet
align="center"
py={4}
height={150}
preview={<UseBreakpointExample />}
code={useBreakpointExampleSnippet}
/>
## Breakpoints
The default breakpoints are:
- **initial**: < 640px
- **xs**: ≥ 640px < 768px
- **sm**: ≥ 768px < 1024px
- **md**: ≥ 1024px < 1280px
- **lg**: ≥ 1280px < 1536px
- **xl**: ≥ 1536px
## Return Value
<PropsTable data={useBreakpointReturnDefs} isHook />
<ChangelogComponent component="use-breakpoint" />
@@ -0,0 +1,23 @@
import { type PropDef } from '@/utils/propDefs';
const Breakpoint = ['"initial"', '"xs"', '"sm"', '"md"', '"lg"', '"xl"'];
export const useBreakpointReturnDefs: Record<string, PropDef> = {
breakpoint: {
type: 'enum',
values: Breakpoint,
description: 'The current active breakpoint based on screen width',
},
up: {
type: 'enum',
values: [`(breakpoint: ${Breakpoint.join(' | ')}) => boolean`],
description:
'Function that takes a breakpoint and returns true if the screen width is at or above that breakpoint',
},
down: {
type: 'enum',
values: [`(breakpoint: ${Breakpoint.join(' | ')}) => boolean`],
description:
'Function that takes a breakpoint and returns true if the screen width is at or below that breakpoint',
},
};
@@ -0,0 +1,13 @@
export const useBreakpointExampleSnippet = `import { useBreakpoint } from '@backstage/ui';
function ResponsiveComponent() {
const { breakpoint, up, down } = useBreakpoint();
return (
<div>
<p>Current Breakpoint: {breakpoint}</p>
{up('md') && <p>The viewport is medium or larger.</p>}
{down('sm') && <p>The viewport is small or smaller.</p>}
</div>
);
}`;
@@ -0,0 +1,42 @@
'use client';
import { useMediaQuery } from '@backstage/ui/src/hooks/useMediaQuery';
export function UseMediaQueryThemeExample() {
const isDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
return (
<div>
{isDarkMode ? 'User prefers Dark mode' : 'User prefers Light mode'}
</div>
);
}
export function UseMediaQueryResponsiveExample() {
const isMobile = useMediaQuery('(max-width: 768px)');
const isTablet = useMediaQuery('(min-width: 769px) and (max-width: 1024px)');
const isDesktop = useMediaQuery('(min-width: 1025px)');
return (
<div>
{isMobile && '<MobileLayout />'}
{isTablet && '<TabletLayout />'}
{isDesktop && '<DesktopLayout />'}
</div>
);
}
export function UseMediaQueryPreferencesExample() {
const prefersReducedMotion = useMediaQuery(
'(prefers-reduced-motion: reduce)',
);
return (
<div className={prefersReducedMotion ? 'no-animations' : ''}>Content</div>
);
}
export function UseMediaQueryOrientationExample() {
const isPortrait = useMediaQuery('(orientation: portrait)');
return <div>{isPortrait ? 'Portrait mode' : 'Landscape mode'}</div>;
}
@@ -0,0 +1,89 @@
import { ChangelogComponent } from '@/components/ChangelogComponent';
import { CodeBlock } from '@/components/CodeBlock';
import { PageTitle } from '@/components/PageTitle';
import { PropsTable } from '@/components/PropsTable';
import { Snippet } from '@/components/Snippet';
import {
UseMediaQueryOrientationExample,
UseMediaQueryPreferencesExample,
UseMediaQueryResponsiveExample,
UseMediaQueryThemeExample,
} from './components';
import {
useMediaQueryParamDefs,
useMediaQueryReturnDefs,
} from './props-definition';
import {
useMediaQueryOrientationSnippet,
useMediaQueryPreferencesSnippet,
useMediaQueryResponsiveSnippet,
useMediaQueryUsageSnippet,
} from './snippets';
<PageTitle
title="useMediaQuery"
description="Hook to evaluate and react to CSS media queries programmatically."
/>
## Usage
The `useMediaQuery` hook allows you to evaluate CSS media queries in your components, enabling responsive design and behavior.
<Snippet
align="center"
py={4}
height={150}
open={true}
preview={<UseMediaQueryThemeExample />}
code={useMediaQueryUsageSnippet}
/>
## Parameters
<PropsTable data={useMediaQueryParamDefs} isHook />
## Return Value
<PropsTable data={useMediaQueryReturnDefs} isHook />
## Examples
### Responsive Layouts
Adapt layout based on different screen sizes.
<Snippet
align="center"
py={4}
height={200}
open={true}
preview={<UseMediaQueryResponsiveExample />}
code={useMediaQueryResponsiveSnippet}
/>
### User Preferences
Respect user system preferences.
<Snippet
align="center"
py={4}
height={150}
open={true}
preview={<UseMediaQueryPreferencesExample />}
code={useMediaQueryPreferencesSnippet}
/>
### Device Orientation
Detect screen orientation.
<Snippet
align="center"
py={4}
height={150}
open={true}
preview={<UseMediaQueryOrientationExample />}
code={useMediaQueryOrientationSnippet}
/>
<ChangelogComponent component="use-media-query" />
@@ -0,0 +1,36 @@
import { type PropDef } from '@/utils/propDefs';
export const useMediaQueryParamDefs: Record<string, PropDef> = {
query: {
type: 'string',
description: 'The CSS media query to evaluate',
},
options: {
type: 'complex',
complexType: {
name: 'UseMediaQueryOptions',
properties: {
defaultValue: {
type: 'boolean',
required: false,
description:
'Default value to use when rendering on the server, defaults to false',
},
initializeWithValue: {
type: 'boolean',
required: false,
description:
'Whether to initialize with the current value of the media query, or use the default value initially',
},
},
},
default: 'defaultValue: false\ninitializeWithValue: true',
},
};
export const useMediaQueryReturnDefs: Record<string, PropDef> = {
matches: {
type: 'boolean',
description: 'True if the media query currently matches',
},
};
@@ -0,0 +1,53 @@
export const useMediaQueryUsageSnippet = `import { useMediaQuery } from '@backstage/ui';
function MyComponent() {
const isDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
return (
<div>
{isDarkMode ? 'Dark mode enabled' : 'Light mode enabled'}
</div>
);
}`;
export const useMediaQueryResponsiveSnippet = `import { useMediaQuery } from '@backstage/ui';
function ResponsiveLayout() {
const isMobile = useMediaQuery('(max-width: 768px)');
const isTablet = useMediaQuery('(min-width: 769px) and (max-width: 1024px)');
const isDesktop = useMediaQuery('(min-width: 1025px)');
return (
<div>
{isMobile && <MobileLayout />}
{isTablet && <TabletLayout />}
{isDesktop && <DesktopLayout />}
</div>
);
}`;
export const useMediaQueryPreferencesSnippet = `import { useMediaQuery } from '@backstage/ui';
function AccessibleComponent() {
const prefersReducedMotion = useMediaQuery('(prefers-reduced-motion: reduce)');
return (
<div
className={prefersReducedMotion ? 'no-animations' : ''}
>
Content
</div>
);
}`;
export const useMediaQueryOrientationSnippet = `import { useMediaQuery } from '@backstage/ui';
function OrientationAware() {
const isPortrait = useMediaQuery('(orientation: portrait)');
return (
<div>
{isPortrait ? 'Portrait mode' : 'Landscape mode'}
</div>
);
}`;