@saasicat/ui-vue 0.24.1 → 0.24.2

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": "@saasicat/ui-vue",
3
- "version": "0.24.1",
3
+ "version": "0.24.2",
4
4
  "description": "Vue 3 components, resource clients and composables for the SuperAdmin UI shell. Provides boot and manifest loaders, navigation, actions and standard pages.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -61,7 +61,7 @@
61
61
  "src"
62
62
  ],
63
63
  "dependencies": {
64
- "@saasicat/types": "^0.24.1"
64
+ "@saasicat/types": "^0.24.2"
65
65
  },
66
66
  "peerDependencies": {
67
67
  "pinia": "^2.0.0 || ^3.0.0",
@@ -208,7 +208,12 @@ function onToggle(featureKey: string): void {
208
208
  margin-left: 4px;
209
209
  }
210
210
  .bd-feature-pill.on .bd-feature-key {
211
- color: var(--sa-color-accent);
211
+ /* `-strong`, not the bare accent: the pill's `on` surface is a 24 % tint of
212
+ * blue over the dark card, and the brand does not change between themes —
213
+ * 2.92:1 there. The selected states around this one were moved to
214
+ * `-strong` already; this descendant was missed because it sets a colour
215
+ * and no background, which is a shape no contrast check reads. */
216
+ color: var(--sa-color-accent-strong);
212
217
  }
213
218
  .bd-feature-pill.overlap .bd-feature-key {
214
219
  color: var(--sa-color-negative-fg);
@@ -170,7 +170,7 @@
170
170
  >
171
171
  <span
172
172
  class="pl-plan-opt__dot"
173
- :style="{ background: p.color ?? '#94a3b8' }"
173
+ :style="{ background: p.color ?? IDENTITY_NEUTRAL }"
174
174
  />
175
175
  <div class="pl-plan-opt__text">
176
176
  <span class="pl-plan-opt__key">{{ p.value }}</span>
@@ -263,6 +263,7 @@
263
263
  <script setup lang="ts">
264
264
  import { computed, reactive, ref, watch } from 'vue';
265
265
  import MfaPromptDialog from '../MfaPromptDialog.vue';
266
+ import { IDENTITY_NEUTRAL } from '../../client/identity-accents.js';
266
267
  import { formatMessage } from '../../client/i18n/format.js';
267
268
  import { useSaMessages } from '../../vue/use-super-admin-i18n.js';
268
269
  import type { PilotCopy, PilotCreatePayload, PilotCreateResult } from './types.js';
@@ -46,7 +46,7 @@
46
46
  >
47
47
  <span
48
48
  class="pl-plan-opt__dot"
49
- :style="{ background: p.color ?? '#94a3b8' }"
49
+ :style="{ background: p.color ?? IDENTITY_NEUTRAL }"
50
50
  />
51
51
  <div class="pl-plan-opt__text">
52
52
  <span class="pl-plan-opt__key">{{ p.value }}</span>
@@ -148,6 +148,7 @@
148
148
  <script setup lang="ts">
149
149
  import { computed, reactive, ref, watch } from 'vue';
150
150
  import MfaPromptDialog from '../MfaPromptDialog.vue';
151
+ import { IDENTITY_NEUTRAL } from '../../client/identity-accents.js';
151
152
  import { formatMessage } from '../../client/i18n/format.js';
152
153
  import { useSaMessages } from '../../vue/use-super-admin-i18n.js';
153
154
  import type { PilotRow } from '../../pages-standard/PilotsPage.vue';
@@ -85,7 +85,10 @@
85
85
  :style="planChipStyle(p)"
86
86
  @click="togglePlan(p.key)"
87
87
  >
88
- <span class="pc-plan-opt__mark" :style="{ background: p.color ?? '#64748b' }" />
88
+ <span
89
+ class="pc-plan-opt__mark"
90
+ :style="{ background: p.color ?? IDENTITY_NEUTRAL }"
91
+ />
89
92
  {{ p.label }}
90
93
  </button>
91
94
  </div>
@@ -265,7 +268,7 @@
265
268
 
266
269
  <script setup lang="ts">
267
270
  import { computed } from 'vue';
268
- import { identityChipStyle } from '../../client/identity-accents.js';
271
+ import { IDENTITY_NEUTRAL, identityChipStyle } from '../../client/identity-accents.js';
269
272
  import { formatMessage } from '../../client/i18n/format.js';
270
273
  import { useSaMessages } from '../../vue/use-super-admin-i18n.js';
271
274
  import type { PromoCodeDurationType, PromoCodePlanOption, PromoCodeValueType } from './types.js';
@@ -825,23 +825,61 @@ async function executeTerminate(): Promise<void> {
825
825
  );
826
826
  border-color: var(--sa-color-border);
827
827
  }
828
+ /* The marker block at the head of a diff row.
829
+ *
830
+ * Every rule below carries BOTH halves of its pair, and that is deliberate:
831
+ * the geometry used to live here and the background one rule further down,
832
+ * which made neither rule judgeable on its own. `theme-role-contrast` needs a
833
+ * background and a colour in the same body to measure anything, so the split
834
+ * hid `--sa-color-fg-on-accent` on `--sa-color-positive-strong` — white on
835
+ * green-500, 2.54:1, in BOTH themes — for as long as the component existed.
836
+ *
837
+ * A tint plus the tone's `-fg`, not a solid plus white: `-strong` is the rung
838
+ * chosen to read as a COLOUR against its theme's surface, which puts it in the
839
+ * middle of the lightness range — and nothing reads on the middle. That is
840
+ * what `<tone>-fg` and `-surface-strong` are for. */
828
841
  .pd-diff-icon {
829
842
  width: 32px;
830
843
  align-self: stretch;
831
844
  display: grid;
832
845
  place-items: center;
833
846
  flex: 0 0 32px;
834
- color: var(--sa-color-fg-on-accent);
847
+ background: var(--sa-color-bg-sunken);
848
+ color: var(--sa-color-fg-body);
835
849
  font: 700 var(--sa-text-lg) var(--sa-font-body);
836
850
  }
837
851
  .pd-diff-row.add .pd-diff-icon {
838
- background: var(--sa-color-positive-strong);
852
+ background: var(--sa-color-positive-surface-strong);
853
+ color: var(--sa-color-positive-fg);
839
854
  }
840
855
  .pd-diff-row.rm .pd-diff-icon {
841
- background: var(--sa-color-negative-strong);
856
+ background: var(--sa-color-negative-surface-strong);
857
+ color: var(--sa-color-negative-fg);
842
858
  }
859
+ /* Unchanged, and deliberately not brought into line with the two above: it was
860
+ * already readable (14.6:1) and `--sa-color-bg-sunken` is what the `mod` row
861
+ * itself starts its gradient with, so a neutral tint here would leave the
862
+ * marker with almost nothing to stand against in the light theme. It only
863
+ * gains the foreground it was already inheriting, so the rule can be read. */
843
864
  .pd-diff-row.mod .pd-diff-icon {
844
865
  background: var(--sa-color-inverse-surface);
866
+ color: var(--sa-color-inverse-fg);
867
+ }
868
+ /* The single-version listing marks WHAT a row is rather than what changed, so
869
+ * it reads the catalogue-entity roles. These three were the last colour
870
+ * literals in a template: `style="background: #f59e0b"` and friends, painted
871
+ * white by the base rule above at 2.15:1, 2.77:1 and 4.23:1. */
872
+ .pd-diff-row.plain .pd-diff-icon.feature {
873
+ background: var(--sa-color-feature-surface);
874
+ color: var(--sa-color-feature-fg);
875
+ }
876
+ .pd-diff-row.plain .pd-diff-icon.quota {
877
+ background: var(--sa-color-quota-surface);
878
+ color: var(--sa-color-quota-fg);
879
+ }
880
+ .pd-diff-row.plain .pd-diff-icon.bundle {
881
+ background: var(--sa-color-bundle-surface);
882
+ color: var(--sa-color-bundle-fg);
845
883
  }
846
884
  .pd-diff-body {
847
885
  flex: 1;
@@ -66,7 +66,7 @@
66
66
  :key="'cf-' + f"
67
67
  class="pd-diff-row plain"
68
68
  >
69
- <div class="pd-diff-icon" style="background: #8b5cf6">·</div>
69
+ <div class="pd-diff-icon feature">·</div>
70
70
  <div class="pd-diff-body">
71
71
  <span class="pd-diff-label">{{ featureLabel(f) }}</span>
72
72
  <code class="pd-diff-key">{{ f }}</code>
@@ -88,7 +88,7 @@
88
88
  :key="'cq-' + k"
89
89
  class="pd-diff-row plain"
90
90
  >
91
- <div class="pd-diff-icon" style="background: #0ea5e9">·</div>
91
+ <div class="pd-diff-icon quota">·</div>
92
92
  <div class="pd-diff-body">
93
93
  <span class="pd-diff-label">{{ quotaLabel(k) }}</span>
94
94
  <code class="pd-diff-key">{{ k }}</code>
@@ -111,7 +111,7 @@
111
111
  :key="'cb-' + b"
112
112
  class="pd-diff-row plain"
113
113
  >
114
- <div class="pd-diff-icon" style="background: #f59e0b">·</div>
114
+ <div class="pd-diff-icon bundle">·</div>
115
115
  <div class="pd-diff-body">
116
116
  <span class="pd-diff-label">{{ bundleLabel(b) }}</span>
117
117
  <code class="pd-diff-key">{{ b }}</code>
@@ -25,9 +25,13 @@
25
25
 
26
26
  <div class="pve-prev-window" :class="`pve-prev-window--${previewMode}`">
27
27
  <div class="pve-prev-chrome">
28
- <span class="pve-prev-dot" style="background: #ef4444" />
29
- <span class="pve-prev-dot" style="background: #f59e0b" />
30
- <span class="pve-prev-dot" style="background: #10b981" />
28
+ <!-- The same window controls as MarketingCatalogPreview, drawn
29
+ a second time, and the same reason for the `-strong`
30
+ rungs. The chrome itself is duplicated markup and belongs
31
+ in one component; that is a Phase 4 job, not a colour one. -->
32
+ <span class="pve-prev-dot" style="background: var(--sa-color-negative-strong)" />
33
+ <span class="pve-prev-dot" style="background: var(--sa-color-warning-strong)" />
34
+ <span class="pve-prev-dot" style="background: var(--sa-color-positive-strong)" />
31
35
  <div class="pve-prev-url">{{ catalogUrl }}</div>
32
36
  </div>
33
37
  <div class="pve-prev-body">
@@ -1724,8 +1724,13 @@ async function onLocaleChange(loc: string): Promise<void> {
1724
1724
  color 0.12s;
1725
1725
  }
1726
1726
  .sa-marketing-tf-chip em {
1727
+ /* No colour of its own — the mono face and the smaller step already set it
1728
+ * apart from the chip's label, and a colour here does not follow the chip.
1729
+ * `--sa-color-fg-subtle` stayed put when :hover moved the chip's surface to
1730
+ * a 22 % accent tint, which measured 2.92:1 in the dark theme: a foreground
1731
+ * declared without the background it will end up on is a pair nothing can
1732
+ * check, and this one was wrong in exactly the state nobody screenshots. */
1727
1733
  font-style: normal;
1728
- color: var(--sa-color-fg-subtle);
1729
1734
  font: 500 var(--sa-text-xs) var(--sa-font-mono);
1730
1735
  }
1731
1736
  .sa-marketing-tf-chip:hover:not(:disabled) {
@@ -1,9 +1,23 @@
1
1
  <template>
2
2
  <div class="sa-marketing-window">
3
3
  <div class="sa-marketing-chrome">
4
- <span class="sa-marketing-chrome-dot" style="background: #ef4444" />
5
- <span class="sa-marketing-chrome-dot" style="background: #f59e0b" />
6
- <span class="sa-marketing-chrome-dot" style="background: #10b981" />
4
+ <!-- The window controls of the browser this mock-up draws. Their hue
5
+ is fixed by what they depict rather than by what they mean, and
6
+ the `-strong` rungs are exactly that hue — the three replaced
7
+ the same three literals byte for byte. Only the amber differs
8
+ between themes, and it lifts one rung in the dark one. -->
9
+ <span
10
+ class="sa-marketing-chrome-dot"
11
+ style="background: var(--sa-color-negative-strong)"
12
+ />
13
+ <span
14
+ class="sa-marketing-chrome-dot"
15
+ style="background: var(--sa-color-warning-strong)"
16
+ />
17
+ <span
18
+ class="sa-marketing-chrome-dot"
19
+ style="background: var(--sa-color-positive-strong)"
20
+ />
7
21
  <div class="sa-marketing-chrome-url">{{ previewUrl }}</div>
8
22
  </div>
9
23
  <div class="sa-marketing-canvas">
@@ -120,9 +120,11 @@ body.body--dark {
120
120
  --sa-color-feature-fg: var(--sa-violet-200);
121
121
  --sa-color-feature-surface: color-mix(in srgb, var(--sa-violet-500) 16%, transparent);
122
122
  --sa-color-quota: var(--sa-sky-500);
123
+ --sa-color-quota-fg: var(--sa-sky-200);
123
124
  --sa-color-quota-surface: color-mix(in srgb, var(--sa-sky-500) 16%, transparent);
124
125
  --sa-color-quota-border: color-mix(in srgb, var(--sa-sky-500) 36%, transparent);
125
126
  --sa-color-bundle: var(--sa-amber-500);
127
+ --sa-color-bundle-fg: var(--sa-amber-200);
126
128
  --sa-color-bundle-surface: color-mix(in srgb, var(--sa-amber-500) 16%, transparent);
127
129
 
128
130
  /* The identity ramp, one rung lighter throughout — see the light file for
@@ -141,16 +141,25 @@
141
141
  --sa-color-scheduled-surface-strong: var(--sa-indigo-100);
142
142
  --sa-color-scheduled-border: var(--sa-indigo-200);
143
143
 
144
- /* ── Catalogue entities. Not statuses: these two say WHAT a row is, and
144
+ /* ── Catalogue entities. Not statuses: these three say WHAT a row is, and
145
145
  * the plan editor, the matrix, the review and the discovery page all need
146
- * to agree, or the same dot means two things on two screens. ────────── */
146
+ * to agree, or the same dot means two things on two screens.
147
+ *
148
+ * Each one has the same three slots a status tone has: the colour itself,
149
+ * a tinted SURFACE, and an `-fg` that is readable on that surface. Only
150
+ * `feature` had the third, and the two that were missing are why a diff
151
+ * marker painted white on `--sa-sky-500` (2.77:1) and on `--sa-amber-500`
152
+ * (2.15:1): with no role to point at, the panel reached past the layer for
153
+ * the primitive and wrote it into the template. ───────────────────────── */
147
154
  --sa-color-feature: var(--sa-violet-500);
148
155
  --sa-color-feature-fg: var(--sa-violet-700);
149
156
  --sa-color-feature-surface: var(--sa-violet-50);
150
157
  --sa-color-quota: var(--sa-sky-500);
158
+ --sa-color-quota-fg: var(--sa-sky-700);
151
159
  --sa-color-quota-surface: var(--sa-sky-50);
152
160
  --sa-color-quota-border: var(--sa-sky-200);
153
161
  --sa-color-bundle: var(--sa-amber-500);
162
+ --sa-color-bundle-fg: var(--sa-amber-700);
154
163
  --sa-color-bundle-surface: var(--sa-amber-100);
155
164
 
156
165
  /* ── Identity. A CATEGORICAL ramp: the only job of these seven is to be