-
-
Notifications
You must be signed in to change notification settings - Fork 476
Feat/theming #450
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/theming #450
Conversation
Codecov ReportBase: 97.08% // Head: 98.86% // Increases project coverage by
Additional details and impacted files@@ Coverage Diff @@
## main #450 +/- ##
==========================================
+ Coverage 97.08% 98.86% +1.77%
==========================================
Files 127 102 -25
Lines 4741 4770 +29
Branches 433 402 -31
==========================================
+ Hits 4603 4716 +113
+ Misses 138 54 -84
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report at Codecov. |
|
@rluders ready for review. Thank you. |
| } | ||
|
|
||
| export const FlowbiteThemeProvider: FC<ThemeProviderProps> = ({ children, theme }) => ( | ||
| <Flowbite theme={{ theme }}>{children}</Flowbite> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about this... The Flowbite component handles not just the component styling, but also, dark and light mode. I'm afraid that it will cause a lot of "hooks" and extra processing under the hood.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think @tulup-conner?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that make sense, also we can create object and then pass it to props and this way seems clear
const theme = {
avatar: {
size: {
md: 'w-6 h-6',
},
},
};
const Test = () => (
<Flowbite theme={{ theme }}>
<div />
</Flowbite>
);There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not convinced that using Flowbite everywhere or FlowbiteThemeProvider is the best approach. But I could be totally wrong. The initial idea to pass to the components the theme= was from @tulup-conner, so... I really would like to get his opinion about it.
What are the pros and cons of both approaches? How many renderings or hooks do we get? How does it impact the performance? AFAIK, provider context could be quite expensive: check here and also here.
But I'm not a front-end expert. 😶🌫️
From a code perspective, I feel quite confused about wrapping every component with the context provider in order to pass the theme to it. OK, it could look nice if you have multiple components that you need to customize in a section, but... Still, feels weird to have an "application theme context" and then inside this context have another "theme context" to overwrite one, two, or more components themes.
But this is just my opinion, I would like to hear some pros and cons of both approaches, so we could take a solid decision here. I felt like this is a really important and nice feature either way, and it will help the flowbite-react community a lot.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I've only thought having theme-per-component because I know it would be useful; I haven't reasoned through it at all until now.
With that said, this
<Flowbite theme={..}>
<Component props />
</Flowbite>Is more verbose than
<Component props theme={..} />Critically, the theme context solution also adds a level of nesting, which is just not ideal ergonomically IMO.
With theme-per-component, in situations where you would like to reuse a flowbite-react component with a specific custom theme, you just extract that line to its own component.
const ThemedNavbar: FC = function () {
return (
<Navbar props theme={..} />
)
}This is the same methodology encouraged by the underlying technology, Tailwind CSS, in situations where you find yourself writing long-winded classNames.
Like @rluders said, the existing design of this Flowbite component serves a few different purposes, including the global dark/light theme setting. We would need to change this implementation further to extract the theme to its own component and context, presumably. I can't imagine a situation where having multiple contexts with their own idea of the current theme setting is useful. But I would have to see if DarkThemeToggle works as usual on this branch, in which case, probably not a big deal.
- I think the decision to couple the
FlowbiteThemepieces to their actual components is beyond sensible. We should definitely do that, IMO. - I agree we should update
mergeDeepsince JS is call-by-sharing. I misunderstood the behavior. Thanks, I just learned about this because of your PR! - On performance, I think people generally have a habit of prematurely optimizing things. We would want to look for metrics to determine whether performance meaningfully degrades with the
Flowbitecontext providers, and how many providers need to exist before degradation starts. Tangentially, the inline theme solution also has the benefit of not being React Context - just a prop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I think the decision to couple the FlowbiteTheme pieces to their actual components is beyond sensible. We should definitely do that, IMO.
+1 to this... I think that we should definitely do it, no matter if we decide to go for per-component theming or not, this is definitely a huge benefit and introduces a lot to maintainability and readability to the codebase.
- On performance, I think people generally have a habit of prematurely optimizing things. We would want to look for metrics to determine whether performance meaningfully degrades with the Flowbite context providers, and how many providers need to exist before degradation starts. Tangentially, the inline theme solution also has the benefit of not being React Context - just a prop.
I don't want to look for premature optimization here, I think that the point was that given its complexity, and from what I read using Context could be a little bit trickier to use.
I would definitely aim for simplicity, and use the theme property per component. It would give us the flexibility that we are looking for to introduce an easier and more solid way to customize flowbite-react components without introducing unnecessary verbosity and under-the-hood processes.
So, @sldk-yuri how about we first aim to make all components have their own theme interface?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for you opinions @rluders @tulup-conner. Nested context is a one of the ways that we can use, probably the simpliest in current situation, becaue we don't have to refactor/update all components with theme prop to aplly theme ovveriding, just use wrapper. But in the same case deep context nesting could be a potential problem in the future and probably it's over-solution right now. Also we may add this feature in the future if needed. I'm going to start with theme prop option.
About this PR, I'm going to revert branch to f45cecf because this commit remove nested providers feature c4e195c and save:
- interface decomposition 1acaae8,
- moves interfaces to their components 1ac4e68,
- test cases for Flowbite provider 95e02fb
- deep Merge fix f45cecf.
Should we merge this PR with these 4 commits and open new one for components theme prop or should I continue to work here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sldk-yuri agreed. Let's continue on this PR, there is no problem. Maybe you just need to rebase it and drop the commits that we don't want, and it will be fine.
|
@sldk-yuri BTW, nice tip here... you don't need to merge the
git remote add upstream https://github.com/themesberg/flowbite-react.git
git pull upstream main --rebase
git push origin your/pr --forceIt is easier, better, cleaner, and elegant. :) |
61a4bfc to
6550c23
Compare
6550c23 to
6e79ba8
Compare
|
@rluders @tulup-conner PR is updated and ready to merge. I also think we have to add |
Good, let's make #433 an |
| import { TextareaColors } from './Textarea'; | ||
| import { TextInputColors, TextInputSizes } from './TextInput'; | ||
|
|
||
| export interface FlowbiteFormControlsTheme { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally, we will have to move the interfaces inside their own component folders.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I created the respective tasks for every single component. We are going to handle it in separated PR.
Description
To achieve theme overwrite per component:
FlowbiteThemeinterface insrc/lib/components/Flowbite/Flow bytes Theme.tsrefactored. It make code more readable and self-documented.FlowbiteTheme.tsto their main component files.Flowbitecomponent hasn't been tested. Test cases added. We can be more confident when update/change logic.mergeDeppinsrc/helpers/mergeDeep.tsmutated target object, it fixed.mergeDeppadditionally makes deep copy of target object.Flowbiteupdated to handle nested providers. Added test cases to make sure that components themes isolated.FlowbiteThemeProviderwrapper added to handlethemeprop withoutdarkandusePreferencesprops. Just for keep things simple.All these steps allow us to use
FlowbiteandFlowbiteThemeProviderto ovveride components theme in the follow way:or a bit cleaner with wrapper:
Fixes #443 #442
Type of change
How Has This Been Tested?
Adds test cases
src/lib/components/Flowbite/Flowbite.spec.tsxChecklist: