Skip to content

Commit c4e195c

Browse files
committed
feat(flowbite): adds feature to use nested providers
#443
1 parent f45cecf commit c4e195c

File tree

3 files changed

+59
-9
lines changed

3 files changed

+59
-9
lines changed

src/lib/components/Flowbite/Flowbite.spec.tsx

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
import { act, render } from '@testing-library/react';
1+
import { act, render, screen } from '@testing-library/react';
2+
import classNames from 'classnames';
3+
import { ComponentProps, FC } from 'react';
24
import { afterEach, describe, expect, it } from 'vitest';
35
import { mergeDeep } from '../../helpers/mergeDeep';
46
import defaultTheme from '../../theme/default';
@@ -83,19 +85,54 @@ describe('Components / Flowbite', () => {
8385
expect(mode2).toBe('dark');
8486
expect(documentEl()).toHaveClass('dark');
8587
});
88+
89+
it('should incapsulate nested themes', () => {
90+
render(
91+
<>
92+
<Flowbite theme={{ theme: { avatar: { size: { md: 'w-1 h-1' } } } }}>
93+
{/* should be w-1 h-1 */}
94+
<TestComponent data-testid="first-lvl" />
95+
96+
<Flowbite theme={{ theme: { avatar: { size: { md: 'w-2 h-2' } } } }}>
97+
{/* should be w-2 h-2 */}
98+
<TestComponent data-testid="second-lvl" />
99+
100+
<Flowbite>
101+
{/* should be w-2 h-2, closest provider return w-2 h-2 */}
102+
<TestComponent data-testid="third-lvl" />
103+
</Flowbite>
104+
</Flowbite>
105+
</Flowbite>
106+
{/* should be w-10 h-10 default */}
107+
<TestComponent data-testid="without-provider" />
108+
</>,
109+
);
110+
111+
const withoutProvider = screen.getByTestId('without-provider');
112+
const firstLvlProvider = screen.getByTestId('first-lvl');
113+
const secondLvlProvider = screen.getByTestId('second-lvl');
114+
const thirdLvlProvider = screen.getByTestId('third-lvl');
115+
116+
expect(firstLvlProvider).toHaveClass('w-1 h-1');
117+
expect(secondLvlProvider).toHaveClass('w-2 h-2');
118+
expect(thirdLvlProvider).toHaveClass('w-2 h-2');
119+
expect(withoutProvider).toHaveClass('w-10 h-10');
120+
});
86121
});
87122
});
88123

89124
let context: ThemeContextProps;
90-
const TestComponent = () => {
125+
const TestComponent: FC<ComponentProps<'div'>> = (props) => {
126+
const { className, ...other } = props;
91127
context = useTheme();
92-
return null;
128+
129+
return <div className={classNames(context.theme.avatar.size.md, className)} {...other} />;
93130
};
94131

95132
const customTheme = {
96133
avatar: {
97134
size: {
98-
xxl: 'h-64 w-64',
135+
md: 'h-64 w-64',
99136
},
100137
},
101138
};

src/lib/components/Flowbite/Flowbite.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import type { FC, HTMLAttributes } from 'react';
1+
import type { FC, HTMLAttributes, ReactNode } from 'react';
22
import { useEffect, useMemo } from 'react';
33
import type { DeepPartial } from '..';
44
import { mergeDeep } from '../../helpers/mergeDeep';
55
import windowExists from '../../helpers/window-exists';
6-
import defaultTheme from '../../theme/default';
76
import type { FlowbiteTheme } from './FlowbiteTheme';
87
import { ThemeContext, useTheme, useThemeMode } from './ThemeContext';
98

@@ -14,15 +13,17 @@ export interface ThemeProps {
1413
}
1514

1615
interface FlowbiteProps extends HTMLAttributes<HTMLDivElement> {
17-
children: React.ReactNode;
16+
children: ReactNode;
1817
theme?: ThemeProps;
1918
}
2019

2120
export const Flowbite: FC<FlowbiteProps> = ({ children, theme = {} }) => {
22-
const { theme: customTheme = {}, dark, usePreferences = true } = theme;
21+
const { theme: localTheme = {}, dark, usePreferences = true } = theme;
22+
2323
const [mode, setMode, toggleMode] = useThemeMode(usePreferences);
24+
const outerTheme = useTheme().theme;
2425

25-
const mergedTheme = mergeDeep<FlowbiteTheme>(defaultTheme, customTheme);
26+
const mergedTheme = mergeDeep(outerTheme, localTheme);
2627

2728
useEffect(() => {
2829
if (dark) {
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { FC, ReactNode } from 'react';
2+
import { DeepPartial } from '..';
3+
import { Flowbite, FlowbiteTheme } from './Flowbite';
4+
5+
interface ThemeProviderProps {
6+
children: ReactNode;
7+
theme: DeepPartial<FlowbiteTheme>;
8+
}
9+
10+
export const FlowbiteThemeProvider: FC<ThemeProviderProps> = ({ children, theme }) => (
11+
<Flowbite theme={{ theme }}>{children}</Flowbite>
12+
);

0 commit comments

Comments
 (0)