@crisp-ui-kit/crisp 0.53.4 → 0.54.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 (99) hide show
  1. package/dist/cjs/components/bulkbar/bulkbar.js +5 -1
  2. package/dist/cjs/components/fileupload/fileupload.js +19 -3
  3. package/dist/cjs/components/formfield/formfield.js +8 -1
  4. package/dist/cjs/components/heatmapchart/heatmapchart.js +14 -2
  5. package/dist/cjs/components/skiplink/index.js +17 -0
  6. package/dist/cjs/components/skiplink/skiplink.js +16 -0
  7. package/dist/cjs/components/skiplink/skiplink.recipe.js +33 -0
  8. package/dist/cjs/components/textlink/index.js +7 -0
  9. package/dist/cjs/components/textlink/textlink.js +16 -0
  10. package/dist/cjs/components/textlink/textlink.recipe.js +35 -0
  11. package/dist/cjs/components/visuallyhidden/index.js +17 -0
  12. package/dist/cjs/components/visuallyhidden/visuallyhidden.js +16 -0
  13. package/dist/cjs/components/visuallyhidden/visuallyhidden.recipe.js +20 -0
  14. package/dist/cjs/index.js +4 -0
  15. package/dist/cjs/product/board/board.js +11 -2
  16. package/dist/cjs/product/command/command.js +13 -1
  17. package/dist/cjs/product/flowcanvas/flowcanvas.js +9 -2
  18. package/dist/cjs/product/headerbar/headerbar.js +15 -0
  19. package/dist/cjs/product/headerbar/headerbar.recipe.js +35 -0
  20. package/dist/cjs/product/headerbar/index.js +17 -0
  21. package/dist/cjs/product/inbox/inbox.js +13 -1
  22. package/dist/cjs/product/onboarding/onboarding.js +22 -1
  23. package/dist/cjs/product/recordpage/index.js +2 -1
  24. package/dist/cjs/product/recordpage/recordpage.js +197 -123
  25. package/dist/cjs/product/recordpage/recordpage.recipe.js +5 -0
  26. package/dist/cjs/product/richtext/richtext.js +3 -3
  27. package/dist/cjs/product/settingssection/settingssection.recipe.js +11 -2
  28. package/dist/cjs/product/tasklist/tasklist.js +8 -1
  29. package/dist/esm/components/bulkbar/bulkbar.js +5 -1
  30. package/dist/esm/components/fileupload/fileupload.js +20 -4
  31. package/dist/esm/components/formfield/formfield.js +8 -1
  32. package/dist/esm/components/heatmapchart/heatmapchart.js +14 -2
  33. package/dist/esm/components/skiplink/index.js +1 -0
  34. package/dist/esm/components/skiplink/skiplink.js +13 -0
  35. package/dist/esm/components/skiplink/skiplink.recipe.js +30 -0
  36. package/dist/esm/components/textlink/index.js +2 -0
  37. package/dist/esm/components/textlink/textlink.js +13 -0
  38. package/dist/esm/components/textlink/textlink.recipe.js +32 -0
  39. package/dist/esm/components/visuallyhidden/index.js +1 -0
  40. package/dist/esm/components/visuallyhidden/visuallyhidden.js +13 -0
  41. package/dist/esm/components/visuallyhidden/visuallyhidden.recipe.js +17 -0
  42. package/dist/esm/index.js +4 -0
  43. package/dist/esm/product/board/board.js +12 -3
  44. package/dist/esm/product/command/command.js +14 -2
  45. package/dist/esm/product/flowcanvas/flowcanvas.js +9 -2
  46. package/dist/esm/product/headerbar/headerbar.js +12 -0
  47. package/dist/esm/product/headerbar/headerbar.recipe.js +32 -0
  48. package/dist/esm/product/headerbar/index.js +1 -0
  49. package/dist/esm/product/inbox/inbox.js +13 -1
  50. package/dist/esm/product/onboarding/onboarding.js +22 -1
  51. package/dist/esm/product/recordpage/index.js +1 -1
  52. package/dist/esm/product/recordpage/recordpage.js +197 -124
  53. package/dist/esm/product/recordpage/recordpage.recipe.js +5 -0
  54. package/dist/esm/product/richtext/richtext.js +3 -3
  55. package/dist/esm/product/settingssection/settingssection.recipe.js +11 -2
  56. package/dist/esm/product/tasklist/tasklist.js +8 -1
  57. package/dist/headerbar.css +7 -0
  58. package/dist/headerbar.d.ts +7 -0
  59. package/dist/headerbar.layered.css +9 -0
  60. package/dist/recordpage.css +17 -31
  61. package/dist/recordpage.layered.css +17 -31
  62. package/dist/settingssection.css +2 -2
  63. package/dist/settingssection.layered.css +2 -2
  64. package/dist/skiplink.css +5 -0
  65. package/dist/skiplink.d.ts +7 -0
  66. package/dist/skiplink.layered.css +7 -0
  67. package/dist/styles.css +49 -33
  68. package/dist/styles.layered.css +49 -33
  69. package/dist/textlink.css +11 -0
  70. package/dist/textlink.d.ts +7 -0
  71. package/dist/textlink.layered.css +13 -0
  72. package/dist/types/components/bulkbar/bulkbar.d.ts +1 -1
  73. package/dist/types/components/heatmapchart/heatmapchart.d.ts +1 -1
  74. package/dist/types/components/skiplink/index.d.ts +1 -0
  75. package/dist/types/components/skiplink/skiplink.d.ts +18 -0
  76. package/dist/types/components/skiplink/skiplink.recipe.d.ts +3 -0
  77. package/dist/types/components/textlink/index.d.ts +2 -0
  78. package/dist/types/components/textlink/textlink.d.ts +19 -0
  79. package/dist/types/components/textlink/textlink.recipe.d.ts +13 -0
  80. package/dist/types/components/visuallyhidden/index.d.ts +1 -0
  81. package/dist/types/components/visuallyhidden/visuallyhidden.d.ts +15 -0
  82. package/dist/types/components/visuallyhidden/visuallyhidden.recipe.d.ts +3 -0
  83. package/dist/types/index.d.ts +4 -0
  84. package/dist/types/product/board/board.d.ts +1 -1
  85. package/dist/types/product/command/command.d.ts +1 -1
  86. package/dist/types/product/flowcanvas/flowcanvas.d.ts +1 -1
  87. package/dist/types/product/headerbar/headerbar.d.ts +27 -0
  88. package/dist/types/product/headerbar/headerbar.recipe.d.ts +3 -0
  89. package/dist/types/product/headerbar/index.d.ts +1 -0
  90. package/dist/types/product/inbox/inbox.d.ts +1 -1
  91. package/dist/types/product/onboarding/onboarding.d.ts +1 -1
  92. package/dist/types/product/recordpage/index.d.ts +1 -1
  93. package/dist/types/product/recordpage/recordpage.d.ts +90 -1
  94. package/dist/types/product/richtext/richtext.d.ts +20 -0
  95. package/dist/types/product/tasklist/tasklist.d.ts +1 -1
  96. package/dist/visuallyhidden.css +3 -0
  97. package/dist/visuallyhidden.d.ts +7 -0
  98. package/dist/visuallyhidden.layered.css +5 -0
  99. package/package.json +21 -1
@@ -47,6 +47,10 @@
47
47
  & .crisp-recordpage-detailsearch { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: var(--crisp-size-chip); flex-shrink: 0; padding: 0; margin: 0; border: none; border-radius: var(--crisp-radius-sm); background: none; color: var(--crisp-fg-muted); font-family: inherit; cursor: pointer; transition: background-color .12s, color .12s; }
48
48
  & .crisp-recordpage-detailsearch:hover, & .crisp-recordpage-detailsearch[data-active] { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
49
49
  & .crisp-recordpage-noresults { padding: var(--crisp-space-1-5) var(--crisp-space-1); font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
50
+ /* A caller-supplied `sections` grouping (#528) is not an Attio-measured
51
+ shape (its own Details column is flat) -- this heading reuses
52
+ .crisp-recordpage-section-title's own type treatment verbatim, just spaced from the group above it. */
53
+ & .crisp-recordpage-fieldsection-title { margin-top: var(--crisp-space-3); }
50
54
  & .crisp-recordpage-morevalues { display: inline-flex; align-items: center; padding: 0; margin: 0; border: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-muted); cursor: pointer; }
51
55
  & .crisp-recordpage-morevalues:hover { color: var(--crisp-fg-primary); }
52
56
  & .crisp-recordpage-viewall { flex-basis: 100%; margin-top: var(--crisp-space-0-5); border: none; background: none; padding: 0; color: color-mix(in srgb, var(--crisp-fg-primary) 55%, transparent); font-family: inherit; font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-regular); cursor: pointer; text-align: start; }
@@ -61,31 +65,25 @@
61
65
  & .crisp-recordpage-field-label-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
62
66
  & .crisp-recordpage-field-value { flex: 1; min-width: 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--crisp-space-1); padding-top: 2px; line-height: 20px; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
63
67
  & .crisp-recordpage-field-value[data-editable] { cursor: pointer; }
64
- /* the click-to-edit trigger is a real <button> (keyboard-operable),
65
- reset back to plain inline text and made a flex-wrap container of its
66
- own -- FieldValue can render several chips (tags), which still need
67
- to wrap the way they did before this had a button around them at
68
- all. It wraps only FieldValue, never the error slot beside it (see
69
- the component's own comment) -- NOT `display: contents`, which drops a button's accessible semantics in some engines. */
68
+ /* the click-to-edit trigger is a real <button> (keyboard-operable), reset back to plain inline text and made a flex-wrap container of its own -- FieldValue can render several chips (tags), which still need to wrap the way they did before this had a button around them at all. It wraps only FieldValue, never the error slot beside it (see the component's own comment) -- NOT `display: contents`, which
69
+ drops a button's accessible semantics in some engines. */
70
70
  & .crisp-recordpage-edit-trigger { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--crisp-space-1); margin: 0; padding: 0; border: none; background: none; text-align: start; font: inherit; color: inherit; cursor: pointer; }
71
71
  & .crisp-recordpage-empty { color: var(--crisp-fg-muted); }
72
-
73
- /* #431: measured live on app.attio.com's record page Details column -- clicking a field's value opens a plain, borderless field exactly
74
- filling the value's own box (no border, no background, no box-shadow), same font as the value it replaces (hence `font: inherit`, not a restated size/weight). A field row's own hover tint
75
- above already carries the "this is interactive" affordance; the
76
- pending/error treatment isn't Attio-measured -- it reuses the same tokens DataTable's identical states already use (opacity 0.5,
77
- `bgDanger`), per #385/#430. */
72
+ /* #431: measured live on app.attio.com's record page Details column --
73
+ clicking a field's value opens a plain, borderless field exactly filling the value's own box (no border, no background, no
74
+ box-shadow), same font as the value it replaces (hence `font:
75
+ inherit`, not a restated size/weight). A field row's own hover tint above already carries the "this is interactive" affordance; the pending/error treatment isn't Attio-measured -- it reuses the same
76
+ tokens DataTable's identical states already use (opacity 0.5, `bgDanger`), per #385/#430. */
78
77
  & .crisp-recordpage-edit { display: block; width: 100%; margin: 0; padding: 0; border: none; border-radius: var(--crisp-radius-sm); background: none; box-shadow: none; outline: none; font: inherit; color: inherit; }
79
- /* not Attio-measured (its own field shows no focus ring either, caret
80
- only) -- kept for real keyboard users, the same brand ring every
81
- other crisp field already shows on focus (DataTable's identical .crisp-datatable-edit:focus, e.g.). */
78
+ /* not Attio-measured (its own field shows no focus ring either, caret only) -- kept for real keyboard users, the same brand ring every other crisp field already shows on focus (DataTable's identical
79
+ .crisp-datatable-edit:focus, e.g.). */
82
80
  & .crisp-recordpage-edit:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
83
81
  & .crisp-recordpage-edit:disabled { opacity: 0.5; cursor: not-allowed; }
84
82
  & .crisp-recordpage-edit-pending { flex-shrink: 0; color: var(--crisp-fg-muted); }
85
83
  & .crisp-recordpage-edit-error { flex-basis: 100%; margin-top: var(--crisp-space-0-5); font-size: var(--crisp-text-sm); color: var(--crisp-bg-danger); }
86
- /* #457: an `editor: "select"` field's at-rest chip -- same shape as
87
- RecordsTable's own `.crisp-recordstable-status[-dot]` (already measured against Attio there), but its own classes: that pair is scoped under `.crisp-recordstable`'s own recipe root, so reusing the
88
- classnames verbatim here would resolve to nothing. */
84
+ /* #457: an `editor: "select"` field's at-rest chip -- same shape as RecordsTable's own `.crisp-recordstable-status[-dot]` (already
85
+ measured against Attio there), but its own classes: that pair is
86
+ scoped under `.crisp-recordstable`'s own recipe root, so reusing the classnames verbatim here would resolve to nothing. */
89
87
  & .crisp-recordpage-status { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; }
90
88
  & .crisp-recordpage-status-dot { flex-shrink: 0; width: 8px; height: 8px; border-radius: var(--crisp-radius-full); }
91
89
  & .crisp-recordpage-edit-picker { display: flex; align-items: center; gap: var(--crisp-space-1); width: 100%; }
@@ -93,23 +91,18 @@
93
91
  & .crisp-recordpage-link { color: var(--crisp-fg-primary); text-decoration: none; overflow: hidden; text-overflow: ellipsis; }
94
92
  & .crisp-recordpage-link:hover { text-decoration: underline; }
95
93
  & .crisp-recordpage-emptystate { padding: var(--crisp-space-2) var(--crisp-space-1); font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
96
-
97
94
  & .crisp-recordpage-main { flex: 1; min-width: 0; display: flex; flex-direction: column; min-height: 0; overflow-y: auto; padding: var(--crisp-space-3) var(--crisp-space-5); }
98
-
99
95
  & .crisp-recordpage-panel { padding-top: var(--crisp-space-4); display: flex; flex-direction: column; gap: var(--crisp-space-4); }
100
96
  & .crisp-recordpage-card { border: 1px solid var(--crisp-border-subtle); border-radius: var(--crisp-radius-2xl); background: var(--crisp-bg-surface); overflow: hidden; }
101
97
  & .crisp-recordpage-card-title { font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-semibold); letter-spacing: -0.14px; color: var(--crisp-fg-primary); padding: var(--crisp-space-3) var(--crisp-space-3) var(--crisp-space-2); }
102
98
  & .crisp-recordpage-hl-card { border: 1px solid var(--crisp-border-subtle); border-radius: var(--crisp-radius-2xl); overflow: hidden; }
103
- /* gap-as-gridlines: a 1px gap over the border colour draws dividers at any
104
- column count, so the grid stays responsive (auto-fit) without per-cell
105
- nth-child border hacks that break when the column count changes. */
99
+ /* gap-as-gridlines: a 1px gap over the border colour draws dividers at any column count, so the grid stays responsive (auto-fit) without per-cell nth-child border hacks that break when the column count changes. */
106
100
  & .crisp-recordpage-hl-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 1px; background: var(--crisp-border-subtle); }
107
101
  & .crisp-recordpage-hl-cell { position: relative; min-height: 84px; padding: var(--crisp-space-2-5) var(--crisp-space-3); background: var(--crisp-bg-surface); }
108
102
  & .crisp-recordpage-hl-icon { position: absolute; top: var(--crisp-space-2-5); inset-inline-end: var(--crisp-space-3); color: var(--crisp-fg-muted); }
109
103
  & .crisp-recordpage-hl-label { font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); margin-bottom: var(--crisp-space-2-5); padding-inline-end: var(--crisp-space-4); }
110
104
  & .crisp-recordpage-hl-value { display: flex; flex-wrap: wrap; align-items: center; gap: var(--crisp-space-1); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
111
105
  & .crisp-recordpage-hl-value--empty { color: var(--crisp-fg-muted); font-weight: var(--crisp-weight-regular); }
112
-
113
106
  & .crisp-recordpage-feed { display: flex; flex-direction: column; }
114
107
  & .crisp-recordpage-feed-item { display: flex; align-items: flex-start; gap: var(--crisp-space-2-5); padding: var(--crisp-space-2) 0; }
115
108
  & .crisp-recordpage-feed-dot { position: relative; display: flex; align-items: center; justify-content: center; width: 24px; height: 24px; flex-shrink: 0; border-radius: var(--crisp-radius-full); background: var(--crisp-bg-raised); color: var(--crisp-fg-muted); }
@@ -118,7 +111,6 @@
118
111
  & .crisp-recordpage-feed-time { font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); margin-top: 2px; }
119
112
  & .crisp-recordpage-feed-more { align-self: flex-start; margin-top: var(--crisp-space-1); border: none; background: none; padding: var(--crisp-space-1) 0; color: var(--crisp-bg-brand-solid); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: pointer; }
120
113
  & .crisp-recordpage-feed-more:hover { text-decoration: underline; }
121
-
122
114
  & .crisp-recordpage-section-head { display: flex; align-items: center; gap: var(--crisp-space-1-5); padding: var(--crisp-space-1); }
123
115
  & .crisp-recordpage-section-head .crisp-recordpage-section-title { padding: 0; }
124
116
  & .crisp-recordpage-section-count { display: inline-flex; align-items: center; justify-content: center; min-width: 16px; height: 16px; padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-sm); background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); font-size: var(--crisp-text-xs); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
@@ -126,7 +118,6 @@
126
118
  & .crisp-recordpage-addbtn { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: 26px; padding: 0 var(--crisp-space-1-5); margin: 0; border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: pointer; }
127
119
  & .crisp-recordpage-addbtn:hover { background: var(--crisp-bg-raised); }
128
120
  & .crisp-recordpage-addbtn svg { flex-shrink: 0; }
129
-
130
121
  & .crisp-recordpage-composer { display: flex; flex-direction: column; gap: var(--crisp-space-2); padding: var(--crisp-space-2); border: 1px solid var(--crisp-border-default); border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-surface); margin-bottom: var(--crisp-space-2); }
131
122
  & .crisp-recordpage-composer textarea { width: 100%; min-height: 56px; resize: vertical; border: none; outline: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); }
132
123
  & .crisp-recordpage-composer textarea:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); border-radius: var(--crisp-radius-md); }
@@ -136,23 +127,18 @@
136
127
  & .crisp-recordpage-btn:hover { background: var(--crisp-bg-raised); }
137
128
  & .crisp-recordpage-btn--primary { box-shadow: none; background: var(--crisp-bg-brand-solid); color: var(--crisp-fg-on-brand); }
138
129
  & .crisp-recordpage-btn--primary:disabled { opacity: 0.5; cursor: not-allowed; }
139
-
140
130
  & .crisp-recordpage-note { display: flex; gap: var(--crisp-space-2-5); padding: var(--crisp-space-2-5) 0; border-top: 1px solid var(--crisp-border-subtle); }
141
131
  & .crisp-recordpage-note-body { flex: 1; min-width: 0; }
142
132
  & .crisp-recordpage-note-head { display: flex; align-items: center; gap: var(--crisp-space-1-5); margin-bottom: var(--crisp-space-0-5); }
143
133
  & .crisp-recordpage-note-author { font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
144
134
  & .crisp-recordpage-note-time { font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); }
145
135
  & .crisp-recordpage-note-text { font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); white-space: pre-wrap; word-break: break-word; }
146
-
147
136
  & .crisp-recordpage-task { display: flex; align-items: flex-start; gap: var(--crisp-space-2); padding: var(--crisp-space-1-5) 0; border-top: 1px solid var(--crisp-border-subtle); }
148
137
  & .crisp-recordpage-task-text { flex: 1; min-width: 0; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); padding-top: 1px; }
149
138
  & .crisp-recordpage-task[data-done] .crisp-recordpage-task-text { text-decoration: line-through; color: var(--crisp-fg-muted); }
150
-
151
139
  & .crisp-recordpage-emptycard { display: flex; flex-direction: column; align-items: center; gap: var(--crisp-space-1-5); padding: var(--crisp-space-6) var(--crisp-space-3); border: 1px dashed var(--crisp-border-default); border-radius: var(--crisp-radius-xl); color: var(--crisp-fg-muted); font-size: var(--crisp-text-md); text-align: center; }
152
140
  & .crisp-recordpage-emptycard svg { color: var(--crisp-fg-muted); opacity: 0.7; }
153
-
154
141
  & .crisp-recordpage-action[data-active] svg { color: #f5b83d; fill: #f5b83d; }
155
-
156
142
  & .crisp-recordstable-tag { display: inline-flex; align-items: center; height: var(--crisp-size-chip); padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-chip); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); white-space: nowrap; background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: color-mix(in srgb, var(--crisp-fg-primary) 82%, transparent); }
157
143
  & .crisp-recordstable-tag[data-tone="brand"] { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 14%, transparent); color: color-mix(in srgb, var(--crisp-bg-brand-solid) 82%, var(--crisp-fg-primary)); }
158
144
  & .crisp-recordstable-tag[data-tone="success"] { background: color-mix(in srgb, var(--crisp-bg-success) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-success) 78%, var(--crisp-fg-primary)); }
@@ -48,6 +48,10 @@
48
48
  & .crisp-recordpage-detailsearch { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: var(--crisp-size-chip); flex-shrink: 0; padding: 0; margin: 0; border: none; border-radius: var(--crisp-radius-sm); background: none; color: var(--crisp-fg-muted); font-family: inherit; cursor: pointer; transition: background-color .12s, color .12s; }
49
49
  & .crisp-recordpage-detailsearch:hover, & .crisp-recordpage-detailsearch[data-active] { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
50
50
  & .crisp-recordpage-noresults { padding: var(--crisp-space-1-5) var(--crisp-space-1); font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
51
+ /* A caller-supplied `sections` grouping (#528) is not an Attio-measured
52
+ shape (its own Details column is flat) -- this heading reuses
53
+ .crisp-recordpage-section-title's own type treatment verbatim, just spaced from the group above it. */
54
+ & .crisp-recordpage-fieldsection-title { margin-top: var(--crisp-space-3); }
51
55
  & .crisp-recordpage-morevalues { display: inline-flex; align-items: center; padding: 0; margin: 0; border: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-muted); cursor: pointer; }
52
56
  & .crisp-recordpage-morevalues:hover { color: var(--crisp-fg-primary); }
53
57
  & .crisp-recordpage-viewall { flex-basis: 100%; margin-top: var(--crisp-space-0-5); border: none; background: none; padding: 0; color: color-mix(in srgb, var(--crisp-fg-primary) 55%, transparent); font-family: inherit; font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-regular); cursor: pointer; text-align: start; }
@@ -62,31 +66,25 @@
62
66
  & .crisp-recordpage-field-label-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
63
67
  & .crisp-recordpage-field-value { flex: 1; min-width: 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--crisp-space-1); padding-top: 2px; line-height: 20px; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
64
68
  & .crisp-recordpage-field-value[data-editable] { cursor: pointer; }
65
- /* the click-to-edit trigger is a real <button> (keyboard-operable),
66
- reset back to plain inline text and made a flex-wrap container of its
67
- own -- FieldValue can render several chips (tags), which still need
68
- to wrap the way they did before this had a button around them at
69
- all. It wraps only FieldValue, never the error slot beside it (see
70
- the component's own comment) -- NOT `display: contents`, which drops a button's accessible semantics in some engines. */
69
+ /* the click-to-edit trigger is a real <button> (keyboard-operable), reset back to plain inline text and made a flex-wrap container of its own -- FieldValue can render several chips (tags), which still need to wrap the way they did before this had a button around them at all. It wraps only FieldValue, never the error slot beside it (see the component's own comment) -- NOT `display: contents`, which
70
+ drops a button's accessible semantics in some engines. */
71
71
  & .crisp-recordpage-edit-trigger { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--crisp-space-1); margin: 0; padding: 0; border: none; background: none; text-align: start; font: inherit; color: inherit; cursor: pointer; }
72
72
  & .crisp-recordpage-empty { color: var(--crisp-fg-muted); }
73
-
74
- /* #431: measured live on app.attio.com's record page Details column -- clicking a field's value opens a plain, borderless field exactly
75
- filling the value's own box (no border, no background, no box-shadow), same font as the value it replaces (hence `font: inherit`, not a restated size/weight). A field row's own hover tint
76
- above already carries the "this is interactive" affordance; the
77
- pending/error treatment isn't Attio-measured -- it reuses the same tokens DataTable's identical states already use (opacity 0.5,
78
- `bgDanger`), per #385/#430. */
73
+ /* #431: measured live on app.attio.com's record page Details column --
74
+ clicking a field's value opens a plain, borderless field exactly filling the value's own box (no border, no background, no
75
+ box-shadow), same font as the value it replaces (hence `font:
76
+ inherit`, not a restated size/weight). A field row's own hover tint above already carries the "this is interactive" affordance; the pending/error treatment isn't Attio-measured -- it reuses the same
77
+ tokens DataTable's identical states already use (opacity 0.5, `bgDanger`), per #385/#430. */
79
78
  & .crisp-recordpage-edit { display: block; width: 100%; margin: 0; padding: 0; border: none; border-radius: var(--crisp-radius-sm); background: none; box-shadow: none; outline: none; font: inherit; color: inherit; }
80
- /* not Attio-measured (its own field shows no focus ring either, caret
81
- only) -- kept for real keyboard users, the same brand ring every
82
- other crisp field already shows on focus (DataTable's identical .crisp-datatable-edit:focus, e.g.). */
79
+ /* not Attio-measured (its own field shows no focus ring either, caret only) -- kept for real keyboard users, the same brand ring every other crisp field already shows on focus (DataTable's identical
80
+ .crisp-datatable-edit:focus, e.g.). */
83
81
  & .crisp-recordpage-edit:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
84
82
  & .crisp-recordpage-edit:disabled { opacity: 0.5; cursor: not-allowed; }
85
83
  & .crisp-recordpage-edit-pending { flex-shrink: 0; color: var(--crisp-fg-muted); }
86
84
  & .crisp-recordpage-edit-error { flex-basis: 100%; margin-top: var(--crisp-space-0-5); font-size: var(--crisp-text-sm); color: var(--crisp-bg-danger); }
87
- /* #457: an `editor: "select"` field's at-rest chip -- same shape as
88
- RecordsTable's own `.crisp-recordstable-status[-dot]` (already measured against Attio there), but its own classes: that pair is scoped under `.crisp-recordstable`'s own recipe root, so reusing the
89
- classnames verbatim here would resolve to nothing. */
85
+ /* #457: an `editor: "select"` field's at-rest chip -- same shape as RecordsTable's own `.crisp-recordstable-status[-dot]` (already
86
+ measured against Attio there), but its own classes: that pair is
87
+ scoped under `.crisp-recordstable`'s own recipe root, so reusing the classnames verbatim here would resolve to nothing. */
90
88
  & .crisp-recordpage-status { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; }
91
89
  & .crisp-recordpage-status-dot { flex-shrink: 0; width: 8px; height: 8px; border-radius: var(--crisp-radius-full); }
92
90
  & .crisp-recordpage-edit-picker { display: flex; align-items: center; gap: var(--crisp-space-1); width: 100%; }
@@ -94,23 +92,18 @@
94
92
  & .crisp-recordpage-link { color: var(--crisp-fg-primary); text-decoration: none; overflow: hidden; text-overflow: ellipsis; }
95
93
  & .crisp-recordpage-link:hover { text-decoration: underline; }
96
94
  & .crisp-recordpage-emptystate { padding: var(--crisp-space-2) var(--crisp-space-1); font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
97
-
98
95
  & .crisp-recordpage-main { flex: 1; min-width: 0; display: flex; flex-direction: column; min-height: 0; overflow-y: auto; padding: var(--crisp-space-3) var(--crisp-space-5); }
99
-
100
96
  & .crisp-recordpage-panel { padding-top: var(--crisp-space-4); display: flex; flex-direction: column; gap: var(--crisp-space-4); }
101
97
  & .crisp-recordpage-card { border: 1px solid var(--crisp-border-subtle); border-radius: var(--crisp-radius-2xl); background: var(--crisp-bg-surface); overflow: hidden; }
102
98
  & .crisp-recordpage-card-title { font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-semibold); letter-spacing: -0.14px; color: var(--crisp-fg-primary); padding: var(--crisp-space-3) var(--crisp-space-3) var(--crisp-space-2); }
103
99
  & .crisp-recordpage-hl-card { border: 1px solid var(--crisp-border-subtle); border-radius: var(--crisp-radius-2xl); overflow: hidden; }
104
- /* gap-as-gridlines: a 1px gap over the border colour draws dividers at any
105
- column count, so the grid stays responsive (auto-fit) without per-cell
106
- nth-child border hacks that break when the column count changes. */
100
+ /* gap-as-gridlines: a 1px gap over the border colour draws dividers at any column count, so the grid stays responsive (auto-fit) without per-cell nth-child border hacks that break when the column count changes. */
107
101
  & .crisp-recordpage-hl-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 1px; background: var(--crisp-border-subtle); }
108
102
  & .crisp-recordpage-hl-cell { position: relative; min-height: 84px; padding: var(--crisp-space-2-5) var(--crisp-space-3); background: var(--crisp-bg-surface); }
109
103
  & .crisp-recordpage-hl-icon { position: absolute; top: var(--crisp-space-2-5); inset-inline-end: var(--crisp-space-3); color: var(--crisp-fg-muted); }
110
104
  & .crisp-recordpage-hl-label { font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); margin-bottom: var(--crisp-space-2-5); padding-inline-end: var(--crisp-space-4); }
111
105
  & .crisp-recordpage-hl-value { display: flex; flex-wrap: wrap; align-items: center; gap: var(--crisp-space-1); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
112
106
  & .crisp-recordpage-hl-value--empty { color: var(--crisp-fg-muted); font-weight: var(--crisp-weight-regular); }
113
-
114
107
  & .crisp-recordpage-feed { display: flex; flex-direction: column; }
115
108
  & .crisp-recordpage-feed-item { display: flex; align-items: flex-start; gap: var(--crisp-space-2-5); padding: var(--crisp-space-2) 0; }
116
109
  & .crisp-recordpage-feed-dot { position: relative; display: flex; align-items: center; justify-content: center; width: 24px; height: 24px; flex-shrink: 0; border-radius: var(--crisp-radius-full); background: var(--crisp-bg-raised); color: var(--crisp-fg-muted); }
@@ -119,7 +112,6 @@
119
112
  & .crisp-recordpage-feed-time { font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); margin-top: 2px; }
120
113
  & .crisp-recordpage-feed-more { align-self: flex-start; margin-top: var(--crisp-space-1); border: none; background: none; padding: var(--crisp-space-1) 0; color: var(--crisp-bg-brand-solid); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: pointer; }
121
114
  & .crisp-recordpage-feed-more:hover { text-decoration: underline; }
122
-
123
115
  & .crisp-recordpage-section-head { display: flex; align-items: center; gap: var(--crisp-space-1-5); padding: var(--crisp-space-1); }
124
116
  & .crisp-recordpage-section-head .crisp-recordpage-section-title { padding: 0; }
125
117
  & .crisp-recordpage-section-count { display: inline-flex; align-items: center; justify-content: center; min-width: 16px; height: 16px; padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-sm); background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); font-size: var(--crisp-text-xs); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
@@ -127,7 +119,6 @@
127
119
  & .crisp-recordpage-addbtn { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: 26px; padding: 0 var(--crisp-space-1-5); margin: 0; border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: pointer; }
128
120
  & .crisp-recordpage-addbtn:hover { background: var(--crisp-bg-raised); }
129
121
  & .crisp-recordpage-addbtn svg { flex-shrink: 0; }
130
-
131
122
  & .crisp-recordpage-composer { display: flex; flex-direction: column; gap: var(--crisp-space-2); padding: var(--crisp-space-2); border: 1px solid var(--crisp-border-default); border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-surface); margin-bottom: var(--crisp-space-2); }
132
123
  & .crisp-recordpage-composer textarea { width: 100%; min-height: 56px; resize: vertical; border: none; outline: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); }
133
124
  & .crisp-recordpage-composer textarea:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); border-radius: var(--crisp-radius-md); }
@@ -137,23 +128,18 @@
137
128
  & .crisp-recordpage-btn:hover { background: var(--crisp-bg-raised); }
138
129
  & .crisp-recordpage-btn--primary { box-shadow: none; background: var(--crisp-bg-brand-solid); color: var(--crisp-fg-on-brand); }
139
130
  & .crisp-recordpage-btn--primary:disabled { opacity: 0.5; cursor: not-allowed; }
140
-
141
131
  & .crisp-recordpage-note { display: flex; gap: var(--crisp-space-2-5); padding: var(--crisp-space-2-5) 0; border-top: 1px solid var(--crisp-border-subtle); }
142
132
  & .crisp-recordpage-note-body { flex: 1; min-width: 0; }
143
133
  & .crisp-recordpage-note-head { display: flex; align-items: center; gap: var(--crisp-space-1-5); margin-bottom: var(--crisp-space-0-5); }
144
134
  & .crisp-recordpage-note-author { font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
145
135
  & .crisp-recordpage-note-time { font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); }
146
136
  & .crisp-recordpage-note-text { font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); white-space: pre-wrap; word-break: break-word; }
147
-
148
137
  & .crisp-recordpage-task { display: flex; align-items: flex-start; gap: var(--crisp-space-2); padding: var(--crisp-space-1-5) 0; border-top: 1px solid var(--crisp-border-subtle); }
149
138
  & .crisp-recordpage-task-text { flex: 1; min-width: 0; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); padding-top: 1px; }
150
139
  & .crisp-recordpage-task[data-done] .crisp-recordpage-task-text { text-decoration: line-through; color: var(--crisp-fg-muted); }
151
-
152
140
  & .crisp-recordpage-emptycard { display: flex; flex-direction: column; align-items: center; gap: var(--crisp-space-1-5); padding: var(--crisp-space-6) var(--crisp-space-3); border: 1px dashed var(--crisp-border-default); border-radius: var(--crisp-radius-xl); color: var(--crisp-fg-muted); font-size: var(--crisp-text-md); text-align: center; }
153
141
  & .crisp-recordpage-emptycard svg { color: var(--crisp-fg-muted); opacity: 0.7; }
154
-
155
142
  & .crisp-recordpage-action[data-active] svg { color: #f5b83d; fill: #f5b83d; }
156
-
157
143
  & .crisp-recordstable-tag { display: inline-flex; align-items: center; height: var(--crisp-size-chip); padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-chip); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); white-space: nowrap; background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: color-mix(in srgb, var(--crisp-fg-primary) 82%, transparent); }
158
144
  & .crisp-recordstable-tag[data-tone="brand"] { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 14%, transparent); color: color-mix(in srgb, var(--crisp-bg-brand-solid) 82%, var(--crisp-fg-primary)); }
159
145
  & .crisp-recordstable-tag[data-tone="success"] { background: color-mix(in srgb, var(--crisp-bg-success) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-success) 78%, var(--crisp-fg-primary)); }
@@ -2,8 +2,8 @@
2
2
  display: flex; flex-direction: column; box-sizing: border-box; font-family: var(--crisp-font-sans);
3
3
  & .crisp-settingssection-head { display: flex; align-items: flex-start; gap: var(--crisp-space-2); }
4
4
  & .crisp-settingssection-heading { flex: 1; min-width: 0; }
5
- & .crisp-settingssection-title { font-size: var(--crisp-text-xl); line-height: 24px; font-weight: var(--crisp-weight-semibold); letter-spacing: -0.2px; color: var(--crisp-fg-primary); }
6
- & .crisp-settingssection-sub { margin-top: var(--crisp-space-0-5); font-size: var(--crisp-text-md); line-height: 18px; color: var(--crisp-fg-muted); }
5
+ & .crisp-settingssection-title { font-size: var(--crisp-text-xl); line-height: 20px; font-weight: var(--crisp-weight-semibold); letter-spacing: -0.16px; color: var(--crisp-fg-primary); }
6
+ & .crisp-settingssection-sub { margin-top: var(--crisp-space-0-5); font-size: var(--crisp-text-lg); line-height: 20px; color: var(--crisp-fg-muted); }
7
7
  & .crisp-settingssection-action { flex-shrink: 0; }
8
8
  & .crisp-settingssection-body { display: flex; flex-direction: column; gap: var(--crisp-space-4); margin-top: var(--crisp-space-3); }
9
9
  }
@@ -3,8 +3,8 @@
3
3
  display: flex; flex-direction: column; box-sizing: border-box; font-family: var(--crisp-font-sans);
4
4
  & .crisp-settingssection-head { display: flex; align-items: flex-start; gap: var(--crisp-space-2); }
5
5
  & .crisp-settingssection-heading { flex: 1; min-width: 0; }
6
- & .crisp-settingssection-title { font-size: var(--crisp-text-xl); line-height: 24px; font-weight: var(--crisp-weight-semibold); letter-spacing: -0.2px; color: var(--crisp-fg-primary); }
7
- & .crisp-settingssection-sub { margin-top: var(--crisp-space-0-5); font-size: var(--crisp-text-md); line-height: 18px; color: var(--crisp-fg-muted); }
6
+ & .crisp-settingssection-title { font-size: var(--crisp-text-xl); line-height: 20px; font-weight: var(--crisp-weight-semibold); letter-spacing: -0.16px; color: var(--crisp-fg-primary); }
7
+ & .crisp-settingssection-sub { margin-top: var(--crisp-space-0-5); font-size: var(--crisp-text-lg); line-height: 20px; color: var(--crisp-fg-muted); }
8
8
  & .crisp-settingssection-action { flex-shrink: 0; }
9
9
  & .crisp-settingssection-body { display: flex; flex-direction: column; gap: var(--crisp-space-4); margin-top: var(--crisp-space-3); }
10
10
  }
@@ -0,0 +1,5 @@
1
+ .crisp-skiplink {
2
+ position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; text-decoration: none; font-family: var(--crisp-font-sans); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary);
3
+ &:focus { position: fixed; top: var(--crisp-space-3); inset-inline-start: var(--crisp-space-3); z-index: 90; width: auto; height: auto; margin: 0; overflow: visible; clip: auto; white-space: normal; padding: var(--crisp-space-2) var(--crisp-space-3); border-radius: var(--crisp-radius-md); background: var(--crisp-bg-popover); box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); }
4
+ &:focus-visible { outline: 2px solid var(--crisp-bg-brand-solid); outline-offset: 1px; }
5
+ }
@@ -0,0 +1,7 @@
1
+ import type { RecipeFn } from "../core/types";
2
+
3
+ export interface SkiplinkVariants {
4
+
5
+ }
6
+
7
+ export declare const skiplinkRecipe: RecipeFn<{ }>;
@@ -0,0 +1,7 @@
1
+ @layer crisp-components {
2
+ .crisp-skiplink {
3
+ position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; text-decoration: none; font-family: var(--crisp-font-sans); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary);
4
+ &:focus { position: fixed; top: var(--crisp-space-3); inset-inline-start: var(--crisp-space-3); z-index: 90; width: auto; height: auto; margin: 0; overflow: visible; clip: auto; white-space: normal; padding: var(--crisp-space-2) var(--crisp-space-3); border-radius: var(--crisp-radius-md); background: var(--crisp-bg-popover); box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); }
5
+ &:focus-visible { outline: 2px solid var(--crisp-bg-brand-solid); outline-offset: 1px; }
6
+ }
7
+ }
package/dist/styles.css CHANGED
@@ -1490,6 +1490,12 @@
1490
1490
  }
1491
1491
  }
1492
1492
 
1493
+ .crisp-skiplink {
1494
+ position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; text-decoration: none; font-family: var(--crisp-font-sans); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary);
1495
+ &:focus { position: fixed; top: var(--crisp-space-3); inset-inline-start: var(--crisp-space-3); z-index: 90; width: auto; height: auto; margin: 0; overflow: visible; clip: auto; white-space: normal; padding: var(--crisp-space-2) var(--crisp-space-3); border-radius: var(--crisp-radius-md); background: var(--crisp-bg-popover); box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); }
1496
+ &:focus-visible { outline: 2px solid var(--crisp-bg-brand-solid); outline-offset: 1px; }
1497
+ }
1498
+
1493
1499
  .crisp-slider {
1494
1500
  display: flex; flex-direction: column; align-items: stretch; width: 100%; min-width: 0; gap: var(--crisp-space-0-5); font-family: var(--crisp-font-sans); user-select: none; touch-action: none; /* the position words ("minimum"/"maximum") that ARIA concatenates onto a thumb's name — read, never drawn */
1495
1501
  & .crisp-slider-thumblabel {
@@ -1784,6 +1790,18 @@
1784
1790
  }
1785
1791
  }
1786
1792
 
1793
+ .crisp-textlink {
1794
+ display: inline; font-family: var(--crisp-font-sans); text-decoration: none; cursor: pointer;
1795
+ &:hover { text-decoration: underline; }
1796
+ }
1797
+ .crisp-textlink--tone_brand {
1798
+ font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: var(--crisp-bg-brand-solid);
1799
+ }
1800
+ .crisp-textlink--tone_muted {
1801
+ font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-regular); color: var(--crisp-fg-muted);
1802
+ &:hover { color: var(--crisp-bg-brand-solid); }
1803
+ }
1804
+
1787
1805
  .crisp-toast {
1788
1806
  display: contents; font-family: var(--crisp-font-sans);
1789
1807
  & .crisp-toast-viewport { position: fixed; z-index: 80; inset-inline-end: var(--crisp-space-4); top: var(--crisp-space-4); display: flex; flex-direction: column; gap: var(--crisp-space-2); width: 360px; max-width: calc(100vw - var(--crisp-space-8)); pointer-events: none; }
@@ -1823,6 +1841,10 @@
1823
1841
  }
1824
1842
  }
1825
1843
 
1844
+ .crisp-visuallyhidden {
1845
+ position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
1846
+ }
1847
+
1826
1848
  .crisp-wheelpicker {
1827
1849
  position: relative; box-sizing: border-box; width: 100%; overflow: hidden; background: var(--crisp-bg-surface); font-family: var(--crisp-font-sans); /* the band the selected row sits in; behind the items, never hit-tested */
1828
1850
  & .crisp-wheelpicker-indicator { position: absolute; z-index: 0; inset-inline: var(--crisp-space-4); top: 50%; transform: translateY(-50%); border-radius: var(--crisp-radius-md); background: var(--crisp-bg-neutral-weak); pointer-events: none; }
@@ -2019,6 +2041,14 @@
2019
2041
  & .crisp-flowcanvas-tool-sep { width: 1px; height: 18px; background: var(--crisp-border-subtle); }
2020
2042
  }
2021
2043
 
2044
+ .crisp-headerbar {
2045
+ box-sizing: border-box; display: flex; align-items: center; justify-content: space-between; gap: var(--crisp-space-2); height: var(--crisp-size-header); flex-shrink: 0; padding: 0 var(--crisp-space-3); font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
2046
+ &[data-bordered] { border-bottom: 1px solid var(--crisp-border-subtle); }
2047
+ & .crisp-headerbar-leading { display: flex; align-items: center; gap: var(--crisp-space-2); flex-shrink: 0; min-width: 0; }
2048
+ & .crisp-headerbar-title { flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--crisp-space-2); overflow: hidden; }
2049
+ & .crisp-headerbar-trailing { display: flex; align-items: center; gap: var(--crisp-space-2); flex-shrink: 0; }
2050
+ }
2051
+
2022
2052
  .crisp-inbox {
2023
2053
  display: flex; flex-direction: column; box-sizing: border-box; width: 380px; max-height: 588px; border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-surface); font-family: var(--crisp-font-sans); overflow: hidden; box-shadow: inset 0 0 0 1px var(--crisp-ring-popover), 0 0 0 1px var(--crisp-shadow-popover1), 0 4px 8px -4px var(--crisp-shadow-popover2), 0 4px 12px -2px var(--crisp-shadow-popover3); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
2024
2054
  & .crisp-inbox-head { padding: var(--crisp-space-3) var(--crisp-space-3) 0; }
@@ -2179,6 +2209,10 @@
2179
2209
  & .crisp-recordpage-detailsearch { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: var(--crisp-size-chip); flex-shrink: 0; padding: 0; margin: 0; border: none; border-radius: var(--crisp-radius-sm); background: none; color: var(--crisp-fg-muted); font-family: inherit; cursor: pointer; transition: background-color .12s, color .12s; }
2180
2210
  & .crisp-recordpage-detailsearch:hover, & .crisp-recordpage-detailsearch[data-active] { background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); }
2181
2211
  & .crisp-recordpage-noresults { padding: var(--crisp-space-1-5) var(--crisp-space-1); font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
2212
+ /* A caller-supplied `sections` grouping (#528) is not an Attio-measured
2213
+ shape (its own Details column is flat) -- this heading reuses
2214
+ .crisp-recordpage-section-title's own type treatment verbatim, just spaced from the group above it. */
2215
+ & .crisp-recordpage-fieldsection-title { margin-top: var(--crisp-space-3); }
2182
2216
  & .crisp-recordpage-morevalues { display: inline-flex; align-items: center; padding: 0; margin: 0; border: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-muted); cursor: pointer; }
2183
2217
  & .crisp-recordpage-morevalues:hover { color: var(--crisp-fg-primary); }
2184
2218
  & .crisp-recordpage-viewall { flex-basis: 100%; margin-top: var(--crisp-space-0-5); border: none; background: none; padding: 0; color: color-mix(in srgb, var(--crisp-fg-primary) 55%, transparent); font-family: inherit; font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-regular); cursor: pointer; text-align: start; }
@@ -2193,31 +2227,25 @@
2193
2227
  & .crisp-recordpage-field-label-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
2194
2228
  & .crisp-recordpage-field-value { flex: 1; min-width: 0; display: flex; flex-wrap: wrap; align-items: center; gap: var(--crisp-space-1); padding-top: 2px; line-height: 20px; font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
2195
2229
  & .crisp-recordpage-field-value[data-editable] { cursor: pointer; }
2196
- /* the click-to-edit trigger is a real <button> (keyboard-operable),
2197
- reset back to plain inline text and made a flex-wrap container of its
2198
- own -- FieldValue can render several chips (tags), which still need
2199
- to wrap the way they did before this had a button around them at
2200
- all. It wraps only FieldValue, never the error slot beside it (see
2201
- the component's own comment) -- NOT `display: contents`, which drops a button's accessible semantics in some engines. */
2230
+ /* the click-to-edit trigger is a real <button> (keyboard-operable), reset back to plain inline text and made a flex-wrap container of its own -- FieldValue can render several chips (tags), which still need to wrap the way they did before this had a button around them at all. It wraps only FieldValue, never the error slot beside it (see the component's own comment) -- NOT `display: contents`, which
2231
+ drops a button's accessible semantics in some engines. */
2202
2232
  & .crisp-recordpage-edit-trigger { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--crisp-space-1); margin: 0; padding: 0; border: none; background: none; text-align: start; font: inherit; color: inherit; cursor: pointer; }
2203
2233
  & .crisp-recordpage-empty { color: var(--crisp-fg-muted); }
2204
-
2205
- /* #431: measured live on app.attio.com's record page Details column -- clicking a field's value opens a plain, borderless field exactly
2206
- filling the value's own box (no border, no background, no box-shadow), same font as the value it replaces (hence `font: inherit`, not a restated size/weight). A field row's own hover tint
2207
- above already carries the "this is interactive" affordance; the
2208
- pending/error treatment isn't Attio-measured -- it reuses the same tokens DataTable's identical states already use (opacity 0.5,
2209
- `bgDanger`), per #385/#430. */
2234
+ /* #431: measured live on app.attio.com's record page Details column --
2235
+ clicking a field's value opens a plain, borderless field exactly filling the value's own box (no border, no background, no
2236
+ box-shadow), same font as the value it replaces (hence `font:
2237
+ inherit`, not a restated size/weight). A field row's own hover tint above already carries the "this is interactive" affordance; the pending/error treatment isn't Attio-measured -- it reuses the same
2238
+ tokens DataTable's identical states already use (opacity 0.5, `bgDanger`), per #385/#430. */
2210
2239
  & .crisp-recordpage-edit { display: block; width: 100%; margin: 0; padding: 0; border: none; border-radius: var(--crisp-radius-sm); background: none; box-shadow: none; outline: none; font: inherit; color: inherit; }
2211
- /* not Attio-measured (its own field shows no focus ring either, caret
2212
- only) -- kept for real keyboard users, the same brand ring every
2213
- other crisp field already shows on focus (DataTable's identical .crisp-datatable-edit:focus, e.g.). */
2240
+ /* not Attio-measured (its own field shows no focus ring either, caret only) -- kept for real keyboard users, the same brand ring every other crisp field already shows on focus (DataTable's identical
2241
+ .crisp-datatable-edit:focus, e.g.). */
2214
2242
  & .crisp-recordpage-edit:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); }
2215
2243
  & .crisp-recordpage-edit:disabled { opacity: 0.5; cursor: not-allowed; }
2216
2244
  & .crisp-recordpage-edit-pending { flex-shrink: 0; color: var(--crisp-fg-muted); }
2217
2245
  & .crisp-recordpage-edit-error { flex-basis: 100%; margin-top: var(--crisp-space-0-5); font-size: var(--crisp-text-sm); color: var(--crisp-bg-danger); }
2218
- /* #457: an `editor: "select"` field's at-rest chip -- same shape as
2219
- RecordsTable's own `.crisp-recordstable-status[-dot]` (already measured against Attio there), but its own classes: that pair is scoped under `.crisp-recordstable`'s own recipe root, so reusing the
2220
- classnames verbatim here would resolve to nothing. */
2246
+ /* #457: an `editor: "select"` field's at-rest chip -- same shape as RecordsTable's own `.crisp-recordstable-status[-dot]` (already
2247
+ measured against Attio there), but its own classes: that pair is
2248
+ scoped under `.crisp-recordstable`'s own recipe root, so reusing the classnames verbatim here would resolve to nothing. */
2221
2249
  & .crisp-recordpage-status { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); min-width: 0; }
2222
2250
  & .crisp-recordpage-status-dot { flex-shrink: 0; width: 8px; height: 8px; border-radius: var(--crisp-radius-full); }
2223
2251
  & .crisp-recordpage-edit-picker { display: flex; align-items: center; gap: var(--crisp-space-1); width: 100%; }
@@ -2225,23 +2253,18 @@
2225
2253
  & .crisp-recordpage-link { color: var(--crisp-fg-primary); text-decoration: none; overflow: hidden; text-overflow: ellipsis; }
2226
2254
  & .crisp-recordpage-link:hover { text-decoration: underline; }
2227
2255
  & .crisp-recordpage-emptystate { padding: var(--crisp-space-2) var(--crisp-space-1); font-size: var(--crisp-text-md); color: var(--crisp-fg-muted); }
2228
-
2229
2256
  & .crisp-recordpage-main { flex: 1; min-width: 0; display: flex; flex-direction: column; min-height: 0; overflow-y: auto; padding: var(--crisp-space-3) var(--crisp-space-5); }
2230
-
2231
2257
  & .crisp-recordpage-panel { padding-top: var(--crisp-space-4); display: flex; flex-direction: column; gap: var(--crisp-space-4); }
2232
2258
  & .crisp-recordpage-card { border: 1px solid var(--crisp-border-subtle); border-radius: var(--crisp-radius-2xl); background: var(--crisp-bg-surface); overflow: hidden; }
2233
2259
  & .crisp-recordpage-card-title { font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-semibold); letter-spacing: -0.14px; color: var(--crisp-fg-primary); padding: var(--crisp-space-3) var(--crisp-space-3) var(--crisp-space-2); }
2234
2260
  & .crisp-recordpage-hl-card { border: 1px solid var(--crisp-border-subtle); border-radius: var(--crisp-radius-2xl); overflow: hidden; }
2235
- /* gap-as-gridlines: a 1px gap over the border colour draws dividers at any
2236
- column count, so the grid stays responsive (auto-fit) without per-cell
2237
- nth-child border hacks that break when the column count changes. */
2261
+ /* gap-as-gridlines: a 1px gap over the border colour draws dividers at any column count, so the grid stays responsive (auto-fit) without per-cell nth-child border hacks that break when the column count changes. */
2238
2262
  & .crisp-recordpage-hl-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 1px; background: var(--crisp-border-subtle); }
2239
2263
  & .crisp-recordpage-hl-cell { position: relative; min-height: 84px; padding: var(--crisp-space-2-5) var(--crisp-space-3); background: var(--crisp-bg-surface); }
2240
2264
  & .crisp-recordpage-hl-icon { position: absolute; top: var(--crisp-space-2-5); inset-inline-end: var(--crisp-space-3); color: var(--crisp-fg-muted); }
2241
2265
  & .crisp-recordpage-hl-label { font-size: var(--crisp-text-sm); font-weight: var(--crisp-weight-medium); color: color-mix(in srgb, var(--crisp-fg-primary) 63%, transparent); margin-bottom: var(--crisp-space-2-5); padding-inline-end: var(--crisp-space-4); }
2242
2266
  & .crisp-recordpage-hl-value { display: flex; flex-wrap: wrap; align-items: center; gap: var(--crisp-space-1); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
2243
2267
  & .crisp-recordpage-hl-value--empty { color: var(--crisp-fg-muted); font-weight: var(--crisp-weight-regular); }
2244
-
2245
2268
  & .crisp-recordpage-feed { display: flex; flex-direction: column; }
2246
2269
  & .crisp-recordpage-feed-item { display: flex; align-items: flex-start; gap: var(--crisp-space-2-5); padding: var(--crisp-space-2) 0; }
2247
2270
  & .crisp-recordpage-feed-dot { position: relative; display: flex; align-items: center; justify-content: center; width: 24px; height: 24px; flex-shrink: 0; border-radius: var(--crisp-radius-full); background: var(--crisp-bg-raised); color: var(--crisp-fg-muted); }
@@ -2250,7 +2273,6 @@
2250
2273
  & .crisp-recordpage-feed-time { font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); margin-top: 2px; }
2251
2274
  & .crisp-recordpage-feed-more { align-self: flex-start; margin-top: var(--crisp-space-1); border: none; background: none; padding: var(--crisp-space-1) 0; color: var(--crisp-bg-brand-solid); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: pointer; }
2252
2275
  & .crisp-recordpage-feed-more:hover { text-decoration: underline; }
2253
-
2254
2276
  & .crisp-recordpage-section-head { display: flex; align-items: center; gap: var(--crisp-space-1-5); padding: var(--crisp-space-1); }
2255
2277
  & .crisp-recordpage-section-head .crisp-recordpage-section-title { padding: 0; }
2256
2278
  & .crisp-recordpage-section-count { display: inline-flex; align-items: center; justify-content: center; min-width: 16px; height: 16px; padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-sm); background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); font-size: var(--crisp-text-xs); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
@@ -2258,7 +2280,6 @@
2258
2280
  & .crisp-recordpage-addbtn { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: 26px; padding: 0 var(--crisp-space-1-5); margin: 0; border: none; border-radius: var(--crisp-radius-md); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); cursor: pointer; }
2259
2281
  & .crisp-recordpage-addbtn:hover { background: var(--crisp-bg-raised); }
2260
2282
  & .crisp-recordpage-addbtn svg { flex-shrink: 0; }
2261
-
2262
2283
  & .crisp-recordpage-composer { display: flex; flex-direction: column; gap: var(--crisp-space-2); padding: var(--crisp-space-2); border: 1px solid var(--crisp-border-default); border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-surface); margin-bottom: var(--crisp-space-2); }
2263
2284
  & .crisp-recordpage-composer textarea { width: 100%; min-height: 56px; resize: vertical; border: none; outline: none; background: none; font-family: inherit; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); }
2264
2285
  & .crisp-recordpage-composer textarea:focus { box-shadow: inset 0 0 0 1px var(--crisp-bg-brand-solid); border-radius: var(--crisp-radius-md); }
@@ -2268,23 +2289,18 @@
2268
2289
  & .crisp-recordpage-btn:hover { background: var(--crisp-bg-raised); }
2269
2290
  & .crisp-recordpage-btn--primary { box-shadow: none; background: var(--crisp-bg-brand-solid); color: var(--crisp-fg-on-brand); }
2270
2291
  & .crisp-recordpage-btn--primary:disabled { opacity: 0.5; cursor: not-allowed; }
2271
-
2272
2292
  & .crisp-recordpage-note { display: flex; gap: var(--crisp-space-2-5); padding: var(--crisp-space-2-5) 0; border-top: 1px solid var(--crisp-border-subtle); }
2273
2293
  & .crisp-recordpage-note-body { flex: 1; min-width: 0; }
2274
2294
  & .crisp-recordpage-note-head { display: flex; align-items: center; gap: var(--crisp-space-1-5); margin-bottom: var(--crisp-space-0-5); }
2275
2295
  & .crisp-recordpage-note-author { font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-primary); }
2276
2296
  & .crisp-recordpage-note-time { font-size: var(--crisp-text-sm); color: var(--crisp-fg-muted); }
2277
2297
  & .crisp-recordpage-note-text { font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); white-space: pre-wrap; word-break: break-word; }
2278
-
2279
2298
  & .crisp-recordpage-task { display: flex; align-items: flex-start; gap: var(--crisp-space-2); padding: var(--crisp-space-1-5) 0; border-top: 1px solid var(--crisp-border-subtle); }
2280
2299
  & .crisp-recordpage-task-text { flex: 1; min-width: 0; font-size: var(--crisp-text-lg); color: var(--crisp-fg-primary); padding-top: 1px; }
2281
2300
  & .crisp-recordpage-task[data-done] .crisp-recordpage-task-text { text-decoration: line-through; color: var(--crisp-fg-muted); }
2282
-
2283
2301
  & .crisp-recordpage-emptycard { display: flex; flex-direction: column; align-items: center; gap: var(--crisp-space-1-5); padding: var(--crisp-space-6) var(--crisp-space-3); border: 1px dashed var(--crisp-border-default); border-radius: var(--crisp-radius-xl); color: var(--crisp-fg-muted); font-size: var(--crisp-text-md); text-align: center; }
2284
2302
  & .crisp-recordpage-emptycard svg { color: var(--crisp-fg-muted); opacity: 0.7; }
2285
-
2286
2303
  & .crisp-recordpage-action[data-active] svg { color: #f5b83d; fill: #f5b83d; }
2287
-
2288
2304
  & .crisp-recordstable-tag { display: inline-flex; align-items: center; height: var(--crisp-size-chip); padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-chip); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); white-space: nowrap; background: color-mix(in srgb, var(--crisp-fg-primary) 6%, transparent); color: color-mix(in srgb, var(--crisp-fg-primary) 82%, transparent); }
2289
2305
  & .crisp-recordstable-tag[data-tone="brand"] { background: color-mix(in srgb, var(--crisp-bg-brand-solid) 14%, transparent); color: color-mix(in srgb, var(--crisp-bg-brand-solid) 82%, var(--crisp-fg-primary)); }
2290
2306
  & .crisp-recordstable-tag[data-tone="success"] { background: color-mix(in srgb, var(--crisp-bg-success) 16%, transparent); color: color-mix(in srgb, var(--crisp-bg-success) 78%, var(--crisp-fg-primary)); }
@@ -2674,8 +2690,8 @@
2674
2690
  display: flex; flex-direction: column; box-sizing: border-box; font-family: var(--crisp-font-sans);
2675
2691
  & .crisp-settingssection-head { display: flex; align-items: flex-start; gap: var(--crisp-space-2); }
2676
2692
  & .crisp-settingssection-heading { flex: 1; min-width: 0; }
2677
- & .crisp-settingssection-title { font-size: var(--crisp-text-xl); line-height: 24px; font-weight: var(--crisp-weight-semibold); letter-spacing: -0.2px; color: var(--crisp-fg-primary); }
2678
- & .crisp-settingssection-sub { margin-top: var(--crisp-space-0-5); font-size: var(--crisp-text-md); line-height: 18px; color: var(--crisp-fg-muted); }
2693
+ & .crisp-settingssection-title { font-size: var(--crisp-text-xl); line-height: 20px; font-weight: var(--crisp-weight-semibold); letter-spacing: -0.16px; color: var(--crisp-fg-primary); }
2694
+ & .crisp-settingssection-sub { margin-top: var(--crisp-space-0-5); font-size: var(--crisp-text-lg); line-height: 20px; color: var(--crisp-fg-muted); }
2679
2695
  & .crisp-settingssection-action { flex-shrink: 0; }
2680
2696
  & .crisp-settingssection-body { display: flex; flex-direction: column; gap: var(--crisp-space-4); margin-top: var(--crisp-space-3); }
2681
2697
  }