-
-
Notifications
You must be signed in to change notification settings - Fork 247
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: formatClassName, formatTokenName, and formatCssVar #1848
Conversation
…rator to separate the prefix
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
@ivanbanov is attempting to deploy a commit to the Chakra UI Team on Vercel. A member of the Team first needs to authorize it. |
5f6abc4
to
aeb5322
Compare
Hey @astahmer @segunadebayo let me know if there is anything I could do to get this one merged :) |
Found a bug @ivanbanov when I set prefix in the config, the separator is automatically set to This is not happening in the generated css, but in the generated classNames |
Hey @anubra266 Im not sure Im following 🤔 the default separator from Panda is actually _ While switching the configs I also got stuck in the state that you show in the image, but after rebuilding everything was properly built, Im wondering if it was a glitch in the autoreload |
Thanks for working on this @ivanbanov. @astahmer and I have discussed this PR at least 3-4 times this past week. Here are some potential pitfalls we found with this PR.
Given the following panda config: const dasherize = (token) => token
.toString()
.replace(/[^a-zA-Z0-9]+/g, '-')
.replace(/^-+|-+$/g, '')
export default defineConfig({
// Stitches preset
separator: '-',
formatTokenName: (path) => `$${path.join('-')}`,
formatClassName: dasherize,
formatCssVar: dasherize,
}) These use cases will lead to incorrect class names. css({ content: 'Price: $25.99' }) // the dollar will be altered
// => content-Price-25-99
css({ content: 'Price: 25.99' }) // the same className will be emitted leading to conflicts
// => content-Price-25-99 For the Stitches example, this might lead to className conflicts and style issues since you can't predict all css style declarations. Allowing users to customize the className formatting can be much worse depending on the function passed.
The recommended approach we agreed on is to replace these functions with a single export default defineConfig({
tokenNamePrefix: '$'
}) With this approach, we would get most of the features requested. The only downside is that the className would still include the "$" prefix, something like, To get the className to look something like // before
const colors = {
red: {
200: { value: '<value>' }
}
}
// after
const colors = {
red200: { value: '<value>' }
} What do you think of this approach?
|
hey @segunadebayo when I first added the For sure, adding Just dropping other ideas that I had to walk around it
// config
{
theme: {
colors: {
red: { 200: { value: '<value>' } }
}
},
tokenNamePrefix: '$',
tokenFormat: 'dash'
}
css({ color: '$red-200' })
/**
* classname: .text_red-200
* cssvar: --var(--colors-red-200)
* token: $red-200
*/ would it be a possible middle-term in the approaches? |
Good points @ivanbanov. The goal of the CSS function is to join the property and value with Not adding the prefix to the final class name is primarily an aesthetic concern; I don't assume it'll be a deal breaker for most users. I recommend using the The |
@segunadebayo Actually before I started implementing the cssVar formatter as a function I first tried the predefined approach, which worked as expected, you can see it here. I even thought it would be possible to do the same with the className and tokenName, but instead I went for the 100% customization. Going in this direction I'd say that we could have the following API theme: {
tokens: {
spacing: {
xLarge: { value: '12px' }
}
},
tokenNamePrefix: '$',
tokenFormat: <'dash' | 'camelCase' | 'snakeCase' | 'escaped'>
}
/**
* dash
* classname: .m_x-large
* cssvar: --var(--spacing-x-large)
* token: $x-large
*/
/**
* camelCase
* classname: .m_xLarge
* cssvar: --var(--spacingXLarge)
* token: $xLarge
*/
/**
* snakeCase
* classname: .m_x_large
* cssvar: --var(--spacing_x_large)
* token: $x_large
*/
/**
* escaped
* classname: .m_\$xLarge
* cssvar: --var(--spacing-\$xLarge)
* token: $xLarge
*/
// -- edited (adding colors nested example too)
theme: {
tokens: {
colors: {
red: {
100: { value: '<value>' }
}
}
},
tokenNamePrefix: '$',
tokenFormat: <'dash' | 'camelCase' | 'snakeCase' | 'escaped'>
}
/**
* dash
* classname: .text_red-100
* cssvar: --var(--colors-red-100)
* token: $red-100
*/
/**
* camelCase
* classname: .text_red100
* cssvar: --var(--colors-red100)
* token: $red100
*/
/**
* snakeCase
* classname: .text_red_100
* cssvar: --var(--colors-red_100)
* token: $x_large
*/
/**
* escaped
* classname: .text_\$red.100
* cssvar: --var(--colors-\$red.100)
* token: $red.100
*/ It would still achieve my main goal, and give less flexibility to the final user, which can be good to avoid class name clashes, how does it sound to you? |
Sounds good to me @ivanbanov The If we consider another token category, say spacing, there should be a semantic difference between "using a token" or not. css({ margin: "$40" })
// class: m_$40
// css: margin: var(--spacing-40)
css({ margin: "40" })
// class: m_40
// css: margin: 40px Customizing the className will be problematic in this use case. If we're going to move forward with this, I'd recommend scoping this down to configuring the token name and format. |
@segunadebayo I see it, the Im fine removing it, do you think that the other formatters are in good shape to make their way into the |
* refactor: token dictionary * feat: hooks "tokens:created" test: allow passing custom hooks refactor: dict.formatTokenName refactor: use array of string as path rather than dot-delimited string for colorPalette -> so that the formatTokenName can be replaced with custom logic with hooks, we couldnt before because the join('.') logic was hardcoded everywhere * feat: dictionary.formatCssVar * feat: utility.toHash + 'utility:created' hook with setToHashFn * feat: 'codegen:prepare' hook * test: port those from #1848 * chore: add changeset * chore: update changeset * refactor: code * chore: remove semantic token strictness * test: update snaps * refactor: rename methid * chore: update * refactor: config resolved hook --------- Co-authored-by: Segun Adebayo <[email protected]>
📝 Description
Migrating a large codebase from Stitches to PandaCSS imposed some challenges due to the naming convention differences between the libraries. The main complication comes from the
$
prefix in Stitches, the workaround suggested by PandaCSS is simply adding a$
sign in the token name, but it causes some problems.--colors-\$red.100
--colors-red-100
.text_\$red.100
-
or_
for example in the css vars. It would be nice to have an option to modify how the final token name is generated.red.100
$red-100
⛳️ Current behavior
It's not possible to customize the token names, class names, and cssvars
🚀 New behavior
Added a new config
formatTokenName
This config receives the token path and returns a string with the new token name
Added a new config
formatClassName
This config receives the token as a string (from the formatTokenName) and returns a string that will be used as
<prefix>-<formatted classname>
. Hashed class names are not affectedAdded a new config
formatCssVar
This config receives the token path and returns a formatted name. Hashed class names are not affected
all together
💣 Is this a breaking change (Yes/No):
No