-
Notifications
You must be signed in to change notification settings - Fork 501
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: add dark mode #2322
base: main
Are you sure you want to change the base?
feat: add dark mode #2322
Conversation
Thank you for submitting this PR!
Getting other community members to do a review would be great help too on complex PRs (you can ask in the chats/forums). If you are unsure about something, just leave us a comment.
We currently aim to provide initial feedback/triaging within two business days. Please keep an eye on any labelling actions, as these will indicate priorities and status of your contribution. |
Hi @lidel, kindly take a look at this when you get the chance. Thanks. |
@kaf-lamed-beyt I would love for all components in ipfs-webui to be functional components. That is the direction we're moving. However, since that will likely be a significant change, we should probably do that as a separate PR. You can see an example of a simple function component that is also using redux-bundler-react at
|
Oh! Thanks for the feedback, @SgtPooki! I'll take a look at the file you pointed me to now. So, from the looks of things now, are you suggesting that i use the manual approach of targeting each element based on the styles in We can always keep the hook. |
src/navigation/NavBar.js
Outdated
<div className='mb4'> | ||
<ThemeToggle /> | ||
</div> |
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.
💭 the space in the left NavBar is limited especially in ipfs-desktop where UI acts as native app. and window height is limited by default.
we want to add diagnostics screen at some point
perhaps it is better to move this toggle to top right corner where we already have two items:
thoughts?
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.
oh, yeah! that sounds goood, @lidel!
i originally thought of placing it there, but couldn't locate the icons in the code. I'll try looking for them and update the theme toggle's position
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.
some comments
src/context/theme-provider.tsx
Outdated
const [theme, setTheme] = React.useState<boolean>(() => { | ||
const savedTheme = | ||
typeof window !== 'undefined' && localStorage.getItem('theme') | ||
if (savedTheme) return savedTheme === 'dark' | ||
return window.matchMedia('prefers-color-scheme: dark').matches | ||
}) | ||
React.useEffect(() => { | ||
const htmlElem = document.documentElement | ||
const currentTheme = theme ? 'dark' : 'light' |
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.
seems like we can use better names for theme
and setTheme
since it seems to be a boolean indicating whether dark
theme is selected or not
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.
true. how does isDarkTheme
and setDarkTheme
sound?
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.
perfect
src/context/theme-provider.tsx
Outdated
} | ||
} | ||
const values: ThemeContextValues = { | ||
currentTheme: theme as unknown as Theme, |
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.
theme
is boolean, not a Theme
, so setting it to as unknown as Theme
is wrong.
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, use of as
(typescript casting) should be limited as much as possible.
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 catching this. I'll update it.
export interface ThemeProviderProps { | ||
children: React.ReactNode | ||
} |
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.
instead of explicitly setting children for props, you can extend React.FC<PropsWithChildren>
or similar..
or, my preference since there are no custom props, remove this and do it below
export interface ThemeProviderProps { | |
children: React.ReactNode | |
} |
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 there's this minor issue with using React.FC
in newer versions of React and I understand that it sits well with this component since it expects children which React.FC<PropsWithChildren>
provides implicitly.
why shouldn't we set the children
prop explicitly?
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.
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.
@kaf-lamed-beyt no huge reason, but here are a few:
- prevent issues if React changes the type of the children prop
- less code to maintain
- using prop types from react directly prevents needing to add other props if we need to extend them (adding className or other common props in the future)
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 there's this minor issue with using React.FC in newer versions of React
I haven't ran into this, can you link to examples?
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.
huh. makes sense.
for this 👇🏼
using prop types from react directly prevents needing to add other props if we need to extend them (adding className or other common props in the future)
I may be wrong... but, can't we do ...props
?
I haven't ran into this, can you link to examples?
This issue from facebook/create-react-app sheds more light on why they deprecated React.FC
@SgtPooki
const createThemeContext = () => React.createContext<ThemeContextValues | null>(null) | ||
export const ThemeContext = createThemeContext() | ||
|
||
export const ThemeProvider = ({ children }: ThemeProviderProps) => { |
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.
export const ThemeProvider = ({ children }: ThemeProviderProps) => { | |
export const ThemeProvider: React.FC<PropsWithChildren> = ({ children }) => { |
src/context/theme-provider.tsx
Outdated
toggleTheme: () => void; | ||
toggleThemeWithKey: (event: React.KeyboardEvent<HTMLButtonElement>) => void; |
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 we need both of these. Can toggleTheme
accept an optional event and handle expected keys?
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'll try refactoring this.
Co-authored-by: Russell Dempsey <[email protected]>
Co-authored-by: Russell Dempsey <[email protected]>
Co-authored-by: Russell Dempsey <[email protected]>
Co-authored-by: Russell Dempsey <[email protected]>
Co-authored-by: Russell Dempsey <[email protected]>
Co-authored-by: Russell Dempsey <[email protected]>
Co-authored-by: Russell Dempsey <[email protected]>
- previously, pretty much all the keys on the keyboard can trigger the theme toggle when it is focused. we don't want that. Instead we should only limit it to specific keys (spacebar & enter). - include all the varying colors when the theme is dark on all routes - extend the Box component to use the theme value instead of explicitly passing it in the style prop across the codebase
done with this. @SgtPooki, @lidel, kindly review. the explore route was quite tricky to work on. I couldn't locate the elements/components that are used to render data in the UI, that's why the one on the right still retained a white background. perhaps, if anyone can point me to where they are exactly. |
fixes #1702
Hi @lidel, This is what I have so far. I'm currently using an approach involving a Context Provider to access the theme value across the entire application.
I'm also adding the styles individually in index.css by targeting the
data-theme
attribute. This is nice, but it can be quite tasking, hence my move towards a custom context hook. This would allow us to dynamically change colors across components in the application.I ran into a slight blocker though.
App.js
uses a legacy React pattern — a class-based component which makes it a bit difficult to use the hook in this component, so I resorted to using the value fromlocalStorage
which is outside of the component/app life-cycle. So even if the value oftheme
inlocalStorage
changes, the color — based on the ternary operation below — of the header won't change, because we do not trigger a re-render. Which is what the hook helps us achieve.So, my question now is if it is possible to refactor
App.js
into a function-based component