How to Override Astryx Component Styles Using className

Pass a className prop to any Astryx component to merge custom CSS with internal StyleX-generated classes via stylex.props(), allowing safe visual customization without modifying component behavior.

Astryx is a React component library built on StyleX, Meta's compile-time CSS-in-JS system. Every component in the facebook/astryx repository accepts a className prop that integrates seamlessly with the internal styling architecture, enabling developers to apply custom styles while preserving accessibility and interaction logic.

Understanding the className Architecture in Astryx

StyleX Foundation and Class Name Generation

Astryx components rely on StyleX to generate deterministic class names at build time. In packages/core/src/Button/Button.tsx, the component uses stylex.props() to combine internal styles with external class names:

export const Button = (props) => {
  const {className, ...rest} = props;
  const styles = useButtonStyles(); // StyleX-generated object
  return <button {...rest} className={stylex.props(styles.root, className)} />;
};

The styles.root class provides the baseline appearance, while the className prop is appended to allow CSS cascade overrides.

Prop Signature and Type Safety

According to packages/core/src/Button/Button.doc.mjs, the className prop is explicitly typed as string and documented as the standard entry point for style overrides. This pattern remains consistent across all public components in the library.

Methods to Override Component Styles

CSS Module Integration

For scoped styles, pass a CSS Module class to the className prop:

// src/MyButton.module.css
.myButton {
  margin: 8px 0;
  font-weight: 600;
}

// MyComponent.tsx
import styles from './MyButton.module.css';
import {Button} from '@astryxdesign/core';

export const MyComponent = () => (
  <Button className={styles.myButton}>Click me</Button>
);

Global Stylesheet Overrides

Apply global CSS classes for cross-component styling:

/* index.css */
.customBtn {
  background-color: teal;
  border-radius: 4px;
}
import {Button} from '@astryxdesign/core';
import './index.css';

export const MyComponent = () => (
  <Button className="customBtn">Styled Button</Button>
);

StyleX Marker Overrides

For complex interactions involving child elements, use stylex.defineMarker():

import {Button} from '@astryxdesign/core';
import stylex from '@stylexjs/stylex';

const marker = stylex.defineMarker('myHover');

export const MyComponent = () => (
  <Button className={marker}>
    <span className={stylex.when.ancestor(':hover', marker)}>
      Hover text
    </span>
  </Button>
);

className vs. Theming: When to Use Each Approach

Use className for one-off visual adjustments, component-specific positioning, or integrating with existing CSS architectures.

Use Theming for global design system changes. Create a theme using createTheme and wrap your application in ThemeProvider:

import {ThemeProvider, createTheme} from '@astryxdesign/core';

const myTheme = createTheme({
  button: {
    primaryColor: 'magenta',
  },
});

export const App = () => (
  <ThemeProvider theme={myTheme}>
    <Button>Themed Button</Button>
  </ThemeProvider>
);

Use astryx swizzle for structural modifications. This CLI command ejects the component source when you need to add or remove DOM elements.

Key Source Files

Understanding the implementation requires examining these specific files in the facebook/astryx repository:

Summary

  • Astryx components accept a className prop that merges with internal StyleX classes using stylex.props()
  • The merging preserves internal behavior while allowing external CSS to cascade
  • CSS Modules, global stylesheets, and StyleX markers are all valid override mechanisms
  • Use theming for global changes and astryx swizzle for structural modifications
  • All styling approaches maintain the library's accessibility and interaction guarantees

Frequently Asked Questions

How does Astryx merge className with internal styles?

Astryx uses stylex.props() to concatenate the internal StyleX-generated class (e.g., styles.root) with the user-provided className string. The internal classes appear first in the DOM, followed by the custom class, ensuring your CSS rules apply via the cascade without !important declarations.

Can I use CSS Modules with Astryx components?

Yes. Import your module styles and pass the imported class directly to the className prop. Astryx accepts any valid string, including hashed CSS Module class names, making it compatible with most React styling workflows.

What is the difference between using className and theming in Astryx?

className overrides are instance-specific and ideal for positioning or one-off visual tweaks. Theming via ThemeProvider modifies design tokens (colors, spacing) across all component instances globally. Choose className for exceptions; choose theming for systematic design changes.

How do I override styles for a specific component instance without affecting others?

Pass a unique className to that specific component instance. For complex overrides requiring internal structure changes, use the astryx swizzle <Component> command to eject and customize the component source code directly.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →