diff --git a/docs-ui/src/app/hooks/page.mdx b/docs-ui/src/app/hooks/page.mdx
index b2e2b81e7d..75bee70743 100644
--- a/docs-ui/src/app/hooks/page.mdx
+++ b/docs-ui/src/app/hooks/page.mdx
@@ -18,17 +18,7 @@ Backstage UI custom hooks provide easy access to design system features, style m
/>
-
-
diff --git a/docs-ui/src/app/hooks/use-media-query/page.mdx b/docs-ui/src/app/hooks/use-media-query/page.mdx
index 84668b2a3e..bd01152581 100644
--- a/docs-ui/src/app/hooks/use-media-query/page.mdx
+++ b/docs-ui/src/app/hooks/use-media-query/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 {
UseMediaQueryOrientationExample,
UseMediaQueryPreferencesExample,
@@ -25,6 +26,11 @@ import {
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.
diff --git a/docs-ui/src/app/hooks/use-styles/page.mdx b/docs-ui/src/app/hooks/use-styles/page.mdx
new file mode 100644
index 0000000000..ca235c4778
--- /dev/null
+++ b/docs-ui/src/app/hooks/use-styles/page.mdx
@@ -0,0 +1,59 @@
+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
new file mode 100644
index 0000000000..0c8a2a1728
--- /dev/null
+++ b/docs-ui/src/app/hooks/use-styles/props-definition.ts
@@ -0,0 +1,58 @@
+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
new file mode 100644
index 0000000000..55cf7ddee7
--- /dev/null
+++ b/docs-ui/src/app/hooks/use-styles/snippets.ts
@@ -0,0 +1,105 @@
+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;
+}`;