@7365admin1/layer-common 3.2.2-staging.121 → 3.2.2-staging.122

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.
@@ -386,6 +386,59 @@
386
386
  filter: none;
387
387
  }
388
388
 
389
+ /* ------------------------------------------------------------------ */
390
+ /* The check-in / check-out pair. */
391
+ /* ------------------------------------------------------------------ */
392
+
393
+ /**
394
+ * NEW DESIGN, approved by the owner on 2026-08-14. The handoff draws no
395
+ * check-in and no check-out button, so there is nothing to match here; the
396
+ * gatehouse screens had been carrying Vuetify's `color="success"` and a
397
+ * hardcoded `color="red"` instead.
398
+ *
399
+ * Both are `.app-btn` first - the same 40px box, the same 10px radius, the
400
+ * same 13.5px/800 - so only the fill, the ink and the edge differ and the pair
401
+ * sits level with every other button in the product. The 16px icon at an 8px
402
+ * gap is the only metric either adds.
403
+ *
404
+ * CHECK IN is SOLID. It is the affirmative action a guard hits hundreds of
405
+ * times a shift and should be the heaviest thing on its row.
406
+ *
407
+ * CHECK OUT is TONAL, and that is measured rather than preferred: white on
408
+ * `--err` reads 2.99:1 in the dark theme, which is why batch C built a solid
409
+ * danger button, measured it and reverted it. `--err-bg` fill + `--err` ink +
410
+ * a 24%/28% `--err` edge is the construction the status chips already use, it
411
+ * passes in both themes, and it keeps a routine action from reading as a
412
+ * destructive one.
413
+ */
414
+ .app-btn--ok,
415
+ .app-btn--err {
416
+ gap: 8px;
417
+ }
418
+
419
+ /* The label is `--on-ok`, not a literal white - see tokens.css. White on the
420
+ DARK theme's `--ok` measures 2.14:1; `--on-ok` is the on-fill pair the theme
421
+ already carries, so the green stays exactly the green the design names. */
422
+ .app-btn--ok {
423
+ border: 1px solid var(--ok);
424
+ background: var(--ok);
425
+ color: var(--on-ok);
426
+ }
427
+
428
+ .app-btn--err {
429
+ border: 1px solid var(--err-border);
430
+ background: var(--err-bg);
431
+ color: var(--err);
432
+ }
433
+
434
+ /* A tint cannot be hovered with `brightness()` - above 1 it fades in the light
435
+ theme, which is the wrong direction. Layering the theme's own `--hover` over
436
+ the fill darkens in light and lightens in dark, with no new token. */
437
+ .app-btn--err:hover {
438
+ background: linear-gradient(var(--hover), var(--hover)), var(--err-bg);
439
+ filter: none;
440
+ }
441
+
389
442
  /* ------------------------------------------------------------------ */
390
443
  /* AppField / AppSelect / AppDateField. */
391
444
  /* ------------------------------------------------------------------ */
@@ -39,6 +39,15 @@
39
39
 
40
40
  /* Semantic status */
41
41
  --ok: rgb(var(--v-theme-success));
42
+ /*
43
+ * The label on a SOLID `--ok` fill. Not `#fff`: the dark theme's `--ok` is
44
+ * `#41c795`, a light mint, and white on it measures 2.14:1 - worse than the
45
+ * 2.99:1 that got batch C's solid danger button reverted. `on-success` is
46
+ * the pair Vuetify already computes per theme from `PALETTE.onFill`
47
+ * (`#ffffff` light, `#131418` dark), so the fill keeps the colour the design
48
+ * asks for and only the label follows the theme.
49
+ */
50
+ --on-ok: rgb(var(--v-theme-on-success));
42
51
  --warn: rgb(var(--v-theme-warning));
43
52
  --err: rgb(var(--v-theme-error));
44
53
  --info: rgb(var(--v-theme-info));
@@ -78,6 +87,11 @@
78
87
  --warn-bg: rgba(190, 140, 25, 0.13);
79
88
  --err-bg: rgba(207, 75, 75, 0.1);
80
89
  --info-bg: rgba(59, 111, 212, 0.1);
90
+
91
+ /* The edge of a TONAL error control - the check-out button. Alpha over the
92
+ live `--err` rather than a literal, exactly the way `--accent-soft` is
93
+ built, so it tracks the theme's error colour instead of restating it. */
94
+ --err-border: rgba(var(--v-theme-error), 0.24);
81
95
  }
82
96
 
83
97
  .v-theme--dark {
@@ -89,6 +103,8 @@
89
103
  --warn-bg: rgba(220, 175, 78, 0.13);
90
104
  --err-bg: rgba(229, 115, 115, 0.12);
91
105
  --info-bg: rgba(125, 166, 236, 0.12);
106
+
107
+ --err-border: rgba(var(--v-theme-error), 0.28);
92
108
  }
93
109
 
94
110
  /* ------------------------------------------------------------------ */
@@ -13,6 +13,12 @@
13
13
  box as primary; the handoff differs only in fill, border and weight
14
14
  icon 32px transparent square, 8px radius
15
15
  row 30px bordered square - the `more_vert` at the end of a table row
16
+
17
+ Two more the handoff does NOT draw, added as NEW design on the owner's
18
+ ruling of 2026-08-14 - see `assets/css/primitives.css` for why check-out is
19
+ tonal and not solid red:
20
+ ok 40px solid `--ok` fill, white label - CHECK IN
21
+ err 40px tonal `--err` fill, `--err` label, `--err` edge - CHECK OUT
16
22
  -->
17
23
  <template>
18
24
  <component
@@ -33,7 +39,7 @@ import { resolveComponent } from "vue";
33
39
 
34
40
  const props = defineProps({
35
41
  variant: {
36
- type: String as PropType<"primary" | "ghost" | "icon" | "row">,
42
+ type: String as PropType<"primary" | "ghost" | "icon" | "row" | "ok" | "err">,
37
43
  default: "primary",
38
44
  },
39
45
  icon: { type: String, default: "" },
@@ -48,6 +54,9 @@ const resolveLink = resolveComponent("NuxtLink");
48
54
  const iconSize = computed(() => {
49
55
  if (props.variant === "primary") return 18;
50
56
  if (props.variant === "row") return 17;
57
+ /* The check-in tick and the check-out cross are drawn at 16px - a glyph, not
58
+ a second focal point beside a two-word label. */
59
+ if (props.variant === "ok" || props.variant === "err") return 16;
51
60
  return 18;
52
61
  });
53
62
  </script>
@@ -19,6 +19,22 @@
19
19
  word - a padlock on "Closed - View Only" - so adopting the design's
20
20
  pill does not quietly drop it. -->
21
21
  <slot>{{ label ?? status }}</slot>
22
+ <!--
23
+ The remove control. NEW design, approved by the owner on 2026-08-14 - the
24
+ handoff draws no removable chip. It is an affordance ON the existing pill,
25
+ not a second shape, so a removable "KEY-309" and a read-only "Issued" stay
26
+ visibly the same family: same 999px pill, same 4px 10px, same 12px/700,
27
+ same 24px height. A chip that cannot be removed is byte-for-byte unchanged.
28
+ -->
29
+ <button
30
+ v-if="removable"
31
+ type="button"
32
+ class="status-chip__x"
33
+ :aria-label="removeLabel || `Remove ${label ?? status}`"
34
+ @click="emit('remove')"
35
+ >
36
+ <v-icon icon="mdi-close" :size="12" />
37
+ </button>
22
38
  </span>
23
39
  </template>
24
40
 
@@ -47,8 +63,19 @@ const props = defineProps({
47
63
  type: String as PropType<"ok" | "warn" | "err" | "info" | "neutral" | "">,
48
64
  default: "",
49
65
  },
66
+ /** Draws the × and emits `remove` when it is pressed. */
67
+ removable: { type: Boolean, default: false },
68
+ /**
69
+ * The × 's accessible name. Defaults to `Remove <the printed label>`, which
70
+ * is right for an identifier chip ("Remove KEY-309"); give it explicitly
71
+ * whenever the printed text alone would not tell a screen-reader user what
72
+ * is about to be taken away.
73
+ */
74
+ removeLabel: { type: String, default: "" },
50
75
  });
51
76
 
77
+ const emit = defineEmits<{ (e: "remove"): void }>();
78
+
52
79
  const toneClass = computed(() =>
53
80
  props.tone ? `tone-${props.tone}` : statusToneClass(props.status)
54
81
  );
@@ -83,6 +110,42 @@ const toneClass = computed(() =>
83
110
  font-size: var(--fs-chip);
84
111
  }
85
112
 
113
+ /*
114
+ * A 12px glyph needs a 24px target to stay pressable at 360px, but the chip is
115
+ * only 24px tall - so the hit area is INSET into the pill's own padding rather
116
+ * than added to it. The negative margin is what keeps the × from making a
117
+ * removable chip taller than the read-only one beside it.
118
+ */
119
+ .status-chip__x {
120
+ display: inline-flex;
121
+ align-items: center;
122
+ justify-content: center;
123
+ width: 24px;
124
+ height: 24px;
125
+ margin: -6px -6px -6px 0;
126
+ padding: 0;
127
+ border: none;
128
+ border-radius: var(--r-pill);
129
+ background: transparent;
130
+ /* Chips read as labels first and controls second, so the × sits back from
131
+ the word until it is reached for. */
132
+ color: inherit;
133
+ opacity: 0.62;
134
+ cursor: pointer;
135
+ transition: opacity var(--motion) ease, background var(--motion) ease;
136
+ }
137
+
138
+ .status-chip__x:hover,
139
+ .status-chip__x:focus-visible {
140
+ opacity: 1;
141
+ background: rgba(0, 0, 0, 0.06);
142
+ }
143
+
144
+ .v-theme--dark .status-chip__x:hover,
145
+ .v-theme--dark .status-chip__x:focus-visible {
146
+ background: rgba(255, 255, 255, 0.08);
147
+ }
148
+
86
149
  .status-chip__dot {
87
150
  width: 6px;
88
151
  height: 6px;
@@ -613,15 +613,21 @@
613
613
  class="d-flex align-center"
614
614
  >
615
615
  <strong>{{ label }}:</strong>
616
- <v-btn
617
- size="x-small"
618
- class="ml-3 text-capitalize"
619
- color="success"
620
- text="Checkin"
616
+ <!-- The design's check-in / check-out pair. Was Vuetify's
617
+ `color="success"` beside a hardcoded `color="red"` - two
618
+ different systems on one field list, and neither of them a
619
+ token. `:loading` is dropped rather than re-invented: the
620
+ same flag already drives `:disabled`, which is the
621
+ precedent set when the scanned-visitor form converted. -->
622
+ <AppButton
623
+ variant="ok"
624
+ icon="mdi-check"
625
+ class="ml-3"
621
626
  :disabled="isVisitorDataFromScannedQRCodeCheckingInOut"
622
627
  @click="handleCheckin(selectedVisitorDataObject)"
623
- :loading="isVisitorDataFromScannedQRCodeCheckingInOut"
624
- />
628
+ >
629
+ Check In
630
+ </AppButton>
625
631
  </span>
626
632
  <span
627
633
  v-if="
@@ -633,14 +639,15 @@
633
639
  class="d-flex align-center"
634
640
  >
635
641
  <strong>{{ label }}:</strong>
636
- <v-btn
637
- size="x-small"
638
- class="ml-3 text-capitalize"
639
- color="red"
640
- text="Checkout"
642
+ <AppButton
643
+ variant="err"
644
+ icon="mdi-close"
645
+ class="ml-3"
641
646
  :disabled="loading.checkingOut"
642
647
  @click="handleCheckout(selectedVisitorId as string)"
643
- />
648
+ >
649
+ Check Out
650
+ </AppButton>
644
651
  </span>
645
652
 
646
653
  <span
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@7365admin1/layer-common",
3
3
  "license": "MIT",
4
4
  "type": "module",
5
- "version": "3.2.2-staging.121",
5
+ "version": "3.2.2-staging.122",
6
6
  "author": "7365admin1",
7
7
  "main": "./nuxt.config.ts",
8
8
  "publishConfig": {