@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/.mcp.json +8 -0
- package/README.md +297 -0
- package/data/code.ttl +437 -0
- package/data/css.ttl +265 -0
- package/data/icons.ttl +359 -0
- package/data/packaging.ttl +464 -0
- package/data/react.ttl +752 -0
- package/data/rust.ttl +1806 -0
- package/data/storybook.ttl +403 -0
- package/data/styling.ttl +165 -0
- package/data/tsdoc.ttl +216 -0
- package/data/turtle.ttl +179 -0
- package/definitions/CodeStandard.ttl +80 -0
- package/docs/code.md +720 -0
- package/docs/css.md +275 -0
- package/docs/icons.md +367 -0
- package/docs/index.md +15 -0
- package/docs/react.md +766 -0
- package/docs/rust.md +1784 -0
- package/docs/storybook.md +413 -0
- package/docs/styling.md +163 -0
- package/docs/tsdoc.md +213 -0
- package/docs/turtle.md +179 -0
- package/package.json +9 -0
- package/skills/add-standard/SKILL.md +288 -0
- package/src/scripts/generate-docs.ts +131 -0
- package/src/scripts/index.ts +19 -0
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
|
+
""" .
|