Skip to content

Commit dffb998

Browse files
committed
docs(/pages/theme): update /theme documentation to include new theme strategies
We have more powerful options to customize themes now, and they deserve proper documentation.
1 parent 5b9de73 commit dffb998

File tree

1 file changed

+218
-40
lines changed

1 file changed

+218
-40
lines changed

src/docs/pages/ThemePage.tsx

Lines changed: 218 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,215 @@
1-
import type { FC } from 'react';
1+
import type { FC, PropsWithChildren } from 'react';
22
import reactElementToJSXString from 'react-element-to-jsx-string';
3+
import { FaMinus, FaPlus } from 'react-icons/fa';
34
import { HiInformationCircle } from 'react-icons/hi';
45
import { PrismLight as SyntaxHighlighter } from 'react-syntax-highlighter';
56
import { dracula } from 'react-syntax-highlighter/dist/esm/styles/prism';
67
import { Alert, Card, DarkThemeToggle } from '../../lib';
7-
import { Flowbite } from '../../lib/components';
8-
import type { CustomFlowbiteTheme } from '../../lib/components/Flowbite/FlowbiteTheme';
8+
import { Flowbite, Table } from '../../lib/components';
99

1010
const ThemePage: FC = () => {
11-
const theme: CustomFlowbiteTheme = { alert: { color: { info: 'bg-primary' } } };
11+
return (
12+
<div className="mx-auto max-w-4xl dark:text-white">
13+
<h1 className="mb-3 text-2xl font-bold">Theme</h1>
14+
<Alert color="warning" icon={HiInformationCircle}>
15+
This feature is highly experimental. In the future, it could be deprecated or even suffer several changes.
16+
</Alert>
17+
<CustomizeFlowbiteComponentsSection />
18+
<SwitchToDarkModeSection />
19+
<ReadTheThemeSection />
20+
</div>
21+
);
22+
};
1223

24+
const CustomizeFlowbiteComponentsSection: FC = () => {
1325
return (
14-
<div className="mx-auto flex max-w-4xl flex-col gap-8 dark:text-white">
15-
<div className="flex flex-col gap-2">
16-
<span className="text-2xl font-bold">Theme</span>
17-
<div className="py-4">
18-
<Alert color="yellow" icon={HiInformationCircle}>
19-
This feature is highly experimental. In the future, it could be deprecated or even suffer several changes.
20-
</Alert>
21-
<p className="mt-4">
22-
Sometimes you want to give your web application a little more personality and customize some aspects of
23-
Flowbite. This is possible thanks to the support we offer for themes. To use our theme support, your
24-
application needs to be surrounded by the Flowbite component, and you must tell this component which theme
25-
you want to load for your application.
26-
</p>
27-
</div>
28-
<Card>
29-
<SyntaxHighlighter language="tsx" style={dracula}>
30-
{reactElementToJSXString(<Flowbite theme={{ theme }}>...</Flowbite>, {
31-
showFunctions: true,
32-
functionValue: (fn) => fn.name,
33-
sortProps: false,
34-
useBooleanShorthandSyntax: false,
35-
useFragmentShortSyntax: false,
36-
})}
37-
</SyntaxHighlighter>
38-
</Card>
39-
</div>
40-
<span className="text-xl font-bold">Switch to dark theme</span>
41-
<p>
26+
<section className="mb-6">
27+
<header>
28+
<h2 className="my-3 text-xl font-bold">Customize Flowbite components using Tailwind CSS</h2>
29+
</header>
30+
<p className="mb-3">
31+
You want to customize Flowbite. Specifically, you would like to remove/add Tailwind CSS classes to one or more
32+
components.
33+
</p>
34+
<p className="mb-3">
35+
You have a few options. They each have benefits and drawbacks, and you can combine them how you want.
36+
</p>
37+
<FlowbiteCustomizationOptionsTable />
38+
<BenefitsAndDrawbacks />
39+
</section>
40+
);
41+
};
42+
43+
const FlowbiteCustomizationOptionsTable: FC = () => {
44+
return (
45+
<Table>
46+
<Table.Head>
47+
<Table.HeadCell className="w-64">Option</Table.HeadCell>
48+
<Table.HeadCell>Example</Table.HeadCell>
49+
</Table.Head>
50+
<Table.Body>
51+
<Table.Row>
52+
<Table.Cell>Custom theme</Table.Cell>
53+
<Table.Cell>
54+
<SyntaxHighlighter language="tsx" style={dracula}>
55+
{`const theme: CustomFlowbiteTheme = {
56+
accordion: {
57+
root: {
58+
base: 'bg-primary',
59+
},
60+
},
61+
};
62+
63+
<Flowbite theme={{ theme }}>...</Flowbite>`}
64+
</SyntaxHighlighter>
65+
</Table.Cell>
66+
</Table.Row>
67+
<Table.Row>
68+
<Table.Cell>
69+
Custom component with <strong>className=&#123;&#125;</strong>
70+
</Table.Cell>
71+
<Table.Cell>
72+
<SyntaxHighlighter language="tsx" style={dracula}>
73+
{`<Accordion className="bg-primary">
74+
<Accordion.Title>My accordion</Accordion.Title>
75+
<Accordion.Content>Contains</Accordion.Content>
76+
</Accordion>`}
77+
</SyntaxHighlighter>
78+
</Table.Cell>
79+
</Table.Row>
80+
<Table.Row>
81+
<Table.Cell>
82+
Custom component with <strong>theme=&#123;&#125;</strong>
83+
</Table.Cell>
84+
<Table.Cell>
85+
<SyntaxHighlighter language="tsx" style={dracula}>
86+
{`const accordionTheme: CustomFlowbiteTheme = {
87+
accordion: {
88+
root: {
89+
base: 'bg-primary',
90+
},
91+
},
92+
}
93+
94+
<Accordion theme={{ accordionTheme }}>
95+
<Accordion.Title>My accordion</Accordion.Title>
96+
<Accordion.Content>Contains</Accordion.Content>
97+
</Accordion>`}
98+
</SyntaxHighlighter>
99+
</Table.Cell>
100+
</Table.Row>
101+
</Table.Body>
102+
</Table>
103+
);
104+
};
105+
106+
const BenefitsAndDrawbacks: FC = () => {
107+
return (
108+
<div>
109+
<h3 className="mt-6 mb-3 text-lg font-bold">
110+
Benefits &amp; drawbacks of <strong>custom themes</strong>
111+
</h3>
112+
<ul className="list-none [&>li]:mb-2">
113+
<Benefit>You can customize every component, one time, in one place</Benefit>
114+
<Benefit>Changes will apply to every usage of the component in your app</Benefit>
115+
<Benefit>
116+
<span>
117+
You get the best performance
118+
<span>
119+
<span className="sr-only">See disclaimer</span>
120+
<sup aria-hidden>*</sup>
121+
</span>
122+
&nbsp;compared to other options
123+
</span>
124+
</Benefit>
125+
<Drawback>Customizations can quickly become complex and hard to maintain in one large JSON file</Drawback>
126+
</ul>
127+
<h3 className="mt-6 mb-3 text-lg font-bold">
128+
Benefits &amp; drawbacks of&nbsp;
129+
<strong>custom components with className=&#123;&#125;</strong>
130+
</h3>
131+
<ul className="list-none [&>li]:mb-2">
132+
<Benefit>You can customize with very little effort and code</Benefit>
133+
<Benefit>You don't need to learn how to use the theme API</Benefit>
134+
<Drawback>
135+
<span>
136+
Some components have nested elements, and you can't customize all of them with one&nbsp;
137+
<strong>className</strong>
138+
</span>
139+
</Drawback>
140+
<Drawback>
141+
You need to customize every usage of a component individually, or create and remember to use a custom
142+
component of your own
143+
</Drawback>
144+
</ul>
145+
<h3 className="mt-6 mb-3 text-lg font-bold">
146+
Benefits &amp; drawbacks of&nbsp;
147+
<strong>custom components with theme=&#123;&#125;</strong>
148+
</h3>
149+
<ul className="mb-6 list-none [&>li]:mb-2">
150+
<Benefit>You can customize one usage of a component that has nested elements</Benefit>
151+
<Benefit>
152+
You can still create a custom component of your own to reuse the customizations rather than repeating them
153+
</Benefit>
154+
<Drawback>You add further complexity and indirection to your app</Drawback>
155+
<Drawback>
156+
<span>
157+
Your app will probably perform worse at scale
158+
<span>
159+
<span className="sr-only">See disclaimer</span>
160+
<sup aria-hidden>*</sup>
161+
</span>
162+
</span>
163+
</Drawback>
164+
</ul>
165+
<p className="text-gray-700 dark:text-gray-400">
166+
<strong>
167+
<span className="sr-only">Disclaimer:</span>
168+
<span aria-hidden>*</span>
169+
</strong>
170+
&nbsp;We haven't tested performance at any scale. The <strong>theme=&#123;&#125;</strong> attribute merges the
171+
necessary part of the global theme with what is provided in the attribute, which is a deep object merge &mdash;
172+
and it isn't fast. It is safe to assume that <strong>theme=&#123;&#125;</strong> attribute will degrade
173+
performance with enough components using that technique. It is safe to assume performance won't degrade
174+
meaningfully at scale if you just use a global theme and/or <strong>className=&#123;&#125;</strong> attributes.
175+
</p>
176+
</div>
177+
);
178+
};
179+
180+
const Benefit: FC<PropsWithChildren> = ({ children }) => {
181+
return (
182+
<li className="flex items-center gap-3 leading-4 text-green-700 dark:text-green-100">
183+
<span>
184+
<FaPlus aria-hidden className="w-6" />
185+
<span className="sr-only">Benefit:</span>
186+
</span>
187+
{children}
188+
</li>
189+
);
190+
};
191+
192+
const Drawback: FC<PropsWithChildren> = ({ children }) => {
193+
return (
194+
<li className="flex items-center gap-3 leading-4 text-red-700 dark:text-red-100">
195+
<span>
196+
<FaMinus aria-hidden className="w-6" />
197+
<span className="sr-only">Drawback:</span>
198+
</span>
199+
{children}
200+
</li>
201+
);
202+
};
203+
204+
const SwitchToDarkModeSection: FC = () => {
205+
return (
206+
<section className="mb-6">
207+
<header>
208+
<h2 className="mb-3 text-xl font-bold">Switch to dark theme</h2>
209+
</header>
210+
<p className="mb-3">
42211
Since the Flowbite component creates and context to manage the theme, it also enables your application to use
43-
the <strong>DarkThemeToggle</strong> component.
212+
the <strong>&lt;DarkThemeToggle/&gt;</strong> component.
44213
</p>
45214
<Card>
46215
<SyntaxHighlighter language="tsx" style={dracula}>
@@ -58,20 +227,29 @@ const ThemePage: FC = () => {
58227
)}
59228
</SyntaxHighlighter>
60229
</Card>
61-
<span className="text-xl font-bold">Get the theme</span>
62-
<p>
63-
For more customizations, there is the possibility to get the theme with the <strong>useTheme</strong> hook and
64-
its mode with the <strong>useThemeMode</strong> hook.
230+
</section>
231+
);
232+
};
233+
234+
const ReadTheThemeSection: FC = () => {
235+
return (
236+
<section className="mb-6">
237+
<header>
238+
<h2 className="mb-3 text-xl font-bold">Read the theme</h2>
239+
</header>
240+
<p className="mb-3">
241+
You can obtain active Tailwind CSS Classes in the theme via <strong>useTheme</strong> as well as the status of
242+
light/dark mode via <strong>useThemeMode</strong>.
65243
</p>
66244
<Card>
67245
<SyntaxHighlighter language="tsx" style={dracula}>
68-
const theme = useTheme().theme.button;
246+
{`const theme = useTheme().theme.button; // -> { base: "..", color: { ... }, ... }`}
69247
</SyntaxHighlighter>
70248
<SyntaxHighlighter language="tsx" style={dracula}>
71-
const [mode, setMode, toggleMode] = useThemeMode(usePreferences);
249+
{`const [mode, setMode, toggleMode] = useThemeMode(usePreferences); // -> ["light", ..]`}
72250
</SyntaxHighlighter>
73251
</Card>
74-
</div>
252+
</section>
75253
);
76254
};
77255

0 commit comments

Comments
 (0)