@brickclay-org/ui 0.1.72 → 0.1.74

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.72",
3
+ "version": "0.1.74",
4
4
  "schematics": "./schematics/collection.json",
5
5
  "ng-add": {
6
6
  "save": "dependencies"
@@ -16,7 +16,12 @@
16
16
  }
17
17
 
18
18
  .hierarchical-select-control.disabled {
19
- @apply bg-[#F4F4F6] cursor-not-allowed opacity-60;
19
+ @apply cursor-not-allowed opacity-60;
20
+ /* !important beats the inline accent (showDots): a disabled control must read
21
+ as disabled even when a node's colour is applied. */
22
+ background-color: #f4f4f6 !important;
23
+ border-color: rgb(227 227 231) !important;
24
+ color: rgb(161 163 174) !important;
20
25
 
21
26
  .hierarchical-placeholder {
22
27
  @apply text-gray-400;
@@ -31,10 +36,26 @@
31
36
  @apply text-[#6B7080] font-normal text-sm truncate w-full pointer-events-none;
32
37
  }
33
38
 
39
+ /* Keeps the dot/avatar on the same line as the w-full label, which would
40
+ otherwise wrap inside the flex-wrap value container. */
41
+ .hierarchical-value-row {
42
+ @apply flex items-center gap-1.5 w-full min-w-0;
43
+ }
44
+
34
45
  .hierarchical-value-label {
35
46
  @apply font-normal text-sm leading-[18px] text-[#141414] truncate w-full flex items-center;
36
47
  }
37
48
 
49
+ /* Accent dot (showDots). Background is set inline per node. */
50
+ .hierarchical-dot {
51
+ @apply inline-block w-2 h-2 rounded-full shrink-0;
52
+ }
53
+
54
+ /* Leading side of an option row: dot / avatar / label. */
55
+ .hierarchical-option-body {
56
+ @apply flex items-center gap-2 min-w-0 flex-1;
57
+ }
58
+
38
59
  .hierarchical-actions {
39
60
  @apply flex items-center gap-2 flex-shrink-0;
40
61
  }
@@ -82,10 +103,6 @@
82
103
  @apply w-full outline-none font-normal text-sm text-[#141414] placeholder-[#A1A3AE] bg-transparent;
83
104
  }
84
105
 
85
- .hierarchical-search-input:-moz-focusring {
86
- outline: none;
87
- }
88
-
89
106
  .hierarchical-back {
90
107
  @apply w-full text-left px-2.5 py-2 text-sm text-[#141414] bg-[#F8F8F8] rounded-md transition-colors mt-1 flex items-center gap-1.5;
91
108
  }
@@ -124,9 +141,11 @@
124
141
  }
125
142
  }
126
143
 
127
- .hierarchical-option:hover,
144
+ .hierarchical-option:hover{
145
+ @apply bg-[#f9f9f9];
146
+ }
128
147
  .hierarchical-option.selected {
129
- @apply bg-[#F8F8F8];
148
+ @apply bg-[#f7f7f7];
130
149
  }
131
150
 
132
151
  .hierarchical-option.selected.disabled-item {
@@ -191,6 +210,8 @@
191
210
  }
192
211
 
193
212
 
213
+ /* !important beats the inline accent border (showDots): an errored control must
214
+ read as errored even when a node's colour is tinting it. */
194
215
  .hierarchical-select-control.hierarchical-select-control-has-error {
195
- @apply border-[#d11e14];
216
+ border-color: #d11e14 !important;
196
217
  }
@@ -2,6 +2,7 @@
2
2
  bk-menu — simple responsive navigation menu.
3
3
  Single light theme, matching the default bk-tabs styling:
4
4
  text #141414, hover #EDEEF0, active #141414 bg with white text.
5
+ Styling uses Tailwind @apply; CSS variables below drive the theme.
5
6
  ========================================================================= */
6
7
 
7
8
  .bk-menu {
@@ -17,239 +18,169 @@
17
18
  --menu-radius: 8px;
18
19
  --menu-disabled: 0.5;
19
20
 
20
- display: block;
21
- width: 100%;
22
- font-size: 0.875rem;
23
- line-height: 1.25rem;
24
- font-weight: 500;
25
- letter-spacing: -0.28px;
26
- background: var(--menu-bg);
27
- color: var(--menu-text);
28
- border: 1px solid var(--menu-border);
29
- border-radius: var(--menu-radius);
30
- }
31
-
32
- /* Clip rounded corners for inline/default menus. Pop-up menus must NOT clip,
33
- otherwise the fly-out panels get cut off at the menu's edge. */
34
- .bk-menu:not(.bk-menu--popup) {
35
- overflow: hidden;
36
- }
37
-
38
- /* Round the first/last top-level buttons in pop-up mode so the active/hover
39
- background still respects the menu's corners without clipping fly-outs. */
40
- .bk-menu--popup.bk-menu--vertical > .bk-menu__list > .bk-menu__item:first-child > .bk-menu__button {
41
- border-radius: 8px 8px 0 0;
42
- }
43
- .bk-menu--popup.bk-menu--vertical > .bk-menu__list > .bk-menu__item:last-child > .bk-menu__button {
44
- border-radius: 0 0 8px 8px;
45
- }
46
- .bk-menu--popup.bk-menu--horizontal > .bk-menu__list > .bk-menu__item:first-child > .bk-menu__button {
47
- border-radius: 8px 0 0 8px;
48
- }
49
- .bk-menu--popup.bk-menu--horizontal > .bk-menu__list > .bk-menu__item:last-child > .bk-menu__button {
50
- border-radius: 0 8px 8px 0;
21
+ /* Safe to clip to rounded corners: pop-up fly-outs are position:fixed and
22
+ escape this box entirely, so nothing gets cut off. */
23
+ @apply block w-full max-w-full text-sm font-medium tracking-[-0.28px]
24
+ bg-[var(--menu-bg)] text-[color:var(--menu-text)]
25
+ border border-[var(--menu-border)] rounded-[var(--menu-radius)] overflow-hidden;
51
26
  }
52
27
 
53
28
  /* ---- Lists ---- */
54
29
  .bk-menu__list,
55
30
  .bk-menu__submenu {
56
- list-style: none;
57
- margin: 0;
58
- padding: 0;
31
+ @apply list-none m-0 p-0;
59
32
  }
60
33
 
61
- /* Horizontal top-level row (menubar). */
62
- .bk-menu--horizontal > .bk-menu__list {
63
- display: flex;
64
- flex-direction: row;
65
- align-items: stretch;
34
+ /* Scroll container: vertical scroll past max-height, horizontal scroll if a
35
+ deeply-indented inline row is wider than the menu. Fixed fly-outs escape it. */
36
+ .bk-menu__list--scroll {
37
+ @apply overflow-auto;
66
38
  }
67
39
 
68
- /* Scroll a crowded row only when NOT in pop-up mode — `overflow-x: auto`
69
- forces `overflow-y` to `auto`, which would clip the drop-down fly-outs. */
70
- .bk-menu--horizontal:not(.bk-menu--popup) > .bk-menu__list {
71
- overflow-x: auto;
40
+ /* Horizontal top-level row (menubar). Scrolls when crowded fixed fly-outs are
41
+ unaffected by the overflow. */
42
+ .bk-menu--horizontal > .bk-menu__list {
43
+ @apply flex flex-row items-stretch overflow-x-auto;
72
44
  }
73
45
 
74
46
  /* ---- Item / button ---- */
75
47
  .bk-menu__item {
76
- position: relative; /* anchor for pop-up submenus */
48
+ @apply relative; /* anchor for pop-up submenus */
77
49
  }
78
50
 
79
51
  .bk-menu__button {
80
- display: flex;
81
- align-items: center;
82
- gap: 8px;
83
- width: 100%;
84
- padding: 10px 12px;
85
- margin: 0;
86
- border: 0;
87
- background: transparent;
88
- color: inherit;
52
+ @apply flex items-center gap-2 w-full py-2.5 px-3 m-0 border-0
53
+ bg-transparent text-inherit text-left cursor-pointer whitespace-nowrap
54
+ transition-colors duration-100;
89
55
  font: inherit;
90
56
  letter-spacing: inherit;
91
- text-align: left;
92
- cursor: pointer;
93
- white-space: nowrap;
94
- border-radius: 6px;
95
- transition: background 0.1s ease, color 0.1s ease;
96
57
  }
97
58
 
98
59
  .bk-menu--horizontal > .bk-menu__list > .bk-menu__item > .bk-menu__button {
99
- width: auto;
60
+ @apply w-auto;
61
+ }
62
+
63
+ /* ---- Edge rounding: make the first/last top-level items' outer corners match
64
+ the container so hover/active fills sit flush in the rounded corners.
65
+ Vertical = column → first rounds the top, last rounds the bottom.
66
+ Horizontal = row → first rounds the left, last rounds the right. ---- */
67
+ .bk-menu--vertical > .bk-menu__list > .bk-menu__item:first-child > .bk-menu__button {
68
+ @apply rounded-t-[var(--menu-radius)];
69
+ }
70
+ .bk-menu--vertical > .bk-menu__list > .bk-menu__item:last-child > .bk-menu__button {
71
+ @apply rounded-b-[var(--menu-radius)];
72
+ }
73
+ .bk-menu--horizontal > .bk-menu__list > .bk-menu__item:first-child > .bk-menu__button {
74
+ @apply rounded-l-[var(--menu-radius)];
75
+ }
76
+ .bk-menu--horizontal > .bk-menu__list > .bk-menu__item:last-child > .bk-menu__button {
77
+ @apply rounded-r-[var(--menu-radius)];
100
78
  }
101
79
 
102
80
  .bk-menu__button:hover:not(:disabled):not(.bk-menu__button--active) {
103
- background: var(--menu-hover-bg);
104
- color: var(--menu-hover-text);
81
+ @apply bg-[var(--menu-hover-bg)] text-[color:var(--menu-hover-text)];
105
82
  }
106
83
 
107
84
  .bk-menu__button--active {
108
- background: var(--menu-active-bg);
109
- color: var(--menu-active-text);
85
+ @apply bg-[var(--menu-active-bg)] text-[color:var(--menu-active-text)];
110
86
  }
111
87
 
112
88
  .bk-menu__button--disabled,
113
89
  .bk-menu__button:disabled {
114
- opacity: var(--menu-disabled);
115
- cursor: not-allowed;
90
+ @apply opacity-[var(--menu-disabled)] cursor-not-allowed;
116
91
  }
117
92
 
118
93
  /* Nested (child) items use the muted sub-text colour. */
119
94
  .bk-menu__submenu .bk-menu__button {
120
- color: var(--menu-subtext);
121
- font-weight: 400;
95
+ @apply text-[color:var(--menu-subtext)] font-normal;
122
96
  }
123
97
 
124
98
  .bk-menu__submenu .bk-menu__button--active {
125
- color: var(--menu-active-text);
99
+ @apply text-[color:var(--menu-active-text)];
126
100
  }
127
101
 
128
102
  /* ---- Icon (optional). Tinted monochrome when .bk-menu--tint. ---- */
129
103
  .bk-menu__icon {
130
- width: 16px;
131
- height: 16px;
132
- flex-shrink: 0;
133
- object-fit: contain;
104
+ @apply w-4 h-4 shrink-0 object-contain;
134
105
  }
135
106
 
136
107
  .bk-menu--tint .bk-menu__icon {
137
- filter: brightness(0) saturate(0); /* → near-black, matches #141414 text */
108
+ @apply [filter:brightness(0)_saturate(0)]; /* → near-black, matches #141414 text */
138
109
  }
139
110
 
140
111
  /* Active row has a dark background → force a white icon for contrast. */
141
112
  .bk-menu--tint .bk-menu__button--active .bk-menu__icon {
142
- filter: brightness(0) invert(1);
113
+ @apply [filter:brightness(0)_invert(1)];
143
114
  }
144
115
 
145
116
  .bk-menu__label {
146
- flex: 1 1 auto;
147
- min-width: 0;
117
+ @apply flex-auto min-w-0 overflow-hidden text-ellipsis;
148
118
  }
149
119
 
150
120
  .bk-menu--horizontal > .bk-menu__list > .bk-menu__item > .bk-menu__button > .bk-menu__label {
151
- flex: 0 0 auto;
121
+ @apply flex-none overflow-visible;
152
122
  }
153
123
 
154
124
  /* ---- Chevron ---- */
155
125
  .bk-menu__chevron {
156
- flex-shrink: 0;
157
- transition: transform 0.18s ease;
158
- opacity: 0.8;
126
+ @apply shrink-0 opacity-80 transition-transform duration-[180ms];
159
127
  }
160
128
 
161
129
  /* Inline: rotate down → up on open. */
162
130
  .bk-menu__chevron--open {
163
- transform: rotate(180deg);
131
+ @apply rotate-180;
164
132
  }
165
133
 
166
134
  /* Pop-up fly-out: static caret pointing to where the panel opens (right). */
167
135
  .bk-menu__chevron--right {
168
- transform: rotate(-90deg);
136
+ @apply -rotate-90;
169
137
  }
170
138
 
171
139
  /* =========================================================================
172
140
  Inline submenus (accordion) — expand in place.
173
141
  ========================================================================= */
174
142
  .bk-menu__submenu--inline {
175
- overflow: hidden;
176
- max-height: 0;
177
- transition: max-height 0.2s ease;
143
+ @apply overflow-hidden max-h-0 transition-[max-height] duration-200;
178
144
  }
179
145
 
180
146
  .bk-menu__submenu--inline.bk-menu__submenu--open {
181
- max-height: 1000px; /* large enough to reveal nested content */
147
+ @apply max-h-[1000px]; /* large enough to reveal nested content */
182
148
  }
183
149
 
184
150
  /* =========================================================================
185
151
  Pop-up submenus — floating panels, hidden until open.
186
152
  ========================================================================= */
187
153
  .bk-menu__submenu--popup {
188
- position: absolute;
189
- z-index: 50;
190
- min-width: 200px;
191
- background: var(--menu-bg);
192
- border: 1px solid var(--menu-border);
193
- border-radius: 12px;
194
- box-shadow: var(--menu-shadow);
195
- padding: 4px;
196
- display: none;
154
+ /* Fixed so the fly-out escapes the menu's overflow/scroll box and renders
155
+ outside the nav. Coordinates are set inline (top/left) from JS. */
156
+ @apply fixed z-[1000] min-w-[200px] max-w-[280px] max-h-[calc(100vh-16px)]
157
+ overflow-y-auto bg-[var(--menu-bg)] border border-[var(--menu-border)]
158
+ rounded-xl shadow-[var(--menu-shadow)] p-1 hidden;
197
159
  }
198
160
 
199
161
  .bk-menu__submenu--popup.bk-menu__submenu--open {
200
- display: block;
201
- }
202
-
203
- /* Fly out to the right (vertical menus and all deeper levels). */
204
- .bk-menu__submenu--popup-right {
205
- top: 0;
206
- left: 100%;
207
- margin-left: 4px;
208
- }
209
-
210
- /* Drop down below (horizontal top-level items). */
211
- .bk-menu__submenu--popup-down {
212
- top: 100%;
213
- left: 0;
214
- margin-top: 4px;
162
+ @apply block;
215
163
  }
216
164
 
217
165
  /* Invisible bridges spanning the gap between a parent and its fly-out, so the
218
166
  pointer stays "inside" the item while crossing — prevents hover flicker. */
219
167
  .bk-menu__submenu--popup-right::before {
220
168
  content: '';
221
- position: absolute;
222
- top: 0;
223
- left: -6px;
224
- width: 6px;
225
- height: 100%;
169
+ @apply absolute top-0 left-[-6px] w-1.5 h-full;
226
170
  }
227
171
  .bk-menu__submenu--popup-down::before {
228
172
  content: '';
229
- position: absolute;
230
- top: -6px;
231
- left: 0;
232
- width: 100%;
233
- height: 6px;
173
+ @apply absolute top-[-6px] left-0 w-full h-1.5;
234
174
  }
235
175
 
236
176
  /* =========================================================================
237
- Responsive: stack a horizontal menu into a vertical one on small screens.
177
+ Responsive: a horizontal menu STAYS horizontal on small screens and scrolls
178
+ sideways when the items don't fit (overflow-x: auto). Items keep their
179
+ natural width so they sit in a clean scrollable row instead of stretching.
238
180
  ========================================================================= */
239
181
  @media (max-width: 640px) {
240
182
  .bk-menu--horizontal > .bk-menu__list {
241
- flex-direction: column;
242
- overflow-x: visible;
243
- }
244
- .bk-menu--horizontal > .bk-menu__list > .bk-menu__item > .bk-menu__button {
245
- width: 100%;
246
- }
247
- /* On small screens, horizontal pop-ups behave like inline sections. */
248
- .bk-menu--horizontal .bk-menu__submenu--popup-down {
249
- position: static;
250
- box-shadow: none;
251
- border: 0;
252
- margin: 0;
253
- border-radius: 0;
183
+ @apply overflow-x-auto;
184
+ -webkit-overflow-scrolling: touch;
254
185
  }
255
186
  }
@@ -17,14 +17,29 @@
17
17
  }
18
18
 
19
19
  &.bk-focused {
20
- @apply border-[#6B7080] shadow-none z-10;
20
+ @apply shadow-none z-10;
21
21
  outline: none !important;
22
22
  }
23
23
 
24
+ /* Only an untinted control borrows the neutral focus border; a tinted one
25
+ keeps its accent border (set inline) so the colour never flicks to grey. */
26
+ &.bk-focused:not(.bk-filled) {
27
+ @apply border-[#6B7080];
28
+ }
29
+
30
+ /* Tinted by a selected option (showDots, single-select). The accent supplies
31
+ its own border, so the default shadow would only muddy it. */
32
+ &.bk-filled {
33
+ box-shadow: none;
34
+ }
35
+
24
36
  &.bk-disabled {
25
37
  @apply cursor-not-allowed;
26
- border-color: rgb(227 227 231);
27
- background-color: rgb(244 244 246);
38
+ /* !important beats the inline accent: a disabled control must read as
39
+ disabled even when an option's colour is applied. */
40
+ border-color: rgb(227 227 231) !important;
41
+ background-color: rgb(244 244 246) !important;
42
+ color: rgb(161 163 174) !important;
28
43
 
29
44
  .bk-placeholder {
30
45
  color: rgb(161 163 174);
@@ -40,8 +55,11 @@
40
55
  @apply px-3 py-[5px];
41
56
  }
42
57
 
58
+ /* The error background is applied inline (see controlStyle) so it can replace an
59
+ option's accent tint. The border can't be: !important is what makes it beat
60
+ the softer inline border that comes with that tint. */
43
61
  .bk-select-control.bk-has-error {
44
- @apply border-[#d11e14];
62
+ border-color: #d11e14 !important;
45
63
  }
46
64
 
47
65
 
@@ -64,8 +82,11 @@
64
82
  @apply text-[14px] !leading-[18px];
65
83
  }
66
84
 
85
+ /* 18px line box, same as the placeholder and the `default` value — otherwise a
86
+ text-only `sm` row is 16px while a row with an avatar is 18px, and the
87
+ control resizes as soon as something is selected. */
67
88
  .bk-select-container.sm .bk-select-control .bk-value-label-single {
68
- @apply text-xs;
89
+ @apply text-xs !leading-[18px];
69
90
  }
70
91
 
71
92
  /* --- NEW: Multi Select Chips --- */
@@ -101,6 +122,14 @@
101
122
  min-width: 0;
102
123
  }
103
124
 
125
+ /* The 16px avatar is taller than the 12px label, so drop the vertical padding
126
+ and let it set the chip height: 16 + 2px border = 18px, exactly matching a
127
+ text-only chip. Without this the row grows the moment showAvatar is on. */
128
+ .bk-multi-badge-item.bk-chip-has-avatar {
129
+ @apply py-0 ps-0.5;
130
+ max-width: 140px;
131
+ }
132
+
104
133
  .bk-multi-badge-item-text {
105
134
  @apply text-[10px] leading-[12px] font-normal text-[#6B7080];
106
135
  white-space: nowrap;
@@ -289,3 +318,15 @@
289
318
  .bk-chip-icon {
290
319
  @apply w-3 h-3 object-contain rounded-sm;
291
320
  }
321
+
322
+ /* ---- Accent dots (showDots). Background is set inline per option. ---- */
323
+
324
+ /* Options and the single-select value. */
325
+ .bk-value-dot {
326
+ @apply inline-block w-2 h-2 rounded-full shrink-0;
327
+ }
328
+
329
+ /* Multi-select chips — smaller to suit the 18px chip row. */
330
+ .bk-chip-dot {
331
+ @apply inline-block w-1.5 h-1.5 rounded-full shrink-0;
332
+ }
@@ -1,10 +1,13 @@
1
1
  /* =========================
2
2
  Base Avatar
3
3
  ========================= */
4
+ /* No transition here on purpose: bgColor/textColor arrive via [ngStyle] a tick
5
+ after the element first paints, so `transition-all` made every avatar fade
6
+ its colours in on render — very visible in a list of options. Nothing on the
7
+ avatar changes on hover/focus, so the transition bought nothing. */
4
8
  .avatar {
5
9
  @apply relative inline-flex items-center justify-center
6
- rounded-full flex-shrink-0 select-none
7
- transition-all duration-200;
10
+ rounded-full flex-shrink-0 select-none;
8
11
  }
9
12
 
10
13
  .avatar-img {
@@ -18,6 +21,10 @@
18
21
  /* =========================
19
22
  Sizes (container + text)
20
23
  ========================= */
24
+ /* Sized to sit inside an 18px text line box (form controls) without changing
25
+ the row height. 16px rather than 18px so it also fits a bordered chip
26
+ (16 + 2px border = 18px) — the same height as a text-only chip. */
27
+ .avatar.xxsm { @apply size-4 text-[8px] leading-[10px]; }
21
28
  .avatar.xsm { @apply size-6 text-[10px] leading-[14px]; }
22
29
  .avatar.sm { @apply size-8 text-sm; }
23
30
  .avatar.md { @apply size-10 text-base; }
@@ -28,6 +35,7 @@
28
35
  /* =========================
29
36
  Placeholder Icon Sizes
30
37
  ========================= */
38
+ .avatar.xxsm .placeholder-icon { @apply size-3; }
31
39
  .avatar.xsm .placeholder-icon { @apply size-4; }
32
40
  .avatar.sm .placeholder-icon { @apply size-5; }
33
41
  .avatar.md .placeholder-icon { @apply size-6; }
@@ -44,6 +52,7 @@
44
52
  }
45
53
 
46
54
  /* Dot size follows avatar size */
55
+ .avatar.xxsm .avatar-dot { @apply size-1; }
47
56
  .avatar.xsm .avatar-dot { @apply size-1; }
48
57
  .avatar.sm .avatar-dot { @apply size-1.5; }
49
58
  .avatar.md .avatar-dot { @apply size-2.5; }
@@ -69,5 +78,3 @@
69
78
  .avatar .none {
70
79
  @apply hidden;
71
80
  }
72
-
73
-
package/src/styles.css CHANGED
@@ -26,3 +26,6 @@
26
26
  @import './lib/pagination/pagination.css';
27
27
  @import './lib/loader/loader.css';
28
28
  @import './lib/dropdown/dropdown.css';
29
+ @import './lib/popover/popover.css';
30
+ @import './lib/menu/menu.css';
31
+ @import './lib/ui-avatar-group/ui-avatar-group.css';