Skip to content

Commit efefecd

Browse files
chore: updating avoid => recommended order, adding pitfall examples
1 parent b46270a commit efefecd

File tree

1 file changed

+101
-75
lines changed

1 file changed

+101
-75
lines changed

docs/tailwind-css.md

Lines changed: 101 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ Always prefer components over raw JSX elements with Tailwind classes. Use compon
1010

1111
**React:**
1212

13+
**Avoid**
14+
15+
```tsx
16+
<div className="bg-default p-4 rounded-lg">Content</div>
17+
```
18+
1319
**Recommended**
1420

1521
```tsx
@@ -28,14 +34,14 @@ import {
2834
</Box>;
2935
```
3036

37+
**React Native:**
38+
3139
**Avoid**
3240

3341
```tsx
34-
<div className="bg-default p-4 rounded-lg">Content</div>
42+
<View style={tw`bg-default p-4 rounded-lg`}>Content</View>
3543
```
3644

37-
**React Native:**
38-
3945
**Recommended**
4046

4147
```tsx
@@ -54,48 +60,25 @@ import {
5460
</Box>;
5561
```
5662

57-
**Avoid**
58-
59-
```tsx
60-
<View style={tw`bg-default p-4 rounded-lg`}>Content</View>
61-
```
62-
6363
### Color and Typography
6464

6565
Use only design token based classes that are generated from our design system. Never use Tailwind's default color palette, arbitrary colors like hex or rgb values or font sizes. Always use the `Text` component for text styling instead of Tailwind's typography classes.
6666

6767
**React:**
6868

69-
**Recommended**
70-
71-
```tsx
72-
import { Box, BoxBackgroundColor, BoxBorderRadius, Text, TextVariant, TextColor } from '@metamask/design-system-react';
73-
74-
<Box backgroundColor={BoxBackgroundColor.PrimaryDefault} padding={4}>
75-
<Text variant={TextVariant.HeadingLg} color={TextColor.PrimaryInverse}>
76-
Title
77-
</Text>
78-
</Box>
79-
<Text variant={TextVariant.BodyMd} color={TextColor.TextAlternative}>
80-
Content
81-
</Text>
82-
```
83-
8469
**Avoid**
8570

8671
```tsx
87-
<div className="bg-blue-500 text-white p-4 text-lg font-bold">
72+
<div className="bg-blue-500 text-[#FFFFFF] p-4 text-lg font-bold">
8873
<h1 className="text-2xl">Title</h1>
8974
</div>
9075
<p className="text-gray-600">Content</p>
9176
```
9277

93-
**React Native:**
94-
9578
**Recommended**
9679

9780
```tsx
98-
import { Box, BoxBackgroundColor, BoxBorderRadius, Text, TextVariant, TextColor } from '@metamask/design-system-react-native';
81+
import { Box, BoxBackgroundColor, BoxBorderRadius, Text, TextVariant, TextColor } from '@metamask/design-system-react';
9982

10083
<Box backgroundColor={BoxBackgroundColor.PrimaryDefault} padding={4}>
10184
<Text variant={TextVariant.HeadingLg} color={TextColor.PrimaryInverse}>
@@ -107,6 +90,8 @@ import { Box, BoxBackgroundColor, BoxBorderRadius, Text, TextVariant, TextColor
10790
</Text>
10891
```
10992

93+
**React Native:**
94+
11095
**Avoid**
11196

11297
```tsx
@@ -127,41 +112,71 @@ const styles = StyleSheet.create({
127112
</View>;
128113
```
129114

115+
**Recommended**
116+
117+
```tsx
118+
import { Box, BoxBackgroundColor, BoxBorderRadius, Text, TextVariant, TextColor } from '@metamask/design-system-react-native';
119+
120+
<Box backgroundColor={BoxBackgroundColor.PrimaryDefault} padding={4}>
121+
<Text variant={TextVariant.HeadingLg} color={TextColor.PrimaryInverse}>
122+
Title
123+
</Text>
124+
</Box>
125+
<Text variant={TextVariant.BodyMd} color={TextColor.TextAlternative}>
126+
Content
127+
</Text>
128+
```
129+
130130
## Platform-Specific Guidelines
131131

132132
### React
133133

134134
Leverage Tailwind's utility classes for styling via `className`.
135135

136+
**Avoid**
137+
138+
```tsx
139+
const styles = {
140+
backgroundColor: '#F2F4F6',
141+
padding: '16px',
142+
};
143+
144+
<div style={styles}>Content</div>;
145+
```
146+
136147
**Recommended**
137148

138149
```tsx
139150
import { Box, BoxBackgroundColor } from '@metamask/design-system-react';
140151

141-
// When no prop exists
142152
<Box
143153
tabIndex={0}
144154
backgroundColor={BoxBackgroundColor.BackgroundDefault}
145-
className="hover:bg-hover active:bg-pressed"
155+
className="hover:bg-hover active:bg-pressed" // When no prop exists
146156
>
147157
Content
148158
</Box>;
149159
```
150160

161+
### React Native
162+
163+
Use `useTailwind` hook from `@metamask/design-system-twrnc-preset` instead of importing `twrnc` directly. The preset automatically handles light/dark theme switching and design token integration.
164+
151165
**Avoid**
152166

153167
```tsx
154-
const styles = {
155-
backgroundColor: '#F2F4F6',
156-
padding: '16px',
157-
};
158-
159-
<div style={styles}>Content</div>;
160-
```
168+
import tw from 'twrnc';
161169

162-
### React Native
170+
const styles = StyleSheet.create({
171+
container: {
172+
backgroundColor: colors.background.default,
173+
padding: 16,
174+
},
175+
});
163176

164-
Use `useTailwind` hook from `@metamask/design-system-twrnc-preset` instead of importing `twrnc` directly. The preset automatically handles light/dark theme switching and design token integration.
177+
// Direct twrnc without design system integration
178+
const styles = tw`bg-default p-4`;
179+
```
165180

166181
**Recommended**
167182

@@ -179,7 +194,7 @@ const MyComponent = () => {
179194
};
180195

181196
// Using Box component with twClassName
182-
<Box twClassName="h-[100px]">
197+
<Box twClassName="overflow-hidden">
183198
Content
184199
</Box>
185200

@@ -196,22 +211,6 @@ const MyComponent = () => {
196211
</Pressable>
197212
```
198213

199-
**Avoid**
200-
201-
```tsx
202-
import tw from 'twrnc';
203-
204-
const styles = StyleSheet.create({
205-
container: {
206-
backgroundColor: colors.background.default,
207-
padding: 16,
208-
},
209-
});
210-
211-
// Direct twrnc without design system integration
212-
const styles = tw`bg-default p-4`;
213-
```
214-
215214
## Style Guidelines
216215

217216
### Platform-Specific Styling Patterns
@@ -221,8 +220,8 @@ const styles = tw`bg-default p-4`;
221220
```tsx
222221
import { ButtonBase, Icon, IconName } from '@metamask/design-system-react';
223222

224-
// Layout and spacing
225-
// Interactive states (react supports hover/active)
223+
// Use the className prop to override existing tailwind classnames when necessary
224+
// Example overriding the default size/shape, layout and interactive states
226225
<ButtonBase className="h-auto flex-1 flex-col justify-center rounded-lg bg-muted py-4 hover:bg-muted-hover active:bg-muted-pressed">
227226
<Icon name={IconName.Bank} className="mb-2" />
228227
Buy/Sell
@@ -288,17 +287,32 @@ Example [eslint.config.mjs](https://github.com/MetaMask/metamask-design-system/b
288287
### Anti-patterns to Avoid
289288

290289
- **No Arbitrary Values**: Don't use `[]` syntax for arbitrary values unless absolutely necessary
290+
291291
- **No Direct Styles**: Avoid inline `style` objects
292292
- **No @apply**: Don't use `@apply` in CSS files
293293
- **Avoid Style Mixing**: Try to avoid mixing Tailwind with other styling approaches like inline styles in the same component when not necessary. Style mixing may be necessary for custom animations or dynamic values that can't be achieved with Tailwind alone. However, combining component props with Tailwind classes via `className`/`twClassName`/`tw` is acceptable when no equivalent prop exists
294-
- **No Default Colors**: Never use Tailwind's default color palette
295-
- **No Direct Typography**: Never use typography classes directly
296294

297295
**React:**
298296

299297
**Avoid**
300298

301299
```tsx
300+
// Arbitrary values
301+
<button className="m-[16px] bg-[#FFFFFF] w-[100%] h-[100px]">Confirm</button>
302+
303+
// Unnecessary inline styles
304+
<button style={{ marginTop: '16px'}}>Confirm</button>
305+
```
306+
307+
```css
308+
/* Using @apply */
309+
.btn {
310+
@apply px-5 py-2 rounded-full cursor-pointer border disabled:cursor-auto;
311+
}
312+
```
313+
314+
```tsx
315+
// Style mixing
302316
<div className="bg-default p-4" style={{ marginTop: '16px' }}>
303317
Content
304318
</div>
@@ -307,35 +321,47 @@ Example [eslint.config.mjs](https://github.com/MetaMask/metamask-design-system/b
307321
**Recommended**
308322

309323
```tsx
310-
<Box backgroundColor={BoxBackgroundColor.BackgroundDefault} padding={4} marginTop={4}>
311-
Content
312-
</Box>
324+
// Use classes provided by Tailwind config and necessary arbitrary value
325+
<button className="m-4 bg-default w-full h-[100px]">Content</button>;
313326

314-
// When no prop exists
315-
<Box backgroundColor={BoxBackgroundColor.BackgroundDefault} padding={4} className="hover:bg-hover">
316-
Content with margin
317-
</Box>
327+
// Necessary inline styles only
328+
<button style={{ marginTop: dynamicValue }}>Confirm</button>;
329+
330+
// Create components instead of using @apply
331+
import { twMerge } from '@metamask/design-system-react';
332+
333+
const MyButton = ({ className }) => (
334+
<button
335+
className={twMerge(
336+
'px-5 py-2 rounded-full cursor-pointer border disabled:cursor-auto',
337+
className,
338+
)}
339+
>
340+
Confirm
341+
</button>
342+
);
318343
```
319344

320345
**React Native:**
321346

322347
**Avoid**
323348

324349
```tsx
325-
<View style={[tw`bg-default p-4`, { marginTop: 16 }]}>Content</View>
350+
// Style mixing
351+
<Scrollable style={[tw`bg-default p-4`, { marginTop: 16 }]}>Content</Scrollable>
352+
353+
// Arbitrary values
354+
<Pressable style={[tw`m-[16px] bg-[#FFFFFF] w-[100%] h-[100px]`]}>Confirm</Pressable>
326355
```
327356

328357
**Recommended**
329358

330359
```tsx
331-
<Box backgroundColor={BoxBackgroundColor.BackgroundDefault} padding={4} marginTop={4}>
332-
Content
333-
</Box>
360+
// Use classes provided by Tailwind config
361+
<Scrollable style={tw`bg-default p-4 mt-4`}>Content</Scrollable>
334362

335-
// When no prop exists
336-
<Box backgroundColor={BoxBackgroundColor.BackgroundDefault} padding={4} twClassName="my-2">
337-
Content with margin
338-
</Box>
363+
// Use classes provided by Tailwind config and necessary arbitrary value
364+
<Pressable style={tw`m-4 bg-default w-full h-[100px]`} >Confirm</Pressable>
339365
```
340366

341367
---

0 commit comments

Comments
 (0)