Skip to content

tailwindCSS.classAttributes custom name when using typescript not working #823

@isimmons

Description

@isimmons

What version of VS Code are you using?

1.80.0

What version of Tailwind CSS IntelliSense are you using?

0.9.11

What version of Tailwind CSS are you using?

3.2.1

What package manager are you using?

npm

What operating system are you using?

Windows 10

Tailwind config

const defaultTheme = require('tailwindcss/defaultTheme')
const stripesPlugin = require('./stripes-plugin.cjs')

module.exports = {
  content: ['./src/**/*.{astro,js,jsx,ts,tsx}'],
  theme: {
    extend: {
      fontFamily: {
        sans: ['Open Sans', 'sans-serif', ...defaultTheme.fontFamily.sans],
      },
    },
  },
  plugins: [require('@tailwindcss/typography'), stripesPlugin],
}

VS Code settings

{
  "tailwindCSS.classAttributes": ["class", "className", "ngClass", ".*Classes"],
  "tailwindCSS.experimental.classRegex": [
    // Support for the `cx()` function from classnames / clsx
    ["cx\\(([^)]*)\\)", "(?:\"|'|`)([^(?:\"|'|`)]*)(?:\"|'|`)"]
  ]
}

Reproduction URL

Describe your issue

Working on dynamic class lookup based on component props in a Button.tsx component in Astro. I need several classes objects so I added the custom name in settings.json tailwindCSS.classAttributes as you see above.

Now with simple demos, this does not work when I use TS annotations. But it works if I use TS assertion

const fooClasses = 'bg-indigo-500'; // works
const fooClasses = 'bg-indigo-500' as string; // works
const fooClasses: string = 'bg-indigo-500'; // not working

const fooClasses = {
  foo: 'bg-indigo-500' // works
}
const fooClasses = {
  foo: 'bg-indigo-500'
} as Record<string, string> // works

const fooClasses: Record<string, string>  = {
  foo: 'bg-indigo-500'  // not working
}

I can modify the existing custom name or add another one like ".*Classes.*" and all of the above works and even this works

const impactClasses: Record<ButtonProps['impact'], string> = {
  bold: 'bg-indigo-500 text-white shadow-md hover:bg-indigo-600 disabled:shadow-none',
  light: 'bg-indigo-100 text-indigo-700 hover:bg-indigo-200',
  none: 'bg-transparent text-indigo-700 hover:bg-indigo-50',
}

But when I go more complex with embedded objects, adding more ".*.*" at the end of my custom name doesn't fix it.

This does not work

const impactClasses: Record<
  ButtonProps["tone"],
  Record<ButtonProps["impact"], string>
> = {
  default: {
    bold: "bg-indigo-500 text-white shadow-md hover:bg-indigo-600",
    light: "bg-indigo-100 text-indigo-700 hover:bg-indigo-200",
    none: "bg-transparent text-indigo-700 hover:bg-indigo-50",
  },
  danger: {
    bold: "bg-indigo-500 text-white shadow-md hover:bg-indigo-600",
    light: "bg-indigo-100 text-indigo-700 hover:bg-indigo-200",
    none: "bg-transparent text-indigo-700 hover:bg-indigo-50",
  },
  success: {
    bold: "bg-indigo-500 text-white shadow-md hover:bg-indigo-600",
    light: "bg-indigo-100 text-indigo-700 hover:bg-indigo-200",
    none: "bg-transparent text-indigo-700 hover:bg-indigo-50",
  },
};

This works and completely removing the type annotation works but of course removing the type annotation removes the TS portion of autocomplete and type safety

const impactClasses = {
  default: {
    bold: "bg-indigo-500 text-white shadow-md hover:bg-indigo-600",
    light: "bg-indigo-100 text-indigo-700 hover:bg-indigo-200",
    none: "bg-transparent text-indigo-700 hover:bg-indigo-50",
  },
  danger: {
    bold: "bg-indigo-500 text-white shadow-md hover:bg-indigo-600",
    light: "bg-indigo-100 text-indigo-700 hover:bg-indigo-200",
    none: "bg-transparent text-indigo-700 hover:bg-indigo-50",
  },
  success: {
    bold: "bg-indigo-500 text-white shadow-md hover:bg-indigo-600",
    light: "bg-indigo-100 text-indigo-700 hover:bg-indigo-200",
    none: "bg-transparent text-indigo-700 hover:bg-indigo-50",
  },
} as Record<ButtonProps["tone"], Record<ButtonProps["impact"], string>>;

So I guess the question/issue is how to make .*Classes.* extend further for embedded objects? I would like to avoid using 'as' but I don't understand how the extension parses my custom classes object name and where TS comes into play.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions