@7365admin1/layer-common 3.2.2-staging.139 → 3.2.2-staging.141

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.
@@ -958,3 +958,29 @@ select.app-field__input {
958
958
  min-width: 720px;
959
959
  }
960
960
  }
961
+
962
+ /* ------------------------------------------------------------------ */
963
+ /* Field label (`components/InputLabel.vue`, 125 caller files). */
964
+ /* */
965
+ /* Every form label in the product rendered Vuetify's `text-subtitle-2`:*/
966
+ /* 14px/500 at 0.0071em tracking, declaring `font-family: Roboto`. */
967
+ /* The handoff's own label - the Create Role modal - is 12.5px/700 with*/
968
+ /* a 6px gap under it and the asterisk on `--err`. */
969
+ /* */
970
+ /* `margin-bottom` is deliberately NOT `!important`, so the ~40 callers*/
971
+ /* that already pass a Vuetify spacing utility (`mb-1`, `mb-2`) keep */
972
+ /* winning - those classes carry `!important` - and only the labels */
973
+ /* that state no spacing take the design's 6px. */
974
+ /* ------------------------------------------------------------------ */
975
+ .app-input-label {
976
+ font-family: var(--font-sans);
977
+ font-size: 12.5px;
978
+ font-weight: 700;
979
+ letter-spacing: 0;
980
+ color: var(--text);
981
+ margin-bottom: 6px;
982
+ }
983
+
984
+ .app-input-label__req {
985
+ color: var(--err);
986
+ }
@@ -739,3 +739,71 @@
739
739
  height: 2px;
740
740
  background: var(--accent);
741
741
  }
742
+
743
+ /* ------------------------------------------------------------------ */
744
+ /* Toast (`components/Snackbar.vue`, 163 caller files). */
745
+ /* */
746
+ /* The handoff draws no toast at all - it is one of the gaps. So this */
747
+ /* is deliberately NOT an invented surface: it is the design's own */
748
+ /* button type scale, inner radius and menu shadow applied to */
749
+ /* Vuetify's snackbar. Vuetify's own default is a 4px radius, a */
750
+ /* Material elevation and Roboto at 14px, none of which are ours. */
751
+ /* */
752
+ /* The FILL is the `color` prop, defaulted in the component to */
753
+ /* `primary-button` - never `primary`, which is a foreground token. */
754
+ /* ------------------------------------------------------------------ */
755
+ .app-toast .v-snackbar__wrapper {
756
+ border-radius: var(--r-inner);
757
+ box-shadow: var(--shadow-menu);
758
+ font-family: var(--font-sans);
759
+ }
760
+
761
+ .app-toast .v-snackbar__content {
762
+ font-size: var(--fs-btn);
763
+ font-weight: 600;
764
+ letter-spacing: 0;
765
+ }
766
+
767
+ /* Vuetify's text button is uppercase with wide tracking; the design has no
768
+ uppercase control anywhere. Named on `.v-btn` so it outweighs the default. */
769
+ .v-btn.app-toast__close {
770
+ border-radius: var(--r-inner-sm);
771
+ font-family: var(--font-sans);
772
+ font-size: var(--fs-btn);
773
+ font-weight: var(--fw-btn);
774
+ letter-spacing: 0;
775
+ text-transform: none;
776
+ }
777
+
778
+ /* ------------------------------------------------------------------ */
779
+ /* The "Back" link that sits above a page title. */
780
+ /* `SpecificAttr.vue` (17 caller files) and `Container/Standard.vue`. */
781
+ /* */
782
+ /* DESIGN GAP, STATED: the handoff draws no back control anywhere, so */
783
+ /* its SIZE is not a value the design gives. What the design DOES give */
784
+ /* is the rule for a link - `iService365 Redesign.dc.html:26`, */
785
+ /* `a{color:var(--accent-text);text-decoration:underline}` - so the */
786
+ /* colour and the underline are literal, and the underline is kept for */
787
+ /* that reason rather than dropped for looking dated. The size is */
788
+ /* taken from the only standalone inline link the handoff draws, the */
789
+ /* panel's "View All" at line 166: 12.5px / 700. */
790
+ /* */
791
+ /* It replaces `text-subtitle-1 font-weight-medium` - Vuetify's */
792
+ /* 16px/400 Roboto scale, which is neither the product font nor a size */
793
+ /* that appears anywhere in the design. */
794
+ /* ------------------------------------------------------------------ */
795
+ .screen-back {
796
+ display: inline-block;
797
+ font-family: var(--font-sans);
798
+ font-size: var(--fs-breadcrumb);
799
+ font-weight: var(--fw-btn);
800
+ letter-spacing: 0;
801
+ line-height: 1.4;
802
+ color: var(--accent-text);
803
+ text-decoration: underline;
804
+ cursor: pointer;
805
+ }
806
+
807
+ .screen-back:hover {
808
+ color: var(--accent);
809
+ }
@@ -1,15 +1,17 @@
1
1
  <template>
2
2
  <v-row no-gutters>
3
+ <!--
4
+ The same Back link and the same page title as `SpecificAttr.vue`, which
5
+ is the other half of this pair - it was already on `PageHeader` and this
6
+ one was still on `text-h5 font-weight-medium`, Vuetify's 24px/500 Roboto
7
+ rather than the design's 22px/800. `.screen-back` is stated once in
8
+ `screens.css` with the design gap written out next to it.
9
+ -->
3
10
  <v-col cols="12">
4
- <span
5
- class="font-weight-medium text-subtitle-1 text-decoration-underline cursor-pointer"
6
- @click="emit('back')"
7
- >
8
- Back
9
- </span>
11
+ <span class="screen-back" @click="emit('back')"> Back </span>
10
12
  </v-col>
11
13
  <v-col cols="12">
12
- <span class="text-h5 font-weight-medium">{{ props.title }}</span>
14
+ <PageHeader :title="props.title" />
13
15
  </v-col>
14
16
 
15
17
  <v-col cols="12" class="mt-4">
@@ -1,6 +1,6 @@
1
1
  <template>
2
- <span :class="`text-subtitle-2 font-weight-medium ${props.class}`">
3
- {{ title }} <span v-if="props.required" class="text-error">*</span>
2
+ <span :class="`app-input-label ${props.class}`">
3
+ {{ title }} <span v-if="props.required" class="app-input-label__req">*</span>
4
4
  </span>
5
5
  </template>
6
6
 
@@ -370,12 +370,13 @@ const handleClick = (item: any) => {
370
370
  opacity: 1;
371
371
  }
372
372
 
373
- /* Vuetify's own 16px gap between the icon and the label, brought to the 10px
374
- the design draws. The spacer element is what holds that distance - a margin
375
- on the icon leaves it where it was. */
376
- .brand-drawer :deep(.v-list-item__spacer) {
377
- width: 10px;
378
- }
373
+ /* The icon-to-label gap USED to be stated here and it never applied: Vuetify's
374
+ own rule is `.v-list-item__prepend > .v-icon ~ .v-list-item__spacer`, three
375
+ classes, and `.brand-drawer :deep(.v-list-item__spacer)` is also three once
376
+ the scope attribute is counted - a tie, decided by load order, and Vuetify
377
+ loaded last. Measured, the gap was still Vuetify's 32px. The rule now lives
378
+ in `NavigationItem.vue` in Vuetify's own selector shape, so it wins on
379
+ specificity; every item in this list is a `NavigationItem`. */
379
380
 
380
381
  .brand-drawer :deep(.v-list-item--active) {
381
382
  font-weight: var(--fw-section-label);
@@ -1,18 +1,30 @@
1
+ <!--
2
+ A label/value row. Both columns were `text-subtitle-2` - Vuetify's 14px/500
3
+ Roboto - so the label that names a value and the value itself were drawn
4
+ identically, and the trailing chevron was 30px, larger than any icon the
5
+ design draws anywhere.
6
+
7
+ DESIGN GAP, STATED: the handoff has no list row of this shape. The values
8
+ below are the design's own, taken from the nearest things it does draw: the
9
+ table cell type (`--fs-cell` / `--fw-cell`) for both columns, `--muted` for
10
+ the label exactly as the handoff labels a value at line 659, and 18px for the
11
+ trailing icon, the size its own row icons use (lines 87 and 90).
12
+ -->
1
13
  <template>
2
14
  <v-list-item :class="props.divider ? border : defaultBorder">
3
15
  <v-row>
4
- <v-col cols="4" class="text-subtitle-2">
16
+ <v-col cols="4" class="app-list-row__label">
5
17
  <slot name="title"> List Title </slot>
6
18
  </v-col>
7
19
 
8
- <v-col cols="8" class="text-subtitle-2">
20
+ <v-col cols="8" class="app-list-row__value">
9
21
  <slot name="value"> value </slot>
10
22
  </v-col>
11
23
  </v-row>
12
24
 
13
25
  <template #append>
14
26
  <slot name="append">
15
- <v-icon size="30">{{ props.icon }}</v-icon>
27
+ <v-icon size="18">{{ props.icon }}</v-icon>
16
28
  </slot>
17
29
  </template>
18
30
  </v-list-item>
@@ -33,3 +45,21 @@ const props = defineProps({
33
45
  const defaultBorder = "pa-0 pl-8 pr-6 py-4";
34
46
  const border = "border-b-sm" + " " + defaultBorder;
35
47
  </script>
48
+
49
+ <style scoped>
50
+ .app-list-row__label,
51
+ .app-list-row__value {
52
+ font-family: var(--font-sans);
53
+ font-size: var(--fs-cell);
54
+ font-weight: var(--fw-cell);
55
+ letter-spacing: 0;
56
+ }
57
+
58
+ .app-list-row__label {
59
+ color: var(--muted);
60
+ }
61
+
62
+ .app-list-row__value {
63
+ color: var(--text);
64
+ }
65
+ </style>
@@ -11,7 +11,7 @@
11
11
  v-bind="groupProps"
12
12
  :prepend-icon="icon"
13
13
  color="primary"
14
- class="text-subtitle-2"
14
+ class="nav-item"
15
15
  @click.stop="onParentClick"
16
16
  >
17
17
  {{ title }}
@@ -33,7 +33,7 @@
33
33
  :prepend-icon="icon"
34
34
  :to="routeTo"
35
35
  color="primary"
36
- class="text-subtitle-2"
36
+ class="nav-item"
37
37
  >
38
38
  {{ title }}
39
39
  </v-list-item>
@@ -43,7 +43,7 @@
43
43
  :prepend-icon="icon"
44
44
  :href="props.link"
45
45
  color="primary"
46
- class="text-subtitle-2"
46
+ class="nav-item"
47
47
  >
48
48
  {{ title }}
49
49
  </v-list-item>
@@ -97,3 +97,83 @@ const routeTo = computed(() => {
97
97
  return null;
98
98
  });
99
99
  </script>
100
+
101
+ <style scoped>
102
+ /**
103
+ * The sidebar menu row, taken literally from the handoff's `<aside>` — line 56
104
+ * of `iService365 Redesign.dc.html` for the row and line 57 for its icon:
105
+ *
106
+ * padding:8px 12px; border-radius:10px; font-size:13px;
107
+ * font-weight: 800 when active else 600;
108
+ * color: var(--accent-text) when active else var(--text2);
109
+ * icon: font-size:19px; width:20px; color: var(--accent-text)/var(--muted);
110
+ *
111
+ * What this replaced was `text-subtitle-2` — Vuetify's own type scale, 14px/500
112
+ * with 0.1px tracking — and no inactive colour at all, so an unselected item
113
+ * was full-strength body ink and read exactly as loud as the page you are on.
114
+ *
115
+ * STATED HERE RATHER THAN ONLY IN THE DRAWER because five of this component's
116
+ * six call sites are `layouts/*` in the ORG app, outside `.brand-drawer`.
117
+ * `LayoutNavigationDrawer` already states the same shape for the rows it
118
+ * contains; the values below are deliberately IDENTICAL to that block, so the
119
+ * specificity tie between them cannot change what is drawn.
120
+ *
121
+ * `margin: 1px 10px` from the handoff is NOT set here: the drawer insets its
122
+ * own list (`.v-list { padding: 0 8px 12px }`), and a margin as well would
123
+ * double the inset in the ten apps that do use the drawer.
124
+ */
125
+ .nav-item {
126
+ min-height: 38px;
127
+ padding-top: 8px;
128
+ padding-bottom: 8px;
129
+ padding-inline: 12px;
130
+ /* `!important` is not carelessness: Vuetify puts the `rounded-0` UTILITY on
131
+ the item, and utilities are themselves `!important`. Measured without it,
132
+ this row drew `border-radius: 0px`. */
133
+ border-radius: var(--r-inner) !important;
134
+ font-family: var(--font-sans);
135
+ font-size: var(--fs-nav);
136
+ font-weight: var(--fw-cell);
137
+ letter-spacing: 0;
138
+ color: var(--text2);
139
+ }
140
+
141
+ .nav-item.v-list-item--active {
142
+ font-weight: var(--fw-section-label);
143
+ }
144
+
145
+ /**
146
+ * The active row's INK is not set here on purpose. `color="primary"` puts
147
+ * Vuetify's `text-primary` on the item, that utility is `!important`, and
148
+ * `primary` is mapped to `--accent-text` — which is the colour the handoff
149
+ * names for an active row. So the rule above wins for an inactive row and
150
+ * loses, correctly, for an active one.
151
+ */
152
+ .nav-item :deep(.v-list-item__prepend > .v-icon) {
153
+ font-size: 19px;
154
+ width: 20px;
155
+ text-align: center;
156
+ opacity: 1;
157
+ }
158
+
159
+ /* Muted only while inactive — an explicit colour on the icon would also
160
+ out-rank the inherited `--accent-text` on the row you are actually on. */
161
+ .nav-item:not(.v-list-item--active) :deep(.v-list-item__prepend > .v-icon) {
162
+ color: var(--muted);
163
+ }
164
+
165
+ /**
166
+ * The handoff's 10px between icon and label. Vuetify holds that distance in a
167
+ * spacer element, so a margin on the icon leaves it where it was.
168
+ *
169
+ * The selector is Vuetify's own shape ON PURPOSE. Vuetify sets the gap with
170
+ * `.v-list-item__prepend > .v-icon ~ .v-list-item__spacer { width: 32px }` —
171
+ * three classes. A scoped `.nav-item :deep(.v-list-item__spacer)` is also
172
+ * three (the scope attribute counts), so it TIES and loses on source order.
173
+ * Measured: the gap stayed at Vuetify's 32px. Matching the shape makes it four
174
+ * and it wins on specificity rather than on load order.
175
+ */
176
+ .nav-item :deep(.v-list-item__prepend > .v-icon ~ .v-list-item__spacer) {
177
+ width: 10px;
178
+ }
179
+ </style>
@@ -1,34 +1,50 @@
1
+ <!--
2
+ The "page under maintenance" screen — 38 routes across 10 applications.
3
+
4
+ What it was: `font-family: Arial` on `color: #333`. Not a token, not the
5
+ product font, and the same dark grey on the dark page. It was the one screen
6
+ in the estate that ignored both the theme switch and Manrope.
7
+
8
+ DESIGN GAP, STATED: the handoff draws no maintenance / under-construction
9
+ page at all. So this is assembled from the established primitive rather than
10
+ invented — `.screen-empty` (`assets/css/screens.css:149`) is the design's
11
+ centred, muted, 52px-padded empty block, and the heading takes the
12
+ `--fs-card-title` / `--fw-card-title` type the design uses for every other
13
+ panel heading (handoff line 133, `font-size:15.5px;font-weight:800`).
14
+
15
+ The 🚧 emoji is replaced by the central icon: emoji renders in the OS font,
16
+ which is neither Manrope nor a colour the theme controls. `mdi-wrench-clock`
17
+ is translated centrally to Material Symbols `build` — no hand-mapping here.
18
+ -->
1
19
  <template>
2
- <div class="maintenance-container">
3
- <h1>🚧 Page Under Maintenance</h1>
4
- <p>
20
+ <div class="screen-empty placeholder-screen">
21
+ <v-icon icon="mdi-wrench-clock" size="32" />
22
+ <h1 class="placeholder-screen__title">Page Under Maintenance</h1>
23
+ <p class="placeholder-screen__body">
5
24
  We're currently working on improving this page to serve you better. Please
6
25
  check back soon!
7
26
  </p>
8
- <p>Thank you for your patience.</p>
27
+ <p class="placeholder-screen__body">Thank you for your patience.</p>
9
28
  </div>
10
29
  </template>
11
30
 
12
31
  <style scoped>
13
- .maintenance-container {
14
- display: flex;
15
- flex-direction: column;
16
- justify-content: center;
17
- align-items: center;
18
- text-align: center;
32
+ /* The only value kept from the old stylesheet: it is a whole route, so it
33
+ holds the viewport rather than collapsing to the height of three lines. */
34
+ .placeholder-screen {
19
35
  min-height: 50vh;
20
- margin: 0;
21
- font-family: Arial, sans-serif;
22
- color: #333;
23
36
  }
24
37
 
25
- h1 {
26
- font-size: 2rem;
27
- margin-bottom: 1rem;
38
+ .placeholder-screen__title {
39
+ margin: 0;
40
+ font-size: var(--fs-card-title);
41
+ font-weight: var(--fw-card-title);
42
+ color: var(--text);
28
43
  }
29
44
 
30
- p {
31
- font-size: 1.1rem;
32
- line-height: 1.5;
45
+ .placeholder-screen__body {
46
+ max-width: 42ch;
47
+ margin: 0;
48
+ font-weight: var(--fw-cell);
33
49
  }
34
50
  </style>
@@ -1,22 +1,35 @@
1
+ <!--
2
+ The attachment thumbnail strip (14 caller files).
3
+
4
+ THREE THINGS WERE WRONG AND ONE OF THEM NEVER DREW AT ALL:
5
+
6
+ 1. The strip painted `backgroundColor: '#FFFF'` inline. That is opaque white
7
+ in BOTH themes - a white band behind the thumbnails on the dark page. It
8
+ is deleted rather than re-coloured: the strip has no surface of its own in
9
+ the design, it sits on whatever panel holds it.
10
+ 2. `.selected` was `border: 2px solid var(--v-theme-primary)`. `--v-theme-*`
11
+ holds a BARE TRIPLET, `74, 110, 182`, not a colour - so the declaration was
12
+ invalid and dropped silently, and a selected thumbnail has never had a
13
+ border. It is now `var(--accent)`, which is a colour.
14
+ 3. The remove button's `color="red"` is a fixed Vuetify red, the same red on
15
+ both themes; `error` is the theme's own. Its `x-large` glyph (40px) was
16
+ larger than any icon the design draws - 18px is the size the handoff gives
17
+ a control icon.
18
+ -->
1
19
  <template>
2
- <v-sheet class="mx-auto">
3
- <v-slide-group
4
- class="pa-1"
5
- show-arrows
6
- :style="{ backgroundColor: '#FFFF' }"
7
- >
20
+ <v-sheet class="mx-auto bg-transparent">
21
+ <v-slide-group class="pa-1" show-arrows>
8
22
  <v-slide-group-item
9
23
  v-for="(data, idx) in localDataFiles"
10
24
  :key="idx"
11
25
  v-slot="{ isSelected }"
12
26
  >
13
27
  <v-card
14
- :class="['ma-1', isSelected && 'selected']"
28
+ :class="['ma-1', 'slide-card', isSelected && 'selected']"
15
29
  width="150"
16
30
  height="100"
31
+ elevation="0"
17
32
  @click="clickable && emit('onClickCarousel', data)"
18
- class="rounded-lg border-thin"
19
- border=" opacity-50 thin "
20
33
  >
21
34
  <v-btn
22
35
  icon
@@ -25,7 +38,7 @@
25
38
  class="remove-btn pa-0 ma-0"
26
39
  @click.stop="removeFile(data)"
27
40
  >
28
- <v-icon color="red" class="pa-0 ma-0" size="x-large"
41
+ <v-icon color="error" class="pa-0 ma-0" size="18"
29
42
  >mdi-close-circle</v-icon
30
43
  >
31
44
  </v-btn>
@@ -181,8 +194,19 @@ const removeFile = (file) => {
181
194
  right: 8px;
182
195
  }
183
196
 
197
+ /* The thumbnail tile: the design's inner radius and its own border token,
198
+ in place of Vuetify's `rounded-lg` + `border-thin` + a `border` prop that
199
+ set an opacity as well. */
200
+ .slide-card {
201
+ border: 1px solid var(--border);
202
+ border-radius: var(--r-inner);
203
+ }
204
+
205
+ /* See the note at the top: this used to name `var(--v-theme-primary)`, a bare
206
+ triplet, so the rule was invalid and the selected tile drew no border at
207
+ all. */
184
208
  .selected {
185
- border: 2px solid var(--v-theme-primary);
209
+ border: 2px solid var(--accent);
186
210
  }
187
211
 
188
212
  .remove-btn {
@@ -1,9 +1,16 @@
1
1
  <template>
2
- <v-snackbar v-model="snackbar" :color="props.color" :z-index="100000000" >
2
+ <v-snackbar
3
+ v-model="snackbar"
4
+ class="app-toast"
5
+ :color="props.color || 'primary-button'"
6
+ :z-index="100000000"
7
+ >
3
8
  {{ props.text }}
4
9
 
5
10
  <template #actions>
6
- <v-btn variant="text" @click="snackbar = false"> Close </v-btn>
11
+ <v-btn class="app-toast__close" variant="text" @click="snackbar = false">
12
+ Close
13
+ </v-btn>
7
14
  </template>
8
15
  </v-snackbar>
9
16
  </template>
@@ -15,9 +22,35 @@ const props = defineProps({
15
22
  type: String,
16
23
  default: "",
17
24
  },
25
+ /**
26
+ * A Vuetify theme colour name. `success` / `warning` / `error` / `info` are
27
+ * mapped onto the design palette in `utils/theme.ts` and pass through here
28
+ * unchanged.
29
+ *
30
+ * An UNCOLOURED toast used to land on one of two wrong surfaces, and both are
31
+ * corrected by the `||` in the template rather than by 163 caller files:
32
+ *
33
+ * - the prop omitted or bound to `undefined` fell to the old default
34
+ * `"primary"`, and `theme.ts:228` maps Vuetify's `primary` to
35
+ * `--accent-text` - a FOREGROUND (the link ink), never a fill. Measured:
36
+ * `rgb(74,110,182)` light, `rgb(120,162,244)` dark - the dark one a pale
37
+ * link-blue slab that matches no other accent surface in the product.
38
+ * - `:color=""`, which is how most callers initialise their toast state
39
+ * (`reactive({ show: false, message: "", color: "" })`), is not falsy to
40
+ * Vue's default machinery, so it reached Vuetify as an empty colour and
41
+ * fell through to `.v-snackbar--variant-elevated`, i.e. `surface-variant`
42
+ * = the NAVIGATION RAIL colour with `--text2` ink.
43
+ *
44
+ * `primary-button` is the accent FILL, and its pair `on-primary-button`
45
+ * supplies the white label (4.57:1 in both themes). The same correction is
46
+ * already on `FileInput`, `FeedbackDetail` and `BuildingUnitFormEdit`.
47
+ *
48
+ * The handoff draws no toast at all, so "an uncoloured toast is the accent
49
+ * fill" is our reading of a gap in the design, not a value it states.
50
+ */
18
51
  color: {
19
52
  type: String,
20
- default: "primary",
53
+ default: "",
21
54
  },
22
55
  });
23
56
  </script>
@@ -3,12 +3,14 @@
3
3
  <v-col cols="12" :lg="props.lg" :md="props.md" :sm="props.sm">
4
4
  <v-row no-gutters>
5
5
  <v-col cols="12">
6
- <span
7
- class="font-weight-medium text-subtitle-1 text-decoration-underline cursor-pointer"
8
- @click="emit('back')"
9
- >
10
- Back
11
- </span>
6
+ <!--
7
+ The Back link. `.screen-back` is stated once in `screens.css`; the
8
+ underline and the accent colour are the handoff's own rule for a
9
+ link (line 26), the 12.5px/700 is its "View All" (line 166), and
10
+ the design draws no back control of its own - the gap is written
11
+ out next to the class.
12
+ -->
13
+ <span class="screen-back" @click="emit('back')"> Back </span>
12
14
  </v-col>
13
15
  <!--
14
16
  THE PAGE TITLE ROW. This wrapper is the whole scaffold for every
@@ -1,33 +1,78 @@
1
+ <!--
2
+ The little "i" that explains a field.
3
+
4
+ TWO FIXES, one of them the same defect batch P found in the toast:
5
+
6
+ 1. `size` is declared `default: ""`. An EMPTY STRING IS NOT `undefined`, so
7
+ Vue's default machinery never runs and the empty string reaches Vuetify,
8
+ which builds the class `v-btn--size-` - a class that matches nothing. The
9
+ button then had no size class at all and fell back to the bare `.v-btn`
10
+ box. `props.size || undefined` lets Vuetify's own default apply when a
11
+ caller says nothing, which is what the prop was written to mean.
12
+ 2. `p-0 m-0` are not Vuetify classes and never were - nothing in this project
13
+ defines them. Dead attributes, removed.
14
+
15
+ DESIGN GAP, STATED: the handoff draws no tooltip anywhere (`grep -i tooltip`
16
+ returns nothing). So the surface below is not invented - it is the same
17
+ assembly the toast uses for the same reason: the design's inner radius, its
18
+ menu shadow, its font and its button type scale, applied to Vuetify's
19
+ tooltip in place of a 4px Roboto pill.
20
+ -->
1
21
  <template>
2
- <v-tooltip v-bind="$attrs" :text="text" @click.stop>
3
- <template v-slot:activator="{ props: activatorProps }">
4
- <v-btn icon="mdi-information-symbol" v-bind="activatorProps" class="p-0 m-0 d-flex align-center"
5
- :density="density" :size="size" color="primary-button" />
6
- </template>
7
- </v-tooltip>
22
+ <v-tooltip v-bind="$attrs" :text="text" content-class="app-tooltip" @click.stop>
23
+ <template #activator="{ props: activatorProps }">
24
+ <v-btn
25
+ icon="mdi-information-symbol"
26
+ v-bind="activatorProps"
27
+ class="d-flex align-center"
28
+ :density="density"
29
+ :size="props.size || undefined"
30
+ color="primary-button"
31
+ />
32
+ </template>
33
+ </v-tooltip>
8
34
  </template>
9
35
 
10
36
  <script setup lang="ts">
37
+ import type { VTooltip } from "vuetify/components";
11
38
 
12
- import type { VTooltip} from "vuetify/components"
13
-
14
- type TTooltipDensity = VTooltip["$props"]["density"]
39
+ type TTooltipDensity = VTooltip["$props"]["density"];
15
40
 
16
41
  const props = defineProps({
17
- text: {
18
- type: String,
19
- default: ""
20
- },
21
- size: {
22
- type: String,
23
- default: ""
24
- },
25
- density: {
26
- type: String as PropType<TTooltipDensity>,
27
- default: "default"
28
- }
29
- })
30
-
42
+ text: {
43
+ type: String,
44
+ default: "",
45
+ },
46
+ size: {
47
+ type: String,
48
+ default: "",
49
+ },
50
+ density: {
51
+ type: String as PropType<TTooltipDensity>,
52
+ default: "default",
53
+ },
54
+ });
31
55
  </script>
32
56
 
33
- <style scoped></style>
57
+ <style>
58
+ /* NOT scoped: a tooltip teleports to the overlay container, outside this
59
+ component's DOM, so a scoped rule cannot reach it. The class is namespaced
60
+ for the same reason. */
61
+ .v-tooltip > .v-overlay__content.app-tooltip {
62
+ /* MEASURED FIRST, then fixed. Left to Vuetify the panel came out
63
+ `rgb(251,251,248)` on the light page - `--sidebar`, the navigation-rail
64
+ colour, 1.03:1 against `--bg` with no border. The identical fall-through
65
+ batch P found behind the invisible toast. `--card` + `--border` is what
66
+ every other floating panel in this product uses (see `.app-profile-menu`
67
+ in `Layout/Header.vue`), so the edge is what carries the boundary. */
68
+ background: var(--card);
69
+ border: 1px solid var(--border);
70
+ color: var(--text2);
71
+ border-radius: var(--r-inner);
72
+ box-shadow: var(--shadow-menu);
73
+ font-family: var(--font-sans);
74
+ font-size: var(--fs-btn);
75
+ font-weight: 600;
76
+ letter-spacing: 0;
77
+ }
78
+ </style>
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.139",
5
+ "version": "3.2.2-staging.141",
6
6
  "author": "7365admin1",
7
7
  "main": "./nuxt.config.ts",
8
8
  "//files": "What a consumer extending this layer actually loads. Without this npm ships the whole working tree - the changesets, the CI workflows, the render harness in tools/ and any scratch directory that happened to exist at publish time. Nuxt resolves a layer by directory, so every runtime directory below has to stay listed; adding a new top-level runtime directory means adding it here too.",