Skip to content

Commit b060584

Browse files
committed
fix(types): improve Root Provider theme type definitions and docs
1 parent f983527 commit b060584

File tree

6 files changed

+49
-23
lines changed

6 files changed

+49
-23
lines changed

README.md

+20-7
Original file line numberDiff line numberDiff line change
@@ -168,15 +168,28 @@ The reason this code isn’t correct is that it tries to do something with the D
168168

169169
### Type safety
170170

171-
Global theme type should be defined on a project level. You'll have to redeclare `ThemeType` export from `css-vars-hook`
171+
Developers can provide theme type to `useRootTheme` hook as a TypeScript Generic.
172172

173-
```ts
174-
// types.d.ts
175-
import theme from '@/theme';
173+
```tsx
174+
import { FC } from "react";
175+
176+
type Theme = {
177+
boxColor: 'yellow' | 'blue';
178+
borderColor: string;
179+
};
180+
181+
const themeYellow: Theme = {
182+
boxColor: 'yellow',
183+
borderColor: 'blue',
184+
};
176185

177-
declare module 'css-vars-hook' {
178-
// Provide your global theme type here
179-
export type ThemeType = typeof theme;
186+
const Component: FC = () => {
187+
const {setTheme, getTheme, setVariable} = useRootTheme<Theme>();
188+
const doSomething = () => {
189+
// theme value will be properly typed this way
190+
console.log('root theme', getTheme().boxColor);
191+
};
192+
//...
180193
}
181194
```
182195

src/env/examples/Root/Root.tsx

+8-3
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,25 @@ import {useRootTheme} from '@/lib';
44

55
import classes from './Root.module.css';
66

7-
const themeYellow = {
7+
type Theme = {
8+
boxColor: string;
9+
borderColor: string;
10+
};
11+
12+
const themeYellow: Theme = {
813
boxColor: 'yellow',
914
borderColor: 'blue',
1015
};
1116

12-
const themePink = {
17+
const themePink: Theme = {
1318
boxColor: 'pink',
1419
borderColor: 'brown',
1520
};
1621

1722
let renderCount = 0;
1823

1924
export const Root = () => {
20-
const {setTheme, getTheme, setVariable} = useRootTheme();
25+
const {setTheme, getTheme, setVariable} = useRootTheme<Theme>();
2126

2227
const setThemePink = () => {
2328
setTheme(themePink);

src/lib/RootTheme/HookInterfaceType.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
import type {UnitType, Theme} from '@/lib/ThemeType.ts';
1+
import type {UnitType} from '@/lib/ThemeType.ts';
22

33
/**
44
* @public
55
* `useRootTheme` return type.
66
*/
7-
export type HookInterface = {
8-
setTheme: (nextTheme: Theme) => void;
9-
getTheme: () => Theme;
7+
export type HookInterface<TTheme> = {
8+
setTheme: (nextTheme: TTheme) => void;
9+
getTheme: () => TTheme;
1010
setVariable: (variableName: string, value: UnitType) => void;
1111
getVariable: (variableName: string) => string;
1212
removeVariable: (variableName: string) => void;

src/lib/RootTheme/RootContext.ts

+9-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
1+
import type {Context} from 'react';
12
import {useContext, createContext} from 'react';
23

4+
import type {Theme} from '@/lib/ThemeType.ts';
5+
36
import type {HookInterface} from './HookInterfaceType';
47

5-
export const RootContext = createContext<HookInterface>({
8+
export const RootContext = createContext({
69
setTheme: () => {},
710
getTheme: () => ({}),
811
setVariable: () => {},
912
getVariable: () => '',
1013
removeVariable: () => {},
11-
});
14+
} as HookInterface<Theme>);
1215

13-
export const useRootContext = () => useContext<HookInterface>(RootContext);
16+
export const useRootContext = <TTheme extends Theme>() =>
17+
useContext<HookInterface<TTheme>>(
18+
RootContext as unknown as Context<HookInterface<TTheme>>
19+
);

src/lib/RootTheme/useRootTheme.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ import type {HookInterface} from './HookInterfaceType';
1616
* @private
1717
* Logic for root theme handling such as updates and CSS style creation
1818
*/
19-
export const useRootTheme = (
20-
theme: Theme,
19+
export const useRootTheme = <TTheme extends Theme>(
20+
theme: TTheme,
2121
id: string
22-
): HookInterface & {style: CSSProperties} => {
22+
): HookInterface<TTheme> & {style: CSSProperties} => {
2323
const themeRef = useRef(theme);
2424

2525
const setTheme = useCallback(
26-
(nextTheme: Theme) => {
26+
(nextTheme: TTheme) => {
2727
setRootTheme(id)(nextTheme);
2828
themeRef.current = nextTheme;
2929
},

src/lib/RootTheme/useRootThemePublic.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import type {Theme} from '@/lib/ThemeType.ts';
2+
13
import {useRootContext} from './RootContext';
24

35
/**
@@ -7,9 +9,9 @@ import {useRootContext} from './RootContext';
79
* @see ThemeType
810
* @see https://github.com/morewings/css-vars-hook#type-safety
911
*/
10-
export const useRootThemePublic = () => {
12+
export const useRootThemePublic = <TTheme extends Theme>() => {
1113
const {setTheme, getTheme, setVariable, getVariable, removeVariable} =
12-
useRootContext();
14+
useRootContext<TTheme>();
1315
return {
1416
/** Effect to apply new theme to the application */
1517
setTheme,

0 commit comments

Comments
 (0)