@lotics/ui 47.5.2 → 47.6.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 (64) hide show
  1. package/AGENTS.md +22 -3
  2. package/MIGRATION.md +61 -62
  3. package/docs/ai_patterns.md +9 -2
  4. package/docs/catalog.md +43 -6
  5. package/docs/composition.md +148 -10
  6. package/docs/data_entry.md +8 -0
  7. package/docs/reviewing.md +56 -2
  8. package/examples/tpl_attendance.tsx +1 -1
  9. package/package.json +3 -1
  10. package/src/alert.tsx +1 -1
  11. package/src/avatar.tsx +1 -1
  12. package/src/avatar.web.tsx +1 -1
  13. package/src/avatar_group.tsx +1 -1
  14. package/src/bar_chart.tsx +10 -1
  15. package/src/board.tsx +1 -1
  16. package/src/button.tsx +4 -4
  17. package/src/cell_stack.tsx +140 -0
  18. package/src/column_filter.tsx +1 -1
  19. package/src/combobox.tsx +2 -2
  20. package/src/comments_thread.tsx +2 -2
  21. package/src/count.tsx +32 -16
  22. package/src/date_calendar.tsx +2 -2
  23. package/src/date_filter.tsx +1 -1
  24. package/src/diff_value.tsx +2 -2
  25. package/src/eyebrow.tsx +1 -1
  26. package/src/file_thumbnail.tsx +2 -2
  27. package/src/file_thumbnail_grid.tsx +1 -1
  28. package/src/filter_chip.tsx +5 -2
  29. package/src/finding.tsx +19 -2
  30. package/src/form_field.tsx +1 -1
  31. package/src/inline_date_picker.tsx +1 -1
  32. package/src/inline_edit.tsx +2 -1
  33. package/src/line_chart.tsx +3 -1
  34. package/src/list_item.tsx +1 -1
  35. package/src/loading.tsx +1 -1
  36. package/src/matrix.tsx +1 -1
  37. package/src/member_chip.tsx +1 -1
  38. package/src/member_profile_card.tsx +1 -1
  39. package/src/menu_list_item.tsx +2 -2
  40. package/src/metric.tsx +1 -1
  41. package/src/option_list.tsx +1 -1
  42. package/src/page_header.tsx +26 -25
  43. package/src/pagination.tsx +1 -1
  44. package/src/pie_chart.tsx +4 -2
  45. package/src/progress_bar.tsx +20 -11
  46. package/src/radio_picker.tsx +3 -3
  47. package/src/section_heading.tsx +74 -5
  48. package/src/segmented_control.tsx +1 -1
  49. package/src/select.tsx +1 -1
  50. package/src/shortcut_badge.tsx +1 -1
  51. package/src/stacked_bar_chart.tsx +1 -1
  52. package/src/switcher.tsx +1 -1
  53. package/src/table.tsx +46 -8
  54. package/src/tabs.tsx +2 -2
  55. package/src/text.tsx +2 -7
  56. package/src/text_ink.ts +96 -0
  57. package/src/text_link.tsx +1 -1
  58. package/src/text_utils.ts +1 -46
  59. package/src/thumbnail_stack.tsx +1 -1
  60. package/src/time_picker.tsx +1 -1
  61. package/src/timeline.tsx +1 -1
  62. package/src/tokens.ts +28 -4
  63. package/src/tooltip.tsx +1 -1
  64. package/src/uploading_thumbnail.tsx +1 -1
package/src/tokens.ts CHANGED
@@ -20,10 +20,24 @@
20
20
  * colors.background → var(--lotics-background)
21
21
  * colors.border → var(--lotics-border)
22
22
  *
23
- * No semantic abstraction (no `--lotics-fg`, `--lotics-danger`) those
24
- * names don't exist in the parent's TS code, so introducing them only
25
- * in the iframe creates two vocabularies the agent + a new developer
26
- * have to learn separately.
23
+ * TWO LAYERS, and the second one is where the decisions live. The palette above
24
+ * is primitives: values, owned by nobody, the same ramp anyone could paste. The
25
+ * semantic layer is {@link TEXT_INK} `muted` `zinc.600` and it holds the
26
+ * actual rules ("supporting text is one step lighter than body"). Components
27
+ * address ink only through it.
28
+ *
29
+ * This file used to claim the semantic names "don't exist in the parent's TS
30
+ * code", and that was wrong about its own codebase: the roles had always existed
31
+ * as `Text`'s `color` union, used hundreds of times. They were just not
32
+ * ADDRESSABLE — nothing outside a `.tsx` could name one — so the palette leaked
33
+ * into call sites and into design, and one role ended up rendering in two inks.
34
+ *
35
+ * Emitting only primitives is also what broke the Figma story. A designer picking
36
+ * `zinc-500` and an author typing `zinc-500` look like one source of truth, but
37
+ * what they agree on is a THIRD-PARTY RAMP; the decision itself is written in
38
+ * neither tool. {@link textInkTokens} emits both layers with the alias intact, in
39
+ * the W3C Design Tokens format Figma Variables import as alias variables — so the
40
+ * rule has one home and moving it moves both sides.
27
41
  *
28
42
  * Spacing / type / weight / radius are iframe-side conveniences with no
29
43
  * parent equivalent (parent uses bare numeric pixel values inline).
@@ -33,6 +47,8 @@
33
47
 
34
48
  export { colors } from "./colors";
35
49
  import { colors } from "./colors";
50
+ export { TEXT_INK, TEXT_COLORS, getTextColor, textInkTokens, type TextColor } from "./text_ink";
51
+ import { TEXT_INK } from "./text_ink";
36
52
 
37
53
  /**
38
54
  * Spacing scale (4px base unit). Use for padding, margin, gap.
@@ -150,5 +166,13 @@ export function getCssVariables(): string {
150
166
  lines.push(` --lotics-radius-${key}: ${value}px;`);
151
167
  }
152
168
 
169
+ // TEXT INK — emitted as a var() pointing at the PRIMITIVE, not as a copied hex,
170
+ // so `--lotics-text-muted` and `colors.zinc[600]` cannot drift apart and a
171
+ // hand-rolled DOM surface can address the same role a component does.
172
+ for (const [role, ref] of Object.entries(TEXT_INK)) {
173
+ const primitive = ref.replace(".", "-");
174
+ lines.push(` --lotics-ink-${role.toLowerCase()}: var(--lotics-${primitive});`);
175
+ }
176
+
153
177
  return `:root {\n${lines.join("\n")}\n}`;
154
178
  }
package/src/tooltip.tsx CHANGED
@@ -156,7 +156,7 @@ export function TooltipProvider({ children }: { children: React.ReactNode }) {
156
156
  }),
157
157
  }}
158
158
  >
159
- <Text numberOfLines={1} size="sm" color="inverted">
159
+ <Text numberOfLines={1} size="sm" color="onInverse">
160
160
  {tooltip.text}
161
161
  </Text>
162
162
  </div>,
@@ -172,7 +172,7 @@ function OverlayStack(props: { tone?: "error"; compact: boolean; label: string;
172
172
 
173
173
  function OverlayLabel({ children }: { children: string }) {
174
174
  return (
175
- <Text size="xs" weight="medium" color="inverted" numberOfLines={2} style={styles.overlayLabel} userSelect="none">
175
+ <Text size="xs" weight="medium" color="onInverse" numberOfLines={2} style={styles.overlayLabel} userSelect="none">
176
176
  {children}
177
177
  </Text>
178
178
  );