Home > Back-end >  Storybook Ionic React styled-components CSS order issues
Storybook Ionic React styled-components CSS order issues

Time:10-28

I have custom components, which overrides Ionic's standard component look with the styled-components library. On the app page, this component looks ok. When I try to use it with Storybook it seems Ionic overrides my custom styles. After some discovery, I found that the order of style tags in the HTML header has changed. Firstly CSS from styled-components is included, then CSS from Ionic. Which caused the wrong order of style precedence.

The component:

import styled from 'styled-components'
import { IonInput } from '@ionic/react'
import { TextInputProps } from './TextInput.types'

const StyledIonInput = styled(IonInput)`
  font-weight: normal;
  line-height: 24px;
  height: 40px;
  border: 1px solid #d3d3d3;
  border-radius: 50px;
  --padding-start: 20px;
  --padding-left: 20px;
`

const TextInput = ({
  value,
  type = 'text',
  placeholder,
  onChange,
}: TextInputProps) => (
  <StyledIonInput
    value={value}
    type={type}
    onIonChange={onChange}
    placeholder={placeholder}
  />
)

export default TextInput

The story:

import { ComponentMeta, ComponentStory } from '@storybook/react'
import TextInput from './TextInput.component'

// eslint-disable-next-line import/no-default-export
export default {
  title: 'TextInput',
  component: TextInput,
} as ComponentMeta<typeof TextInput>

const Template: ComponentStory<typeof TextInput> = (args) => (
  <TextInput {...args} />
)

export const Default = Template.bind({})
Default.args = {
  placeholder: 'regular text-input',
}
Default.storyName = 'default'

export const Password = Template.bind({})
Password.args = {
  placeholder: 'password text',
  type: 'password',
}
Password.storyName = 'Password type'

preview.js with decorator configuration:

/* Core CSS required for Ionic components to work properly */
import '@ionic/react/css/core.css'

/* Basic CSS for apps built with Ionic */
import '@ionic/react/css/normalize.css'
import '@ionic/react/css/structure.css'
import '@ionic/react/css/typography.css'

/* Optional CSS utils that can be commented out */
import '@ionic/react/css/padding.css'
import '@ionic/react/css/float-elements.css'
import '@ionic/react/css/text-alignment.css'
import '@ionic/react/css/text-transformation.css'
import '@ionic/react/css/flex-utils.css'
import '@ionic/react/css/display.css'

import '../src/theme/variables.css'

import React, { useState } from 'react'

import { setupConfig } from '@ionic/react'
import { IonApp, IonContent, IonPage } from '@ionic/react'

/* Ionic framework configuration to enforce same look and feel across platforms */
setupConfig({
  rippleEffect: false,
  mode: 'ios',
})

const IonWrapper = ({ children }) => {
  return (
    <IonApp>
      <IonPage style={{ margin: '20px' }}>
        <IonContent>{children}</IonContent>
      </IonPage>
    </IonApp>
  )
}

export const decorators = [
  (Story) => (
    <IonWrapper>
      <Story />
    </IonWrapper>
  ),
]

export const parameters = {
  actions: { argTypesRegex: '^on[A-Z].*' },
  controls: {
    matchers: {
      // color: /(background|color)$/i,
      date: /Date$/,
    },
  },
}

Example of the wrong precedence of styles. Selected line is generated by styled-components. example of wrong generated styles

Any advice will be appreciated!

CodePudding user response:

styled-components priority rules did the trick:

const StyledIonInput = styled(IonInput)`
  && {
    font-weight: normal;
    line-height: 24px;
    height: 40px;
    border: 1px solid #d3d3d3;
    border-radius: 50px;
    --padding-start: 20px;
    --padding-left: 20px;
  }
`
  • Related