emoji-picker-react 4.20.8 → 4.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/llms.txt CHANGED
@@ -238,9 +238,31 @@ Control the footer preview area with `previewConfig`:
238
238
 
239
239
  ## Custom Category Icons
240
240
 
241
- Customize the navigation icons using one of two methods.
241
+ Customize the navigation icons using one of three methods.
242
242
 
243
- **Method 1: The `categoryIcons` prop**
243
+ **Method 1: Recolor the default icons with CSS variables**
244
+
245
+ The default icons follow two variables. Set them on the picker root via
246
+ the `style` prop (the picker defines its own defaults on `.epr-main`, so
247
+ values inherited from outer ancestors are shadowed):
248
+
249
+ ```tsx
250
+ <EmojiPicker
251
+ style={
252
+ {
253
+ '--epr-category-icon-active-color': '#e11d48',
254
+ '--epr-category-icon-inactive-color': '#a8a29e',
255
+ } as React.CSSProperties
256
+ }
257
+ />
258
+ ```
259
+
260
+ | Variable | Default |
261
+ | :----------------------------------- | :---------------------------------- |
262
+ | `--epr-category-icon-active-color` | `#3371B7` (`#6AA9DD` in dark theme) |
263
+ | `--epr-category-icon-inactive-color` | `#868686` (`#C0C0BF` in dark theme) |
264
+
265
+ **Method 2: The `categoryIcons` prop**
244
266
 
245
267
  Map `Categories` enum values to React nodes:
246
268
 
@@ -255,7 +277,7 @@ import EmojiPicker, { Categories } from 'emoji-picker-react';
255
277
  />;
256
278
  ```
257
279
 
258
- **Method 2: The `categories` configuration array**
280
+ **Method 3: The `categories` configuration array**
259
281
 
260
282
  Define the icon directly within the category configuration object:
261
283
 
@@ -386,10 +408,11 @@ aside.EmojiPickerReact {
386
408
 
387
409
  ## 🏷️ Category Navigation
388
410
 
389
- | Variable | Description | Default |
390
- | :-------------------------------------- | :----------------------------------- | :-------- |
391
- | `--epr-category-navigation-button-size` | Size of category navigation buttons. | `30px` |
392
- | `--epr-category-icon-active-color` | Color of the active category icon. | `#6aa8de` |
411
+ | Variable | Description | Default |
412
+ | :-------------------------------------- | :-------------------------------------------------------------- | :------------------ |
413
+ | `--epr-category-navigation-button-size` | Size of category navigation buttons. | `30px` |
414
+ | `--epr-category-icon-active-color` | Color of the active/hovered category icon (and focus ring). | `#3371B7` (`#6AA9DD` in dark theme) |
415
+ | `--epr-category-icon-inactive-color` | Color of inactive category icons. | `#868686` (`#C0C0BF` in dark theme) |
393
416
 
394
417
  ## 📃 Category Labels
395
418
 
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.20.8",
2
+ "version": "4.21.0",
3
3
  "license": "MIT",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
@@ -40,7 +40,7 @@ export const commonInteractionStyles = stylesheet.create({
40
40
  categoryBtn: {
41
41
  ':hover': {
42
42
  opacity: '1',
43
- backgroundPositionY: 'var(--epr-category-navigation-button-size)',
43
+ color: 'var(--epr-category-icon-active-color, #3371B7)',
44
44
  },
45
45
  },
46
46
  hiddenOnSearch: {
@@ -68,11 +68,11 @@ export const commonInteractionStyles = stylesheet.create({
68
68
  categoryBtn: {
69
69
  ':hover': {
70
70
  opacity: '1',
71
- backgroundPositionY: 'var(--epr-category-navigation-button-size)',
71
+ color: 'var(--epr-category-icon-active-color, #3371B7)',
72
72
  },
73
73
  '&.epr-active': {
74
74
  opacity: '1',
75
- backgroundPositionY: 'var(--epr-category-navigation-button-size)',
75
+ color: 'var(--epr-category-icon-active-color, #3371B7)',
76
76
  },
77
77
  },
78
78
  visibleOnSearchOnly: {
@@ -95,6 +95,8 @@ const DarkTheme = {
95
95
  'var(--epr-dark-emoji-variation-indicator-color)',
96
96
  '--epr-category-icon-active-color':
97
97
  'var(--epr-dark-category-icon-active-color)',
98
+ '--epr-category-icon-inactive-color':
99
+ 'var(--epr-dark-category-icon-inactive-color)',
98
100
  '--epr-skin-tone-picker-menu-color':
99
101
  'var(--epr-dark-skin-tone-picker-menu-color)',
100
102
  '--epr-skin-tone-outer-border-color':
@@ -132,7 +134,8 @@ const styles = stylesheet.create({
132
134
  '--epr-picker-border-color': '#e7e7e7',
133
135
  '--epr-bg-color': '#fff',
134
136
  '--epr-reactions-bg-color': '#ffffff90',
135
- '--epr-category-icon-active-color': '#6aa8de',
137
+ '--epr-category-icon-active-color': '#3371B7',
138
+ '--epr-category-icon-inactive-color': '#868686',
136
139
  '--epr-skin-tone-picker-menu-color': '#ffffff95',
137
140
  '--epr-skin-tone-outer-border-color': '#555555',
138
141
  '--epr-skin-tone-inner-border-color': 'var(--epr-bg-color)',
@@ -214,7 +217,8 @@ const styles = stylesheet.create({
214
217
  '--epr-dark-reactions-bg-color': '#22222290',
215
218
  '--epr-dark-search-input-bg-color-active': 'var(--epr-dark)',
216
219
  '--epr-dark-emoji-variation-indicator-color': '#444',
217
- '--epr-dark-category-icon-active-color': '#3271b7',
220
+ '--epr-dark-category-icon-active-color': '#6AA9DD',
221
+ '--epr-dark-category-icon-inactive-color': '#C0C0BF',
218
222
  '--epr-dark-skin-tone-picker-menu-color': '#22222295',
219
223
  '--epr-dark-skin-tone-outer-border-color':
220
224
  'var(--epr-dark-picker-border-color)',
@@ -11,7 +11,7 @@ import { categoryNameFromCategoryConfig } from '../../config/categoryConfig';
11
11
  import { CategoryConfig } from '../../types/exposedTypes';
12
12
  import { Button } from '../atoms/Button';
13
13
 
14
- import SVGNavigation from './svg/CategoryNav.svg';
14
+ import { CategoryNavIcon } from './CategoryNavIcon';
15
15
 
16
16
  type Props = {
17
17
  isActiveCategory: boolean;
@@ -51,23 +51,23 @@ export function CategoryButton({
51
51
  role="tab"
52
52
  aria-controls="epr-category-nav-id"
53
53
  >
54
- {hasCustomIcon ? icon : null}
54
+ {hasCustomIcon ? icon : <CategoryNavIcon category={category} />}
55
55
  </Button>
56
56
  );
57
57
  }
58
58
 
59
- const DarkActivePositionY = {
60
- backgroundPositionY: 'calc(var(--epr-category-navigation-button-size) * 3)',
59
+ const DarkActiveColor = {
60
+ color: 'var(--epr-category-icon-active-color, #6AA9DD)',
61
61
  };
62
- const DarkPositionY = {
63
- backgroundPositionY: 'calc(var(--epr-category-navigation-button-size) * 2)',
62
+ const DarkInactiveColor = {
63
+ color: 'var(--epr-category-icon-inactive-color, #C0C0BF)',
64
64
  };
65
65
 
66
66
  const DarkInactivePosition = {
67
67
  ':not(.epr-search-active)': {
68
68
  catBtn: {
69
- ':hover': DarkActivePositionY,
70
- '&.epr-active': DarkActivePositionY,
69
+ ':hover': DarkActiveColor,
70
+ '&.epr-active': DarkActiveColor,
71
71
  },
72
72
  },
73
73
  };
@@ -80,10 +80,11 @@ const styles = stylesheet.create({
80
80
  position: 'relative',
81
81
  height: 'var(--epr-category-navigation-button-size)',
82
82
  width: 'var(--epr-category-navigation-button-size)',
83
- backgroundSize: 'calc(var(--epr-category-navigation-button-size) * 10)',
84
83
  outline: 'none',
85
- backgroundPosition: '0 0',
86
- backgroundImage: `url(${SVGNavigation})`,
84
+ // Icon glyphs are inline SVGs painted with currentColor, so the fill
85
+ // follows the --epr-category-icon-*-color variables.
86
+ // https://github.com/ealush/emoji-picker-react/issues/399
87
+ color: 'var(--epr-category-icon-inactive-color, #868686)',
87
88
  ':focus:before': {
88
89
  content: '',
89
90
  position: 'absolute',
@@ -94,54 +95,14 @@ const styles = stylesheet.create({
94
95
  border: '2px solid var(--epr-category-icon-active-color)',
95
96
  borderRadius: '50%',
96
97
  },
97
- '&.epr-icn-suggested': {
98
- backgroundPositionX:
99
- 'calc(var(--epr-category-navigation-button-size) * -8)',
100
- },
101
- '&.epr-icn-custom': {
102
- backgroundPositionX:
103
- 'calc(var(--epr-category-navigation-button-size) * -9)',
104
- },
105
- '&.epr-icn-activities': {
106
- backgroundPositionX:
107
- 'calc(var(--epr-category-navigation-button-size) * -4)',
108
- },
109
- '&.epr-icn-animals_nature': {
110
- backgroundPositionX:
111
- 'calc(var(--epr-category-navigation-button-size) * -1)',
112
- },
113
- '&.epr-icn-flags': {
114
- backgroundPositionX:
115
- 'calc(var(--epr-category-navigation-button-size) * -7)',
116
- },
117
- '&.epr-icn-food_drink': {
118
- backgroundPositionX:
119
- 'calc(var(--epr-category-navigation-button-size) * -2)',
120
- },
121
- '&.epr-icn-objects': {
122
- backgroundPositionX:
123
- 'calc(var(--epr-category-navigation-button-size) * -5)',
124
- },
125
- '&.epr-icn-smileys_people': {
126
- backgroundPositionX: '0px',
127
- },
128
- '&.epr-icn-symbols': {
129
- backgroundPositionX:
130
- 'calc(var(--epr-category-navigation-button-size) * -6)',
131
- },
132
- '&.epr-icn-travel_places': {
133
- backgroundPositionX:
134
- 'calc(var(--epr-category-navigation-button-size) * -3)',
135
- },
136
98
  },
137
99
  customIcon: {
138
100
  '.': 'epr-cat-btn-custom-icon',
139
- backgroundImage: 'none',
140
101
  display: 'flex',
141
102
  alignItems: 'center',
142
103
  justifyContent: 'center',
143
104
  },
144
- ...darkMode('catBtn', DarkPositionY),
105
+ ...darkMode('catBtn', DarkInactiveColor),
145
106
  '.epr-dark-theme': {
146
107
  ...DarkInactivePosition,
147
108
  },
@@ -0,0 +1,317 @@
1
+ import * as React from 'react';
2
+
3
+ // Default navigation icons, extracted from the former CategoryNav.svg
4
+ // sprite (row 0). Paint uses currentColor so the fill follows the
5
+ // --epr-category-icon-*-color variables.
6
+ // https://github.com/ealush/emoji-picker-react/issues/399
7
+
8
+ const COLUMNS: Record<string, number> = {
9
+ smileys_people: 0,
10
+ animals_nature: 1,
11
+ food_drink: 2,
12
+ travel_places: 3,
13
+ activities: 4,
14
+ objects: 5,
15
+ symbols: 6,
16
+ flags: 7,
17
+ suggested: 8,
18
+ custom: 9,
19
+ };
20
+
21
+ const SHAPES: Record<number, React.ReactNode> = {
22
+ 0: (
23
+ <>
24
+ <path
25
+ fill="currentColor"
26
+ stroke="currentColor"
27
+ strokeWidth="0.1"
28
+ strokeMiterlimit="10"
29
+ d="M12.8,9.5c0.6,0,1.1-0.5,1.1-1.2
30
+ c0-0.6-0.5-1.1-1.1-1.1c-0.6,0-1.2,0.5-1.2,1.1S12.2,9.5,12.8,9.5z M12.8,7.9c0.2,0,0.4,0.2,0.4,0.4c0,0.2-0.2,0.4-0.4,0.4
31
+ c-0.2,0-0.4-0.2-0.4-0.4C12.4,8.1,12.6,7.9,12.8,7.9z"
32
+ />
33
+ <path
34
+ fill="currentColor"
35
+ stroke="currentColor"
36
+ strokeWidth="0.1"
37
+ strokeMiterlimit="10"
38
+ d="M7.2,9.5c0.6,0,1.2-0.5,1.2-1.2
39
+ c0-0.6-0.5-1.1-1.2-1.1c-0.6,0-1.1,0.5-1.1,1.1S6.6,9.5,7.2,9.5z M7.2,7.9c0.2,0,0.4,0.2,0.4,0.4c0,0.2-0.2,0.4-0.4,0.4
40
+ C7,8.7,6.8,8.5,6.8,8.3C6.8,8.1,7,7.9,7.2,7.9z"
41
+ />
42
+ <path
43
+ fill="currentColor"
44
+ stroke="currentColor"
45
+ strokeWidth="0.1"
46
+ strokeMiterlimit="10"
47
+ d="M14.6,11.2c-0.1-0.1-0.2-0.2-0.3-0.2H5.7
48
+ c-0.1,0-0.2,0.1-0.3,0.2c-0.1,0.1-0.1,0.2,0,0.4c0.7,2,2.5,3.3,4.6,3.3s3.9-1.3,4.6-3.3C14.7,11.4,14.7,11.3,14.6,11.2z M10,14.1
49
+ c-1.6,0-3-0.9-3.7-2.2h7.3C13,13.2,11.6,14.1,10,14.1z"
50
+ />
51
+ <path
52
+ fill="currentColor"
53
+ stroke="currentColor"
54
+ strokeWidth="0.1"
55
+ strokeMiterlimit="10"
56
+ d="M10,3c-3.8,0-7,3.1-7,7s3.1,7,7,7s7-3.1,7-7
57
+ S13.8,3,10,3z M10,16.2c-3.4,0-6.2-2.8-6.2-6.2S6.6,3.8,10,3.8s6.2,2.8,6.2,6.2S13.4,16.2,10,16.2z"
58
+ />
59
+ </>
60
+ ),
61
+ 1: (
62
+ <>
63
+ <path
64
+ fill="none"
65
+ stroke="currentColor"
66
+ d="M24.2,11V3.5c0.1,0.1,0.8,0.9,2.8,3.1c2.5-1.7,5.6-0.7,6.9,0l2.4-3.1v7.1
67
+ c0,1.2-0.1,2.5-0.9,3.4c-1,1.2-2.7,2.5-5.3,2.5c-2.9,0-4.5-1.5-5.3-2.9C24.2,12.9,24.2,11.9,24.2,11z"
68
+ />
69
+ <path
70
+ fill="none"
71
+ stroke="currentColor"
72
+ strokeLinecap="round"
73
+ d="M21.2,10l5.4,1.2"
74
+ />
75
+ <path
76
+ fill="none"
77
+ stroke="currentColor"
78
+ strokeLinecap="round"
79
+ d="M21.2,14.1l5.4-1.2"
80
+ />
81
+ <path
82
+ fill="none"
83
+ stroke="currentColor"
84
+ strokeLinecap="round"
85
+ d="M38.8,10l-5.4,1.2"
86
+ />
87
+ <path
88
+ fill="none"
89
+ stroke="currentColor"
90
+ strokeLinecap="round"
91
+ d="M38.8,14.1l-5.4-1.2"
92
+ />
93
+ <path
94
+ fillRule="evenodd"
95
+ clipRule="evenodd"
96
+ fill="currentColor"
97
+ d="M29.5,12.4L29,11.7c-0.2-0.3,0-0.6,0.3-0.6h1.4
98
+ c0.3,0,0.5,0.4,0.3,0.6l-0.7,1l0,0c-0.7,1.2-2.6,1.1-3.1-0.3l-0.1-0.2c-0.1-0.2,0-0.4,0.2-0.5s0.4,0,0.5,0.2l0.1,0.2
99
+ C28.3,12.7,29.1,12.9,29.5,12.4z"
100
+ />
101
+ <path
102
+ fill="none"
103
+ stroke="currentColor"
104
+ strokeLinecap="round"
105
+ d="M32.4,12.1l-0.1,0.2c-0.4,1-1.8,1.1-2.3,0.2"
106
+ />
107
+ <ellipse fill="currentColor" cx="27.6" cy="9.7" rx="0.7" ry="0.7" />
108
+ <ellipse fill="currentColor" cx="32.4" cy="9.7" rx="0.7" ry="0.7" />
109
+ </>
110
+ ),
111
+ 2: (
112
+ <>
113
+ <path
114
+ fill="none"
115
+ stroke="currentColor"
116
+ d="M48.1,3.5h3.7c2.5,0,4.5,2,4.5,4.5c0,0.5-0.4,0.9-0.9,0.9H44.5c-0.5,0-0.9-0.4-0.9-0.9
117
+ C43.6,5.5,45.6,3.5,48.1,3.5z"
118
+ />
119
+ <path
120
+ fill="none"
121
+ stroke="currentColor"
122
+ strokeLinecap="round"
123
+ d="M43.5,8.7c-0.2,0.1-0.5,1.2,0,1.5c1.4,0.9,8.5,0.8,11.3,0.6
124
+ c0.8-0.1,1.6-0.4,1.7-1.2c0-0.3-0.1-0.6-0.6-0.9"
125
+ />
126
+ <path
127
+ fill="none"
128
+ stroke="currentColor"
129
+ strokeLinecap="round"
130
+ d="M43.5,10.6L43.3,11c-0.2,0.5,0.2,1,0.7,0.9
131
+ c0.3-0.1,0.5,0.1,0.7,0.3l0.1,0.2c0.3,0.5,1,0.6,1.5,0.2l0,0c0.3-0.2,0.7-0.3,1-0.2l0.8,0.3c0.4,0.1,0.8,0.1,1.2,0l0.5-0.2
132
+ c0.4-0.2,0.9-0.2,1.3,0l0.5,0.2c0.4,0.2,0.8,0.1,1.2-0.1l0.2-0.1c0.3-0.2,0.8-0.1,1.1,0.1l0.2,0.2c0.3,0.3,0.8,0.2,1-0.2l0.1-0.2
133
+ c0.1-0.2,0-0.3,0.2-0.4c0.5,0,1.2-0.3,1.1-0.7l-0.4-1.1"
134
+ />
135
+ <path
136
+ fill="none"
137
+ stroke="currentColor"
138
+ strokeLinecap="round"
139
+ d="M43.5,12.1c-0.1,0.2-0.3,0.8,0,1.1c0.3,0.4,3,1.1,6.4,1.1
140
+ c2.2,0,4.6-0.3,6-0.6c0.5-0.1,0.9-0.4,0.8-0.9c0-0.2-0.2-0.5-0.4-0.7"
141
+ />
142
+ <path
143
+ fill="none"
144
+ stroke="currentColor"
145
+ strokeLinecap="round"
146
+ d="M43.5,13.3c0,0.5,0.6,2.4,1.3,2.6c1.8,0.8,5.7,0.7,8.1,0.5
147
+ c1.3-0.1,2.5-0.7,3.2-1.8c0.3-0.5,0.5-1,0.5-1.4"
148
+ />
149
+ <ellipse fill="currentColor" cx="51.6" cy="6.5" rx="0.3" ry="0.4" />
150
+ <ellipse fill="currentColor" cx="53" cy="4.9" rx="0.3" ry="0.4" />
151
+ <ellipse fill="currentColor" cx="53" cy="7.2" rx="0.3" ry="0.4" />
152
+ <ellipse fill="currentColor" cx="54.3" cy="6.5" rx="0.3" ry="0.4" />
153
+ <ellipse fill="currentColor" cx="50.9" cy="4.9" rx="0.3" ry="0.4" />
154
+ </>
155
+ ),
156
+ 3: (
157
+ <>
158
+ <path
159
+ fill="none"
160
+ stroke="currentColor"
161
+ d="M64.1,13.4l2.3,0c0.2,0,0.4,0.2,0.4,0.4v2.1c0,0.2-0.2,0.4-0.4,0.4h-2.3
162
+ c-0.2,0-0.4-0.2-0.4-0.4v-2.1C63.7,13.6,63.8,13.4,64.1,13.4z"
163
+ />
164
+ <path
165
+ fill="none"
166
+ stroke="currentColor"
167
+ d="M73.5,13.4h2.4c0.2,0,0.4,0.2,0.4,0.4v2.1c0,0.2-0.2,0.4-0.4,0.4h-2.4
168
+ c-0.2,0-0.4-0.2-0.4-0.4l0-2.1C73.1,13.6,73.3,13.4,73.5,13.4z"
169
+ />
170
+ <path fill="none" stroke="currentColor" d="M63.7,8.4h12.6v5H63.7V8.4z" />
171
+ <path
172
+ fill="none"
173
+ stroke="currentColor"
174
+ d="M65.5,3.6h8.9c1,0,1.9,0.8,1.9,1.9v3.1H63.7V5.5C63.7,4.4,64.5,3.6,65.5,3.6z"
175
+ />
176
+ <ellipse fill="currentColor" cx="66.2" cy="10.9" rx="0.9" ry="0.9" />
177
+ <ellipse fill="currentColor" cx="73.8" cy="10.9" rx="0.9" ry="0.9" />
178
+ </>
179
+ ),
180
+ 4: (
181
+ <>
182
+ <path
183
+ fill="none"
184
+ stroke="currentColor"
185
+ d="M96.4,10c0,3.6-2.9,6.5-6.4,6.5s-6.4-2.9-6.4-6.5s2.9-6.5,6.4-6.5S96.4,6.4,96.4,10z"
186
+ />
187
+ <path
188
+ fill="none"
189
+ stroke="currentColor"
190
+ d="M96.3,8.6c0,0,0,0.1,0,0.1c-0.9,0.1-2.9,0.1-4.6-1.2c-1.1-0.8-2-1.7-2.6-2.5
191
+ c-0.3-0.4-0.6-0.8-0.7-1.1c-0.1-0.1-0.1-0.2-0.1-0.2c0.5-0.1,1.2-0.2,2-0.2c1.2,0,2.5,0.3,3.5,1.1c1,0.8,1.7,1.8,2.1,2.8
192
+ C96.1,7.9,96.2,8.3,96.3,8.6z"
193
+ />
194
+ <path
195
+ fill="none"
196
+ stroke="currentColor"
197
+ d="M84,12.1c0,0,0-0.1,0-0.1c0.9-0.2,2.9-0.4,4.7,0.6c1.1,0.6,1.9,1.5,2.4,2.3
198
+ c0.4,0.5,0.6,1,0.7,1.3c-0.4,0.1-1,0.2-1.7,0.3c-1,0-2.1-0.1-3.2-0.8c-1.1-0.6-1.9-1.6-2.4-2.5C84.2,12.8,84.1,12.4,84,12.1z"
199
+ />
200
+ </>
201
+ ),
202
+ 5: (
203
+ <>
204
+ <path
205
+ fill="none"
206
+ stroke="currentColor"
207
+ strokeLinecap="round"
208
+ d="M116.3,6.8l-1.4,2L114.1,8l-0.6-0.7l0,0.9l-0.1,8.2h-6.8l-0.1-8.2
209
+ l0-0.9L105.9,8l-0.8,0.8l-1.4-2l2.6-2.9c0.1-0.1,0.2-0.1,0.3-0.1h1.3l0.4,0.7c0.7,1.3,2.6,1.3,3.3-0.1l0.3-0.6h1.2
210
+ c0.1,0,0.2,0,0.3,0.1l0.3-0.3l-0.3,0.3L116.3,6.8z"
211
+ />
212
+ <path
213
+ fill="none"
214
+ stroke="currentColor"
215
+ d="M110.1,7.7h2v0.9c0,0.4-0.4,0.7-1,0.7c-0.6,0-1-0.3-1-0.7L110.1,7.7L110.1,7.7z"
216
+ />
217
+ </>
218
+ ),
219
+ 6: (
220
+ <>
221
+ <path
222
+ fill="none"
223
+ stroke="currentColor"
224
+ d="M126.8,14.3c0,1.2-1,2.2-2.2,2.2s-2.2-1-2.2-2.2s1-2.2,2.2-2.2S126.8,13.1,126.8,14.3z"
225
+ />
226
+ <path
227
+ fill="none"
228
+ stroke="currentColor"
229
+ d="M137.6,14.3c0,1.2-1,2.2-2.2,2.2c-1.2,0-2.2-1-2.2-2.2s1-2.2,2.2-2.2
230
+ C136.6,12.1,137.6,13.1,137.6,14.3z"
231
+ />
232
+ <path fill="none" stroke="currentColor" d="M126.8,4.4v9.9" />
233
+ <path fill="none" stroke="currentColor" d="M137.7,4.4v9.9" />
234
+ <path
235
+ fill="none"
236
+ stroke="currentColor"
237
+ d="M126.8,3.5h10.8v2.7h-10.8C126.8,6.2,126.8,3.5,126.8,3.5z"
238
+ />
239
+ </>
240
+ ),
241
+ 7: (
242
+ <>
243
+ <path
244
+ fill="currentColor"
245
+ stroke="currentColor"
246
+ strokeWidth="0.25"
247
+ strokeMiterlimit="10"
248
+ d="M156,4.3c-0.2-0.1-0.4-0.1-0.5,0
249
+ c0,0-0.2,0.1-0.9,0.1c-0.7,0-2.4-0.1-3.8-0.6c-0.8-0.3-1.7-0.5-2.5-0.5c-0.2,0-0.4,0-0.5,0c-1.3,0-2.5,0.3-3.6,1
250
+ c-0.2,0.1-0.2,0.2-0.2,0.4v11.6c0,0.3,0.1,0.5,0.3,0.5c0.6,0,0.5-0.4,0.5-0.6v-5.7c0.7-0.3,3.2-1.1,5.8-0.1c1.6,0.6,3.5,0.7,4.3,0.7
251
+ c0.8,0,1.3-0.3,1.3-0.3c0.2-0.1,0.3-0.2,0.3-0.4V4.7C156.2,4.5,156.1,4.4,156,4.3z M155.6,10.2c-0.1,0-0.7,0.1-1,0.1
252
+ c-0.7,0-2.4-0.1-3.8-0.6c-2.5-1-5-0.5-6.2-0.1V4.7c0.9-0.5,2.2-0.7,3.2-0.7c0.1,0,0.3,0,0.4,0c0.7,0,1.5,0.2,2.2,0.4
253
+ c1.6,0.6,3.5,0.7,4.3,0.7c0.2,0,0.8,0,1-0.1V10.2z"
254
+ />
255
+ </>
256
+ ),
257
+ 8: (
258
+ <>
259
+ <path
260
+ fill="currentColor"
261
+ d="M170.8,3.1L170.8,3.1c-0.3,0-0.5,0-0.8,0c-2.1,0-4,1-5.3,2.5l-0.1,0l-0.1-0.1l-1-1.2l-0.3,3.4l3.4,0.3
262
+ l-1.1-1.3l-0.1-0.1l0.1-0.1c1.1-1.4,3-2.3,5-2.1l0,0c3.2,0.3,5.5,3.1,5.2,6.3c-0.3,3-3.1,5.3-6.1,5.1c-3.1-0.2-5.4-2.9-5.3-6
263
+ L163,9.5c-0.2,3.8,2.6,7.1,6.3,7.4c3.9,0.4,7.3-2.6,7.6-6.5C177.2,6.8,174.4,3.5,170.8,3.1z"
264
+ />
265
+ <path
266
+ fill="currentColor"
267
+ d="M170.3,7.4c0-0.3-0.3-0.6-0.6-0.6S169,7.1,169,7.4v3.2c0,0.2,0.1,0.3,0.2,0.4c0.1,0.1,0.3,0.2,0.4,0.2
268
+ h2.4c0.4,0,0.6-0.3,0.6-0.6s-0.3-0.6-0.6-0.6h-1.6h-0.2V9.8L170.3,7.4L170.3,7.4z"
269
+ />
270
+ </>
271
+ ),
272
+ 9: (
273
+ <>
274
+ <path
275
+ fill="none"
276
+ stroke="currentColor"
277
+ d="M186.2,3.4h7.7c1.5,0,2.7,1.2,2.7,2.7v7.7c0,1.5-1.2,2.7-2.7,2.7h-7.7
278
+ c-1.5,0-2.7-1.2-2.7-2.7V6.1C183.4,4.6,184.7,3.4,186.2,3.4z"
279
+ />
280
+ <ellipse fill="currentColor" cx="186" cy="8.9" rx="0.7" ry="0.7" />
281
+ <ellipse fill="currentColor" cx="194" cy="6.7" rx="0.7" ry="0.7" />
282
+ <path
283
+ fill="none"
284
+ stroke="currentColor"
285
+ strokeLinecap="round"
286
+ d="M186,13.3l0.4-0.3c0.4-0.3,1-0.3,1.5-0.1l1,0.4
287
+ c0.5,0.2,1,0.2,1.5-0.1l0.8-0.5c0.4-0.3,1-0.3,1.5-0.1l1.8,0.8"
288
+ />
289
+ </>
290
+ ),
291
+ };
292
+
293
+ export function CategoryNavIcon({ category }: { category: string }) {
294
+ const column = COLUMNS[category] ?? 0;
295
+ return (
296
+ <svg
297
+ viewBox={`${column * 20} 0 20 20`}
298
+ width="100%"
299
+ height="100%"
300
+ // Absolutely positioned over the button's padding box, matching the
301
+ // geometry of the former background-image sprite. Percentage sizes
302
+ // alone would resolve against the smaller content box (the button
303
+ // reset carries padding), shrinking the glyph.
304
+ style={{
305
+ display: 'block',
306
+ position: 'absolute',
307
+ top: 0,
308
+ left: 0,
309
+ width: '100%',
310
+ height: '100%',
311
+ }}
312
+ aria-hidden="true"
313
+ >
314
+ {SHAPES[column] ?? null}
315
+ </svg>
316
+ );
317
+ }
@@ -31,6 +31,17 @@ export function CategoryNavigation() {
31
31
  const CategoryNavigationRef = useCategoryNavigationRef();
32
32
  const hideCustomCategory = useShouldHideCustomEmojis();
33
33
 
34
+ const visibleCategories = categoriesConfig.filter(
35
+ categoryConfig =>
36
+ !(isCustomCategory(categoryConfig) && hideCustomCategory),
37
+ );
38
+
39
+ // A single tab navigates nowhere — hide the bar to reclaim its space.
40
+ // https://github.com/ealush/emoji-picker-react/issues/396
41
+ if (visibleCategories.length <= 1) {
42
+ return null;
43
+ }
44
+
34
45
  return (
35
46
  <div
36
47
  className={cx(styles.nav)}
@@ -39,14 +50,10 @@ export function CategoryNavigation() {
39
50
  id="epr-category-nav-id"
40
51
  ref={CategoryNavigationRef}
41
52
  >
42
- {categoriesConfig.map((categoryConfig) => {
53
+ {visibleCategories.map(categoryConfig => {
43
54
  const category = categoryFromCategoryConfig(categoryConfig);
44
55
  const isActiveCategory = category === activeCategory;
45
56
 
46
- if (isCustomCategory(categoryConfig) && hideCustomCategory) {
47
- return null;
48
- }
49
-
50
57
  const allowNavigation = !isSearchMode && !isActiveCategory;
51
58
 
52
59
  return (