@rebasepro/ui 0.16.0 → 0.16.1-canary.g0d7af95

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 (56) hide show
  1. package/dist/components/BooleanSwitchWithLabel.d.ts +1 -1
  2. package/dist/components/Button.d.ts +1 -1
  3. package/dist/components/Chip.d.ts +1 -1
  4. package/dist/components/CircularProgressCenter.d.ts +1 -1
  5. package/dist/components/ColorPicker.d.ts +1 -1
  6. package/dist/components/DebouncedTextField.d.ts +1 -1
  7. package/dist/components/DialogTitle.d.ts +1 -1
  8. package/dist/components/LoadingButton.d.ts +1 -1
  9. package/dist/components/VirtualTable/VirtualTable.d.ts +1 -1
  10. package/dist/components/VirtualTable/VirtualTableCell.d.ts +1 -1
  11. package/dist/components/VirtualTable/VirtualTableHeader.d.ts +1 -1
  12. package/dist/components/VirtualTable/VirtualTableHeaderRow.d.ts +1 -1
  13. package/dist/components/VirtualTable/VirtualTableProps.d.ts +1 -1
  14. package/dist/components/VirtualTable/VirtualTableRow.d.ts +1 -1
  15. package/dist/components/VirtualTable/index.d.ts +10 -10
  16. package/dist/components/VirtualTable/selection/SelectionContext.d.ts +1 -1
  17. package/dist/components/VirtualTable/types.d.ts +2 -2
  18. package/dist/components/common/SelectInputLabel.d.ts +14 -0
  19. package/dist/components/index.d.ts +53 -53
  20. package/dist/hooks/index.d.ts +6 -6
  21. package/dist/icons/GitHubIcon.d.ts +1 -1
  22. package/dist/icons/HandleIcon.d.ts +1 -1
  23. package/dist/icons/index.d.ts +6 -6
  24. package/dist/index.css +19 -7
  25. package/dist/index.d.ts +17 -17
  26. package/dist/index.es.js +61 -15
  27. package/dist/index.es.js.map +1 -1
  28. package/dist/src/index.css +19 -7
  29. package/dist/src/theme.css +51 -3
  30. package/dist/styles.d.ts +36 -4
  31. package/dist/theme.css +51 -3
  32. package/dist/util/index.d.ts +4 -4
  33. package/dist/views/CardView.d.ts +1 -1
  34. package/dist/views/CollectionView/CollectionCardView.d.ts +1 -1
  35. package/dist/views/CollectionView/CollectionKanbanView.d.ts +1 -1
  36. package/dist/views/CollectionView/CollectionListView.d.ts +1 -1
  37. package/dist/views/CollectionView/CollectionTableView.d.ts +1 -1
  38. package/dist/views/CollectionView/CollectionView.d.ts +1 -1
  39. package/dist/views/CollectionView/CollectionViewToolbar.d.ts +1 -1
  40. package/dist/views/CollectionView/CollectionViewTypes.d.ts +1 -1
  41. package/dist/views/CollectionView/DefaultCellRenderer.d.ts +1 -1
  42. package/dist/views/CollectionView/index.d.ts +8 -8
  43. package/dist/views/CollectionView/resolveTitleProperty.d.ts +1 -1
  44. package/dist/views/Kanban/Board.d.ts +1 -1
  45. package/dist/views/Kanban/BoardColumn.d.ts +1 -1
  46. package/dist/views/Kanban/BoardSortableList.d.ts +1 -1
  47. package/dist/views/Kanban/index.d.ts +5 -5
  48. package/dist/views/Kanban/placement.d.ts +1 -1
  49. package/dist/views/KanbanView.d.ts +1 -1
  50. package/dist/views/index.d.ts +4 -4
  51. package/package.json +2 -2
  52. package/src/components/TextField.tsx +10 -1
  53. package/src/components/common/SelectInputLabel.tsx +15 -1
  54. package/src/index.css +19 -7
  55. package/src/styles.ts +40 -4
  56. package/src/theme.css +51 -3
@@ -48,17 +48,29 @@ html.dark {
48
48
 
49
49
  With a single face carrying both headings and body, weight and tracking are
50
50
  the only things separating a heading from the copy around it — so the tiers
51
- have to actually differ, rather than all sitting at 600. */
52
-
53
- /* 500, not 700. This reverses the 2026-08 "700 for display" decision on
54
- purpose: the marketing site and the panel were running different display
55
- weights, which is the single most visible incoherence between them. */
51
+ have to actually differ, rather than all sitting at 600.
52
+
53
+ REVISED 2026-08-24. The ladder above described weight falling with size, but
54
+ the code ran 500/500/600/600/500/500 — a hump, where the LARGEST headings
55
+ were the LIGHTEST and h3 outweighed h1. Two rules were in play and neither
56
+ won cleanly. It is now monotonic: 600 for headings of consequence (h1-h4),
57
+ 500 for small labels (h5/h6), 400 body. The display end still separates
58
+ itself by SIZE and tracking, which is what the paragraph above asks of it;
59
+ what it no longer does is separate itself by being *lighter* than the
60
+ smaller headings beneath it. 600 remains the ceiling. */
61
+
62
+ /* 600. This reverses the earlier "500, not 700" setting — not back toward 700,
63
+ which stays banned, but up to the ceiling the ladder already used for h3/h4.
64
+ The 500 was only ever visible in production: the dev-only TypeDevPanel has
65
+ shipped a `wd: 600` default that overrode this with !important, so every
66
+ local preview of this site has been 600 while rebase.pro rendered 500. The
67
+ panel's constant is now telling the truth. */
56
68
  .typography-h1 {
57
- @apply text-4xl font-headers font-medium tracking-display;
69
+ @apply text-4xl font-headers font-semibold tracking-display;
58
70
  }
59
71
 
60
72
  .typography-h2 {
61
- @apply text-3xl font-headers font-medium tracking-display;
73
+ @apply text-3xl font-headers font-semibold tracking-display;
62
74
  }
63
75
 
64
76
  .typography-h3 {
@@ -26,7 +26,13 @@
26
26
  console and the marketing site all spell the same intent the same way
27
27
  instead of each hardcoding its own em value. Pair display/title with
28
28
  font-semibold and heading with font-medium. */
29
- --tracking-display: -0.022em; /* >= 30px — the headline tier; matches the marketing site */
29
+ /* -0.025em, revised 2026-08-24 from -0.022em. The website's dev-only
30
+ TypeDevPanel has shipped `td: -25` as its "SHIPPED" default all along, so
31
+ every local preview and every design decision taken in front of one was
32
+ made at -0.025em while the built site served -0.022em. Of the panel's
33
+ eleven defaults these two — tracking and display weight — were the only
34
+ ones that did not match the tokens. Both are now true. */
35
+ --tracking-display: -0.025em; /* >= 30px — the headline tier; matches the marketing site */
30
36
  --tracking-title: -0.018em; /* 20-24px — section titles */
31
37
  --tracking-heading: -0.01em; /* <= 18px — labels; still a heading, not a headline */
32
38
 
@@ -43,6 +49,31 @@
43
49
  --text-3xs: 10px;
44
50
  --text-3xs--line-height: 1.4;
45
51
 
52
+ /* Display tier — above `text-4xl`, where the scale stops being a heading
53
+ and starts being a statement. Added 2026-08-24.
54
+
55
+ Fluid rather than fixed because the same token has to survive four
56
+ locales: German and French run 15-25% longer than English, and a fixed
57
+ 112px headline that fits "The Postgres you already have" does not fit
58
+ "Das Postgres, das Sie bereits haben". The `vw` middle term shrinks
59
+ before it can overflow; the `rem` floor protects small screens, where
60
+ the type is already proportionally large.
61
+
62
+ Both carry their own line-height and tracking: at this size 1.1 reads as
63
+ a gap and -0.025em reads as loose. Weight stays on the 600 ceiling —
64
+ this tier separates itself by SIZE, which is the whole point of adding
65
+ it rather than reaching for 700. */
66
+ --text-display-2: clamp(2.25rem, 4.4vw, 4rem); /* 36 -> 64px */
67
+ --text-display-2--line-height: 1.0;
68
+ --text-display-2--letter-spacing: -0.028em;
69
+ /* 7.2vw capped at 7rem was too much: on a wide window the headline filled
70
+ the viewport on its own and pushed the install terminal below the fold,
71
+ which breaks the rule the hero exists to satisfy (SITE-STORY §5 — the
72
+ hero carries a product artifact). Still ~1.7x the 48px it replaced. */
73
+ --text-display-1: clamp(2.5rem, 5.2vw, 4.75rem); /* 40 -> 76px */
74
+ --text-display-1--line-height: 0.94;
75
+ --text-display-1--letter-spacing: -0.032em;
76
+
46
77
  /* Control heights — the one scale every inline control resolves to, so a
47
78
  Button, TextField and Select at the same size share a baseline. Mirrors
48
79
  CONTROL_HEIGHT in styles.ts; that is the source for React components,
@@ -78,8 +109,25 @@
78
109
 
79
110
  /* Text Colors — using opaque values so icon strokes render solidly */
80
111
  --color-text-primary: #212121;
81
- --color-text-secondary: #757575;
82
- --color-text-disabled: #9e9e9e;
112
+ /* #737373, not #757575. Two units, and they are the two that matter.
113
+ The app's light page ground is #fafafa, not #ffffff, and #757575 lands at
114
+ 4.41:1 there — under AA for the 14px type this token carries. It clears
115
+ 4.5 only against pure white, which is not a surface the product actually
116
+ uses. Every field label in light mode was failing by a whisker.
117
+ #737373 measures 4.54:1 on #fafafa and 4.74:1 on #ffffff, so it passes on
118
+ both grounds instead of the theoretical one. Same fix, and the same
119
+ reasoning, as the `--color-surface-500` move recorded below. */
120
+ --color-text-secondary: #737373;
121
+ /* #8b8b8b, not #9e9e9e. Measured against the field fill a disabled label
122
+ actually sits on (`surface-accent-200/50` over #fafafa ≈ #eef1f5),
123
+ #9e9e9e reached 2.36:1 — present, but not readable.
124
+ Full AA is not achievable here and should not be chased: 4.5:1 on that
125
+ fill needs #6e6e6e, which is DARKER than the #737373 an ENABLED label
126
+ uses, so the disabled state would read as the emphasised one. WCAG 1.4.3
127
+ exempts inactive controls for exactly this reason.
128
+ #8b8b8b lands at ~3:1 — legible at a glance, still unmistakably muted
129
+ against its enabled neighbour. */
130
+ --color-text-disabled: #8b8b8b;
83
131
  --color-text-primary-dark: #ffffff;
84
132
  --color-text-secondary-dark: #a0a0a9;
85
133
  --color-text-disabled-dark: #757580;
package/dist/styles.d.ts CHANGED
@@ -28,12 +28,44 @@ export declare const controlPaddingMixin: {
28
28
  };
29
29
  export declare const focusedDisabled = "focus-visible:ring-0 focus-visible:ring-offset-0";
30
30
  export declare const focusedInvisibleMixin = "focus:bg-opacity-70 focus:bg-surface-accent-100 focus:dark:bg-white/[0.07] focus:bg-surface-accent-100/70";
31
- export declare const focusedClasses = "z-30 outline-hidden outline-none ring-2 ring-primary ring-opacity-50 ring-primary/50 ring-offset-0 ring-offset-transparent ";
32
- export declare const fieldBackgroundMixin = "bg-surface-accent-200/50 dark:bg-white/[0.055]";
31
+ /**
32
+ * The focus ring — the single most-seen interaction state in the product, and
33
+ * until now the least tended.
34
+ *
35
+ * Three dead declarations were removed rather than reshuffled:
36
+ * `outline-hidden` + `outline-none` — the same instruction twice.
37
+ * `ring-primary` + `ring-primary/50` — the first could never win.
38
+ * `ring-opacity-50` — Tailwind v3 syntax. v4 expresses
39
+ * opacity with the `/50` slash form, so
40
+ * this generated nothing at all.
41
+ *
42
+ * What is left is the ring that was actually rendering, at 60% rather than 50%:
43
+ * on `surface-900` the old value sat close enough to the field's own border to
44
+ * be missed at a glance, which is the one thing a focus ring may not be.
45
+ * `ring-offset-0` + a transparent offset stay — without them the ring draws a
46
+ * white halo on dark surfaces.
47
+ */
48
+ export declare const focusedClasses = "z-30 outline-none ring-2 ring-primary/60 ring-offset-0 ring-offset-transparent";
49
+ /**
50
+ * Field surfaces.
51
+ *
52
+ * The inset top hairline is the whole difference between a field that reads as
53
+ * a filled rectangle and one that reads as recessed into the surface. It is a
54
+ * 1px inset highlight, not a gradient — the same device `.frame` already uses
55
+ * on the marketing site, and the flat-surface rule stands.
56
+ *
57
+ * Light mode gets none: on a white page the highlight has nothing to catch.
58
+ */
59
+ export declare const fieldBackgroundMixin = "bg-surface-accent-200/50 dark:bg-white/[0.055] dark:shadow-[inset_0_1px_0_rgb(255_255_255/0.045)]";
33
60
  export declare const fieldBackgroundInvisibleMixin = "bg-surface-accent-200/0 dark:bg-white/0";
34
61
  export declare const fieldBackgroundDisabledMixin = "bg-surface-accent-200/50 dark:bg-white/[0.03]";
35
- export declare const fieldBackgroundHoverMixin = "hover:bg-surface-accent-200/70 hover:dark:bg-white/[0.09]";
36
- export declare const defaultBorderMixin = "border-surface-200 dark:border-surface-700/60 ";
62
+ /**
63
+ * `transition-colors` here, because every other interactive surface in the kit
64
+ * has it and fields did not — `cardClickableMixin` eases, a TextField snapped.
65
+ * On a form of eight fields that difference is the whole feel of the screen.
66
+ */
67
+ export declare const fieldBackgroundHoverMixin = "transition-colors duration-150 hover:bg-surface-accent-200/70 hover:dark:bg-white/[0.09]";
68
+ export declare const defaultBorderMixin = "border-surface-200 dark:border-surface-700/60";
37
69
  export declare const paperMixin = "bg-white rounded-lg dark:bg-surface-900 border border-surface-200 dark:border-surface-700";
38
70
  export declare const cardMixin = "bg-white dark:bg-surface-900 rounded-xl border border-surface-200 dark:border-surface-700/60";
39
71
  /**
package/dist/theme.css CHANGED
@@ -26,7 +26,13 @@
26
26
  console and the marketing site all spell the same intent the same way
27
27
  instead of each hardcoding its own em value. Pair display/title with
28
28
  font-semibold and heading with font-medium. */
29
- --tracking-display: -0.022em; /* >= 30px — the headline tier; matches the marketing site */
29
+ /* -0.025em, revised 2026-08-24 from -0.022em. The website's dev-only
30
+ TypeDevPanel has shipped `td: -25` as its "SHIPPED" default all along, so
31
+ every local preview and every design decision taken in front of one was
32
+ made at -0.025em while the built site served -0.022em. Of the panel's
33
+ eleven defaults these two — tracking and display weight — were the only
34
+ ones that did not match the tokens. Both are now true. */
35
+ --tracking-display: -0.025em; /* >= 30px — the headline tier; matches the marketing site */
30
36
  --tracking-title: -0.018em; /* 20-24px — section titles */
31
37
  --tracking-heading: -0.01em; /* <= 18px — labels; still a heading, not a headline */
32
38
 
@@ -43,6 +49,31 @@
43
49
  --text-3xs: 10px;
44
50
  --text-3xs--line-height: 1.4;
45
51
 
52
+ /* Display tier — above `text-4xl`, where the scale stops being a heading
53
+ and starts being a statement. Added 2026-08-24.
54
+
55
+ Fluid rather than fixed because the same token has to survive four
56
+ locales: German and French run 15-25% longer than English, and a fixed
57
+ 112px headline that fits "The Postgres you already have" does not fit
58
+ "Das Postgres, das Sie bereits haben". The `vw` middle term shrinks
59
+ before it can overflow; the `rem` floor protects small screens, where
60
+ the type is already proportionally large.
61
+
62
+ Both carry their own line-height and tracking: at this size 1.1 reads as
63
+ a gap and -0.025em reads as loose. Weight stays on the 600 ceiling —
64
+ this tier separates itself by SIZE, which is the whole point of adding
65
+ it rather than reaching for 700. */
66
+ --text-display-2: clamp(2.25rem, 4.4vw, 4rem); /* 36 -> 64px */
67
+ --text-display-2--line-height: 1.0;
68
+ --text-display-2--letter-spacing: -0.028em;
69
+ /* 7.2vw capped at 7rem was too much: on a wide window the headline filled
70
+ the viewport on its own and pushed the install terminal below the fold,
71
+ which breaks the rule the hero exists to satisfy (SITE-STORY §5 — the
72
+ hero carries a product artifact). Still ~1.7x the 48px it replaced. */
73
+ --text-display-1: clamp(2.5rem, 5.2vw, 4.75rem); /* 40 -> 76px */
74
+ --text-display-1--line-height: 0.94;
75
+ --text-display-1--letter-spacing: -0.032em;
76
+
46
77
  /* Control heights — the one scale every inline control resolves to, so a
47
78
  Button, TextField and Select at the same size share a baseline. Mirrors
48
79
  CONTROL_HEIGHT in styles.ts; that is the source for React components,
@@ -78,8 +109,25 @@
78
109
 
79
110
  /* Text Colors — using opaque values so icon strokes render solidly */
80
111
  --color-text-primary: #212121;
81
- --color-text-secondary: #757575;
82
- --color-text-disabled: #9e9e9e;
112
+ /* #737373, not #757575. Two units, and they are the two that matter.
113
+ The app's light page ground is #fafafa, not #ffffff, and #757575 lands at
114
+ 4.41:1 there — under AA for the 14px type this token carries. It clears
115
+ 4.5 only against pure white, which is not a surface the product actually
116
+ uses. Every field label in light mode was failing by a whisker.
117
+ #737373 measures 4.54:1 on #fafafa and 4.74:1 on #ffffff, so it passes on
118
+ both grounds instead of the theoretical one. Same fix, and the same
119
+ reasoning, as the `--color-surface-500` move recorded below. */
120
+ --color-text-secondary: #737373;
121
+ /* #8b8b8b, not #9e9e9e. Measured against the field fill a disabled label
122
+ actually sits on (`surface-accent-200/50` over #fafafa ≈ #eef1f5),
123
+ #9e9e9e reached 2.36:1 — present, but not readable.
124
+ Full AA is not achievable here and should not be chased: 4.5:1 on that
125
+ fill needs #6e6e6e, which is DARKER than the #737373 an ENABLED label
126
+ uses, so the disabled state would read as the emphasised one. WCAG 1.4.3
127
+ exempts inactive controls for exactly this reason.
128
+ #8b8b8b lands at ~3:1 — legible at a glance, still unmistakably muted
129
+ against its enabled neighbour. */
130
+ --color-text-disabled: #8b8b8b;
83
131
  --color-text-primary-dark: #ffffff;
84
132
  --color-text-secondary-dark: #a0a0a9;
85
133
  --color-text-disabled-dark: #757580;
@@ -1,4 +1,4 @@
1
- export * from "./cls";
2
- export * from "./debounce";
3
- export * from "./chip_colors";
4
- export * from "./key_to_icon_component";
1
+ export * from "./cls.js";
2
+ export * from "./debounce.js";
3
+ export * from "./chip_colors.js";
4
+ export * from "./key_to_icon_component.js";
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { CollectionSize } from "./ListView";
2
+ import { CollectionSize } from "./ListView.js";
3
3
  export type CardViewProps<T> = {
4
4
  data: T[];
5
5
  dataLoading?: boolean;
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import type { CollectionPropertyConfig, CollectionDataController, CellRendererOverride, CollectionViewSize, CollectionSelectionController } from "./CollectionViewTypes";
2
+ import type { CollectionPropertyConfig, CollectionDataController, CellRendererOverride, CollectionViewSize, CollectionSelectionController } from "./CollectionViewTypes.js";
3
3
  /**
4
4
  * Props for the {@link CollectionCardView} component.
5
5
  * @group Collection View
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import type { CollectionPropertyConfig, CollectionDataController, CellRendererOverride, CollectionSelectionController } from "./CollectionViewTypes";
2
+ import type { CollectionPropertyConfig, CollectionDataController, CellRendererOverride, CollectionSelectionController } from "./CollectionViewTypes.js";
3
3
  /**
4
4
  * Props for the {@link CollectionKanbanView} component.
5
5
  * @group Collection View
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import type { CollectionPropertyConfig, CollectionDataController, CellRendererOverride, CollectionViewSize, CollectionSelectionController } from "./CollectionViewTypes";
2
+ import type { CollectionPropertyConfig, CollectionDataController, CellRendererOverride, CollectionViewSize, CollectionSelectionController } from "./CollectionViewTypes.js";
3
3
  /**
4
4
  * Props for the {@link CollectionListView} component.
5
5
  * @group Collection View
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import type { CollectionPropertyConfig, CollectionDataController, CellRendererOverride, CollectionViewSize, CollectionSelectionController } from "./CollectionViewTypes";
2
+ import type { CollectionPropertyConfig, CollectionDataController, CellRendererOverride, CollectionViewSize, CollectionSelectionController } from "./CollectionViewTypes.js";
3
3
  /**
4
4
  * Props for the {@link CollectionTableView} component.
5
5
  * @group Collection View
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import type { CollectionViewMode, CollectionViewSize, CollectionPropertyConfig, CollectionDataController, CellRendererOverride, CollectionCustomViewEntry, CollectionSelectionController, KanbanPropertyOption } from "./CollectionViewTypes";
2
+ import type { CollectionViewMode, CollectionViewSize, CollectionPropertyConfig, CollectionDataController, CellRendererOverride, CollectionCustomViewEntry, CollectionSelectionController, KanbanPropertyOption } from "./CollectionViewTypes.js";
3
3
  /**
4
4
  * Props for the headless {@link CollectionView} component.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import type { CollectionViewMode, CollectionViewSize, KanbanPropertyOption } from "./CollectionViewTypes";
2
+ import type { CollectionViewMode, CollectionViewSize, KanbanPropertyOption } from "./CollectionViewTypes.js";
3
3
  /**
4
4
  * Props for the {@link CollectionViewToolbar} component.
5
5
  * @group Collection View
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import type { VirtualTableSortKey } from "../../components/VirtualTable/VirtualTableProps";
2
+ import type { VirtualTableSortKey } from "../../components/VirtualTable/VirtualTableProps.js";
3
3
  /**
4
4
  * Supported view modes.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import type { CellRendererProps } from "./CollectionViewTypes";
2
+ import type { CellRendererProps } from "./CollectionViewTypes.js";
3
3
  /**
4
4
  * Default cell renderer for the headless CollectionView.
5
5
  * Handles all built-in property types without depending on any Rebase core types.
@@ -8,11 +8,11 @@
8
8
  *
9
9
  * @module CollectionView
10
10
  */
11
- export type { CollectionViewMode, CollectionViewSize, CollectionEnumValueConfig, CollectionPropertyConfig, CollectionDataController, CellRendererProps, CellRendererOverride, CollectionSelectionController, KanbanPropertyOption } from "./CollectionViewTypes";
12
- export { CollectionView } from "./CollectionView";
13
- export type { CollectionViewProps } from "./CollectionView";
14
- export type { CollectionViewToolbarProps } from "./CollectionViewToolbar";
15
- export type { CollectionTableViewProps } from "./CollectionTableView";
16
- export type { CollectionCardViewProps } from "./CollectionCardView";
17
- export type { CollectionListViewProps } from "./CollectionListView";
18
- export type { CollectionKanbanViewProps } from "./CollectionKanbanView";
11
+ export type { CollectionViewMode, CollectionViewSize, CollectionEnumValueConfig, CollectionPropertyConfig, CollectionDataController, CellRendererProps, CellRendererOverride, CollectionSelectionController, KanbanPropertyOption } from "./CollectionViewTypes.js";
12
+ export { CollectionView } from "./CollectionView.js";
13
+ export type { CollectionViewProps } from "./CollectionView.js";
14
+ export type { CollectionViewToolbarProps } from "./CollectionViewToolbar.js";
15
+ export type { CollectionTableViewProps } from "./CollectionTableView.js";
16
+ export type { CollectionCardViewProps } from "./CollectionCardView.js";
17
+ export type { CollectionListViewProps } from "./CollectionListView.js";
18
+ export type { CollectionKanbanViewProps } from "./CollectionKanbanView.js";
@@ -1,4 +1,4 @@
1
- import type { CollectionPropertyConfig } from "./CollectionViewTypes";
1
+ import type { CollectionPropertyConfig } from "./CollectionViewTypes.js";
2
2
  /**
3
3
  * Pick the property that acts as a row's title.
4
4
  *
@@ -1,3 +1,3 @@
1
1
  import React from "react";
2
- import { BoardProps } from "./board_types";
2
+ import { BoardProps } from "./board_types.js";
3
3
  export declare function Board<T, COLUMN extends string>({ data, columns: columnsProp, columnLabels, columnColors, className, assignColumn, allowColumnReorder, onColumnReorder, onItemsReorder, ItemComponent, columnLoadingState, onLoadMoreColumn, onAddItemToColumn, AddColumnComponent }: BoardProps<T, COLUMN>): React.JSX.Element;
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { BoardItem, BoardItemViewProps } from "./board_types";
2
+ import { BoardItem, BoardItemViewProps } from "./board_types.js";
3
3
  export interface BoardColumnProps<T> {
4
4
  id: string;
5
5
  title: string;
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { BoardItem, BoardItemViewProps } from "./board_types";
2
+ import { BoardItem, BoardItemViewProps } from "./board_types.js";
3
3
  interface BoardSortableListProps<T> {
4
4
  columnId: string;
5
5
  items: BoardItem<T>[];
@@ -1,5 +1,5 @@
1
- export * from "./board_types";
2
- export * from "./BoardColumnTitle";
3
- export * from "./BoardSortableList";
4
- export * from "./BoardColumn";
5
- export * from "./Board";
1
+ export * from "./board_types.js";
2
+ export * from "./BoardColumnTitle.js";
3
+ export * from "./BoardSortableList.js";
4
+ export * from "./BoardColumn.js";
5
+ export * from "./Board.js";
@@ -1,4 +1,4 @@
1
- import { BoardItem } from "./board_types";
1
+ import { BoardItem } from "./board_types.js";
2
2
  export interface PlaceDroppedCardParams<T> {
3
3
  /**
4
4
  * The destination column as it stands at the moment of the drop. When the
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { BoardItem, BoardItemViewProps, ColumnLoadingState } from "./Kanban/board_types";
2
+ import { BoardItem, BoardItemViewProps, ColumnLoadingState } from "./Kanban/board_types.js";
3
3
  export type KanbanViewProps<T, COLUMN extends string> = {
4
4
  columns: COLUMN[];
5
5
  columnLabels?: Record<COLUMN, string>;
@@ -1,4 +1,4 @@
1
- export * from "./ListView";
2
- export * from "./CardView";
3
- export * from "./KanbanView";
4
- export * from "./CollectionView";
1
+ export * from "./ListView.js";
2
+ export * from "./CardView.js";
3
+ export * from "./KanbanView.js";
4
+ export * from "./CollectionView/index.js";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@rebasepro/ui",
3
3
  "type": "module",
4
- "version": "0.16.0",
4
+ "version": "0.16.1-canary.g0d7af95",
5
5
  "description": "Rebase design system — React components and design tokens built on Radix UI, Tailwind CSS and lucide-react",
6
6
  "funding": {
7
7
  "url": "https://github.com/sponsors/rebaseco"
@@ -113,7 +113,7 @@
113
113
  },
114
114
  "scripts": {
115
115
  "watch": "vite build --watch",
116
- "build": "rm -rf dist || true && vite build && cp dist/src/index.css dist/src/theme.css dist/ && tsc --emitDeclarationOnly -p tsconfig.prod.json && node ../../scripts/assert-build-output.mjs",
116
+ "build": "rm -rf dist || true && vite build && cp dist/src/index.css dist/src/theme.css dist/ && tsc --emitDeclarationOnly -p tsconfig.prod.json && node ../../tooling/scripts/add-dts-extensions.mjs dist && node ../../tooling/scripts/assert-build-output.mjs",
117
117
  "test:lint": "eslint \"src/**\" --quiet",
118
118
  "test": "jest --passWithNoTests",
119
119
  "clean": "rm -rf dist && find ./src \\( -name '*.js' -o -name '*.d.ts' \\) -type f | xargs rm -f",
@@ -229,7 +229,16 @@ export const TextField = forwardRef<HTMLDivElement, TextFieldProps<string | numb
229
229
  ? "text-primary dark:text-primary"
230
230
  : "text-text-secondary dark:text-text-secondary-dark"
231
231
  : "text-red-500 dark:text-red-600",
232
- disabled ? "opacity-50" : ""
232
+ // A disabled field's LABEL is the one part that must
233
+ // stay readable — it is what tells you which field
234
+ // you cannot edit. `opacity-50` halved the alpha of
235
+ // an already-muted #737373, landing near 2.2:1 over
236
+ // the field fill; the label was effectively gone.
237
+ //
238
+ // The value below it keeps its own `opacity-50`,
239
+ // which is the correct signal: the CONTENT is
240
+ // inactive. Naming the field is not content.
241
+ disabled ? "text-text-disabled dark:text-text-disabled-dark" : ""
233
242
  )}
234
243
  shrink={hasValue || focused}
235
244
  >
@@ -1,9 +1,23 @@
1
1
  import React from "react";
2
2
  import { cls } from "../../util";
3
3
 
4
+ /**
5
+ * The label above a Select or MultiSelect.
6
+ *
7
+ * It used `text-surface-accent-500` — a SURFACE scale, borrowed for type. The
8
+ * label above a TextField has always used `text-text-secondary`, and the two are
9
+ * the same role, so a form mixing the components showed two different label
10
+ * colours: `#64748b` blue-grey over a Select, `#757575` neutral over a TextField.
11
+ * Measured side by side on /debug/ui, which is where it is most obvious, because
12
+ * the reference puts them in adjacent columns.
13
+ *
14
+ * The text tokens are also the tuned ones: `--color-surface-500` was moved to
15
+ * #797979 precisely so muted type clears AA on both grounds. The slate scale
16
+ * carries no such guarantee — it is for surfaces.
17
+ */
4
18
  export function SelectInputLabel({ children, error }: { children: React.ReactNode, error?: boolean }) {
5
19
  return <div className={cls("text-sm font-medium ml-3.5 mb-1",
6
- error ? "text-red-600 dark:text-red-500" : "text-surface-accent-500 dark:text-surface-accent-300")}>
20
+ error ? "text-red-600 dark:text-red-500" : "text-text-secondary dark:text-text-secondary-dark")}>
7
21
  {children}
8
22
  </div>;
9
23
  }
package/src/index.css CHANGED
@@ -48,17 +48,29 @@ html.dark {
48
48
 
49
49
  With a single face carrying both headings and body, weight and tracking are
50
50
  the only things separating a heading from the copy around it — so the tiers
51
- have to actually differ, rather than all sitting at 600. */
52
-
53
- /* 500, not 700. This reverses the 2026-08 "700 for display" decision on
54
- purpose: the marketing site and the panel were running different display
55
- weights, which is the single most visible incoherence between them. */
51
+ have to actually differ, rather than all sitting at 600.
52
+
53
+ REVISED 2026-08-24. The ladder above described weight falling with size, but
54
+ the code ran 500/500/600/600/500/500 — a hump, where the LARGEST headings
55
+ were the LIGHTEST and h3 outweighed h1. Two rules were in play and neither
56
+ won cleanly. It is now monotonic: 600 for headings of consequence (h1-h4),
57
+ 500 for small labels (h5/h6), 400 body. The display end still separates
58
+ itself by SIZE and tracking, which is what the paragraph above asks of it;
59
+ what it no longer does is separate itself by being *lighter* than the
60
+ smaller headings beneath it. 600 remains the ceiling. */
61
+
62
+ /* 600. This reverses the earlier "500, not 700" setting — not back toward 700,
63
+ which stays banned, but up to the ceiling the ladder already used for h3/h4.
64
+ The 500 was only ever visible in production: the dev-only TypeDevPanel has
65
+ shipped a `wd: 600` default that overrode this with !important, so every
66
+ local preview of this site has been 600 while rebase.pro rendered 500. The
67
+ panel's constant is now telling the truth. */
56
68
  .typography-h1 {
57
- @apply text-4xl font-headers font-medium tracking-display;
69
+ @apply text-4xl font-headers font-semibold tracking-display;
58
70
  }
59
71
 
60
72
  .typography-h2 {
61
- @apply text-3xl font-headers font-medium tracking-display;
73
+ @apply text-3xl font-headers font-semibold tracking-display;
62
74
  }
63
75
 
64
76
  .typography-h3 {
package/src/styles.ts CHANGED
@@ -47,12 +47,48 @@ export const controlPaddingMixin = {
47
47
 
48
48
  export const focusedDisabled = "focus-visible:ring-0 focus-visible:ring-offset-0";
49
49
  export const focusedInvisibleMixin = "focus:bg-opacity-70 focus:bg-surface-accent-100 focus:dark:bg-white/[0.07] focus:bg-surface-accent-100/70";
50
- export const focusedClasses = "z-30 outline-hidden outline-none ring-2 ring-primary ring-opacity-50 ring-primary/50 ring-offset-0 ring-offset-transparent ";
51
- export const fieldBackgroundMixin = "bg-surface-accent-200/50 dark:bg-white/[0.055]";
50
+
51
+ /**
52
+ * The focus ring — the single most-seen interaction state in the product, and
53
+ * until now the least tended.
54
+ *
55
+ * Three dead declarations were removed rather than reshuffled:
56
+ * `outline-hidden` + `outline-none` — the same instruction twice.
57
+ * `ring-primary` + `ring-primary/50` — the first could never win.
58
+ * `ring-opacity-50` — Tailwind v3 syntax. v4 expresses
59
+ * opacity with the `/50` slash form, so
60
+ * this generated nothing at all.
61
+ *
62
+ * What is left is the ring that was actually rendering, at 60% rather than 50%:
63
+ * on `surface-900` the old value sat close enough to the field's own border to
64
+ * be missed at a glance, which is the one thing a focus ring may not be.
65
+ * `ring-offset-0` + a transparent offset stay — without them the ring draws a
66
+ * white halo on dark surfaces.
67
+ */
68
+ export const focusedClasses = "z-30 outline-none ring-2 ring-primary/60 ring-offset-0 ring-offset-transparent";
69
+
70
+ /**
71
+ * Field surfaces.
72
+ *
73
+ * The inset top hairline is the whole difference between a field that reads as
74
+ * a filled rectangle and one that reads as recessed into the surface. It is a
75
+ * 1px inset highlight, not a gradient — the same device `.frame` already uses
76
+ * on the marketing site, and the flat-surface rule stands.
77
+ *
78
+ * Light mode gets none: on a white page the highlight has nothing to catch.
79
+ */
80
+ export const fieldBackgroundMixin = "bg-surface-accent-200/50 dark:bg-white/[0.055] dark:shadow-[inset_0_1px_0_rgb(255_255_255/0.045)]";
52
81
  export const fieldBackgroundInvisibleMixin = "bg-surface-accent-200/0 dark:bg-white/0";
53
82
  export const fieldBackgroundDisabledMixin = "bg-surface-accent-200/50 dark:bg-white/[0.03]";
54
- export const fieldBackgroundHoverMixin = "hover:bg-surface-accent-200/70 hover:dark:bg-white/[0.09]";
55
- export const defaultBorderMixin = "border-surface-200 dark:border-surface-700/60 ";
83
+
84
+ /**
85
+ * `transition-colors` here, because every other interactive surface in the kit
86
+ * has it and fields did not — `cardClickableMixin` eases, a TextField snapped.
87
+ * On a form of eight fields that difference is the whole feel of the screen.
88
+ */
89
+ export const fieldBackgroundHoverMixin = "transition-colors duration-150 hover:bg-surface-accent-200/70 hover:dark:bg-white/[0.09]";
90
+
91
+ export const defaultBorderMixin = "border-surface-200 dark:border-surface-700/60";
56
92
 
57
93
  // ---------------------------------------------------------------------------
58
94
  // Surfaces: two kinds, and the difference is what the border is for.