Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

With plugins, auto-completion requires manual TypeScript typings in Twind configuration (error highlighting and hover information work fine out of the box) #8

Open
danielweck opened this issue Mar 14, 2021 · 15 comments

Comments

@danielweck
Copy link
Member

danielweck commented Mar 14, 2021

For example, there is no auto-completion for form-input from @twind/forms, or lg:prose-xl from @twind/typography. Thank you :)

@sastan
Copy link
Collaborator

sastan commented Mar 14, 2021

I know. I'm currently working on re-writing the plugin to support custom auto-completion for plugins. The plugins you mentioned will be updated to support this. It will look something like this for custom plugins:

import type { ThemeSection, FromTheme } from 'twind'

declare module 'twind' {
  interface Theme {
    scrollSnap: ThemeSection
  }

  interface Variants {
    ltr: string
  }
  
  interface Plugins {
    'scroll-snap': 'none' | 'x' | 'y' | FromTheme<'scrollSnap'>
  }
}

I update this issue once I have updated this plugin.

@sastan
Copy link
Collaborator

sastan commented Mar 15, 2021

This should now work. I will update the plugins in the next days.

@danielweck
Copy link
Member Author

The latest update warns about unknown tokens by highlighting keywords with a squiggly orange underline. That's great, thank you! :)

Taking the "@twind/forms" plugin as an example, is there anything we should configure in order to register the additional tokens, or does this happen automatically? (no rush to implement this if not done already, just wondering ;)

Screenshot 2021-03-16 at 06 59 58

@sastan
Copy link
Collaborator

sastan commented Mar 16, 2021

Until I have updated the plugin or someone provides a PR... You can try this:

declare module 'twind' {
  interface Plugins {
    'form-input': ''
  }
}

Take a look at the defintions for the core plugins: https://github.com/tw-in-js/twind/blob/main/src/types/completion.ts#L128

@danielweck
Copy link
Member Author

danielweck commented Mar 16, 2021

You can try this:

declare module 'twind' {
  interface Plugins {
    'form-input': ''
  }
}

Mhmm, I have tried different techniques, to no avail :(

/// <reference path='../twind.d.ts'/>
import '../twind.d.ts';

tsconfig.json

	"files": [
	  "./twind.d.ts"
	]
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// eslint-disable-next-line unused-imports/no-unused-imports
import type { Plugins as _P } from '../twind.d.ts';

Have you successfully managed to augment the Plugins interface?

@sastan
Copy link
Collaborator

sastan commented Mar 16, 2021

Have you successfully managed to augment the Plugins interface?

Yes. Sorry for the lack of documentation.

Create a twind.config.{ts,js,cjs,mjs} in your root folder. I will add support for custom file soon. This config is evaluated and the plugins, variants, theme, and dark mode are read from there.

import { forms, formInput } from '@twind/forms'

/** @type {import('twind').Configuration} */
export default {
  plugins: { forms, 'form-input':  formInput}
}

Downside: Currently only the simple name can be inferred – meaning no params: form-input-lg (if there was such thing). To support that as well we augment the Plugins interface:

This can be done in any file that is included in the typescript compilation. Lets put into the config:

import { forms, formInput } from '@twind/forms'

/** @type {import('twind').Configuration} */
export default {
  plugins: { forms, 'form-input':  formInput}
}

declare module 'twind' {
  interface Plugins {
    // forms should have been detected from setup – not need to add it
    // forms: ''

    // We want to add sm and lg modifiers to the form-input
    'form-input':
      | ''    // plain form-input
      | 'sm' // form-input-sm
      | 'lg' // form-input-lg
  }
}

Downside: A lot of extra types. mapleLeaf and I are thinking of creating a plugin API that would allow detecting all possible class names from the plugin directly. No need for types.

PS You should use the twind.config.ts in you sources as well.

import { setup } from 'twind'
import config from '../twind.config`

setup(config)

The issue I just now realized is that autocompletion and diagnostic/hover use different ways.

  • autocompletion: check types and keys from config – no test (eg invoking tw) if this a real plugin because of performance
  • diagnostic/hover: invoke tw to get its CSS or collect the errors

Maybe I need to adjust the autocompletion part to invoke tw as well. What do you think?

@danielweck
Copy link
Member Author

danielweck commented Mar 16, 2021

Brilliant, this works :)

(I am using the typography plugin as well, and the prose syntax is supported out of the box from the plugin definition)

Just a note specific to Preact WMR: the public subfolder has a special significance, such that the twind.config.ts (or .js) must be located inside it (otherwise the server will fail to fetch from the "external" parent folder, even with an alias directive).

No big deal though, I just added twind.config.ts at the project root with:

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
export { default } from './public/twind.config.ts';

By the way, I love that the config file can be TypeScript instead of Javascript! 👍

@danielweck
Copy link
Member Author

danielweck commented Mar 16, 2021

Maybe I need to adjust the autocompletion part to invoke tw as well. What do you think?

Yes I can see how that could help.

For example right now with the typography plugin:

declare module 'twind' {
	interface Plugins {
		prose: '' | 'xl';
	}
}

...both the grouped and non-grouped syntax work fine with autocompletion, error squiggly underline, and hover info (i.e. raw CSS preview):

tw`prose prose-xl lg:prose-xl`

tw`prose(& xl lg:xl)`;

...however if I use lg instead of xl, autocompletion fails (because I didn't explicitly declare it in the Twind type config) but hover and compiler checks work fine. This inconsistency is confusing indeed, but this will ultimately be fixed when the types don't have to be explicitly listed in the Twind config, right?

@sastan
Copy link
Collaborator

sastan commented Mar 16, 2021

Just a note specific to Preact WMR

I'm aware of this. That's why the default config lookup will [src/,public/]twind.config.{ts,js,mjs,cjs}

@sastan
Copy link
Collaborator

sastan commented Mar 16, 2021

This inconsistency is confusing indeed, but this will ultimately be fixed when the types don't have to be explicitly listed in the Twind config, right?

I hope so 😄

@danielweck
Copy link
Member Author

I filed this separate issue so that we can track it separately: #12
:)

@sastan
Copy link
Collaborator

sastan commented Mar 16, 2021

tw`prose(& &:xl lg:xl)`;

&:xl is not valid. It would be expanded to prose:xl. Did you mean xl:&?

@danielweck
Copy link
Member Author

Sorry, just a copy-paste typo. I will correct it right now in my message (dash instead of colon)

@danielweck
Copy link
Member Author

Correction (if I am not mistaken):

tw`prose(& xl lg:xl)`;

@danielweck
Copy link
Member Author

FYI, I have been testing the latest versions of Twind libs. I just want to confirm that without any additional plugin configuration in twind.config.mjs, error highlighting and hover information popup work absolutely fine.

twprose(& xl lg:xl);
=>
prose prose-xl lg:prose-xl

The only feature that requires the additional "manual" Typescript typings is auto-completion:

declare module 'twind' {
	interface Plugins {
		prose: '' | 'xl';
	}
}

I am changing this issue's title to reflect this.

@danielweck danielweck changed the title How to add tokens from plugins? With plugins, auto-completion requires manual TypeScript typings in Twind configuration (error highlighting and hover information work fine out of the box) Mar 19, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants