#How to create a generic Input when passing prop `class` to override styles?

4 messages · Page 1 of 1 (latest)

wraith shore
#

Hi,

I'm trying to create a generic input. I'm using Tailwindcss for the styling with cva (class-variance-authority) which allows me to create variants.

I want to allow users to pass class to override the input.

I have this component:

import { JSX, mergeProps } from 'solid-js';
import { VariantProps } from 'class-variance-authority';
import { inputStyles } from './inputStyles';

export type InputProps = JSX.InputHTMLAttributes<HTMLInputElement> &
  JSX.InputHTMLAttributes<HTMLLabelElement> &
  VariantProps<typeof inputStyles>;

export const Input = (props: InputProps) => {
  const merged = mergeProps({ type: 'text' }, props);
  const { size = 'md', ...inputProps } = merged;
  return (
    <div class="flex flex-col">
      <label class="text-gray-400" for={props.id}>
        {props.placeholder}
      </label>
      <input class={`${inputStyles({ size })} ${props.class}`} {...inputProps} />
    </div>
  );
};

Ant then I call the component like so

<Input placeholder="Password" size="md" class="text-pink-300" type="password" />

The problem here is that if I try to extract class from props const { size, class, ...inputProps } = merged; I get an error: ** Unexpected keyword 'class'**. I know that class is a reserved word in JavaScript. However, if I try to use className then I get this error: Property 'className' does not exist on type { ... };

Is there a way to pass a class or should I rename the prop as something else?

earnest tulip
#

Hi you can extract class by renaming it
const { size = "md", class: userClass, ...inputProps } = merged;
then pass it like normal ```<input class={${inputStyles({ size })} ${userClass}} {...inputProps} />

#

But you still will have problem with reactivity if you destructure props like that, same with size=md should be in mergeProps. You can use built in solid helper something like this

  const merged = mergeProps({ type: "text", size: "md" }, props);
  const [selectedProps, restInputProps] = splitProps(merged, ["class", "size"]);

then when rendering

      <input
        class={`${inputStyles({ size: selectedProps.size })} ${
          selectedProps.class
        }`}
        {...restInputProps}
      />

wraith shore
#

Hi @earnest tulip,

Thank you very much for your reply. I didn't know about splitProps , this solved my problem.