0

I'm creating a react component library with typescript using CSS Modules to make the project simple but I'm struggling with typescript interfaces when it comes to theming. I want to have several variants of my component to the user just change the property for what he wants.

Without the CSS Modules, using just SCSS for example, I can make it work when I add the prop className = ${styles.theme} but when I change to the Modules, it stops work, it wont regonize anymore the interface properties from the Button.

Like this (Button.tsx):


import styles from "./Button.module.scss";
export interface ButtonProps {
  /**
   * Set this to change button theme properties
   * @default primary
   */
  theme:| "primary"
    | "info"
    | "success"
    | "warning"
    | "danger"
    | "disabled"
    | "primary-outline"
    | "info-outline"
    | "success-outline"
    | "warning-outline"
    | "danger-outline"
    | "primary-flat";
    onClick?: () => void;
}

export const Button: FunctionComponent<ButtonProps> = ({ 
  children, 
  onClick, 
  theme, 
  ...rest 
}) => (
  <div>
    <button 
      className={`${styles.$theme}`} 
      onClick={onClick} 
      {...rest}
    >
      {children}
    </button>
  </div>
) 

And the CSS Module file (Button.module.scss):

button {
  position: relative;
  height: 1.75rem;
  padding: 0.05rem .75rem;

  display: inline-flex;
  justify-content: center;
  align-items: center;

  font-size: 1rem;
  text-align: center;

  cursor: pointer;
  user-select: none;

  border: none;
  border-radius: 4px;
  border-width: 1px solid;
  box-sizing: border-box;

  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  -webkit-transition: background 0.2s ease;
  -moz-transition: background 0.2s ease;
  -o-transition: background 0.2s ease;
  transition: color 200ms ease-in 0s, border-color 200ms ease-in 0s, background-color 200ms ease-in 0s, filter 200ms ease-in 0s;
}

.primary {
  background-color: $snow-04;
  border-color: $snow-04;
  color: $polar-night-04;
  &:hover {
    filter: brightness(90%);
  }
}

.info {
  background-color: $frost-02;
  color: $polar-night-01;
  &:hover {
    filter: brightness(90%);
  }
}

What can I do to have access to the theme props and others from the Button interface? How can I syntax the className on my component to do so?

Thanks so much!

1
  • styles.$theme sounds like this is a typo? The destructuring assignment on props uses theme (without the leading $ sign). Should be styles.theme instead based on the code here. Commented Mar 16, 2021 at 11:48

1 Answer 1

2

Styles is an object after all... you can access the property theme like:

<button className={styles[theme]} onClick={onClick} {...rest}>
  {children}
</button>

I just tried here: https://codesandbox.io/s/typed-css-modules-8itfp?file=/src/App.tsx

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks so much, I was struggling to find the right syntax to make the access for that object.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.