@canonical/code-standards 0.1.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/data/icons.ttl ADDED
@@ -0,0 +1,359 @@
1
+ @prefix cs: <http://pragma.canonical.com/codestandards#> .
2
+ @prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
3
+ @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
4
+ @prefix owl: <http://www.w3.org/2002/07/owl#> .
5
+ @prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
6
+
7
+ # Icons Category
8
+ cs:IconsCategory a cs:Category ;
9
+ rdfs:label "Icons"@en ;
10
+ rdfs:comment "Standards for icon development and implementation"@en ;
11
+ cs:slug "icons" .
12
+
13
+ # Icon File Storage Standard
14
+ cs:IconFileStorage a cs:CodeStandard ;
15
+ cs:name "icons/file/storage" ;
16
+ cs:hasCategory cs:IconsCategory ;
17
+ cs:description "Each icon shall be stored as a single SVG file in the `icons/` directory." ;
18
+ cs:dos """
19
+ (Do) Store each icon as an individual SVG file in the designated `icons/` directory.
20
+ ```
21
+ icons/
22
+ ├── warning.svg
23
+ ├── search.svg
24
+ └── github.svg
25
+ ```
26
+ """ ;
27
+ cs:donts """
28
+ (Don't) Store icons in nested directories or use incorrect file extensions.
29
+ ```
30
+ icons/
31
+ ├── variants/
32
+ │ └── warning-dark.svg
33
+ ├── warning/
34
+ │ └── index.svg
35
+ └── warning.svg.txt
36
+ ```
37
+
38
+ (Don't) Combine multiple icons into a single SVG file.
39
+ ```
40
+ icons/
41
+ └── all-icons.svg
42
+ ```
43
+ """ .
44
+
45
+ # Icon File Naming Standard
46
+ cs:IconFileNaming a cs:CodeStandard ;
47
+ cs:name "icons/file/naming" ;
48
+ cs:hasCategory cs:IconsCategory ;
49
+ cs:description """Icon files must:
50
+ - Use kebab-case naming
51
+ - Use semantic identifiers""" ;
52
+ cs:dos """
53
+ (Do) Use kebab-case and a semantic identifier for the icon file name.
54
+ ```
55
+ warning.svg
56
+ user-profile.svg
57
+ arrow-down.svg
58
+ ```
59
+ """ ;
60
+ cs:donts """
61
+ (Don't) Include size, theme, or redundant suffixes in the file name.
62
+ ```
63
+ warning-16.svg
64
+ warning-dark.svg
65
+ warning_icon.svg
66
+ WARNING.svg
67
+ ```
68
+
69
+ (Don't) Use non-semantic or ambiguous names that do not describe the icon.
70
+ ```
71
+ icon1.svg
72
+ shape.svg
73
+ ```
74
+ """ .
75
+
76
+ # Icon Group Element Standard
77
+ cs:IconGroupElement a cs:CodeStandard ;
78
+ cs:name "icons/svg/group-element" ;
79
+ cs:hasCategory cs:IconsCategory ;
80
+ cs:description "Each icon's SVG markup must contain a single `<g>` element with an `id` matching the filename (without `.svg`)." ;
81
+ cs:dos """
82
+ (Do) Include a single `<g>` element with an `id` that matches the filename.
83
+ ```svg
84
+ <!-- warning.svg -->
85
+ <svg>
86
+ <g id="warning">
87
+ <!-- icon paths -->
88
+ </g>
89
+ </svg>
90
+ ```
91
+ """ ;
92
+ cs:donts """
93
+ (Don't) Use multiple `<g>` elements or an `id` that does not match the filename.
94
+ ```svg
95
+ <!-- warning.svg -->
96
+ <svg>
97
+ <g id="icon-group">
98
+ <!-- icon paths -->
99
+ </g>
100
+ <g id="warning-alt">
101
+ <!-- alternate paths -->
102
+ </g>
103
+ </svg>
104
+ ```
105
+ """ .
106
+
107
+ # Icon ViewBox Standard
108
+ cs:IconViewBox a cs:CodeStandard ;
109
+ cs:name "icons/svg/viewbox" ;
110
+ cs:hasCategory cs:IconsCategory ;
111
+ cs:description "All icon SVGs must use a `viewBox` of `0 0 16 16`." ;
112
+ cs:dos """
113
+ (Do) Set the `viewBox` attribute to `0 0 16 16` in the `<svg>` element.
114
+ ```svg
115
+ <svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'>
116
+ <g id="icon">
117
+ <!-- Icon content scaled to 16x16 -->
118
+ </g>
119
+ </svg>
120
+ ```
121
+ """ ;
122
+ cs:donts """
123
+ (Don't) Use a `viewBox` with dimensions other than `16 16`.
124
+ ```svg
125
+ <!-- Bad: Different viewBox size -->
126
+ <svg viewBox="0 0 24 24">
127
+ <g id="icon">...</g>
128
+ </svg>
129
+ ```
130
+
131
+ (Don't) Use a non-square `viewBox`.
132
+ ```svg
133
+ <!-- Bad: Non-square viewBox -->
134
+ <svg viewBox="0 0 16 24">
135
+ <g id="icon">...</g>
136
+ </svg>
137
+ ```
138
+
139
+ (Don't) Omit the `viewBox` attribute.
140
+ ```svg
141
+ <!-- Bad: Missing viewBox -->
142
+ <svg width="16" height="16">
143
+ <g id="icon">...</g>
144
+ </svg>
145
+ ```
146
+ """ .
147
+
148
+ # Icon Color Usage Standard
149
+ cs:IconColorUsage a cs:CodeStandard ;
150
+ cs:name "icons/svg/color-usage" ;
151
+ cs:hasCategory cs:IconsCategory ;
152
+ cs:description "Icon must use `fill` with `currentColor` for their paths and shapes." ;
153
+ cs:dos """
154
+ (Do) Use `currentColor` for the `fill` of paths in non-branded icons.
155
+ ```svg
156
+ <!-- Non-branded icon -->
157
+ <svg viewBox="0 0 16 16">
158
+ <g id="search">
159
+ <path fill="currentColor" d="..." />
160
+ </g>
161
+ </svg>
162
+ ```
163
+ """ ;
164
+ cs:donts """
165
+ (Don't) Use hard-coded colors in icons.
166
+ ```svg
167
+ <path fill="#000000" d="..." />
168
+ ```
169
+
170
+ (Don't) Use `opacity` to create different shades of a color.
171
+ ```svg
172
+ <path fill="currentColor" opacity="0.5" d="..." />
173
+ ```
174
+ """ .
175
+
176
+ # Icon Variant Standard
177
+ cs:IconVariant a cs:CodeStandard ;
178
+ cs:name "icons/variant/single-file" ;
179
+ cs:hasCategory cs:IconsCategory ;
180
+ cs:description "Each icon concept must have exactly one SVG file. Size and theme variants are not allowed." ;
181
+ cs:dos """
182
+ (Do) Use a single SVG file for each icon and control its size and color with CSS.
183
+ ```svg
184
+ <!-- Single icon file -->
185
+ <svg viewBox="0 0 16 16">
186
+ <g id="warning">
187
+ <path fill="currentColor" d="..." />
188
+ </g>
189
+ </svg>
190
+ ```
191
+ ```css
192
+ /* CSS usage */
193
+ .small-icon { font-size: 1em; } /* 16px */
194
+ .large-icon { font-size: 2em; } /* 32px */
195
+ .warning-icon { color: var(--color-warning); }
196
+ ```
197
+ """ ;
198
+ cs:donts """
199
+ (Don't) Create multiple files for different icon sizes.
200
+ ```
201
+ warning.svg
202
+ warning-small.svg
203
+ warning-large.svg
204
+ ```
205
+
206
+ (Don't) Create multiple files for different themes.
207
+ ```
208
+ warning.svg
209
+ warning-dark.svg
210
+ warning-light.svg
211
+ ```
212
+ """ .
213
+
214
+ # Icon Type Safety Standard
215
+ cs:IconTypeSafety a cs:CodeStandard ;
216
+ cs:name "icons/type-safety/definition" ;
217
+ cs:hasCategory cs:IconsCategory ;
218
+ cs:description """Icon names must be:
219
+ - Maintained in a type-safe constant array
220
+ - Used to generate the `IconName` type
221
+ - Defined in the icon exporter package""" ;
222
+ cs:dos """
223
+ (Do) Define a constant array of icon names and derive the `IconName` type from it in the icon exporter package.
224
+ ```typescript
225
+ // In the icon exporter package
226
+ export const ICON_NAMES = [
227
+ "warning",
228
+ "search",
229
+ "github"
230
+ ] as const;
231
+
232
+ export type IconName = typeof ICON_NAMES[number];
233
+ ```
234
+
235
+ (Do) Import the `IconName` type in consumer code to ensure type safety.
236
+ ```typescript
237
+ // In consumer code
238
+ import type { IconName } from '@canonical/ds-assets';
239
+
240
+ export interface ComponentProps {
241
+ icon: IconName;
242
+ }
243
+ ```
244
+
245
+ (Do) Use `Pick` to restrict choices from `IconName` when necessary.
246
+
247
+ ```typescript
248
+ // In consumer code
249
+ import type { IconName } from '@canonical/ds-assets';
250
+
251
+ export interface ComponentProps {
252
+ icon: Pick<IconName, "warning" | "search">;
253
+ }
254
+ ```
255
+ """ ;
256
+ cs:donts """
257
+ (Don't) Define icon name types or values on the consumer side.
258
+ ```typescript
259
+ // Bad: String literal type defined in consumer code
260
+ type ComponentIconName = "warning" | "search";
261
+
262
+ export interface ComponentProps {
263
+ icon: ComponentIconName;
264
+ }
265
+ ```
266
+
267
+ (Don't) Use a generic `string` type for icon names.
268
+ ```typescript
269
+ // Bad: No type safety for icon names
270
+ export interface ComponentProps {
271
+ icon: string;
272
+ }
273
+ ```
274
+
275
+ (Don't) Maintain separate type and value definitions.
276
+ ```typescript
277
+ // Bad: Duplication of icon names
278
+ const ICONS = ["warning", "search"];
279
+ type IconName = "warning" | "search";
280
+ ```
281
+ """ .
282
+
283
+ # Icon Mask Usage Standard
284
+ cs:IconMaskUsage a cs:CodeStandard ;
285
+ cs:name "icons/svg/mask-usage" ;
286
+ cs:hasCategory cs:IconsCategory ;
287
+ cs:description "Icons may use SVG masks to negate or partially negate paths, enabling advanced visual effects such as cutouts and overlays." ;
288
+ cs:dos """
289
+ (Do) Use SVG <mask> elements to create negative space or overlays in icons.
290
+ Example:
291
+ ```svg
292
+ <svg width='16' height='16' xmlns='http://www.w3.org/2000/svg'>
293
+ <defs>
294
+ <mask id="error-mask">
295
+ <rect width="16" height="16" fill="white"/>
296
+ <path d="..." fill="black"/>
297
+ </mask>
298
+ </defs>
299
+ <g id="error">
300
+ <circle fill='currentColor' cx='8' cy='8' r='7' mask="url(#error-mask)"/>
301
+ </g>
302
+ </svg>
303
+ ```
304
+
305
+ (Do) Use <rect> with fill="white" to define the mask area, and <path> with fill="black" to subtract shapes.
306
+ Example:
307
+ ```svg
308
+ <mask id="mask">
309
+ <rect width="16" height="16" fill="white"/>
310
+ <path d="M4 4h8v8H4z" fill="black"/>
311
+ </mask>
312
+ ```
313
+
314
+ (Do) Use opacity on mask paths to achieve partial negation (e.g., faded or semi-transparent cutouts).
315
+ Example:
316
+ ```svg
317
+ <mask id="progress-mask">
318
+ <rect width="16" height="16" fill="white"/>
319
+ <path d='...' fill="black" opacity=".5"/>
320
+ </mask>
321
+ ```
322
+
323
+ (Do) Reference the mask in the icon's main shape using mask="url(#mask-id)".
324
+ Example:
325
+ ```svg
326
+ <circle fill='currentColor' cx='8' cy='8' r='7' mask="url(#mask-id)"/>
327
+ ```
328
+ """ ;
329
+ cs:donts """
330
+ (Don't) Use masks without clear purpose or visual benefit.
331
+ Example:
332
+ ```svg
333
+ <!-- Bad: Mask used but has no effect -->
334
+ <mask id="empty-mask">
335
+ <rect width="16" height="16" fill="white"/>
336
+ </mask>
337
+ <circle fill='currentColor' cx='8' cy='8' r='7' mask="url(#empty-mask)"/>
338
+ ```
339
+
340
+ (Don't) use non-semantic mask ids or omit mask references in the main shape.
341
+ Example:
342
+ ```svg
343
+ <!-- Bad: Non-semantic mask id -->
344
+ <mask id="123">
345
+ <rect width="16" height="16" fill="white"/>
346
+ <path d="..." fill="black"/>
347
+ </mask>
348
+ ```
349
+
350
+ (Don't) rely on masks for simple icons that do not require negative space or overlays.
351
+ Example:
352
+ ```svg
353
+ <!-- Bad: Mask used for a simple shape -->
354
+ <mask id="simple-mask">
355
+ <rect width="16" height="16" fill="white"/>
356
+ </mask>
357
+ <rect fill='currentColor' x='2' y='2' width='12' height='12' mask="url(#simple-mask)"/>
358
+ ```
359
+ """ .