@cntyclub/ui-react 0.8.0 → 0.8.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": "@cntyclub/ui-react",
3
- "version": "0.8.0",
3
+ "version": "0.8.2",
4
4
  "description": "React component library for the Country Club UI Kit — Base UI primitives styled with the Country Club design system (Tailwind CSS v4)",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -19,19 +19,21 @@ interface PipelineProps extends React.ComponentProps<"div"> {
19
19
  /** Ordered funnel stages, left to right. */
20
20
  stages: PipelineStage[];
21
21
  /**
22
- * Step-to-step conversion markers shown in the connector *between* stages
23
- * (length = `stages.length - 1`). Typically a percentage string; any node works.
22
+ * Step-to-step conversion markers. `conversions[i]` is the share of stage `i`
23
+ * that advances to stage `i + 1`, and is shown as a pill right beside stage
24
+ * `i`'s number (length = `stages.length - 1`). Typically a percentage string.
24
25
  */
25
26
  conversions?: React.ReactNode[];
26
27
  }
27
28
 
28
29
  /**
29
- * A conversion funnel — equal-width stages laid left to right, joined by
30
- * connectors that carry the step-to-step conversion and a chevron pointing to
31
- * the next stage, so the row reads as a flow rather than a set of loose stats.
30
+ * A conversion funnel — equal-width stages laid left to right. Each stage
31
+ * carries its own step-to-step conversion in a pill next to the number, and a
32
+ * chevron points to the next stage, so the row reads as a flow rather than a
33
+ * set of loose stats.
32
34
  *
33
35
  * The component is its own container query context: when it gets narrow (e.g.
34
- * beside a docked panel) the connectors hide and the stages reflow into a
36
+ * beside a docked panel) the chevrons hide and the stages reflow into a
35
37
  * two-column grid, staying readable without squashing the numbers.
36
38
  */
37
39
  function Pipeline({ stages, conversions = [], className, ...props }: PipelineProps) {
@@ -49,19 +51,30 @@ function Pipeline({ stages, conversions = [], className, ...props }: PipelinePro
49
51
  return (
50
52
  <Fragment key={i}>
51
53
  <div className="min-w-0 flex-1 px-0.5" data-slot="pipeline-stage">
52
- <div
53
- className={cn(
54
- "font-sans font-bold text-3xl text-foreground leading-none tabular-nums tracking-tight",
55
- stage.accent && "text-success",
56
- )}
57
- >
58
- {stage.value}
54
+ <div className="flex items-center gap-2">
55
+ <span
56
+ className={cn(
57
+ "font-sans font-bold text-3xl text-foreground leading-none tabular-nums tracking-tight",
58
+ stage.accent && "text-success",
59
+ )}
60
+ >
61
+ {stage.value}
62
+ </span>
63
+ {conv != null ? <PipelineConversion>{conv}</PipelineConversion> : null}
59
64
  </div>
60
65
  <div className="mt-2 text-muted-foreground text-xs leading-snug">
61
66
  {stage.label}
62
67
  </div>
63
68
  </div>
64
- {conv != null ? <PipelineConnector>{conv}</PipelineConnector> : null}
69
+ {conv != null ? (
70
+ <div
71
+ className="flex flex-none items-center px-1 @max-[560px]:hidden"
72
+ data-slot="pipeline-arrow"
73
+ aria-hidden
74
+ >
75
+ <ChevronRight className="size-3.5 text-muted-foreground/40" />
76
+ </div>
77
+ ) : null}
65
78
  </Fragment>
66
79
  );
67
80
  })}
@@ -69,30 +82,21 @@ function Pipeline({ stages, conversions = [], className, ...props }: PipelinePro
69
82
  );
70
83
  }
71
84
 
72
- /**
73
- * The between-stages connector: a conversion pill above a chevron pointing to
74
- * the next stage. Hidden when the funnel collapses to a grid.
75
- */
76
- function PipelineConnector({
85
+ /** The conversion pill sitting beside a stage number. */
86
+ function PipelineConversion({
77
87
  className,
78
- children,
79
88
  ...props
80
- }: React.ComponentProps<"div">) {
89
+ }: React.ComponentProps<"span">) {
81
90
  return (
82
- <div
91
+ <span
83
92
  className={cn(
84
- "flex flex-none flex-col items-center justify-center gap-1.5 px-1 @max-[560px]:hidden",
93
+ "inline-flex items-center rounded-full border border-success/20 bg-success/10 px-2 py-0.5 font-medium text-[11px] text-success tabular-nums dark:bg-success/16",
85
94
  className,
86
95
  )}
87
- data-slot="pipeline-connector"
96
+ data-slot="pipeline-conversion"
88
97
  {...props}
89
- >
90
- <span className="inline-flex items-center rounded-full border border-success/20 bg-success/10 px-2 py-0.5 font-medium text-[11px] text-success tabular-nums dark:bg-success/16">
91
- {children}
92
- </span>
93
- <ChevronRight className="size-3.5 text-muted-foreground/40" aria-hidden />
94
- </div>
98
+ />
95
99
  );
96
100
  }
97
101
 
98
- export { Pipeline, PipelineConnector, type PipelineProps, type PipelineStage };
102
+ export { Pipeline, PipelineConversion, type PipelineProps, type PipelineStage };
@@ -22,6 +22,17 @@ interface SegmentedControlProps<T extends string> {
22
22
  className?: string;
23
23
  }
24
24
 
25
+ /**
26
+ * Per-size segment padding. The base toggle sizes are icon-button tight
27
+ * (~5px), which crowds text labels like "Past 3 months"; a segmented control
28
+ * reads as text tabs, so it wants room to breathe on both axes.
29
+ */
30
+ const SEGMENT_SIZE: Record<NonNullable<SegmentedControlProps<string>["size"]>, string> = {
31
+ sm: "h-8 px-3.5 sm:h-7",
32
+ default: "h-9 px-4 sm:h-8",
33
+ lg: "h-10 px-5 sm:h-9",
34
+ };
35
+
25
36
  /**
26
37
  * A single-select segmented control — a compact row of mutually-exclusive
27
38
  * options (e.g. a time-range switch: Past month / Past 3 months / Overall).
@@ -53,7 +64,11 @@ function SegmentedControl<T extends string>({
53
64
  variant={variant}
54
65
  >
55
66
  {options.map((option) => (
56
- <ToggleGroupItem key={option.value} value={option.value}>
67
+ <ToggleGroupItem
68
+ key={option.value}
69
+ value={option.value}
70
+ className={SEGMENT_SIZE[size]}
71
+ >
57
72
  {option.label}
58
73
  </ToggleGroupItem>
59
74
  ))}