@inkbar/theme 0.4.0 → 0.5.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.
Files changed (3) hide show
  1. package/README.md +7 -8
  2. package/package.json +1 -1
  3. package/theme.css +154 -72
package/README.md CHANGED
@@ -20,7 +20,7 @@
20
20
 
21
21
  ---
22
22
 
23
- `@inkbar/theme` styles the viewer, toolbar controls, note threads and suggestion cards from `@inkbar/vue`, `@inkbar/react`, `@inkbar/svelte` and `createViewer` in `@inkbar/core`. Import it and ship, or override any part of it with your own CSS. If your app already defines shadcn tokens, the theme picks up your colours and radius.
23
+ `@inkbar/theme` styles the viewer, toolbar controls and note threads from `@inkbar/vue`, `@inkbar/react`, `@inkbar/svelte` and `createViewer` in `@inkbar/core`. Import it and ship, or override any part of it with your own CSS. If your app already defines shadcn tokens, the theme picks up your colours and radius.
24
24
 
25
25
  ## Install
26
26
 
@@ -60,13 +60,12 @@ Colour tokens must hold complete CSS colour values. Tokens written as bare HSL c
60
60
 
61
61
  Set these variables on `[data-ink-root]` to change the default colour for new annotations:
62
62
 
63
- | Variable | Used for |
64
- | -------------------------------------------------------------------------- | ----------------------------------- |
65
- | `--ink-highlight`, `--ink-underline`, `--ink-strikeout`, `--ink-squiggly` | Text markup |
66
- | `--ink-note`, `--ink-free-text` | Notes and text boxes |
67
- | `--ink-shape`, `--ink-ink` | Shapes and freehand drawing |
68
- | `--ink-redact`, `--ink-redact-fill` | Redaction outline and fill |
69
- | `--ink-suggestion-low`, `--ink-suggestion-medium`, `--ink-suggestion-high` | Suggested redactions, by confidence |
63
+ | Variable | Used for |
64
+ | ------------------------------------------------------------------------- | --------------------------- |
65
+ | `--ink-highlight`, `--ink-underline`, `--ink-strikeout`, `--ink-squiggly` | Text markup |
66
+ | `--ink-note`, `--ink-free-text` | Notes and text boxes |
67
+ | `--ink-shape`, `--ink-ink` | Shapes and freehand drawing |
68
+ | `--ink-redact`, `--ink-redact-fill` | Redaction outline and fill |
70
69
 
71
70
  Inkbar reads a colour when you create the annotation and stores it on the annotation, because the colour goes into the PDF. Changing a variable later affects new annotations only.
72
71
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inkbar/theme",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Default stylesheet for Inkbar. Zero specificity, so your CSS wins.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://inkbar.dev",
package/theme.css CHANGED
@@ -15,7 +15,7 @@
15
15
  :where(
16
16
  [data-ink-root],
17
17
  [data-ink-thread-popover],
18
- [data-ink-suggestion-card],
18
+ [data-ink-popover],
19
19
  [data-ink-select-content],
20
20
  [data-ink-signature-dialog]
21
21
  ) {
@@ -29,9 +29,6 @@
29
29
  --ink-ink: #151820;
30
30
  --ink-redact: #c0392b;
31
31
  --ink-redact-fill: #000000;
32
- --ink-suggestion-low: #d4a017;
33
- --ink-suggestion-medium: #e67e22;
34
- --ink-suggestion-high: #c0392b;
35
32
 
36
33
  --ink-bg: var(--muted, #f1f2f5);
37
34
  --ink-fg: var(--foreground, #151820);
@@ -52,7 +49,7 @@
52
49
  :where(
53
50
  [data-ink-root]:not(.light, .light *),
54
51
  [data-ink-thread-popover]:not(.light *),
55
- [data-ink-suggestion-card]:not(.light *),
52
+ [data-ink-popover]:not(.light *),
56
53
  [data-ink-select-content]:not(.light *),
57
54
  [data-ink-signature-dialog]:not(.light *)
58
55
  ) {
@@ -73,7 +70,7 @@
73
70
  .dark [data-ink-root]:not(.light, .dark .light *),
74
71
  [data-ink-root].dark,
75
72
  .dark [data-ink-thread-popover]:not(.dark .light *),
76
- .dark [data-ink-suggestion-card]:not(.dark .light *),
73
+ .dark [data-ink-popover]:not(.dark .light *),
77
74
  .dark [data-ink-select-content]:not(.dark .light *),
78
75
  .dark [data-ink-signature-dialog]:not(.dark .light *)
79
76
  ) {
@@ -244,10 +241,11 @@
244
241
  background: transparent;
245
242
  }
246
243
 
247
- /* Tools: the active tool's cursor is set on the root; text spans follow it unless text is the target. */
244
+ /* Tools: the active tool's cursor is set on the root; page text follows it, except under
245
+ select text, where text is the target. */
248
246
  :where(
249
- [data-ink-tool='redact-area'] .ink-text-layer span,
250
- [data-ink-tool='note'] .ink-text-layer span
247
+ [data-ink-tool]:not([data-ink-tool='select-text']) .ink-text-layer span,
248
+ [data-ink-tool]:not([data-ink-tool='select-text']) .ink-text-layer br
251
249
  ) {
252
250
  cursor: inherit;
253
251
  }
@@ -280,7 +278,8 @@
280
278
  fill: none;
281
279
  }
282
280
 
283
- /* Edit handles on a selected annotation: shown with the select tools only. */
281
+ /* Edit handles on a selected annotation: shown with the select tools, and on what a creation
282
+ tool just made (`data-ink-made`). */
284
283
  :where(.ink-handle) {
285
284
  box-sizing: border-box;
286
285
  border: 1px solid var(--ink-accent);
@@ -289,7 +288,11 @@
289
288
  }
290
289
 
291
290
  :where(
292
- [data-ink-tool]:not([data-ink-tool='select'], [data-ink-tool='select-text'])
291
+ [data-ink-tool]:not(
292
+ [data-ink-tool='select'],
293
+ [data-ink-tool='select-text'],
294
+ [data-ink-made]
295
+ )
293
296
  .ink-handle
294
297
  ) {
295
298
  display: none;
@@ -303,9 +306,16 @@
303
306
  cursor: nesw-resize;
304
307
  }
305
308
 
309
+ :where(
310
+ .ink-handle[data-handle='start'],
311
+ .ink-handle[data-handle='end'],
312
+ .ink-handle[data-handle='callout']
313
+ ) {
314
+ cursor: crosshair;
315
+ }
316
+
306
317
  :where(.ink-handle[data-handle='start'], .ink-handle[data-handle='end']) {
307
318
  border-radius: 50%;
308
- cursor: move;
309
319
  }
310
320
 
311
321
  /* Annotations */
@@ -319,17 +329,56 @@
319
329
  outline-offset: 1px;
320
330
  }
321
331
 
332
+ /* An annotation's SVGs (its shape, and a text box's edge band over the text) cover its box. */
322
333
  :where(.ink-annotation:not([data-custom]) > svg) {
323
334
  position: absolute;
324
335
  left: 0;
325
336
  top: 0;
326
337
  }
327
338
 
339
+ /* Cursors say what a press will do: move an annotation, edit a text box's text, or (text
340
+ markup under select text) select text. Under rectangle select a press on text markup
341
+ selects and drags it, so it shows move there. The creation tools' cursor shows through
342
+ elsewhere. */
328
343
  :where(
329
344
  [data-ink-tool='select'] .ink-annotation,
330
- [data-ink-tool='select-text'] .ink-annotation
345
+ [data-ink-tool='select-text'] .ink-annotation,
346
+ [data-ink-made] .ink-annotation[data-state='selected']
331
347
  ) {
332
- cursor: pointer;
348
+ cursor: move;
349
+ }
350
+
351
+ :where(
352
+ [data-ink-tool='select-text']
353
+ .ink-annotation:is(
354
+ [data-type='highlight'],
355
+ [data-type='underline'],
356
+ [data-type='strikeout'],
357
+ [data-type='squiggly']
358
+ )
359
+ ) {
360
+ cursor: text;
361
+ }
362
+
363
+ :where(
364
+ [data-ink-tool='select'] .ink-annotation:not([data-locked]) .ink-free-text,
365
+ [data-ink-tool='select-text'] .ink-annotation:not([data-locked]) .ink-free-text,
366
+ [data-ink-made]
367
+ .ink-annotation[data-state='selected']:not([data-locked])
368
+ .ink-free-text
369
+ ) {
370
+ cursor: text;
371
+ }
372
+
373
+ /* The band along a text box's edge presses to move it, not to edit. */
374
+ :where(
375
+ [data-ink-tool='select'] .ink-annotation:not([data-locked]) [data-ink-edge],
376
+ [data-ink-tool='select-text'] .ink-annotation:not([data-locked]) [data-ink-edge],
377
+ [data-ink-made]
378
+ .ink-annotation[data-state='selected']:not([data-locked])
379
+ [data-ink-edge]
380
+ ) {
381
+ cursor: move;
333
382
  }
334
383
 
335
384
  :where(.ink-annotation[data-state='hover']) {
@@ -345,6 +394,13 @@
345
394
  cursor: default;
346
395
  }
347
396
 
397
+ /* While an annotation is moved the whole viewport shows it, over any element's own cursor.
398
+ The one rule here that is not zero specificity: it has to beat them. */
399
+ [data-ink-dragging],
400
+ [data-ink-dragging] * {
401
+ cursor: move !important;
402
+ }
403
+
348
404
  :where(.ink-annotation[data-locked][data-state='selected']) {
349
405
  outline-style: dotted;
350
406
  }
@@ -379,10 +435,6 @@
379
435
  outline-style: dotted;
380
436
  }
381
437
 
382
- :where(.ink-annotation[data-origin='suggested'] .ink-annotation-shape > *) {
383
- stroke-dasharray: 4 3;
384
- }
385
-
386
438
  :where(.ink-note-icon) {
387
439
  position: absolute;
388
440
  left: 0;
@@ -870,16 +922,48 @@
870
922
  border-color: var(--ink-border);
871
923
  }
872
924
 
873
- /* Shape menu: a split button, the tool part beside a narrow chevron. */
925
+ /*
926
+ * Split buttons (shape, highlight, signature): one control with two parts, the tool button
927
+ * beside a narrow chevron. Hovering either part tints the whole control and the part under
928
+ * the pointer a shade more; with the tool on, both parts take the accent. Plain sibling
929
+ * selectors, not :has(), which costs frames on long documents.
930
+ */
874
931
  :where(.ink-split-button) {
875
932
  display: inline-flex;
876
933
  align-items: stretch;
934
+ border-radius: calc(var(--ink-radius) - 2px);
877
935
  }
878
936
 
879
- :where(.ink-split-button .ink-menu-trigger) {
937
+ :where(.ink-split-button > .ink-tool-button) {
938
+ border-start-end-radius: 0;
939
+ border-end-end-radius: 0;
940
+ }
941
+
942
+ :where(.ink-split-button > .ink-menu-trigger) {
880
943
  min-width: 0;
881
944
  width: 1.25rem;
882
945
  padding-inline: 0.125rem;
946
+ border-start-start-radius: 0;
947
+ border-end-start-radius: 0;
948
+ }
949
+
950
+ :where(.ink-split-button:hover) {
951
+ background: color-mix(in srgb, var(--ink-fg) 8%, transparent);
952
+ }
953
+
954
+ /* The tool button's on state already takes the accent; the chevron beside it follows. */
955
+ :where(.ink-split-button > .ink-tool-button[data-state='on'] + .ink-menu-trigger) {
956
+ background: var(--ink-accent);
957
+ color: var(--ink-accent-fg);
958
+ /* The line between the parts, only while the accent fills both. */
959
+ box-shadow: inset 1px 0 color-mix(in srgb, var(--ink-accent-fg) 35%, transparent);
960
+ }
961
+
962
+ :where(
963
+ .ink-split-button > .ink-tool-button[data-state='on']:hover,
964
+ .ink-split-button > .ink-tool-button[data-state='on'] + .ink-menu-trigger:hover
965
+ ) {
966
+ background: color-mix(in srgb, var(--ink-accent-fg) 16%, var(--ink-accent));
883
967
  }
884
968
 
885
969
  :where(.ink-shape-grid) {
@@ -910,12 +994,54 @@
910
994
  padding-right: 0.5rem;
911
995
  }
912
996
 
997
+ /*
998
+ * The colour row reads as one more item: the swatch sits in the icon column and "Colour" in
999
+ * the label column. The colour menu's trigger covers the whole row, so the row is the target;
1000
+ * the label shows through it.
1001
+ */
913
1002
  :where(.ink-highlight-colour) {
1003
+ position: relative;
914
1004
  display: flex;
915
1005
  align-items: center;
916
- justify-content: space-between;
917
- gap: 0.5rem;
918
- padding: 0.25rem 0.25rem 0.25rem 0.5rem;
1006
+ padding: 0.25rem;
1007
+ }
1008
+
1009
+ :where(.ink-highlight-colour-label) {
1010
+ padding: 0.375rem 0.5rem 0.375rem 2rem;
1011
+ }
1012
+
1013
+ :where(.ink-highlight-colour > .ink-menu-trigger) {
1014
+ position: absolute;
1015
+ inset: 0.25rem;
1016
+ display: flex;
1017
+ align-items: center;
1018
+ justify-content: flex-start;
1019
+ width: auto;
1020
+ min-width: 0;
1021
+ height: auto;
1022
+ padding: 0 0.5rem;
1023
+ border: 0;
1024
+ border-radius: calc(var(--ink-radius) - 4px);
1025
+ background: transparent;
1026
+ }
1027
+
1028
+ :where(
1029
+ .ink-highlight-colour > .ink-menu-trigger:hover,
1030
+ .ink-highlight-colour > .ink-menu-trigger:focus-visible,
1031
+ .ink-highlight-colour > .ink-menu-trigger[data-state='open']
1032
+ ) {
1033
+ background: color-mix(in srgb, var(--ink-fg) 8%, transparent);
1034
+ }
1035
+
1036
+ /* A markup colour is a fill, so its swatch is a disc, not the border ring. */
1037
+ :where(.ink-highlight-colour .ink-swatch) {
1038
+ width: 1rem;
1039
+ height: 1rem;
1040
+ }
1041
+
1042
+ :where(.ink-highlight-colour .ink-swatch[data-kind='color']) {
1043
+ border: 1px solid color-mix(in srgb, var(--ink-fg) 20%, transparent);
1044
+ background: var(--ink-swatch);
919
1045
  }
920
1046
 
921
1047
  /* Stamps: an image filling its box; the overlay sets its geometry and opacity. */
@@ -1159,8 +1285,8 @@
1159
1285
  outline-offset: 2px;
1160
1286
  }
1161
1287
 
1162
- /* Comment threads and suggestion cards */
1163
- :where(.ink-thread-popover, .ink-suggestion-card) {
1288
+ /* Comment threads */
1289
+ :where(.ink-thread-popover) {
1164
1290
  z-index: 50;
1165
1291
  width: 20rem;
1166
1292
  max-width: calc(100vw - 1rem);
@@ -1216,13 +1342,13 @@
1216
1342
  resize: vertical;
1217
1343
  }
1218
1344
 
1219
- :where(.ink-thread-actions, .ink-suggestion-actions) {
1345
+ :where(.ink-thread-actions) {
1220
1346
  display: flex;
1221
1347
  gap: 0.375rem;
1222
1348
  margin-top: 0.5rem;
1223
1349
  }
1224
1350
 
1225
- :where(.ink-thread-actions button, .ink-suggestion-actions button) {
1351
+ :where(.ink-thread-actions button) {
1226
1352
  padding: 0.375rem 0.75rem;
1227
1353
  border: 1px solid var(--ink-border);
1228
1354
  border-radius: calc(var(--ink-radius) - 2px);
@@ -1232,10 +1358,7 @@
1232
1358
  cursor: pointer;
1233
1359
  }
1234
1360
 
1235
- :where(
1236
- .ink-thread-actions button[type='submit'],
1237
- .ink-suggestion-actions button:first-child
1238
- ) {
1361
+ :where(.ink-thread-actions button[type='submit']) {
1239
1362
  border-color: var(--ink-accent);
1240
1363
  background: var(--ink-accent);
1241
1364
  color: var(--ink-accent-fg);
@@ -1256,53 +1379,12 @@
1256
1379
  .ink-select-trigger:focus-visible,
1257
1380
  .ink-toolbar input:focus-visible,
1258
1381
  .ink-thread-actions button:focus-visible,
1259
- .ink-suggestion-actions button:focus-visible,
1260
1382
  .ink-thread-reply textarea:focus-visible
1261
1383
  ) {
1262
1384
  outline: 2px solid var(--ink-ring);
1263
1385
  outline-offset: 2px;
1264
1386
  }
1265
1387
 
1266
- :where(.ink-suggestion-reason, .ink-suggestion-explanation) {
1267
- margin: 0;
1268
- }
1269
-
1270
- :where(.ink-suggestion-explanation) {
1271
- margin-top: 0.25rem;
1272
- color: var(--ink-muted-fg);
1273
- }
1274
-
1275
- /* The label text keeps the body colour for contrast; the confidence colour is a swatch. */
1276
- :where(.ink-suggestion-confidence) {
1277
- display: inline-flex;
1278
- align-items: center;
1279
- gap: 0.375rem;
1280
- margin-left: 0.5rem;
1281
- color: var(--ink-fg);
1282
- font-size: 0.75rem;
1283
- text-transform: capitalize;
1284
- }
1285
-
1286
- :where(.ink-suggestion-confidence)::before {
1287
- content: '';
1288
- width: 0.5rem;
1289
- height: 0.5rem;
1290
- border-radius: 50%;
1291
- background: currentColor;
1292
- }
1293
-
1294
- :where(.ink-suggestion-confidence[data-confidence='low'])::before {
1295
- background: var(--ink-suggestion-low);
1296
- }
1297
-
1298
- :where(.ink-suggestion-confidence[data-confidence='medium'])::before {
1299
- background: var(--ink-suggestion-medium);
1300
- }
1301
-
1302
- :where(.ink-suggestion-confidence[data-confidence='high'])::before {
1303
- background: var(--ink-suggestion-high);
1304
- }
1305
-
1306
1388
  @media (prefers-reduced-motion: no-preference) {
1307
1389
  :where(.ink-annotation) {
1308
1390
  transition: outline-color 120ms ease;