@inkbar/theme 0.8.0 → 0.10.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/README.md +15 -0
- package/package.json +1 -1
- package/theme.css +693 -19
package/README.md
CHANGED
|
@@ -83,6 +83,21 @@ The theme gives a toolbar a background and padding and styles the controls in it
|
|
|
83
83
|
}
|
|
84
84
|
```
|
|
85
85
|
|
|
86
|
+
## Your own controls
|
|
87
|
+
|
|
88
|
+
Two classes give your own controls the look of the built-in ones. Add `ink-select` to a `<select>` to give it the zoom select's box and chevron. To put an icon in a field, wrap the input in `ink-input-group` and add an `ink-input-accessory` before it for an icon at the start, or after it for one at the end. The icon lets clicks through to the field, and the input makes room for it. The find bar and the search results field use this for their search icon.
|
|
89
|
+
|
|
90
|
+
```html
|
|
91
|
+
<select class="ink-select">
|
|
92
|
+
…
|
|
93
|
+
</select>
|
|
94
|
+
|
|
95
|
+
<div class="ink-input-group">
|
|
96
|
+
<span class="ink-input-accessory"><svg aria-hidden="true">…</svg></span>
|
|
97
|
+
<input type="text" aria-label="Filter notes" />
|
|
98
|
+
</div>
|
|
99
|
+
```
|
|
100
|
+
|
|
86
101
|
## Licence
|
|
87
102
|
|
|
88
103
|
[MIT](https://github.com/inkbar/inkbar/blob/main/LICENSE). From the team behind [Redactr](https://redactr.io).
|
package/package.json
CHANGED
package/theme.css
CHANGED
|
@@ -11,9 +11,13 @@
|
|
|
11
11
|
* new annotations only.
|
|
12
12
|
*/
|
|
13
13
|
@layer inkbar {
|
|
14
|
-
/*
|
|
14
|
+
/*
|
|
15
|
+
* Tokens. Popovers are portalled out of the root, and a sidebar may sit outside it, so they
|
|
16
|
+
* carry the tokens too.
|
|
17
|
+
*/
|
|
15
18
|
:where(
|
|
16
19
|
[data-ink-root],
|
|
20
|
+
[data-ink-sidebar],
|
|
17
21
|
[data-ink-thread-popover],
|
|
18
22
|
[data-ink-popover],
|
|
19
23
|
[data-ink-select-content],
|
|
@@ -33,6 +37,12 @@
|
|
|
33
37
|
/* Pages stay white in dark mode and the search layer multiplies, so these serve both. */
|
|
34
38
|
--ink-search-hit: #f1ffa0;
|
|
35
39
|
--ink-search-current: #e4ff4a;
|
|
40
|
+
/* The selected record's mark; pages stay white in dark mode, so this serves both. */
|
|
41
|
+
--ink-mark-selected-outline: 2px solid #2740f5;
|
|
42
|
+
/* Sidebars (createSidebar and the bindings' sidebar): the open sidebar and its rail. */
|
|
43
|
+
--ink-sidebar-width: 280px;
|
|
44
|
+
--ink-sidebar-rail-width: 48px;
|
|
45
|
+
--ink-thumbnail-width: 120px;
|
|
36
46
|
|
|
37
47
|
--ink-bg: var(--muted, #f1f2f5);
|
|
38
48
|
--ink-fg: var(--foreground, #151820);
|
|
@@ -44,6 +54,8 @@
|
|
|
44
54
|
--ink-ring: var(--ring, #2b5a9e);
|
|
45
55
|
--ink-radius: var(--radius, 0.5rem);
|
|
46
56
|
--ink-page-shadow: 0 1px 3px rgb(0 0 0 / 0.2);
|
|
57
|
+
/* Thumbnails are small, so the page shadow reads heavy on them: a hairline edge and a soft lift. */
|
|
58
|
+
--ink-thumbnail-shadow: 0 0 0 1px rgb(0 0 0 / 0.05), 0 1px 2px rgb(0 0 0 / 0.08);
|
|
47
59
|
--ink-text-selection: color-mix(in srgb, AccentColor, transparent 50%);
|
|
48
60
|
/* Form fields sit on the white page, in light and dark alike. */
|
|
49
61
|
--ink-form-field-bg: rgb(43 90 158 / 0.12);
|
|
@@ -56,6 +68,7 @@
|
|
|
56
68
|
@media (prefers-color-scheme: dark) {
|
|
57
69
|
:where(
|
|
58
70
|
[data-ink-root]:not(.light, .light *),
|
|
71
|
+
[data-ink-sidebar]:not(.light, .light *),
|
|
59
72
|
[data-ink-thread-popover]:not(.light *),
|
|
60
73
|
[data-ink-popover]:not(.light *),
|
|
61
74
|
[data-ink-select-content]:not(.light *),
|
|
@@ -71,6 +84,7 @@
|
|
|
71
84
|
--ink-accent-fg: var(--primary-foreground, #151820);
|
|
72
85
|
--ink-ring: var(--ring, #7aa5e6);
|
|
73
86
|
--ink-page-shadow: 0 1px 3px rgb(0 0 0 / 0.6);
|
|
87
|
+
--ink-thumbnail-shadow: 0 1px 2px rgb(0 0 0 / 0.3);
|
|
74
88
|
--ink-form-field-bg: rgb(43 90 158 / 0.16);
|
|
75
89
|
--ink-form-field-focus: #3d73c4;
|
|
76
90
|
--ink-form-field-invalid: #c0392b;
|
|
@@ -81,6 +95,8 @@
|
|
|
81
95
|
:where(
|
|
82
96
|
.dark [data-ink-root]:not(.light, .dark .light *),
|
|
83
97
|
[data-ink-root].dark,
|
|
98
|
+
.dark [data-ink-sidebar]:not(.light, .dark .light *),
|
|
99
|
+
[data-ink-sidebar].dark,
|
|
84
100
|
.dark [data-ink-thread-popover]:not(.dark .light *),
|
|
85
101
|
.dark [data-ink-popover]:not(.dark .light *),
|
|
86
102
|
.dark [data-ink-select-content]:not(.dark .light *),
|
|
@@ -96,6 +112,7 @@
|
|
|
96
112
|
--ink-accent-fg: var(--primary-foreground, #151820);
|
|
97
113
|
--ink-ring: var(--ring, #7aa5e6);
|
|
98
114
|
--ink-page-shadow: 0 1px 3px rgb(0 0 0 / 0.6);
|
|
115
|
+
--ink-thumbnail-shadow: 0 1px 2px rgb(0 0 0 / 0.3);
|
|
99
116
|
--ink-form-field-bg: rgb(43 90 158 / 0.16);
|
|
100
117
|
--ink-form-field-focus: #3d73c4;
|
|
101
118
|
--ink-form-field-invalid: #c0392b;
|
|
@@ -367,6 +384,11 @@
|
|
|
367
384
|
pointer-events: auto;
|
|
368
385
|
}
|
|
369
386
|
|
|
387
|
+
/* The mark of the record selected in a list, the page or the host app. */
|
|
388
|
+
:where(.ink-plugin-layer > button[data-selected]) {
|
|
389
|
+
outline: var(--ink-mark-selected-outline);
|
|
390
|
+
}
|
|
391
|
+
|
|
370
392
|
/* Form fields: over the text layer, under the annotations (after the overlay in the page, at
|
|
371
393
|
the same level), so a press on an annotation's shape is the annotation's. A field is
|
|
372
394
|
tinted, except while it is read-only or signed or highlighting is off. It is ringed while
|
|
@@ -481,6 +503,14 @@
|
|
|
481
503
|
cursor: default;
|
|
482
504
|
}
|
|
483
505
|
|
|
506
|
+
/* A locked note still opens its thread on a click. */
|
|
507
|
+
:where(
|
|
508
|
+
[data-ink-tool='select'] .ink-annotation[data-locked][data-type='text'],
|
|
509
|
+
[data-ink-tool='select-text'] .ink-annotation[data-locked][data-type='text']
|
|
510
|
+
) {
|
|
511
|
+
cursor: pointer;
|
|
512
|
+
}
|
|
513
|
+
|
|
484
514
|
/* While an annotation is moved the whole viewport shows it, over any element's own cursor.
|
|
485
515
|
The one rule here that is not zero specificity: it has to beat them. */
|
|
486
516
|
[data-ink-dragging],
|
|
@@ -522,14 +552,12 @@
|
|
|
522
552
|
outline-style: dotted;
|
|
523
553
|
}
|
|
524
554
|
|
|
555
|
+
/* The icon fills the note's box, so it scales with the zoom as the PDF's own icons do. */
|
|
525
556
|
:where(.ink-note-icon) {
|
|
526
557
|
position: absolute;
|
|
527
|
-
|
|
528
|
-
top: 0;
|
|
558
|
+
inset: 0;
|
|
529
559
|
display: block;
|
|
530
|
-
|
|
531
|
-
height: 20px;
|
|
532
|
-
border-radius: 3px 3px 3px 0;
|
|
560
|
+
border-radius: 15% 15% 15% 0;
|
|
533
561
|
background: var(--ink-note);
|
|
534
562
|
box-shadow: 0 1px 2px rgb(0 0 0 / 0.3);
|
|
535
563
|
pointer-events: none;
|
|
@@ -802,6 +830,373 @@
|
|
|
802
830
|
outline-offset: 2px;
|
|
803
831
|
}
|
|
804
832
|
|
|
833
|
+
/*
|
|
834
|
+
* Sidebars (createSidebar and the bindings' sidebar): a plain block the app places with its
|
|
835
|
+
* own layout. --ink-sidebar-width sets the open width and --ink-sidebar-rail-width the rail's.
|
|
836
|
+
* The border and the rail sit on the inner edge, beside the document: data-side="right"
|
|
837
|
+
* mirrors them.
|
|
838
|
+
*/
|
|
839
|
+
:where(.ink-sidebar) {
|
|
840
|
+
box-sizing: border-box;
|
|
841
|
+
display: flex;
|
|
842
|
+
flex-direction: column;
|
|
843
|
+
width: var(--ink-sidebar-width);
|
|
844
|
+
min-height: 0;
|
|
845
|
+
border-right: 1px solid var(--ink-border);
|
|
846
|
+
background: var(--ink-surface);
|
|
847
|
+
color: var(--ink-fg);
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
:where(.ink-sidebar[data-side='right']) {
|
|
851
|
+
border-right: 0;
|
|
852
|
+
border-left: 1px solid var(--ink-border);
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
/* The rail: icon buttons beside the document, so they stay put as the panel opens and closes;
|
|
856
|
+
the sidebar narrows to the rail with no panel open. The rail comes first in the markup. */
|
|
857
|
+
:where(.ink-sidebar[data-layout='rail']) {
|
|
858
|
+
flex-direction: row-reverse;
|
|
859
|
+
width: auto;
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
:where(.ink-sidebar[data-layout='rail'][data-side='right']) {
|
|
863
|
+
flex-direction: row;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
:where(.ink-sidebar-rail) {
|
|
867
|
+
display: flex;
|
|
868
|
+
flex: none;
|
|
869
|
+
flex-direction: column;
|
|
870
|
+
gap: 0.25rem;
|
|
871
|
+
box-sizing: border-box;
|
|
872
|
+
width: var(--ink-sidebar-rail-width);
|
|
873
|
+
padding: 0.375rem 0;
|
|
874
|
+
align-items: center;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
:where(.ink-sidebar[data-layout='rail'] .ink-sidebar-panels) {
|
|
878
|
+
width: calc(var(--ink-sidebar-width) - var(--ink-sidebar-rail-width));
|
|
879
|
+
border-right: 1px solid var(--ink-border);
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
:where(.ink-sidebar[data-layout='rail'][data-side='right'] .ink-sidebar-panels) {
|
|
883
|
+
border-right: 0;
|
|
884
|
+
border-left: 1px solid var(--ink-border);
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
:where(.ink-sidebar-tabs) {
|
|
888
|
+
display: flex;
|
|
889
|
+
flex: none;
|
|
890
|
+
border-bottom: 1px solid var(--ink-border);
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
:where(.ink-sidebar-panels) {
|
|
894
|
+
display: flex;
|
|
895
|
+
flex: 1;
|
|
896
|
+
flex-direction: column;
|
|
897
|
+
min-width: 0;
|
|
898
|
+
min-height: 0;
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
/* After the rule above, which it overrides at the same specificity. */
|
|
902
|
+
:where(.ink-sidebar[data-layout='rail'][data-state='closed'] .ink-sidebar-panels) {
|
|
903
|
+
display: none;
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
/* Tabs collapse as a whole, strip and all: the host's own button sets `open` to reopen it. */
|
|
907
|
+
:where(.ink-sidebar[data-layout='tabs'][data-state='closed']) {
|
|
908
|
+
display: none;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
:where(.ink-sidebar-panel) {
|
|
912
|
+
flex: 1;
|
|
913
|
+
min-height: 0;
|
|
914
|
+
overflow: auto;
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
:where(.ink-sidebar-panel[hidden]) {
|
|
918
|
+
display: none;
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
/* Not visible: the whole sidebar goes, its state kept. After every display rule above. */
|
|
922
|
+
:where(.ink-sidebar[hidden]) {
|
|
923
|
+
display: none;
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
/* The panel's title shows in the rail only, where the buttons carry no text: a strip as tall
|
|
927
|
+
as the rail is wide, so it lines up with the first button. Tabs and stack name the panel in
|
|
928
|
+
their own triggers, and there the body steps out of the layout. */
|
|
929
|
+
:where(.ink-sidebar-panel-title) {
|
|
930
|
+
display: none;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
:where(.ink-sidebar-panel-body) {
|
|
934
|
+
display: contents;
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
:where(.ink-sidebar-panel[data-layout='rail']:not([hidden])) {
|
|
938
|
+
display: flex;
|
|
939
|
+
flex-direction: column;
|
|
940
|
+
overflow: hidden;
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
:where(.ink-sidebar-panel[data-layout='rail'] > .ink-sidebar-panel-title) {
|
|
944
|
+
display: flex;
|
|
945
|
+
flex: none;
|
|
946
|
+
align-items: center;
|
|
947
|
+
box-sizing: border-box;
|
|
948
|
+
min-height: var(--ink-sidebar-rail-width);
|
|
949
|
+
padding: 0 1rem;
|
|
950
|
+
border-bottom: 1px solid var(--ink-border);
|
|
951
|
+
font-size: 0.875rem;
|
|
952
|
+
font-weight: 600;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
:where(.ink-sidebar-panel[data-layout='rail'] > .ink-sidebar-panel-body) {
|
|
956
|
+
display: block;
|
|
957
|
+
flex: 1;
|
|
958
|
+
min-height: 0;
|
|
959
|
+
overflow: auto;
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
/* The bindings wrap each panel in .ink-sidebar-slot, the stack's section in that layout. In
|
|
963
|
+
rail and tabs it steps out of the layout, so the panel fills the panels area. */
|
|
964
|
+
:where(.ink-sidebar-panels > .ink-sidebar-slot) {
|
|
965
|
+
display: contents;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
/* The stack scrolls as a whole; each expanded panel takes the height of its content. */
|
|
969
|
+
:where(.ink-sidebar[data-layout='stack']) {
|
|
970
|
+
overflow: auto;
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
:where(.ink-sidebar-section) {
|
|
974
|
+
border-bottom: 1px solid var(--ink-border);
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
:where(.ink-sidebar-section > .ink-sidebar-panel) {
|
|
978
|
+
overflow: visible;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
:where(.ink-sidebar-rail button, .ink-sidebar-tabs button, .ink-sidebar-header) {
|
|
982
|
+
position: relative;
|
|
983
|
+
display: inline-flex;
|
|
984
|
+
align-items: center;
|
|
985
|
+
gap: 0.5rem;
|
|
986
|
+
box-sizing: border-box;
|
|
987
|
+
min-width: 44px;
|
|
988
|
+
min-height: 44px;
|
|
989
|
+
padding: 0 0.75rem;
|
|
990
|
+
border: 0;
|
|
991
|
+
border-radius: calc(var(--ink-radius) - 2px);
|
|
992
|
+
background: transparent;
|
|
993
|
+
color: inherit;
|
|
994
|
+
font: inherit;
|
|
995
|
+
cursor: pointer;
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
/* Rail buttons match the toolbar's (--ink-control-size); a halo keeps the 44px hit area. */
|
|
999
|
+
:where(.ink-sidebar-rail button) {
|
|
1000
|
+
justify-content: center;
|
|
1001
|
+
width: var(--ink-control-size, 2.25rem);
|
|
1002
|
+
min-width: 0;
|
|
1003
|
+
height: var(--ink-control-size, 2.25rem);
|
|
1004
|
+
min-height: 0;
|
|
1005
|
+
padding: 0;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
:where(.ink-sidebar-rail button)::after {
|
|
1009
|
+
content: '';
|
|
1010
|
+
position: absolute;
|
|
1011
|
+
inset: -4px;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
:where(.ink-sidebar-tabs button) {
|
|
1015
|
+
flex: 1;
|
|
1016
|
+
justify-content: center;
|
|
1017
|
+
border-radius: 0;
|
|
1018
|
+
border-bottom: 2px solid transparent;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
:where(.ink-sidebar-header) {
|
|
1022
|
+
width: 100%;
|
|
1023
|
+
border-radius: 0;
|
|
1024
|
+
text-align: start;
|
|
1025
|
+
font-weight: 600;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
:where(
|
|
1029
|
+
.ink-sidebar-rail button:hover,
|
|
1030
|
+
.ink-sidebar-tabs button:hover,
|
|
1031
|
+
.ink-sidebar-header:hover
|
|
1032
|
+
) {
|
|
1033
|
+
background: color-mix(in srgb, var(--ink-fg) 8%, transparent);
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
:where(.ink-sidebar-rail button[aria-selected='true']) {
|
|
1037
|
+
background: var(--ink-accent);
|
|
1038
|
+
color: var(--ink-accent-fg);
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
:where(.ink-sidebar-tabs button[aria-selected='true']) {
|
|
1042
|
+
border-bottom-color: var(--ink-accent);
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
:where(
|
|
1046
|
+
.ink-sidebar-rail button:focus-visible,
|
|
1047
|
+
.ink-sidebar-tabs button:focus-visible,
|
|
1048
|
+
.ink-sidebar-header:focus-visible
|
|
1049
|
+
) {
|
|
1050
|
+
outline: 2px solid var(--ink-ring);
|
|
1051
|
+
outline-offset: -2px;
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
:where(.ink-sidebar-badge) {
|
|
1055
|
+
min-width: 1.125rem;
|
|
1056
|
+
padding: 0 0.3125rem;
|
|
1057
|
+
border-radius: 999px;
|
|
1058
|
+
background: var(--ink-accent);
|
|
1059
|
+
color: var(--ink-accent-fg);
|
|
1060
|
+
font-size: 0.75rem;
|
|
1061
|
+
line-height: 1.125rem;
|
|
1062
|
+
text-align: center;
|
|
1063
|
+
font-variant-numeric: tabular-nums;
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
:where(.ink-sidebar-header .ink-sidebar-badge) {
|
|
1067
|
+
margin-inline-start: auto;
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
/* On the rail the badge sits on the button's corner. */
|
|
1071
|
+
:where(.ink-sidebar-rail .ink-sidebar-badge) {
|
|
1072
|
+
position: absolute;
|
|
1073
|
+
top: -5px;
|
|
1074
|
+
right: -5px;
|
|
1075
|
+
z-index: 1;
|
|
1076
|
+
box-shadow: 0 0 0 2px var(--ink-surface);
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
:where(.ink-sidebar-rail button[aria-selected='true'] .ink-sidebar-badge) {
|
|
1080
|
+
background: var(--ink-accent-fg);
|
|
1081
|
+
color: var(--ink-accent);
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
:where(.ink-sidebar-badge[hidden]) {
|
|
1085
|
+
display: none;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
/* Thumbnails: a page as paper, its placeholder the same shape until it renders. The painter
|
|
1089
|
+
sets the size inline; the layers inside are inert copies. */
|
|
1090
|
+
:where(.ink-thumbnail) {
|
|
1091
|
+
position: relative;
|
|
1092
|
+
display: block;
|
|
1093
|
+
flex: none;
|
|
1094
|
+
overflow: hidden;
|
|
1095
|
+
background: #ffffff;
|
|
1096
|
+
box-shadow: var(--ink-thumbnail-shadow);
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
:where(.ink-thumbnail-annotation > svg) {
|
|
1100
|
+
position: absolute;
|
|
1101
|
+
left: 0;
|
|
1102
|
+
top: 0;
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
/* A note's icon fills its box instead of keeping its on-page size; comment glyphs, which keep
|
|
1106
|
+
a fixed size at every zoom, would cover a small page, so they are left out. */
|
|
1107
|
+
:where(.ink-thumbnail-annotation .ink-note-icon) {
|
|
1108
|
+
box-shadow: none;
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
:where(.ink-thumbnail-annotation .ink-comment-marker) {
|
|
1112
|
+
display: none;
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
/*
|
|
1116
|
+
* The thumbnail list (createThumbnails and the bindings' list): it fills its parent's height
|
|
1117
|
+
* and scrolls, with only the items near the visible part mounted, each placed absolutely at
|
|
1118
|
+
* its offset over a spacer of the full height. The controller fits each thumbnail to the list
|
|
1119
|
+
* less a 16px gutter each side, and counts an item as its thumbnail plus 38px: the 16px gutter
|
|
1120
|
+
* above, a 6px gap and the 16px number. The list's own 16px padding closes the last one.
|
|
1121
|
+
*/
|
|
1122
|
+
/* The list is a small viewport: pages on the same canvas, with the same shadow. */
|
|
1123
|
+
:where(.ink-thumbnails) {
|
|
1124
|
+
position: relative;
|
|
1125
|
+
box-sizing: border-box;
|
|
1126
|
+
height: 100%;
|
|
1127
|
+
padding-bottom: 16px;
|
|
1128
|
+
overflow-x: hidden;
|
|
1129
|
+
overflow-y: auto;
|
|
1130
|
+
/* A scrollbar takes the same room on both sides, so the gutters stay even. */
|
|
1131
|
+
scrollbar-gutter: stable both-edges;
|
|
1132
|
+
background: var(--ink-bg);
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
:where(.ink-thumbnails-entry) {
|
|
1136
|
+
position: absolute;
|
|
1137
|
+
left: 0;
|
|
1138
|
+
right: 0;
|
|
1139
|
+
display: flex;
|
|
1140
|
+
justify-content: center;
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
:where(.ink-thumbnails-item) {
|
|
1144
|
+
box-sizing: border-box;
|
|
1145
|
+
display: flex;
|
|
1146
|
+
flex-direction: column;
|
|
1147
|
+
align-items: center;
|
|
1148
|
+
gap: 6px;
|
|
1149
|
+
width: 100%;
|
|
1150
|
+
height: 100%;
|
|
1151
|
+
padding: 16px 16px 0;
|
|
1152
|
+
border: 0;
|
|
1153
|
+
border-radius: var(--ink-radius);
|
|
1154
|
+
background: transparent;
|
|
1155
|
+
color: inherit;
|
|
1156
|
+
font: inherit;
|
|
1157
|
+
cursor: pointer;
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
/* The page carries the states, as the main view's pages do: a ring on hover, the accent ring
|
|
1161
|
+
on the current page, and its number in the accent like a pressed toolbar button. */
|
|
1162
|
+
:where(.ink-thumbnails-item:hover .ink-thumbnail) {
|
|
1163
|
+
box-shadow:
|
|
1164
|
+
var(--ink-thumbnail-shadow),
|
|
1165
|
+
0 0 0 2px color-mix(in srgb, var(--ink-fg) 20%, transparent);
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
:where(.ink-thumbnails-item:focus-visible) {
|
|
1169
|
+
outline: none;
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
:where(.ink-thumbnails-item:focus-visible .ink-thumbnail) {
|
|
1173
|
+
outline: 2px solid var(--ink-ring);
|
|
1174
|
+
outline-offset: 3px;
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1177
|
+
:where(.ink-thumbnails-item[aria-current='page'] .ink-thumbnail) {
|
|
1178
|
+
box-shadow:
|
|
1179
|
+
var(--ink-thumbnail-shadow),
|
|
1180
|
+
0 0 0 2px var(--ink-accent);
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
:where(.ink-thumbnails-label) {
|
|
1184
|
+
min-width: 1.5rem;
|
|
1185
|
+
padding: 0 0.375rem;
|
|
1186
|
+
border-radius: 999px;
|
|
1187
|
+
color: var(--ink-muted-fg);
|
|
1188
|
+
font-size: 0.75rem;
|
|
1189
|
+
line-height: 16px;
|
|
1190
|
+
text-align: center;
|
|
1191
|
+
font-variant-numeric: tabular-nums;
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
:where(.ink-thumbnails-item[aria-current='page'] .ink-thumbnails-label) {
|
|
1195
|
+
background: var(--ink-accent);
|
|
1196
|
+
color: var(--ink-accent-fg);
|
|
1197
|
+
font-weight: 600;
|
|
1198
|
+
}
|
|
1199
|
+
|
|
805
1200
|
/* Text for assistive technology only, such as the find bar's live region. */
|
|
806
1201
|
:where(.ink-visually-hidden) {
|
|
807
1202
|
position: absolute;
|
|
@@ -848,41 +1243,40 @@
|
|
|
848
1243
|
}
|
|
849
1244
|
|
|
850
1245
|
/*
|
|
851
|
-
*
|
|
852
|
-
*
|
|
1246
|
+
* Select. `.ink-select` is the toolbar's select box, for a native select or a button trigger
|
|
1247
|
+
* (`.ink-select-trigger`) with a portalled listbox. The zoom select uses it in every binding,
|
|
1248
|
+
* and an app's own toolbar select takes the class to match.
|
|
853
1249
|
*/
|
|
854
|
-
:where(.ink-
|
|
1250
|
+
:where(.ink-select) {
|
|
855
1251
|
box-sizing: border-box;
|
|
856
1252
|
display: inline-flex;
|
|
857
1253
|
align-items: center;
|
|
858
1254
|
justify-content: space-between;
|
|
859
1255
|
gap: 0.5rem;
|
|
860
|
-
width: 7.5rem;
|
|
861
1256
|
height: var(--ink-control-size, 2.25rem);
|
|
862
1257
|
padding: 0 0.5rem 0 0.75rem;
|
|
863
1258
|
border: 1px solid var(--ink-border);
|
|
864
1259
|
border-radius: calc(var(--ink-radius) - 2px);
|
|
865
|
-
background: var(--ink-surface);
|
|
1260
|
+
background-color: var(--ink-surface);
|
|
866
1261
|
color: inherit;
|
|
867
1262
|
font: inherit;
|
|
868
1263
|
font-size: 0.875rem;
|
|
869
|
-
font-variant-numeric: tabular-nums;
|
|
870
1264
|
text-align: left;
|
|
871
1265
|
white-space: nowrap;
|
|
872
1266
|
cursor: pointer;
|
|
873
1267
|
}
|
|
874
1268
|
|
|
875
|
-
:where(.ink-
|
|
876
|
-
background: color-mix(in srgb, var(--ink-fg) 4%, var(--ink-surface));
|
|
1269
|
+
:where(.ink-select:hover) {
|
|
1270
|
+
background-color: color-mix(in srgb, var(--ink-fg) 4%, var(--ink-surface));
|
|
877
1271
|
}
|
|
878
1272
|
|
|
879
|
-
:where(.ink-
|
|
1273
|
+
:where(.ink-select:disabled) {
|
|
880
1274
|
opacity: 0.5;
|
|
881
1275
|
cursor: default;
|
|
882
1276
|
}
|
|
883
1277
|
|
|
884
|
-
/*
|
|
885
|
-
:where(
|
|
1278
|
+
/* A native select draws the same chevron as the trigger's icon: Lucide's ChevronDown; see LICENSE. */
|
|
1279
|
+
:where(select.ink-select) {
|
|
886
1280
|
padding-right: 2rem;
|
|
887
1281
|
appearance: none;
|
|
888
1282
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%235a6170' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
|
|
@@ -891,6 +1285,12 @@
|
|
|
891
1285
|
background-size: 1rem;
|
|
892
1286
|
}
|
|
893
1287
|
|
|
1288
|
+
/* The zoom select keeps one width as its value changes. */
|
|
1289
|
+
:where(.ink-zoom-select) {
|
|
1290
|
+
width: 7.5rem;
|
|
1291
|
+
font-variant-numeric: tabular-nums;
|
|
1292
|
+
}
|
|
1293
|
+
|
|
894
1294
|
:where(.ink-select-value) {
|
|
895
1295
|
overflow: hidden;
|
|
896
1296
|
text-overflow: ellipsis;
|
|
@@ -1611,7 +2011,7 @@
|
|
|
1611
2011
|
font-size: 0.875rem;
|
|
1612
2012
|
}
|
|
1613
2013
|
|
|
1614
|
-
:where(.ink-card-title, .ink-card-meta, .ink-card-body) {
|
|
2014
|
+
:where(.ink-card-title, .ink-card-meta, .ink-card-body, .ink-card-excerpt) {
|
|
1615
2015
|
margin: 0;
|
|
1616
2016
|
}
|
|
1617
2017
|
|
|
@@ -1640,6 +2040,17 @@
|
|
|
1640
2040
|
color: var(--ink-muted-fg);
|
|
1641
2041
|
}
|
|
1642
2042
|
|
|
2043
|
+
:where(.ink-card-excerpt) {
|
|
2044
|
+
margin-top: 0.25rem;
|
|
2045
|
+
color: var(--ink-muted-fg);
|
|
2046
|
+
}
|
|
2047
|
+
|
|
2048
|
+
:where(.ink-card-excerpt mark) {
|
|
2049
|
+
background: var(--ink-search-hit);
|
|
2050
|
+
/* The hit colour is light in both themes, so the text on it stays dark. */
|
|
2051
|
+
color: var(--ink-free-text);
|
|
2052
|
+
}
|
|
2053
|
+
|
|
1643
2054
|
:where(.ink-card-actions) {
|
|
1644
2055
|
display: flex;
|
|
1645
2056
|
gap: 0.375rem;
|
|
@@ -1663,6 +2074,269 @@
|
|
|
1663
2074
|
color: var(--ink-accent-fg);
|
|
1664
2075
|
}
|
|
1665
2076
|
|
|
2077
|
+
/*
|
|
2078
|
+
* Record lists (createRecordList, createSearchResults and the bindings' lists): the same
|
|
2079
|
+
* cards as the popover, in a list that fills its parent's height and scrolls. These follow the
|
|
2080
|
+
* card rules so a row's card drops the popover's float, width and shadow.
|
|
2081
|
+
*/
|
|
2082
|
+
:where(.ink-records) {
|
|
2083
|
+
display: flex;
|
|
2084
|
+
flex-direction: column;
|
|
2085
|
+
box-sizing: border-box;
|
|
2086
|
+
height: 100%;
|
|
2087
|
+
min-height: 0;
|
|
2088
|
+
}
|
|
2089
|
+
|
|
2090
|
+
:where(.ink-records:focus-visible) {
|
|
2091
|
+
outline: 2px solid var(--ink-ring);
|
|
2092
|
+
outline-offset: -2px;
|
|
2093
|
+
}
|
|
2094
|
+
|
|
2095
|
+
:where(.ink-record-list) {
|
|
2096
|
+
display: flex;
|
|
2097
|
+
flex: 1;
|
|
2098
|
+
flex-direction: column;
|
|
2099
|
+
gap: 0.5rem;
|
|
2100
|
+
min-height: 0;
|
|
2101
|
+
margin: 0;
|
|
2102
|
+
padding: 0.5rem;
|
|
2103
|
+
overflow-x: hidden;
|
|
2104
|
+
overflow-y: auto;
|
|
2105
|
+
list-style: none;
|
|
2106
|
+
}
|
|
2107
|
+
|
|
2108
|
+
:where(.ink-record-list[hidden], .ink-record-list-empty[hidden]) {
|
|
2109
|
+
display: none;
|
|
2110
|
+
}
|
|
2111
|
+
|
|
2112
|
+
:where(.ink-record) {
|
|
2113
|
+
border-radius: var(--ink-radius);
|
|
2114
|
+
cursor: pointer;
|
|
2115
|
+
}
|
|
2116
|
+
|
|
2117
|
+
:where(.ink-record > .ink-card) {
|
|
2118
|
+
z-index: auto;
|
|
2119
|
+
width: auto;
|
|
2120
|
+
max-width: none;
|
|
2121
|
+
box-shadow: none;
|
|
2122
|
+
}
|
|
2123
|
+
|
|
2124
|
+
:where(.ink-record:hover > .ink-card) {
|
|
2125
|
+
background: color-mix(in srgb, var(--ink-fg) 4%, var(--ink-surface));
|
|
2126
|
+
}
|
|
2127
|
+
|
|
2128
|
+
:where(.ink-record:focus-visible) {
|
|
2129
|
+
outline: 2px solid var(--ink-ring);
|
|
2130
|
+
outline-offset: 2px;
|
|
2131
|
+
}
|
|
2132
|
+
|
|
2133
|
+
:where(.ink-record[aria-current='true'] > .ink-card) {
|
|
2134
|
+
border-color: var(--ink-accent);
|
|
2135
|
+
box-shadow: inset 0 0 0 1px var(--ink-accent);
|
|
2136
|
+
}
|
|
2137
|
+
|
|
2138
|
+
:where(.ink-record .ink-card-actions:empty) {
|
|
2139
|
+
display: none;
|
|
2140
|
+
}
|
|
2141
|
+
|
|
2142
|
+
:where(.ink-record .ink-card-actions button) {
|
|
2143
|
+
min-height: 44px;
|
|
2144
|
+
}
|
|
2145
|
+
|
|
2146
|
+
:where(.ink-record-list-empty) {
|
|
2147
|
+
margin: 0;
|
|
2148
|
+
padding: 1rem 0.75rem;
|
|
2149
|
+
color: var(--ink-muted-fg);
|
|
2150
|
+
font-size: 0.875rem;
|
|
2151
|
+
}
|
|
2152
|
+
|
|
2153
|
+
/*
|
|
2154
|
+
* Search results frame their cards as the viewer frames its pages: the field on the surface
|
|
2155
|
+
* at the top, the cards on the page canvas, and the count in a footer on the surface at the
|
|
2156
|
+
* bottom, shown only when it has something to say.
|
|
2157
|
+
*/
|
|
2158
|
+
:where(.ink-search-results) {
|
|
2159
|
+
display: flex;
|
|
2160
|
+
flex-direction: column;
|
|
2161
|
+
box-sizing: border-box;
|
|
2162
|
+
height: 100%;
|
|
2163
|
+
min-height: 0;
|
|
2164
|
+
background: var(--ink-bg);
|
|
2165
|
+
}
|
|
2166
|
+
|
|
2167
|
+
:where(.ink-search-results-bar) {
|
|
2168
|
+
display: flex;
|
|
2169
|
+
flex: none;
|
|
2170
|
+
align-items: center;
|
|
2171
|
+
padding: 0.5rem;
|
|
2172
|
+
border-bottom: 1px solid var(--ink-border);
|
|
2173
|
+
background: var(--ink-surface);
|
|
2174
|
+
}
|
|
2175
|
+
|
|
2176
|
+
:where(.ink-search-results-count) {
|
|
2177
|
+
flex: none;
|
|
2178
|
+
min-width: 0;
|
|
2179
|
+
padding: 0.5rem 0.75rem;
|
|
2180
|
+
border-top: 1px solid var(--ink-border);
|
|
2181
|
+
background: var(--ink-surface);
|
|
2182
|
+
color: var(--ink-muted-fg);
|
|
2183
|
+
font-size: 0.75rem;
|
|
2184
|
+
font-variant-numeric: tabular-nums;
|
|
2185
|
+
line-height: 1rem;
|
|
2186
|
+
}
|
|
2187
|
+
|
|
2188
|
+
:where(.ink-search-results-count:empty) {
|
|
2189
|
+
display: none;
|
|
2190
|
+
}
|
|
2191
|
+
|
|
2192
|
+
:where(.ink-search-results-bar input) {
|
|
2193
|
+
box-sizing: border-box;
|
|
2194
|
+
flex: 1;
|
|
2195
|
+
min-width: 0;
|
|
2196
|
+
min-height: 44px;
|
|
2197
|
+
padding: 0 0.5rem;
|
|
2198
|
+
border: 1px solid var(--ink-border);
|
|
2199
|
+
border-radius: calc(var(--ink-radius) - 2px);
|
|
2200
|
+
background: var(--ink-surface);
|
|
2201
|
+
color: inherit;
|
|
2202
|
+
font: inherit;
|
|
2203
|
+
}
|
|
2204
|
+
|
|
2205
|
+
:where(.ink-search-results-bar input:focus-visible) {
|
|
2206
|
+
outline: 2px solid var(--ink-ring);
|
|
2207
|
+
outline-offset: 2px;
|
|
2208
|
+
}
|
|
2209
|
+
|
|
2210
|
+
/*
|
|
2211
|
+
* An input with an accessory icon: wrap the input in `.ink-input-group` with an
|
|
2212
|
+
* `.ink-input-accessory` before it (at the start) or after it (at the end). The icon is
|
|
2213
|
+
* decorative and lets clicks through to the field. The group holds only the input and its
|
|
2214
|
+
* accessories, so an input that is not first or last has one beside it (no :has(), which
|
|
2215
|
+
* costs frames on long documents). After the find bar's and search results' input rules, so
|
|
2216
|
+
* its padding wins over theirs.
|
|
2217
|
+
*/
|
|
2218
|
+
:where(.ink-input-group) {
|
|
2219
|
+
position: relative;
|
|
2220
|
+
display: flex;
|
|
2221
|
+
align-items: center;
|
|
2222
|
+
min-width: 0;
|
|
2223
|
+
}
|
|
2224
|
+
|
|
2225
|
+
:where(.ink-input-group > input) {
|
|
2226
|
+
flex: 1;
|
|
2227
|
+
min-width: 0;
|
|
2228
|
+
}
|
|
2229
|
+
|
|
2230
|
+
:where(.ink-input-accessory) {
|
|
2231
|
+
position: absolute;
|
|
2232
|
+
display: inline-flex;
|
|
2233
|
+
color: var(--ink-muted-fg);
|
|
2234
|
+
pointer-events: none;
|
|
2235
|
+
}
|
|
2236
|
+
|
|
2237
|
+
:where(.ink-input-accessory:first-child) {
|
|
2238
|
+
left: 0.625rem;
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2241
|
+
:where(.ink-input-accessory:last-child) {
|
|
2242
|
+
right: 0.625rem;
|
|
2243
|
+
}
|
|
2244
|
+
|
|
2245
|
+
:where(.ink-input-accessory .ink-icon) {
|
|
2246
|
+
width: 1rem;
|
|
2247
|
+
height: 1rem;
|
|
2248
|
+
}
|
|
2249
|
+
|
|
2250
|
+
:where(.ink-input-group > input:not(:first-child)) {
|
|
2251
|
+
padding-left: 2rem;
|
|
2252
|
+
}
|
|
2253
|
+
|
|
2254
|
+
:where(.ink-input-group > input:not(:last-child)) {
|
|
2255
|
+
padding-right: 2rem;
|
|
2256
|
+
}
|
|
2257
|
+
|
|
2258
|
+
/* In the find bar and the search results, the group takes the field's place in the row. */
|
|
2259
|
+
:where(.ink-find-bar .ink-input-group, .ink-search-results-bar .ink-input-group) {
|
|
2260
|
+
flex: 1;
|
|
2261
|
+
}
|
|
2262
|
+
|
|
2263
|
+
:where(.ink-search-results > .ink-records) {
|
|
2264
|
+
flex: 1;
|
|
2265
|
+
height: auto;
|
|
2266
|
+
}
|
|
2267
|
+
|
|
2268
|
+
/*
|
|
2269
|
+
* Search result cards: the matched text leads, at full strength, and its page and place sit
|
|
2270
|
+
* in a small footer under a hairline. The cards are surfaces on the page canvas, as the
|
|
2271
|
+
* thumbnails are. The card's markup stays title, meta, excerpt; the grid reorders it.
|
|
2272
|
+
*/
|
|
2273
|
+
:where(.ink-search-results .ink-record > .ink-card) {
|
|
2274
|
+
display: grid;
|
|
2275
|
+
grid-template-columns: auto 1fr;
|
|
2276
|
+
grid-template-areas:
|
|
2277
|
+
'excerpt excerpt'
|
|
2278
|
+
'title meta';
|
|
2279
|
+
padding: 0;
|
|
2280
|
+
overflow: hidden;
|
|
2281
|
+
border-color: color-mix(in srgb, var(--ink-fg) 10%, transparent);
|
|
2282
|
+
box-shadow: var(--ink-thumbnail-shadow);
|
|
2283
|
+
}
|
|
2284
|
+
|
|
2285
|
+
/* The ring sits outside: an inset one would go under the footer's background. */
|
|
2286
|
+
:where(.ink-search-results .ink-record[aria-current='true'] > .ink-card) {
|
|
2287
|
+
border-color: var(--ink-accent);
|
|
2288
|
+
box-shadow:
|
|
2289
|
+
0 0 0 1px var(--ink-accent),
|
|
2290
|
+
var(--ink-thumbnail-shadow);
|
|
2291
|
+
}
|
|
2292
|
+
|
|
2293
|
+
:where(.ink-search-results .ink-card-excerpt) {
|
|
2294
|
+
display: -webkit-box;
|
|
2295
|
+
grid-area: excerpt;
|
|
2296
|
+
margin: 0;
|
|
2297
|
+
/* The space below is a border: a clamped box shows its next line through its padding, and
|
|
2298
|
+
an app's reset of p margins would win over the theme's layer. */
|
|
2299
|
+
padding: 0.625rem 0.75rem 0;
|
|
2300
|
+
border-bottom: 0.75rem solid transparent;
|
|
2301
|
+
overflow: hidden;
|
|
2302
|
+
color: var(--ink-fg);
|
|
2303
|
+
line-height: 1.45;
|
|
2304
|
+
-webkit-box-orient: vertical;
|
|
2305
|
+
-webkit-line-clamp: 3;
|
|
2306
|
+
line-clamp: 3;
|
|
2307
|
+
}
|
|
2308
|
+
|
|
2309
|
+
:where(.ink-search-results .ink-card-excerpt mark) {
|
|
2310
|
+
padding: 0 1px;
|
|
2311
|
+
border-radius: 2px;
|
|
2312
|
+
}
|
|
2313
|
+
|
|
2314
|
+
/* The current match's text takes the current hit's colour, as it does on the page. */
|
|
2315
|
+
:where(.ink-search-results .ink-record[aria-current='true'] .ink-card-excerpt mark) {
|
|
2316
|
+
background: var(--ink-search-current);
|
|
2317
|
+
}
|
|
2318
|
+
|
|
2319
|
+
:where(.ink-search-results .ink-card-title, .ink-search-results .ink-card-meta) {
|
|
2320
|
+
margin: 0;
|
|
2321
|
+
padding: 0.3125rem 0.75rem;
|
|
2322
|
+
border-top: 1px solid color-mix(in srgb, var(--ink-fg) 8%, transparent);
|
|
2323
|
+
background: color-mix(in srgb, var(--ink-fg) 3%, var(--ink-surface));
|
|
2324
|
+
font-size: 0.6875rem;
|
|
2325
|
+
line-height: 1rem;
|
|
2326
|
+
}
|
|
2327
|
+
|
|
2328
|
+
:where(.ink-search-results .ink-card-title) {
|
|
2329
|
+
grid-area: title;
|
|
2330
|
+
padding-right: 0;
|
|
2331
|
+
font-weight: 600;
|
|
2332
|
+
}
|
|
2333
|
+
|
|
2334
|
+
:where(.ink-search-results .ink-card-meta) {
|
|
2335
|
+
grid-area: meta;
|
|
2336
|
+
color: var(--ink-muted-fg);
|
|
2337
|
+
font-weight: 400;
|
|
2338
|
+
}
|
|
2339
|
+
|
|
1666
2340
|
:where(.ink-select-item:focus-visible) {
|
|
1667
2341
|
outline: none;
|
|
1668
2342
|
}
|
|
@@ -1675,7 +2349,7 @@
|
|
|
1675
2349
|
:where(
|
|
1676
2350
|
.ink-toolbar button:focus-visible,
|
|
1677
2351
|
.ink-toolbar select:focus-visible,
|
|
1678
|
-
.ink-select
|
|
2352
|
+
.ink-select:focus-visible,
|
|
1679
2353
|
.ink-toolbar input:focus-visible,
|
|
1680
2354
|
.ink-thread-actions button:focus-visible,
|
|
1681
2355
|
.ink-thread-reply textarea:focus-visible,
|