From 6325d6b307d889d7884858ed13c1b0fea81117ce Mon Sep 17 00:00:00 2001 From: Antony Bouyon Date: Tue, 3 Feb 2026 12:49:22 +0100 Subject: [PATCH] feat: remove internal hooks & add performance disclaimer to useBreakpoint Signed-off-by: Antony Bouyon --- docs-ui/src/app/hooks/page.mdx | 12 +- docs-ui/src/app/hooks/use-breakpoint/page.mdx | 8 +- .../app/hooks/use-media-query/components.tsx | 43 ------- .../src/app/hooks/use-media-query/example.css | 25 ----- .../src/app/hooks/use-media-query/page.mdx | 95 ---------------- .../hooks/use-media-query/props-definition.ts | 36 ------ .../src/app/hooks/use-media-query/snippets.ts | 54 --------- docs-ui/src/app/hooks/use-styles/page.mdx | 62 ----------- .../app/hooks/use-styles/props-definition.ts | 58 ---------- docs-ui/src/app/hooks/use-styles/snippets.ts | 105 ------------------ docs-ui/src/utils/data.ts | 8 -- 11 files changed, 8 insertions(+), 498 deletions(-) delete mode 100644 docs-ui/src/app/hooks/use-media-query/components.tsx delete mode 100644 docs-ui/src/app/hooks/use-media-query/example.css delete mode 100644 docs-ui/src/app/hooks/use-media-query/page.mdx delete mode 100644 docs-ui/src/app/hooks/use-media-query/props-definition.ts delete mode 100644 docs-ui/src/app/hooks/use-media-query/snippets.ts delete mode 100644 docs-ui/src/app/hooks/use-styles/page.mdx delete mode 100644 docs-ui/src/app/hooks/use-styles/props-definition.ts delete mode 100644 docs-ui/src/app/hooks/use-styles/snippets.ts diff --git a/docs-ui/src/app/hooks/page.mdx b/docs-ui/src/app/hooks/page.mdx index 75bee70743..f4b77c3a0c 100644 --- a/docs-ui/src/app/hooks/page.mdx +++ b/docs-ui/src/app/hooks/page.mdx @@ -8,17 +8,7 @@ Backstage UI custom hooks provide easy access to design system features, style m - - diff --git a/docs-ui/src/app/hooks/use-breakpoint/page.mdx b/docs-ui/src/app/hooks/use-breakpoint/page.mdx index 4ee410fc74..a5c1a64e92 100644 --- a/docs-ui/src/app/hooks/use-breakpoint/page.mdx +++ b/docs-ui/src/app/hooks/use-breakpoint/page.mdx @@ -3,6 +3,7 @@ import { CodeBlock } from '@/components/CodeBlock'; import { PageTitle } from '@/components/PageTitle'; import { PropsTable } from '@/components/PropsTable'; import { Snippet } from '@/components/Snippet'; +import { Banner } from '@/components/Banner'; import { UseBreakpointExample } from './components'; import { useBreakpointReturnDefs } from './props-definition'; import { useBreakpointExampleSnippet } from './snippets'; @@ -14,6 +15,11 @@ import { useBreakpointExampleSnippet } from './snippets'; ## 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. - + diff --git a/docs-ui/src/app/hooks/use-media-query/components.tsx b/docs-ui/src/app/hooks/use-media-query/components.tsx deleted file mode 100644 index 1ebcd64dfa..0000000000 --- a/docs-ui/src/app/hooks/use-media-query/components.tsx +++ /dev/null @@ -1,43 +0,0 @@ -'use client'; -import { useMediaQuery } from '@backstage/ui/src/hooks/useMediaQuery'; -import './example.css'; - -export function UseMediaQueryThemeExample() { - const isDarkMode = useMediaQuery('(prefers-color-scheme: dark)'); - - return ( -

{isDarkMode ? 'User prefers Dark mode' : 'User prefers Light mode'}

- ); -} - -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 ( -

- {isMobile && ''} - {isTablet && ''} - {isDesktop && ''} -

- ); -} - -export function UseMediaQueryPreferencesExample() { - const prefersReducedMotion = useMediaQuery( - '(prefers-reduced-motion: reduce)', - ); - - return ( -

- Content -

- ); -} - -export function UseMediaQueryOrientationExample() { - const isPortrait = useMediaQuery('(orientation: portrait)'); - - return

{isPortrait ? 'Portrait mode' : 'Landscape mode'}

; -} diff --git a/docs-ui/src/app/hooks/use-media-query/example.css b/docs-ui/src/app/hooks/use-media-query/example.css deleted file mode 100644 index 5fb132f9f4..0000000000 --- a/docs-ui/src/app/hooks/use-media-query/example.css +++ /dev/null @@ -1,25 +0,0 @@ -@keyframes borderSlide { - 0%, - 100% { - transform: translateX(-90%); - } - 50% { - transform: translateX(190%); - } -} - -.animated-border { - position: relative; - overflow: hidden; -} - -.animated-border::after { - content: ''; - position: absolute; - bottom: 0; - left: 0; - width: 50%; - height: 2px; - background-color: currentColor; - animation: borderSlide 5s ease-in-out infinite; -} diff --git a/docs-ui/src/app/hooks/use-media-query/page.mdx b/docs-ui/src/app/hooks/use-media-query/page.mdx deleted file mode 100644 index bd01152581..0000000000 --- a/docs-ui/src/app/hooks/use-media-query/page.mdx +++ /dev/null @@ -1,95 +0,0 @@ -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 { Banner } from '@/components/Banner'; -import { - UseMediaQueryOrientationExample, - UseMediaQueryPreferencesExample, - UseMediaQueryResponsiveExample, - UseMediaQueryThemeExample, -} from './components'; -import { - useMediaQueryParamDefs, - useMediaQueryReturnDefs, -} from './props-definition'; -import { - useMediaQueryOrientationSnippet, - useMediaQueryPreferencesSnippet, - useMediaQueryResponsiveSnippet, - useMediaQueryUsageSnippet, -} from './snippets'; - - - - - -## Usage - -The `useMediaQuery` hook allows you to evaluate CSS media queries in your components, enabling responsive design and behavior. - -} - code={useMediaQueryUsageSnippet} -/> - -## Parameters - - - -## Return Value - - -## Examples - -### Responsive Layouts - -Adapt layout based on different screen sizes. - -} - code={useMediaQueryResponsiveSnippet} -/> - -### User Preferences - -Respect user system preferences. - -} - code={useMediaQueryPreferencesSnippet} -/> - -### Device Orientation - -Detect screen orientation. - -} - code={useMediaQueryOrientationSnippet} -/> - - diff --git a/docs-ui/src/app/hooks/use-media-query/props-definition.ts b/docs-ui/src/app/hooks/use-media-query/props-definition.ts deleted file mode 100644 index 315696e74a..0000000000 --- a/docs-ui/src/app/hooks/use-media-query/props-definition.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { type PropDef } from '@/utils/propDefs'; - -export const useMediaQueryParamDefs: Record = { - 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 = { - matches: { - type: 'boolean', - description: 'True if the media query currently matches', - }, -}; diff --git a/docs-ui/src/app/hooks/use-media-query/snippets.ts b/docs-ui/src/app/hooks/use-media-query/snippets.ts deleted file mode 100644 index 157da945f0..0000000000 --- a/docs-ui/src/app/hooks/use-media-query/snippets.ts +++ /dev/null @@ -1,54 +0,0 @@ -export const useMediaQueryUsageSnippet = `import { useMediaQuery } from '@backstage/ui'; - -function MyComponent() { - const isDarkMode = useMediaQuery('(prefers-color-scheme: dark)'); - - return ( -

- {isDarkMode - ? 'User prefers Dark mode' - : 'User prefers Light mode' - } -

- ); -}`; - -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 ( -

- {isMobile && } - {isTablet && } - {isDesktop && } -

- ); -}`; - -export const useMediaQueryPreferencesSnippet = `import { useMediaQuery } from '@backstage/ui'; - -function AccessibleComponent() { - const prefersReducedMotion = useMediaQuery('(prefers-reduced-motion: reduce)'); - - return ( -

- Content -

- ); -}`; - -export const useMediaQueryOrientationSnippet = `import { useMediaQuery } from '@backstage/ui'; - -function OrientationAware() { - const isPortrait = useMediaQuery('(orientation: portrait)'); - - return ( -

- {isPortrait ? 'Portrait mode' : 'Landscape mode'} -

- ); -}`; diff --git a/docs-ui/src/app/hooks/use-styles/page.mdx b/docs-ui/src/app/hooks/use-styles/page.mdx deleted file mode 100644 index 080a283dcc..0000000000 --- a/docs-ui/src/app/hooks/use-styles/page.mdx +++ /dev/null @@ -1,62 +0,0 @@ -import { ChangelogComponent } from '@/components/ChangelogComponent'; -import { CodeBlock } from '@/components/CodeBlock'; -import { Banner } from '@/components/Banner'; -import { PageTitle } from '@/components/PageTitle'; -import { PropsTable } from '@/components/PropsTable'; -import { - useStylesUsageSnippet, - useStylesDefsSnippet, - useStylesAttributesSnippet, -} from './snippets'; -import { useStylesPropsDefs, useStylesReturnDefs } from './props-definition'; - - - - - -## Usage - -The `useStyles` hook is the core styling utility that processes component definitions and props to generate: - -- **Class names** -- **Data attributes** for state-based styling (e.g., `data-disabled`, `data-variant`) -- **Utility classes** from utility props like `padding`, `margin`, `display` (with responsive support) -- **CSS custom properties** for custom values not in predefined utility lists -- **Cleaned props** with utility props removed (safe to spread onto DOM elements) - - - -## Parameters - - - -## Return Value - - - -## How It Works - -### Component Definition - -A component definition describes how a component should be styled: - - - - - -### Data Attributes - -Data attributes enable state-based styling through CSS selectors. The hook automatically adds `data-*` to the attributes based on the defined props: - - - - diff --git a/docs-ui/src/app/hooks/use-styles/props-definition.ts b/docs-ui/src/app/hooks/use-styles/props-definition.ts deleted file mode 100644 index 0c8a2a1728..0000000000 --- a/docs-ui/src/app/hooks/use-styles/props-definition.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { type PropDef } from '@/utils/propDefs'; - -export const useStylesPropsDefs: Record = { - componentDefinition: { - type: 'complex', - complexType: { - name: 'ComponentDefinition', - properties: { - classNames: { - type: 'Record', - required: true, - }, - dataAttributes: { - type: 'Record', - required: false, - }, - utilityProps: { - type: 'string[]', - required: false, - }, - }, - }, - }, - props: { - type: 'enum', - description: 'All component props', - values: ['{ [key: string]: any; }'], - }, -}; - -export const useStylesReturnDefs: Record = { - classNames: { - type: 'enum', - values: ['Record'], - description: - "The component's class names mapped to their style definitions", - }, - dataAttributes: { - type: 'enum', - values: ['Record'], - description: - 'Data attributes generated from the component definition and props', - }, - utilityClasses: { - type: 'string', - description: 'Combined utility classes based on utility props', - }, - style: { - type: 'enum', - values: ['React.CSSProperties'], - description: 'The combined style object for the component', - }, - cleanedProps: { - type: 'enum', - values: ['Record'], - description: 'The original props with utility props removed', - }, -}; diff --git a/docs-ui/src/app/hooks/use-styles/snippets.ts b/docs-ui/src/app/hooks/use-styles/snippets.ts deleted file mode 100644 index 60c5a66a9b..0000000000 --- a/docs-ui/src/app/hooks/use-styles/snippets.ts +++ /dev/null @@ -1,105 +0,0 @@ -export const useStylesUsageSnippet = `import { useStyles } from '@backstage/ui'; -import type { - ComponentDefinition, - SpaceProps, - UtilityProps, -} from '@backstage/ui'; - -// Define your component's styling configuration -const buttonDefinition: ComponentDefinition = { - classNames: { - root: 'bui-button', - icon: 'bui-button-icon', - }, - dataAttributes: { - variant: ['primary', 'secondary', 'ghost'] as const, - size: ['small', 'medium', 'large'] as const, - 'is-disabled': [true, false] as const, - }, - utilityProps: ['gap', 'mb', 'mt', 'ml', 'mr'], -} as const satisfies ComponentDefinition; - -// type the component props -interface ButtonProps { - variant?: 'primary' | 'secondary' | 'ghost'; - size?: 'small' | 'medium' | 'large'; - isDisabled?: boolean; - gap?: UtilityProps['gap']; - mb?: SpaceProps['mb']; - mt?: SpaceProps['mt']; - ml?: SpaceProps['ml']; - mr?: SpaceProps['mr']; - icon?: React.ReactElement; - children?: React.ReactNode; -} - -// Use the useStyles hook in your component -export function Button({ - variant = 'primary', - size = 'medium', - isDisabled, - ...props -}: Readonly) { - const { classNames, dataAttributes, utilityClasses, cleanedProps } = - useStyles(buttonDefinition, { - variant, - size, - 'is-disabled': isDisabled, - ...props, - }); - - return ( - - ); -}`; - -export const useStylesDefsSnippet = `const componentDefinition = { - // CSS class names for component parts - classNames: { - root: 'bui-button', - icon: 'bui-button-icon', - }, - - // Props that become data attributes for CSS targeting - // data-attribute must be kebab-case to respect HTML standards - // And casing matters here, lowercase only: - // 'variant' not 'Variant', 'is-disabled' not 'isDisabled'.. - dataAttributes: { - variant: ['primary', 'secondary'] as const, - size: ['small', 'large'] as const, - 'is-disabled': [true, false] as const, - }, - - // Props that become utility classes (spacing, layout, etc.) - utilityProps: ['m', 'mb', 'mt', 'ml', 'mr'], -};`; - -export const useStylesAttributesSnippet = `/* Component CSS can use data attributes for variants */ -.bui-button { - padding: 0.5rem 1rem; - border-radius: 0.25rem; -} - -/* Variant styles */ -.bui-button[data-variant="primary"] { - background: blue; - color: white; -} - -.bui-button[data-variant="secondary"] { - background: gray; - color: black; -} - -/* State styles */ -.bui-button[data-is-disabled="true"] { - opacity: 0.5; - pointer-events: none; -}`; diff --git a/docs-ui/src/utils/data.ts b/docs-ui/src/utils/data.ts index a750f75bd6..a1a6672135 100644 --- a/docs-ui/src/utils/data.ts +++ b/docs-ui/src/utils/data.ts @@ -144,12 +144,4 @@ export const hooks: Page[] = [ title: 'useBreakpoint', slug: 'use-breakpoint', }, - { - title: 'useMediaQuery', - slug: 'use-media-query', - }, - { - title: 'useStyles', - slug: 'use-styles', - }, ];