@@ -31,11 +31,13 @@ import { SearchInput } from '../../packages/circuit-ui/components/SearchInput/Se
31
31
import { Select } from '../../packages/circuit-ui/components/Select/Select.js' ;
32
32
import { SelectorGroup } from '../../packages/circuit-ui/components/SelectorGroup/SelectorGroup.js' ;
33
33
import { Tooltip } from '../../packages/circuit-ui/components/Tooltip/Tooltip.js' ;
34
+ import { IconButton } from '../../packages/circuit-ui/components/Button/IconButton.js' ;
35
+ import { ToastProvider } from '../../packages/circuit-ui/components/ToastContext/ToastContext.js' ;
36
+ import { useNotificationToast } from '../../packages/circuit-ui/components/NotificationToast/NotificationToast.js' ;
34
37
import { clsx } from '../../packages/circuit-ui/styles/clsx.js' ;
35
38
import { utilClasses } from '../../packages/circuit-ui/styles/utility.js' ;
36
39
import { slugify } from '../slugify.js' ;
37
40
import classes from './Icons.module.css' ;
38
- import { IconButton } from '@sumup-oss/circuit-ui' ;
39
41
40
42
function groupBy (
41
43
icons : IconsManifest [ 'icons' ] ,
@@ -114,113 +116,144 @@ export function Icons() {
114
116
115
117
return (
116
118
< Unstyled >
117
- < fieldset className = { classes . filters } >
118
- < legend className = { utilClasses . hideVisually } > Icon filters</ legend >
119
- < SearchInput
120
- label = "Search by name or keyword"
121
- placeholder = "Search..."
122
- value = { search }
123
- onChange = { handleChange ( setSearch ) }
124
- onClear = { ( ) => setSearch ( '' ) }
125
- clearLabel = "Clear"
126
- />
127
- < Select
128
- label = "Size"
129
- options = { sizeOptions }
130
- value = { size }
131
- onChange = { handleChange ( setSize ) }
132
- />
133
- < Select
134
- label = "Color"
135
- options = { colorOptions }
136
- value = { color }
137
- onChange = { handleChange ( setColor ) }
119
+ < ToastProvider >
120
+ < fieldset className = { classes . filters } >
121
+ < legend className = { utilClasses . hideVisually } > Icon filters</ legend >
122
+ < SearchInput
123
+ label = "Search by name or keyword"
124
+ placeholder = "Search..."
125
+ value = { search }
126
+ onChange = { handleChange ( setSearch ) }
127
+ onClear = { ( ) => setSearch ( '' ) }
128
+ clearLabel = "Clear"
129
+ />
130
+ < Select
131
+ label = "Size"
132
+ options = { sizeOptions }
133
+ value = { size }
134
+ onChange = { handleChange ( setSize ) }
135
+ />
136
+ < Select
137
+ label = "Color"
138
+ options = { colorOptions }
139
+ value = { color }
140
+ onChange = { handleChange ( setColor ) }
141
+ />
142
+ < SelectorGroup
143
+ label = "Scale"
144
+ options = { scaleOptions }
145
+ value = { scale }
146
+ onChange = { handleChange ( setScale ) }
147
+ />
148
+ </ fieldset >
149
+
150
+ { activeIcons . length <= 0 ? (
151
+ < Body > No icons found</ Body >
152
+ ) : (
153
+ Object . entries < IconsManifest [ 'icons' ] > (
154
+ groupBy ( activeIcons , 'category' ) ,
155
+ ) . map ( ( [ category , items ] ) => (
156
+ < section key = { category } className = { classes . category } >
157
+ < Headline as = "h2" size = "m" id = { slugify ( category ) } >
158
+ { category }
159
+ </ Headline >
160
+ < div className = { classes . list } >
161
+ { sortBy ( items , 'name' ) . map ( ( icon ) => (
162
+ < Icon
163
+ key = { `${ icon . name } -${ icon . size } ` }
164
+ icon = { icon }
165
+ scale = { scale }
166
+ color = { color }
167
+ />
168
+ ) ) }
169
+ </ div >
170
+ </ section >
171
+ ) )
172
+ ) }
173
+ </ ToastProvider >
174
+ </ Unstyled >
175
+ ) ;
176
+ }
177
+
178
+ function Icon ( {
179
+ icon,
180
+ scale,
181
+ color,
182
+ } : { icon : IconsManifest [ 'icons' ] [ number ] ; scale : string ; color : string } ) {
183
+ const { setToast } = useNotificationToast ( ) ;
184
+
185
+ const id = `${ icon . name } -${ icon . size } ` ;
186
+ const componentName = getComponentName (
187
+ icon . name ,
188
+ ) as keyof typeof iconComponents ;
189
+ const Icon = iconComponents [ componentName ] as IconComponentType ;
190
+
191
+ const copyIconURL = ( ) => {
192
+ const iconURL = `https://circuit.sumup.com/icons/v2/${ icon . name } _${ icon . size } .svg` ;
193
+ navigator . clipboard
194
+ . writeText ( iconURL )
195
+ . then ( ( ) => {
196
+ setToast ( {
197
+ variant : 'success' ,
198
+ body : `Copied the ${ componentName } (${ icon . size } ) icon URL to the clipboard.` ,
199
+ } ) ;
200
+ } )
201
+ . catch ( ( error ) => {
202
+ console . error ( error ) ;
203
+ setToast ( {
204
+ variant : 'danger' ,
205
+ body : `Failed to copy the ${ componentName } (${ icon . size } ) icon URL to the clipboard.` ,
206
+ } ) ;
207
+ } ) ;
208
+ } ;
209
+
210
+ return (
211
+ < div className = { classes . wrapper } >
212
+ < div className = { clsx ( classes [ 'icon-wrapper' ] , classes [ scale ] ) } >
213
+ < Icon
214
+ aria-labelledby = { id }
215
+ size = { icon . size }
216
+ className = { classes . icon }
217
+ style = { {
218
+ color,
219
+ backgroundColor :
220
+ color === 'var(--cui-fg-on-strong)'
221
+ ? 'var(--cui-bg-strong)'
222
+ : 'var(--cui-bg-normal)' ,
223
+ } }
138
224
/>
139
- < SelectorGroup
140
- label = "Scale"
141
- options = { scaleOptions }
142
- value = { scale }
143
- onChange = { handleChange ( setScale ) }
225
+ </ div >
226
+ < span id = { id } className = { classes . label } >
227
+ { componentName }
228
+ < span className = { classes . size } > { icon . size } </ span >
229
+ </ span >
230
+ { icon . deprecation && (
231
+ < Tooltip
232
+ type = "description"
233
+ label = { icon . deprecation }
234
+ component = { ( props ) => (
235
+ < Badge
236
+ { ...props }
237
+ tabIndex = { 0 }
238
+ variant = "warning"
239
+ className = { classes . badge }
240
+ >
241
+ Deprecated
242
+ </ Badge >
243
+ ) }
144
244
/>
145
- </ fieldset >
146
-
147
- { activeIcons . length <= 0 ? (
148
- < Body > No icons found</ Body >
149
- ) : (
150
- Object . entries < IconsManifest [ 'icons' ] > (
151
- groupBy ( activeIcons , 'category' ) ,
152
- ) . map ( ( [ category , items ] ) => (
153
- < section key = { category } className = { classes . category } >
154
- < Headline as = "h2" size = "m" id = { slugify ( category ) } >
155
- { category }
156
- </ Headline >
157
- < div className = { classes . list } >
158
- { sortBy ( items , 'name' ) . map ( ( icon ) => {
159
- const id = `${ icon . name } -${ icon . size } ` ;
160
- const componentName = getComponentName (
161
- icon . name ,
162
- ) as keyof typeof iconComponents ;
163
- const Icon = iconComponents [ componentName ] as IconComponentType ;
164
- const copyIconURL = ( ) => {
165
- const iconURL = `https://circuit.sumup.com/icons/v2/${ icon . name } _${ icon . size } .svg` ;
166
- navigator . clipboard . writeText ( iconURL ) ;
167
- } ;
168
- return (
169
- < div key = { id } className = { classes . wrapper } >
170
- < div
171
- className = { clsx ( classes [ 'icon-wrapper' ] , classes [ scale ] ) }
172
- >
173
- < Icon
174
- aria-labelledby = { id }
175
- size = { icon . size }
176
- className = { classes . icon }
177
- style = { {
178
- color,
179
- backgroundColor :
180
- color === 'var(--cui-fg-on-strong)'
181
- ? 'var(--cui-bg-strong)'
182
- : 'var(--cui-bg-normal)' ,
183
- } }
184
- />
185
- </ div >
186
- < span id = { id } className = { classes . label } >
187
- { componentName }
188
- < span className = { classes . size } > { icon . size } </ span >
189
- </ span >
190
- { icon . deprecation && (
191
- < Tooltip
192
- type = "description"
193
- label = { icon . deprecation }
194
- component = { ( props ) => (
195
- < Badge
196
- { ...props }
197
- tabIndex = { 0 }
198
- variant = "warning"
199
- className = { classes . badge }
200
- >
201
- Deprecated
202
- </ Badge >
203
- ) }
204
- />
205
- ) }
206
- { navigator . clipboard && (
207
- < IconButton
208
- variant = "tertiary"
209
- size = "s"
210
- icon = { iconComponents . Link }
211
- className = { classes . copy }
212
- onClick = { copyIconURL }
213
- >
214
- Copy URL
215
- </ IconButton >
216
- ) }
217
- </ div >
218
- ) ;
219
- } ) }
220
- </ div >
221
- </ section >
222
- ) )
223
245
) }
224
- </ Unstyled >
246
+ { navigator . clipboard && (
247
+ < IconButton
248
+ variant = "tertiary"
249
+ size = "s"
250
+ icon = { iconComponents . Link }
251
+ className = { classes . copy }
252
+ onClick = { copyIconURL }
253
+ >
254
+ Copy URL
255
+ </ IconButton >
256
+ ) }
257
+ </ div >
225
258
) ;
226
259
}
0 commit comments