@proyecto-viviana/ui 0.4.0 → 0.4.1

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.
Files changed (63) hide show
  1. package/dist/CalendarCard.js +2 -3
  2. package/dist/CalendarCard.js.map +1 -1
  3. package/dist/CalendarCard.jsx +7 -8
  4. package/dist/CalendarCard.jsx.map +1 -1
  5. package/dist/Conversation.js +44 -45
  6. package/dist/Conversation.js.map +1 -1
  7. package/dist/Conversation.jsx +49 -50
  8. package/dist/Conversation.jsx.map +1 -1
  9. package/dist/EventCard.js +3 -5
  10. package/dist/EventCard.js.map +1 -1
  11. package/dist/EventCard.jsx +17 -19
  12. package/dist/EventCard.jsx.map +1 -1
  13. package/dist/Logo.js +64 -64
  14. package/dist/Logo.js.map +1 -1
  15. package/dist/Logo.jsx +64 -64
  16. package/dist/Logo.jsx.map +1 -1
  17. package/dist/PageLayout.js +7 -7
  18. package/dist/PageLayout.jsx +7 -7
  19. package/dist/PageLayout.jsx.map +1 -1
  20. package/dist/ProfileCard.js +2 -3
  21. package/dist/ProfileCard.js.map +1 -1
  22. package/dist/ProfileCard.jsx +8 -9
  23. package/dist/ProfileCard.jsx.map +1 -1
  24. package/dist/ProjectCard.js +86 -88
  25. package/dist/ProjectCard.js.map +1 -1
  26. package/dist/ProjectCard.jsx +86 -88
  27. package/dist/ProjectCard.jsx.map +1 -1
  28. package/dist/TimelineItem.js +2 -2
  29. package/dist/TimelineItem.js.map +1 -1
  30. package/dist/TimelineItem.jsx +4 -4
  31. package/dist/TimelineItem.jsx.map +1 -1
  32. package/dist/chip2.js +43 -43
  33. package/dist/chip2.js.map +1 -1
  34. package/dist/chip2.jsx +43 -43
  35. package/dist/chip2.jsx.map +1 -1
  36. package/dist/custom/calendar-card/index.d.ts.map +1 -1
  37. package/dist/custom/chip/index.d.ts.map +1 -1
  38. package/dist/custom/conversation/index.d.ts.map +1 -1
  39. package/dist/custom/event-card/index.d.ts.map +1 -1
  40. package/dist/custom/lateral-nav/index.d.ts.map +1 -1
  41. package/dist/custom/logo/index.d.ts.map +1 -1
  42. package/dist/custom/nav-header/index.d.ts.map +1 -1
  43. package/dist/custom/profile-card/index.d.ts.map +1 -1
  44. package/dist/custom/timeline-item/index.d.ts.map +1 -1
  45. package/dist/styles.css +1 -1
  46. package/dist/vite.d.ts +1 -0
  47. package/dist/vite.d.ts.map +1 -1
  48. package/dist/vite.js +9 -1
  49. package/dist/vite.js.map +1 -1
  50. package/dist/vite.jsx +9 -1
  51. package/dist/vite.jsx.map +1 -1
  52. package/package.json +3 -3
  53. package/src/custom/calendar-card/index.tsx +10 -1
  54. package/src/custom/chip/index.tsx +5 -1
  55. package/src/custom/conversation/index.tsx +23 -6
  56. package/src/custom/event-card/index.tsx +25 -4
  57. package/src/custom/lateral-nav/index.tsx +10 -1
  58. package/src/custom/logo/index.tsx +8 -1
  59. package/src/custom/nav-header/index.tsx +9 -1
  60. package/src/custom/profile-card/index.tsx +11 -2
  61. package/src/custom/project-card/index.tsx +1 -1
  62. package/src/custom/timeline-item/index.tsx +10 -2
  63. package/src/vite.ts +13 -1
@@ -65,13 +65,18 @@ const previewName = style({
65
65
 
66
66
  const previewTime = style({
67
67
  font: "detail-sm",
68
- color: "[var(--color-text-muted)]",
68
+ // `--color-text-muted` renders ~1.7:1 light / ~2.4:1 dark on the `bg-200`
69
+ // panel (fails AA both modes); the flipping `--color-text` clears it. Muting
70
+ // is carried by the smaller `detail-sm` size, not a sub-AA color.
71
+ color: "[var(--color-text)]",
69
72
  flexShrink: 0,
70
73
  });
71
74
 
72
75
  const previewMessage = style({
73
76
  font: "ui-sm",
74
- color: "[var(--color-text-secondary)]",
77
+ // `--color-text-secondary` renders 3.84:1 on the light `bg-200` panel (fails
78
+ // the 4.5 small-text floor); the flipping `--color-text` clears both themes.
79
+ color: "[var(--color-text)]",
75
80
  overflow: "hidden",
76
81
  textOverflow: "ellipsis",
77
82
  whiteSpace: "nowrap",
@@ -88,7 +93,11 @@ const unread = style({
88
93
  font: "detail-sm",
89
94
  fontWeight: "bold",
90
95
  backgroundColor: "[var(--color-accent)]",
91
- color: "[var(--color-bg-400)]",
96
+ // Text on the non-flipping pink `--color-accent` fill: the near-white
97
+ // `--color-bg-400` gives only 2.74:1 in light mode (fail). `--color-grey-900`
98
+ // (the darkest token) reaches ~5.2:1 light / ~6.1:1 dark — the Chip accent-fill
99
+ // resolution.
100
+ color: "[var(--color-grey-900)]",
92
101
  });
93
102
 
94
103
  export function ConversationPreview(props: ConversationPreviewProps) {
@@ -142,16 +151,24 @@ const bubble = style<{ isUser: boolean }>({
142
151
  isUser: "[var(--color-accent)]",
143
152
  },
144
153
  color: {
154
+ // `other` bubble: `--color-primary-100` on the neutral `bg-300` fill (AA both
155
+ // themes). `user` bubble text on the pink `--color-accent` fill: the near-white
156
+ // `--color-bg-400` gives only 2.74:1 light (fail) → `--color-grey-900` (~5.2:1
157
+ // light / ~6.1:1 dark), the Chip accent-fill resolution.
145
158
  default: "[var(--color-primary-100)]",
146
- isUser: "[var(--color-bg-400)]",
159
+ isUser: "[var(--color-grey-900)]",
147
160
  },
148
161
  });
149
162
 
150
163
  const bubbleTime = style<{ isUser: boolean }>({
151
164
  font: "detail-sm",
152
165
  color: {
153
- default: "[var(--color-text-muted)]",
154
- isUser: "[var(--color-bg-300)]",
166
+ // `other` timestamp on `bg-300`: `--color-text-muted` fails AA both modes
167
+ // (~2.2:1 light / ~2.8:1 dark) → the flipping `--color-text`. `user` timestamp
168
+ // on the `--color-accent` fill: `--color-bg-300` gives 2.42:1 light (fail) →
169
+ // `--color-grey-900` (matching the bubble body).
170
+ default: "[var(--color-text)]",
171
+ isUser: "[var(--color-grey-900)]",
155
172
  },
156
173
  });
157
174
 
@@ -58,7 +58,15 @@ const body = style({
58
58
 
59
59
  const title = style({
60
60
  font: "heading",
61
- color: "[var(--color-accent)]",
61
+ // WCAG AA fix: the title sits on the `--color-bg-200` card. `--color-accent`
62
+ // (#df5c9a) is a fixed pink in BOTH themes, so it does not flip against a card
63
+ // that is dark-grey in dark mode and light-blue in light mode — it read 4.48:1
64
+ // dark / 1.89:1 light. `font: heading` renders 22px / weight 800, which is WCAG
65
+ // large text via the BOLD path (≥18.66px && ≥700), NOT because it is ≥24px — so
66
+ // the 3:1 large-text floor applies. `--color-accent-500` is the smallest ramp
67
+ // step that flips with the theme (bright pink dark / deep magenta light) AND
68
+ // clears 3:1 both ways (3.87:1 dark / 4.91:1 light), keeping the brand accent.
69
+ color: "[var(--color-accent-500)]",
62
70
  });
63
71
 
64
72
  const meta = style({
@@ -66,7 +74,12 @@ const meta = style({
66
74
  alignItems: "center",
67
75
  gap: 16,
68
76
  font: "ui-sm",
69
- color: "[var(--color-text-secondary)]",
77
+ // WCAG AA fix: the meta text is small (`ui-sm`), so the 4.5:1 normal-text
78
+ // floor applies. `--color-text-secondary` read only 3.84:1 on the light
79
+ // `--color-bg-200` card; `--color-text` flips and clears 4.5:1 both ways
80
+ // (15.33:1 dark / 7.53:1 light). Secondary de-emphasis rides on the smaller
81
+ // `ui-sm` size rather than a sub-AA color.
82
+ color: "[var(--color-text)]",
70
83
  });
71
84
 
72
85
  const metaItem = style({
@@ -76,7 +89,12 @@ const metaItem = style({
76
89
  });
77
90
 
78
91
  const metaIcon = style({
79
- color: "[var(--color-accent)]",
92
+ // WCAG AA fix: the meta glyphs (@ / ⏱) are small (inherit `ui-sm`), so the
93
+ // 4.5:1 floor applies. `--color-accent` fails on the card (4.48:1 dark /
94
+ // 1.89:1 light) and no pink ramp step clears 4.5:1 on both the dark-grey and
95
+ // light-blue card, so the glyphs take the flipping `--color-text` like the
96
+ // meta text they prefix.
97
+ color: "[var(--color-text)]",
80
98
  });
81
99
 
82
100
  const attendeesRow = style({
@@ -93,7 +111,10 @@ const avatars = style({
93
111
 
94
112
  const more = style({
95
113
  font: "ui-sm",
96
- color: "[var(--color-text-secondary)]",
114
+ // WCAG AA fix: the "+N más" overflow count is small text on the same
115
+ // `--color-bg-200` card as the meta, so it shares the same 3.84:1-light
116
+ // failure and the same `--color-text` fix.
117
+ color: "[var(--color-text)]",
97
118
  });
98
119
 
99
120
  const actionRow = style({
@@ -35,11 +35,20 @@ export interface NavLinkProps {
35
35
  }
36
36
 
37
37
  const link = style<{ isActive: boolean }>({
38
+ // A ≥24px hit target (WCAG 2.5.8): the link is a full-width flex row, not a
39
+ // bare inline anchor (which rendered ~15px tall on the `ui` ramp).
40
+ display: "flex",
41
+ alignItems: "center",
42
+ minHeight: 32,
38
43
  font: "ui",
39
44
  textDecoration: { default: "none", isActive: "underline" },
40
45
  fontWeight: { default: "normal", isActive: "medium" },
46
+ // `color` MUST stay after `font`: the S2 style() `font` shorthand emits a
47
+ // default text color that wins on source order otherwise. The resting link
48
+ // uses the flipping `--color-text` (AA on the light `bg-200` panel); the active
49
+ // link is set apart by its underline + medium weight + `--color-primary-300`.
41
50
  color: {
42
- default: "[var(--color-text-secondary)]",
51
+ default: "[var(--color-text)]",
43
52
  isActive: "[var(--color-primary-300)]",
44
53
  },
45
54
  });
@@ -34,7 +34,14 @@ const word = style<{ tone: "primary" | "accent" }>({
34
34
  color: {
35
35
  tone: {
36
36
  primary: "[var(--color-primary-100)]",
37
- accent: "[var(--color-accent)]",
37
+ // `--color-accent` (#df5c9a) is the SAME non-flipping pink in both themes;
38
+ // on the light `--color-bg-200` panel the wordmark reads only 1.89:1 (fails
39
+ // even the 3:1 large-text floor the `black`-weight `title-xl` earns). No
40
+ // single non-flipping shade clears a near-white AND a near-black panel, so
41
+ // the accent word takes the *flipping* `--color-accent-500` (dark #d84a8f /
42
+ // light #8a1e4a) → 3.86:1 dark / 4.91:1 light — clearing the large-text
43
+ // floor in both themes while keeping the two-tone wordmark identity.
44
+ accent: "[var(--color-accent-500)]",
38
45
  },
39
46
  },
40
47
  });
@@ -38,7 +38,15 @@ const logoText = style({
38
38
  alignItems: "center",
39
39
  font: "title-xl",
40
40
  fontWeight: "normal",
41
- color: "[var(--color-primary-700)]",
41
+ // WCAG AA fix: the wordmark sits on the `--color-bg-400` bar. `--color-primary-700`
42
+ // is a non-flipping brand fill (light blue in light mode, dark blue in dark mode) —
43
+ // the SAME direction as the bar, so it read only 2.10:1 light / 2.92:1 dark. The
44
+ // rendered `title-xl` measures under 24px, so WCAG scores it as normal text (4.5:1
45
+ // floor, not the 3:1 large-text exception). `--color-primary-500` is the smallest
46
+ // ramp step that flips with the theme (dark-on-light / light-on-dark) AND clears
47
+ // 4.5:1, lifting the wordmark to 5.37:1 light / 7.00:1 dark while keeping a prominent
48
+ // brand blue.
49
+ color: "[var(--color-primary-500)]",
42
50
  });
43
51
 
44
52
  const logoImage = style({
@@ -54,14 +54,23 @@ const name = style({
54
54
 
55
55
  const bio = style({
56
56
  font: "ui-sm",
57
- color: "[var(--color-text-secondary)]",
57
+ // WCAG AA fix: the bio is small text (`ui-sm`) on the `--color-bg-200` card, so
58
+ // the 4.5:1 floor applies. `--color-text-secondary` read only 3.84:1 on the
59
+ // light-blue card (5.86:1 dark); `--color-text` flips and clears 4.5:1 both
60
+ // ways (15.33:1 dark / 7.53:1 light). The bio stays visually secondary to the
61
+ // `heading-sm` name through its smaller size, not a sub-AA color.
62
+ color: "[var(--color-text)]",
58
63
  });
59
64
 
60
65
  const stats = style({
61
66
  display: "flex",
62
67
  gap: 16,
63
68
  font: "ui-sm",
64
- color: "[var(--color-text-secondary)]",
69
+ // WCAG AA fix: the stat connector words ("seguidores" / "siguiendo") share the
70
+ // bio's 3.84:1-light failure on the `--color-bg-200` card and take the same
71
+ // flipping `--color-text`. (The stat VALUES are `--color-primary-100`, which
72
+ // already clears AA — 13.47:1 dark / 10.37:1 light.)
73
+ color: "[var(--color-text)]",
65
74
  });
66
75
 
67
76
  const statValue = style({
@@ -47,8 +47,8 @@ const caption = style<{ size: ProjectCardSize }>({
47
47
  overflow: "hidden",
48
48
  textOverflow: "ellipsis",
49
49
  whiteSpace: "nowrap",
50
- color: "[var(--color-primary-200)]",
51
50
  font: { size: { sm: "ui-sm", md: "ui", lg: "ui-lg" } },
51
+ color: "[var(--color-primary-200)]",
52
52
  });
53
53
 
54
54
  export function ProjectCard(props: ProjectCardProps): JSX.Element {
@@ -35,7 +35,11 @@ export interface TimelineItemProps {
35
35
 
36
36
  const nameEmph = style({
37
37
  fontWeight: "bold",
38
- color: "[var(--color-accent)]",
38
+ // Emphasis via weight, not color: `--color-accent` (#df5c9a) fails AA on the
39
+ // `--color-bg-200` card (~1.9:1 light, ~4.48:1 dark) and no accent shade clears
40
+ // 4.5:1 in BOTH themes. The flipping `--color-text` does (7.53 light / 15.33
41
+ // dark); the `bold` weight sets the names apart from the message body.
42
+ color: "[var(--color-text)]",
39
43
  });
40
44
 
41
45
  const eventMessages: Record<TimelineEventType, (left: string, right: string) => JSX.Element> = {
@@ -95,7 +99,11 @@ const messageRow = style({
95
99
  justifyContent: "center",
96
100
  textAlign: "center",
97
101
  font: "ui",
98
- color: "[var(--color-text-secondary)]",
102
+ // `--color-text-secondary` renders 3.84:1 on the light `--color-bg-200` card
103
+ // (fails the 4.5:1 small-text floor); the flipping `--color-text` clears it in
104
+ // both themes. `color` stays after `font` (the S2 macro font-shorthand default
105
+ // color would otherwise win on source order).
106
+ color: "[var(--color-text)]",
99
107
  });
100
108
 
101
109
  export function TimelineItem(props: TimelineItemProps) {
package/src/vite.ts CHANGED
@@ -46,6 +46,7 @@ import macros from "unplugin-parcel-macros";
46
46
  // typed `Plugin | Plugin[]`; we always get the single-plugin form.
47
47
  interface MacroPlugin {
48
48
  name?: string;
49
+ transformInclude?: (id: string) => boolean | void;
49
50
  transform?: (this: unknown, code: string, id: string) => unknown;
50
51
  resolveId?: (this: unknown, id: string, importer?: string, options?: object) => unknown;
51
52
  loadInclude?: (id: string) => boolean | void;
@@ -56,6 +57,14 @@ interface MacroPlugin {
56
57
  const macroCssIdPattern = /^macro-[a-f0-9]+\.css$/;
57
58
  const macroCssImportPattern = /import\s+["']macro-[a-f0-9]+\.css["'];\n?/g;
58
59
 
60
+ function getMacroSourceFilePath(id: string) {
61
+ const queryIndex = id.indexOf("?");
62
+ if (queryIndex === -1 || !/^\?tsr-split=[^&#]+(?:#.*)?$/.test(id.slice(queryIndex))) {
63
+ return id;
64
+ }
65
+ return id.slice(0, queryIndex);
66
+ }
67
+
59
68
  function getMacroCssFileName(id: string) {
60
69
  const fileName = id.split("/").pop();
61
70
  return fileName && macroCssIdPattern.test(fileName) ? fileName : null;
@@ -97,8 +106,11 @@ export function vivianaMacros(): MacroPlugin {
97
106
 
98
107
  return {
99
108
  ...plugin,
109
+ transformInclude(id: string) {
110
+ return plugin.transformInclude?.(getMacroSourceFilePath(id)) ?? false;
111
+ },
100
112
  async transform(this: unknown, code: string, id: string) {
101
- const result = await plugin.transform?.call(this, code, id);
113
+ const result = await plugin.transform?.call(this, code, getMacroSourceFilePath(id));
102
114
  const transformedCode =
103
115
  typeof result === "string"
104
116
  ? result