@brickclay-org/ui 0.1.92 → 0.1.93

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brickclay-org/ui",
3
- "version": "0.1.92",
3
+ "version": "0.1.93",
4
4
  "schematics": "./schematics/collection.json",
5
5
  "ng-add": {
6
6
  "save": "dependencies"
@@ -0,0 +1,288 @@
1
+ /* =====================================================================
2
+ bk-kanban
3
+
4
+ Visual language matches bk-table / bk-grid: #EBEDF3 rules, #F9FAFA header
5
+ fill, #15191E / #60646C text, 0.75rem corners. WIP-limit feedback reuses
6
+ Tailwind's amber-* scale — the same family table-demo already reaches for
7
+ on its tree-drag refusal message — rather than inventing a new warning
8
+ color for this one control.
9
+
10
+ Styles are global (ViewEncapsulation.None): `cardTemplate`'s content is
11
+ projected in from the consumer and never carries this component's scope
12
+ attribute, so column/card chrome has to be reachable without it. Every
13
+ class is namespaced `bk-kanban-` to keep that safe.
14
+ ===================================================================== */
15
+
16
+ .bk-kanban-host {
17
+ display: block;
18
+ height: 100%;
19
+ }
20
+
21
+ /* ---------- Board ----------
22
+
23
+ Three nested boxes now, each with exactly one job:
24
+
25
+ .bk-kanban-host — structural passthrough only (above). Never styled.
26
+ .bk-kanban-board — `boardClass` lands here. Purely decorative: a
27
+ background, a border, padding around the whole
28
+ board. Never scrolls, never sized by CDK.
29
+ .bk-kanban — the scroll container. Holds every column, owns
30
+ `overflow-x`/`overflow-y`, and is what
31
+ `cdkDropList` (column reordering) attaches to.
32
+
33
+ Collapsing `boardClass` onto the same box that scrolls was the bug this
34
+ split fixes: a consumer's `padding` became part of what had to be
35
+ scrolled past, and the scrollbar itself ended up sitting inside that
36
+ padding instead of at the board's true content edge. Keeping
37
+ `.bk-kanban-board` between `boardClass` and the scrolling box means
38
+ nothing a consumer passes in can ever change *which* element owns
39
+ scrolling, or where its scrollbar sits — `.bk-kanban` fills
40
+ `.bk-kanban-board`'s content box (`w-full h-full`, below), correctly
41
+ inset by whatever padding/border `boardClass` added, and scrolls entirely
42
+ on its own from there. */
43
+ .bk-kanban-board {
44
+ display: block;
45
+ height: 100%;
46
+ }
47
+
48
+ /* `height: 100%` resolves against whatever the host was given: a container
49
+ with an explicit height (e.g. `class="h-[calc(100vh-200px)]"` on
50
+ <bk-kanban>) makes the board itself bounded; against an auto-height
51
+ ancestor it computes as auto instead (ordinary CSS behaviour for a
52
+ percentage height), so the board just grows with its content when nothing
53
+ constrains it. No JS measurement needed either way.
54
+
55
+ `overflow-x: auto` is what makes the board responsive on its own — always
56
+ on, regardless of `columnScrollMode` — and stays on `.bk-kanban` in both
57
+ modes: columns never shrink below their own min-width, so a narrow
58
+ viewport (or ten columns' worth of width) scrolls the row horizontally
59
+ (the standard kanban pattern) rather than squeezing every column
60
+ unreadably thin. `columnScrollMode` only ever decides where the *vertical*
61
+ scroll lives.
62
+
63
+ `items-stretch` is what makes `columnScrollMode: 'body'` (the default,
64
+ see below) actually work rather than being aspirational: every column
65
+ stretches to fill `.bk-kanban`'s own cross-axis size, so once that size is
66
+ *definite* (host given an explicit height) each column is bounded too,
67
+ and `.bk-kanban-column-body`'s own `overflow-y: auto` has something to
68
+ clip against. `.bk-kanban--scroll-wrapper` (also below) overrides this for
69
+ `'wrapper'` mode, where columns go back to their own natural height and
70
+ the board handles scrolling instead. */
71
+ .bk-kanban {
72
+ @apply flex items-stretch gap-4 w-full h-full overflow-x-auto;
73
+ scroll-snap-type: x proximity;
74
+ }
75
+
76
+ /* `columnScrollMode: 'wrapper'` (`BkKanbanColumnScrollMode`) — moves
77
+ vertical scrolling from each column's own body up to the board itself, so
78
+ every column (header *and* body, all of them, together) scrolls as one
79
+ region instead of each column scrolling independently. `align-items:
80
+ flex-start` undoes the stretch above: columns no longer need bounding
81
+ individually now that the board itself is the bounded, scrollable one.
82
+ `overflow-x` stays `auto` (inherited from `.bk-kanban` — nothing here
83
+ touches it), so horizontal scrolling across columns keeps working exactly
84
+ as it does in `'body'` mode; this box just scrolls on both axes now. */
85
+ .bk-kanban--scroll-wrapper {
86
+ align-items: flex-start;
87
+ overflow-y: auto;
88
+ }
89
+
90
+ /* Columns are naturally-sized in this mode (no `items-stretch` to fill), so
91
+ a column's own body never actually has surplus space to overflow into —
92
+ this is mostly documentation of that fact rather than a fix for a real
93
+ collision, kept explicit so nobody re-adds a per-column scrollbar here by
94
+ accident later. */
95
+ .bk-kanban--scroll-wrapper .bk-kanban-column-body {
96
+ overflow-y: visible;
97
+ }
98
+
99
+ /* ---------- Column ---------- */
100
+
101
+ /*
102
+ `background` reads a custom property with a fallback, rather than a plain
103
+ `bg-[#F9FAFA]` utility, for the same reason `.bk-kanban-column-header`
104
+ does below: this component's styleUrl is injected after the app's global
105
+ stylesheet, so a same-specificity utility landing here via `columnClass`
106
+ would lose to a plain background utility regardless of source order.
107
+ `--bk-kanban-column-bg` is never assigned a value here, so it's the only
108
+ reliable way in.
109
+ */
110
+ .bk-kanban-column {
111
+ @apply flex flex-col shrink-0 w-[300px] max-w-[85vw] rounded-xl border border-[#EBEDF3] overflow-hidden;
112
+ background: var(--bk-kanban-column-bg, #f9fafa);
113
+ scroll-snap-align: start;
114
+ }
115
+
116
+ /* Same custom-property trick as `.bk-kanban-column` above, for the same
117
+ reason, so `columns[].colHeaderClass` can reliably win on background too —
118
+ plus the trick `bk-dialog` uses for `--bk-dialog-panel-bg` via
119
+ `panelClass`. */
120
+ .bk-kanban-column-header {
121
+ @apply flex items-center justify-between gap-2 px-3 py-2.5;
122
+ background: var(--bk-kanban-header-bg, #f9fafa);
123
+ border-bottom: 1px solid #ebedf3;
124
+ }
125
+
126
+ /* `columnDragEnabled` makes this the drag handle (see kanban.html) — cursor
127
+ feedback only shows up once dragging is actually possible, and switches to
128
+ `grabbing` mid-drag the same way `.bk-kanban-card` does for cards. CDK adds
129
+ `cdk-drag-disabled` to the `cdkDrag` host itself (`.bk-kanban-column`), not
130
+ this handle, hence scoping through the parent rather than the class living
131
+ here directly. */
132
+ .bk-kanban-column:not(.cdk-drag-disabled) > .bk-kanban-column-header {
133
+ cursor: grab;
134
+ }
135
+
136
+ .bk-kanban-column.cdk-drag-dragging > .bk-kanban-column-header {
137
+ cursor: grabbing;
138
+ }
139
+
140
+ .bk-kanban-column-title {
141
+ @apply text-[13px] font-semibold text-[#15191E] truncate;
142
+ }
143
+
144
+ .bk-kanban-column-count {
145
+ @apply shrink-0;
146
+ }
147
+
148
+ /* No `ms-auto` here — `justify-between` on `.bk-kanban-column-header` above
149
+ already spreads title, count badge, and this slot apart on its own; a
150
+ `margin-inline-start: auto` on top of that would claim all the header's
151
+ leftover space for itself before `justify-content` ever sees it, silently
152
+ cancelling the spread between title and badge whenever an actions
153
+ template renders. */
154
+ .bk-kanban-column-actions {
155
+ @apply shrink-0 flex items-center;
156
+ }
157
+
158
+ /* ---------- Column body / drop list ---------- */
159
+
160
+ .bk-kanban-column-body {
161
+ @apply flex-1 flex flex-col gap-2 p-2.5 overflow-y-auto;
162
+ min-height: 96px;
163
+ }
164
+
165
+ .bk-kanban-empty {
166
+ @apply flex flex-1 flex-col items-center justify-center py-6 text-center;
167
+ }
168
+
169
+ .bk-kanban-empty-text {
170
+ @apply text-xs font-medium text-[#78829D];
171
+ }
172
+
173
+ /* ---------- Card ---------- */
174
+
175
+ .bk-kanban-card {
176
+ @apply bg-white rounded-lg border border-[#EBEDF3] p-3 cursor-pointer;
177
+ box-shadow: 0 1px 2px rgba(16, 24, 40, 0.04);
178
+ transition:
179
+ box-shadow 150ms ease,
180
+ border-color 150ms ease;
181
+ }
182
+
183
+ .bk-kanban-card:hover {
184
+ @apply border-[#C4CADA];
185
+ box-shadow: 0 2px 6px rgba(16, 24, 40, 0.08);
186
+ }
187
+
188
+ /* CDK holds the dragged card at a fixed pointer offset while it flies to its
189
+ drop position; a stray transition on `transform` during that flight reads
190
+ as lag rather than motion. `cdk-drag-animating` (added only for the
191
+ settle-into-place snap after release) is what should transition. */
192
+ .bk-kanban-card.cdk-drag-dragging {
193
+ transition: none;
194
+ }
195
+
196
+ /* ---------- WIP limit feedback ----------
197
+
198
+ `-warn` is the persistent, post-drop state (`wipLimitBehavior: 'warn'`,
199
+ §6). `-live-over` is the transient one drawn while a card is being
200
+ dragged over a column that would exceed its limit (§12) — independent of
201
+ `wipLimitBehavior`, since it's pure information shown before anything has
202
+ actually happened. Both can theoretically apply at once (a column already
203
+ over limit being hovered again); the rules simply stack. */
204
+
205
+ .bk-kanban-column-warn {
206
+ @apply border-amber-300 bg-amber-50;
207
+ }
208
+
209
+ .bk-kanban-column-warn .bk-kanban-column-header {
210
+ @apply bg-amber-50 border-amber-200;
211
+ }
212
+
213
+ .bk-kanban-column-live-over {
214
+ @apply border-amber-400 bg-amber-50;
215
+ outline: 2px dashed theme('colors.amber.400');
216
+ outline-offset: -2px;
217
+ }
218
+
219
+ .bk-kanban-column-live-over .bk-kanban-column-header {
220
+ @apply bg-amber-50 border-amber-200;
221
+ }
222
+
223
+ /* ---------- Drag sorting ----------
224
+
225
+ Deliberately scoped to `.bk-kanban-card` rather than the bare
226
+ `.cdk-drag-preview` / `.cdk-drag-placeholder` selectors bk-table and
227
+ bk-grid already publish globally (ViewEncapsulation.None puts all three
228
+ stylesheets in the same global scope) — CDK's `display: table` there is
229
+ right for a cloned `<tr>` and wrong for a card `<div>`; the extra class
230
+ also just wins on specificity, so which stylesheet loads last can't flip
231
+ this component's own drag visuals. */
232
+
233
+ .bk-kanban-card.cdk-drag-preview {
234
+ @apply rounded-lg;
235
+ box-shadow:
236
+ 0 5px 5px -3px rgba(0, 0, 0, 0.2),
237
+ 0 8px 10px 1px rgba(0, 0, 0, 0.14),
238
+ 0 3px 14px 2px rgba(0, 0, 0, 0.12);
239
+ cursor: grabbing;
240
+ }
241
+
242
+ .bk-kanban-card.cdk-drag-placeholder {
243
+ @apply border-dashed border-[#C4CADA] bg-[#F1F2F4];
244
+ box-shadow: none;
245
+ opacity: 0.6;
246
+ }
247
+
248
+ .bk-kanban-column-body.cdk-drop-list-dragging .bk-kanban-card:not(.cdk-drag-placeholder) {
249
+ transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
250
+ }
251
+
252
+ /* Same treatment one level up, for `columnDragEnabled` — a column being
253
+ dragged gets the heavier shadow a whole column's worth of chrome warrants
254
+ (cards use a lighter one, being the smaller unit), and its placeholder
255
+ reuses the exact dashed-border look `.bk-kanban-card`'s placeholder uses,
256
+ just sized to a column instead. */
257
+ .bk-kanban-column.cdk-drag-preview {
258
+ box-shadow:
259
+ 0 8px 10px -6px rgba(0, 0, 0, 0.2),
260
+ 0 20px 25px -5px rgba(0, 0, 0, 0.14);
261
+ }
262
+
263
+ .bk-kanban-column.cdk-drag-placeholder {
264
+ @apply border-dashed border-[#C4CADA] bg-[#F1F2F4];
265
+ box-shadow: none;
266
+ opacity: 0.5;
267
+ }
268
+
269
+ .bk-kanban-column.cdk-drag-placeholder .bk-kanban-column-header,
270
+ .bk-kanban-column.cdk-drag-placeholder .bk-kanban-column-body {
271
+ visibility: hidden;
272
+ }
273
+
274
+ .bk-kanban.cdk-drop-list-dragging .bk-kanban-column:not(.cdk-drag-placeholder) {
275
+ transition: transform 250ms cubic-bezier(0, 0, 0.2, 1);
276
+ }
277
+
278
+ /* ---------- Responsive ----------
279
+
280
+ Below tablet width, a fixed 300px column plus its neighbours peeking in
281
+ reads as clutter rather than an obvious "swipe for more" board — one
282
+ column at a time (minus a sliver of the next, so the horizontal scroll is
283
+ still discoverable) reads better on a phone-width viewport. */
284
+ @media (max-width: 640px) {
285
+ .bk-kanban-column {
286
+ width: 86vw;
287
+ }
288
+ }
package/src/styles.css CHANGED
@@ -44,7 +44,7 @@
44
44
  @import './lib/menu/menu.css';
45
45
  @import './lib/ui-avatar-group/ui-avatar-group.css';
46
46
  @import './lib/table/table.css';
47
- @import './lib/kanban/kanban.css';
47
+ @import './lib/kanban/component/kanban/kanban.css';
48
48
  @import './lib/calender/components/custom-calendar/custom-calendar.component.css';
49
49
  @import './lib/calender/components/scheduled-date-picker/scheduled-date-picker.component.css';
50
50
  @import './lib/calender/components/time-picker/time-picker.component.css';