No Preview

Sorry, but you either have no stories or none are selected somehow.

If the problem persists, check the browser console, or the terminal you've run Storybook from.

The component failed to render properly, likely due to a configuration issue in Storybook. Here are some common causes and how you can address them:

  1. Missing Context/Providers: You can use decorators to supply specific contexts or providers, which are sometimes necessary for components to render correctly. For detailed instructions on using decorators, please visit the Decorators documentation.
  2. Misconfigured Webpack or Vite: Verify that Storybook picks up all necessary settings for loaders, plugins, and other relevant parameters. You can find step-by-step guides for configuring Webpack or Vite with Storybook.
  3. Missing Environment Variables: Your Storybook may require specific environment variables to function as intended. You can set up custom environment variables as outlined in the Environment Variables documentation.

ESLint rules

Custom ESLint rules for Gamut projects

The eslint-plugin-gamut package provides custom ESLint rules to enforce best practices and maintain code quality across Gamut projects. These rules help ensure consistent styling patterns and proper usage of Gamut components.

Available rules

gamut/no-inline-style

Level: error

Disallows the use of inline style props on JSX elements. This rule encourages the use of styled components, CSS classes, or design system utilities instead of inline styles.

Why? Inline styles make it harder to maintain consistent styling, can't be optimized by build tools, and don't benefit from our design token system.

❌ Incorrect

// Don't use inline style objects <div style={{ padding: 0, margin: 10 }} /> // Even with variables <Component style={customStyles} /> // Or with dynamic values <Alert style={{ width: isOpen ? '100%' : '50%' }} />

✅ Correct

// Use styled components import styled from '@emotion/styled'; import { css } from '@codecademy/gamut-styles'; import { Box } from '@codecademy/gamut'; const Container = styled(Box)( css({ p: 0, m: 10, }) ) // Use system props from Box components import { Box } from '@codecademy/gamut'; <Box p={0} m={10} /> // Use states utility for conditional styling import { states } from '@codecademy/gamut-styles'; import styled from '@emotion/styled'; const ExpandableContainer = styled.Box( css({ width: '50%', }), states({ isExpanded: { width: '100%' }, }) ); <ExpandableContainer isExpanded={isExpanded} /> // If need be, use className with CSS modules or global styles <div className="my-component" />

Disabling the rule

For third-party components or edge cases where inline styles are necessary (e.g., framer-motion animations), you can disable the rule:

// eslint-disable-next-line gamut/no-inline-style <motion.div style={{ transformOrigin: 'center' }} />

gamut/no-css-standalone

Level: error

Prevents importing standalone .css or .scss files. This rule enforces the use of CSS-in-JS solutions that integrate with our design system.

Why? Standalone stylesheets bypass our theming system, can cause specificity conflicts, and don't benefit from component-scoped styling.

❌ Incorrect

// Don't import CSS/SCSS files import './styles.css'; import '../components/Button.scss';

✅ Correct

// Use styled components import styled from '@emotion/styled'; import { StrokeButton } from '@codecademy/gamut'; import { css } from '@codecademy/gamut-styles'; const StyledStrokeButton = styled(StrokeButton)( css({ p: 32, bg: 'primary', }) ); // Use utility functions from gamut-styles import { variant } from '@codecademy/gamut-styles'; const buttonStyles = variant({ variants: { primary: { p: 16, bg: 'primary', }, }, });

gamut/import-paths

Level: error Fixable: Yes (auto-fixable using --fix)

Ensures Gamut import statements use proper module paths. This rule enforces three requirements:

  1. Use relative imports when importing from the same package
  2. Don't append /src to import paths
  3. Don't append /dist to import paths

Why? Proper import paths ensure compatibility across different environments and make refactoring easier.

❌ Incorrect

// Don't use package imports within the same package // (when in @codecademy/gamut package) import { FillButton } from '@codecademy/gamut'; // Don't append /src import { FillButton } from '@codecademy/gamut/src'; // Don't append /dist import { theme } from '@codecademy/gamut-styles/dist';

✅ Correct

// Use relative imports within the same package import { Box } from '../Box'; // Use clean package imports from other packages import { FillButton } from '@codecademy/gamut'; import { theme } from '@codecademy/gamut-styles';
This rule includes auto-fix capabilities for /src and /dist violations!

gamut/prefer-themed

Level: off (by default) Fixable: Yes (auto-fixable using --fix)

Suggests using the themed() utility from gamut-styles instead of directly accessing theme values in styled components. When enabled, this rule helps maintain consistent theme access patterns.

Why? The themed() utility provides better type safety and ensures proper theme value resolution.

❌ Flagged (when enabled)

const StyledDiv = styled.div` color: ${({ theme }) => theme.colors.primary}; `;

✅ Preferred

import { css, themed } from '@codecademy/gamut-styles'; import { Box } from '@codecademy/gamut'; const StyledBox = styled(Box)( css({ color: themed('colors.primary'), }) );
This rule is disabled by default but can be enabled in your project's ESLint config.

Configuration

These rules are automatically included when you extend the recommended configuration:

// .eslintrc.js module.exports = { plugins: ['eslint-plugin-gamut'], rules: { 'gamut/no-inline-style': 'error', 'gamut/no-css-standalone': 'error', 'gamut/import-paths': 'error', 'gamut/prefer-themed': 'off', }, };

Overriding rules

You can override rules for specific files or directories:

// .eslintrc.js module.exports = { overrides: [ { files: ['packages/gamut-illustrations/**'], rules: { 'gamut/no-inline-style': 'off', }, }, ], };
  • - Learn about Gamut styling best practices
  • - Using system props as an alternative to inline styles
  • - Creating styled variants with gamut-styles