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

Theme typing discrepencies. #1465

Open
krijoh92 opened this issue May 3, 2022 · 4 comments
Open

Theme typing discrepencies. #1465

krijoh92 opened this issue May 3, 2022 · 4 comments
Labels
theming Question, feedback, etc. around theming architecture

Comments

@krijoh92
Copy link
Contributor

krijoh92 commented May 3, 2022

Missing components in exported 'Components' type

When checking the value of the defaultTheme runtime, I saw a couple of components that I would like to override that weren't included in the type Components you export from the typings.

Would it be sensible to inlcude those components in the type?
The components I found missing were:
DialogBody, DialogFooter, DialogHeader, Option and Table

Missing typing for theme callback function

I've seen that some components have functions to apply styles in the default theme and experimented with it, and what I found was that the callbackfunction basically has a signature of (theme: Theme, props: ComponentProps) where "ComponentProps" is the given component's props. Would it be sensible to expand the theme type to allow those functions? Atm I'm overriding the theme type to allow it in our project.

@krijoh92
Copy link
Contributor Author

krijoh92 commented May 3, 2022

A side question I have: Have you considered migrating away from js and only develop in typescript? I might make it easier to infer types from all components, theme, etc if you're implementing everything in typescript from the get-go?

@brandongregoryscott
Copy link
Contributor

brandongregoryscott commented May 3, 2022

Would it be sensible to inlcude those components in the type?
The components I found missing were:
DialogBody, DialogFooter, DialogHeader, Option and Table

Table was probably an oversight, and the rest were probably missed because they aren’t really “first-class” components or meant to be used on their own. (Option is used internally in the SelectMenu and Autocomplete components, and while we do export it from index.js, it probably doesn’t have a lot of use on its own). However, I don’t see the harm in adding them to the type alias since they are themed like regular components are.

Speaking of which, I’ve been thinking for a while now that DialogBody, DialogFooter and DialogHeader should be exposed as their own components tacked on to the Dialog object - similar to Menu.Item, Menu.Group or the EmptyState.PrimaryButton extension components - I’ve lost count of how many times I’ve needed to slightly tweak a Dialog header and had to reference the source for spacing/styling. I can spin up a separate issue for this. (#1466)

Would it be sensible to expand the theme type to allow those functions? Atm I’m overriding the theme type to allow it in our project.

AFAIK, these theme callback functions are remnants from a previous iteration of the theming architecture. There’s still internal theme objects that use it, but I’m not sure it’s a pattern we still want to move forward with or encourage others to use externally - do you have specific use-cases in mind where this sort of function would help you do something the standard theming conventions wouldn’t?

A side question I have: Have you considered migrating away from js and only develop in typescript? I might make it easier to infer types from all components, theme, etc if you’re implementing everything in typescript from the get-go?

We’d love to - it would certainly make the typing aspect of theming (and all things) much smoother and more accurate overall. (In the most recent theme typing improvements, I manually went through and documented all of the pseudoselectors available in the default theme - that wasn’t very fun) As you can imagine, porting over a codebase of this size is no small feat, even with tooling like ts-migrate available.

I’ve got a running branch on my fork that has the vast majority ported over, but there’s still a lot of testing + some polish before it’ll be ready to merge in and release.

@krijoh92
Copy link
Contributor Author

krijoh92 commented May 4, 2022

Thanks for the detailed response Brandon!
I know I would prefer that not just "first-class" components are able to be "themed". I would rather be able to have fine-grained control over all components through the theme if able.

Our specific use-cases for using the callback function are when we want to style something based on a combination of props. Example is our primary buttons with specific intents can be colored correctly etc. Not sure if there are any other good ways to do so, but at least that is the way we found to get it to work atm.

Another use-case was to basically calculate variations of colors from our "common" theme. We went for doing that over enumerating all of the specific colors in multiple themes and so we wouldn't pollute theme.colors with a lot of colors.

As you can imagine, porting over a codebase of this size is no small feat

Yeah I know exactly what you mean, I spent a couple of months doing this exact thing last year.

Side question: Do you know how one would go about to set specific styling for the spinner that appears in buttons that have isLoading ? Haven't figured a way to do it, and our regular spinner color is basically invisible when our primary button is loading.

@brandongregoryscott
Copy link
Contributor

brandongregoryscott commented May 4, 2022

I know I would prefer that not just "first-class" components are able to be "themed". I would rather be able to have fine-grained control over all components through the theme if able.

Totally understandable. PRs welcome - I believe adding these to the Components type alias should 'just work' and let you define overrides for those specific object keys.

Our specific use-cases for using the callback function are when we want to style something based on a combination of props. Example is our primary buttons with specific intents can be colored correctly etc.

Ah, I see. That's fair. The typing for this might be a little more complex - from what I've gathered, the object passed as the second param in that callback there isn't really the full component props object but an object of the "modifier" props like intent or appearance, basically what we pass as the second argument to useStyleConfig:

/**
* Takes a styleConfig object and outputs a `className` and `boxProps` that can be spread on a Box component
* @param {string} componentKey the name of the component in the theme
* @param {StyleModifiers} props props that modify the resulting visual style (e.g. `size` or `appearance`)
* @param {PseudoSelectors} pseudoSelectors mapping for the component between states and actual pseudo selectors
* @param {GlamorAndBoxStyle} [internalStyles] additional styles that are specified internally, separate from the visual styles
* @returns {{ className: string; boxProps: import('ui-box').EnhancerProps }}
*/
export function useStyleConfig(componentKey, props, pseudoSelectors, internalStyles) {

const { className: themedClassName, ...boxProps } = useStyleConfig(
'Button',
{ appearance, color, intent, size: restProps.size || 'medium' },
pseudoSelectors,
internalStyles
)

const { className: themedClassName, ...boxProps } = useStyleConfig(
'Input',
{ appearance, size: restProps.size || 'medium' },
pseudoSelectors,
internalStyles
)

Side question: Do you know how one would go about to set specific styling for the spinner that appears in buttons that have isLoading ?

I don't think that's possible right now with the way the Button is built - we'd need to pass through some color prop to the Spinner it renders (which it doesn't support as a prop now regardless), I think:

{isLoading && (
<Spinner
marginLeft={-Math.round(height / 8)}
marginRight={Math.round(height / 4)}
size={Math.round(height / 2)}
/>
)}

@brandongregoryscott brandongregoryscott added the theming Question, feedback, etc. around theming architecture label Jan 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
theming Question, feedback, etc. around theming architecture
Projects
None yet
Development

No branches or pull requests

2 participants