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

[Feat] Support CSS variables defined by TypeScript #98

Closed
penx opened this issue Nov 8, 2022 · 10 comments
Closed

[Feat] Support CSS variables defined by TypeScript #98

penx opened this issue Nov 8, 2022 · 10 comments
Assignees
Labels
enhancement New feature or request

Comments

@penx
Copy link

penx commented Nov 8, 2022

Is your feature request related to a problem? Please describe.

When using Chakra UI, and calling the extendTheme function:

import { extendTheme } from "@chakra-ui/react"

const colors = {
  admin: {
    dark: '#000',
  }
} as const

const theme = extendTheme({
  colors
});

CSS variables will be made available of the format --chakra-colors-admin-dark.

Describe the solution you'd like

If I could define a TypeScript type as follows:

type ColorVars = "--chakra-colors-admin-dark" | "--chakra-colors-admin-light" | "--chakra-colors-admin-rebeccapurple"

It would be great to be able to point vscode-cssvar at this type and have it pick up these variables to include them in autocomplete.

Describe alternatives you've considered

Somehow generate a css file from the typescript type or call to extendTheme.

Additional context

I may be able to help contribute this feature if you give me some pointers.

@penx penx added the enhancement New feature or request label Nov 8, 2022
@phoenisx
Copy link
Contributor

phoenisx commented Nov 8, 2022

I think this: #92 is what you are trying to solve by creating a TS type.

JSON data is more informative compared to TS types and is widely known & used. I feel it would be good to use .json to define dynamically generated CSS custom props (If that's what you are looking for).😉

If you want to contribute, you can check src/main.ts#setup and src/parser.ts#parseFile methods, where we need the changes, and conditionally handle parsing a CSS or JSON file. 👍🏽

@penx
Copy link
Author

penx commented Nov 8, 2022

Thanks!

Loading from a JSON file means we would need a build step to create a JSON file when the colors object changes to keep up to date, and ideally to have something running in the background to build when there are changes.

Loading from the TypeScript type means the CSS variables would come directly from the source code, not requiring a background task or build step.

I would prefer the TypeScript support, but yes I think #92 is solving the same problem.

Thanks for creating this library <3

@penx
Copy link
Author

penx commented Nov 8, 2022

In case it helps illustrate what I mean, the type would come straight from the source code by using:

const colors = {
  dark: '#111',
  light: '#EEE',
  admin: {
    dark: '#000',
    light: '#FFF',
    rebeccapurple: '#639'
  }
} as const

type Squashed<T> = keyof {
  [Property in keyof T as T[Property] extends string | number | boolean | null
    ? Property
    : `${string & Property}-${string & Squashed<T[Property]>}`]: true;
};

type ColorVars = `--chakra-colors-${Squashed<typeof colors>}`
// "--chakra-colors-dark" | "--chakra-colors-light" | "--chakra-colors-admin-dark" | "--chakra-colors-admin-light" | "--chakra-colors-admin-rebeccapurple"

Playground

@penx
Copy link
Author

penx commented Nov 8, 2022

I was thinking that, given a a path to file in the workspace, a vscode extension could connect to the TS language server and load the types for that file.

I thought there was something in the vscode API to do this, but I can't find it, nor can I find any documentation to help.

Please let me know if you've seen anything :)

@phoenisx
Copy link
Contributor

phoenisx commented Nov 9, 2022

If you want typing support, isn't Typescript already providing that for the dynamic CSS variables created by Chakra?

Can u help me understand what you are looking for with an example?

@penx
Copy link
Author

penx commented Nov 9, 2022

Say we're defining our CSS variables as follows:

import { extendTheme } from "@chakra-ui/react";

const themeExtension = {
  colors: {
    dark: '#111',
    light: '#EEE',
  }
} as const

export const theme = extendTheme(themeExtension)

And then using them as:

const someCss = css({
  backgroundColor: "var(--chakra-colors-dark)",
})

...it would be good to have code hinting in vscode for the variable names, generated from the TypeScript type.

No, Chakra doesn't provide any typing to help with this as far as I'm aware.

I think you're right, in our use case we can enforce this with TypeScript.

If we were defining CSS variables in TypeScript and then using them in CSS files, this wouldn't work - but we're not doing that :)

@phoenisx
Copy link
Contributor

phoenisx commented Nov 10, 2022

@penx I think what you are talking about is not Typing support for the CSS variable, but instead, IntelliSense (auto-completion) support, that this extension provides.

This extension requires at least a key-value pair ([key]: CSS variable name, and [value]: CSS variables value) to provide CSS variable IntelliSense.
This was the reason I mentioned here: #98 (comment), to use JSON, as it will contain required metadata, which Typescript types won't be able to provide.

@penx
Copy link
Author

penx commented Nov 10, 2022

I think what you are talking about is not Typing support for the CSS variable, but instead, IntelliSense (auto-completion) support, that this extension provides

Originally yes, but I have since realised I can create a typed helper cssvar["colors-dark"] that autocompletes and is checked by TS.

This extension requires at least a key-value pair ([key]: CSS variable name, and [value]: CSS variables value

My thinking was that the value wouldn't be known, and the extension would set this to null/empty string for TypeScript defined CSS variables. But yes, a JSON file containing your themes and their respective values would be a better experience.

Feel free to close this issue! There may be a benefit to people defining their CSS variables in TypeScript and consuming them in CSS files, but that doesn't apply to us :)

@penx
Copy link
Author

penx commented Nov 10, 2022

Our ts-only solution is as follows, in case anyone ends up here looking for something similar :)

import type { Theme } from "@chakra-ui/theme";
import { extendTheme } from "@chakra-ui/react";

const customTheme = {
  colors: {
    dark: '#111',
    light: '#EEE',
  }
} as const;

export const theme = extendTheme(customTheme);

export type CustomTheme = typeof themeExtension & Theme;

type ThemeObject = {
  [key: string]: number | string | ThemeObject;
};

type Squashed<T extends ThemeObject> = keyof {
  [Property in keyof T as T[Property] extends ThemeObject
    ? `${(string | number) & Property}-${(string | number) &
        Squashed<T[Property]>}`
    : Property]: true;
};

const tokens = [
  "colors",
  // "borders",
  // "fonts", etc.
] as const;

type Tokens = Squashed<Pick<CustomTheme, typeof tokens[number]>>;

export const cssvar = (key: Tokens) => {
  return `var(--chakra-${key})`;
};

Usage:

const MyComponent = styled("div")({
  color: cssvar("colors-dark"),
});

@phoenisx
Copy link
Contributor

phoenisx commented Nov 10, 2022

@penx Thanks for the detailed explanation.

I will close this issue and track support for dynamic variables in #92
Do comment on that issue, if you feel we can have a better approach!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants