Search code examples
javascripttypescriptstorybookstenciljs

Stencil camelCase @Prop is not working in Storybook


I am writing a story in Storybook for the Stencil component. Seems like all props work as expected if they are all lowercase. However, if the prop is camelCase, it is not working. I tried both camelCase and 'dash-case' .nothing works.

Stencil component:

import {Component, Prop, h} from '@stencil/core';

@Component({
  tag: 'text-input',
  shadow: true,
})
export class TextInput {
  @Prop() label: string;
  @Prop() inputId: string;

  render() {
    return (
      <div class="text-input">
        <label htmlFor={this.inputId}>{this.label}</label>
        <input type="text" id={this.inputId} />
      </div>
    )
  }
}

Storybook story:

export default {
  title: 'Components/Text Input',
  argTypes: {
    label: {control: 'text'},
    inputid : {control: 'text'},
  }
};

const Template = (args) => {
  let tag = `<text-input label="${args.label}" inputId="${args.inputid}"></text-input>`;
  return tag
};

export const Default = Template.bind({});
Default.args = {
  label: 'First name:',
  inputid: 'Input1'
};

inputId is the one that doesn't work while label is fine. Renaming inputId="${args.inputid}" to input-id="${args.inputid}"is not helping. It only works if I rename the Stencil prop to the all-lowercase inputid.

How to solve this issue? How can I keep Stencil props camelCase and make it work in Storybook?


Solution

  • Might be something to do with the casing of your argTypes and Default args, i.e. "inputid" is all lowercase. Maybe try the below?

    export default {
      title: 'Components/Text Input',
      argTypes: {
        label: {control: 'text'},
        inputId : {control: 'text'},
      }
    };
    
    const Template = (args) => {
      let tag = `<text-input label="${args.label}" inputId="${args.inputId}"></text-input>`;
      return tag
    };
    
    export const Default = Template.bind({});
    Default.args = {
      label: 'First name:',
      inputId: 'Input1'
    };
    

    I would also try and create your template without string concatenation. EG:

    const Template = ({ label, inputId }) => {
      const element = document.createElement('text-input');
      element.label = label;
      element.inputId = inputId;
      return rootEl;
    };
    

    This will make it easier when you pass in params of another type than string