@lateralus-ai/shipping-ui 2.0.0-dev.8 → 2.0.0-dev.9

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.
@@ -1,11 +1,14 @@
1
1
  import { ReactNode } from 'react';
2
- type BadgeColor = "blue" | "green" | "red" | "orange" | "purple" | "grey";
3
- type BadgeType = "label" | "icon";
2
+ export type BadgeColor = "blue" | "green" | "red" | "orange" | "purple" | "grey";
3
+ export type BadgeType = "label" | "icon";
4
4
  export type BadgeProps = {
5
5
  color: BadgeColor;
6
+ /** `label` grows with content (pill). `icon` is a compact circle for a glyph/digit. */
6
7
  type?: BadgeType;
7
8
  children: ReactNode;
8
9
  className?: string;
9
10
  };
10
- export declare const Badge: ({ color, type, children, className }: BadgeProps) => import("react/jsx-runtime").JSX.Element;
11
- export {};
11
+ /**
12
+ * Figma Badge (4365:74363) — padding + rounded-full; no fixed width on labels.
13
+ */
14
+ export declare const Badge: ({ color, type, children, className, }: BadgeProps) => import("react/jsx-runtime").JSX.Element;
@@ -11,5 +11,5 @@ export { Tooltip, TooltipProvider, type TooltipProps, type TooltipSide } from '.
11
11
  export { ThinkingDot, type ThinkingDotProps } from './ThinkingDot';
12
12
  export { Count, type CountProps } from './Count';
13
13
  export { Switch, type SwitchProps } from './Switch';
14
- export { Badge, type BadgeProps } from './Badge';
14
+ export { Badge, type BadgeProps, type BadgeColor, type BadgeType } from './Badge';
15
15
  export { Callout, type CalloutProps } from './Callout';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lateralus-ai/shipping-ui",
3
- "version": "2.0.0-dev.8",
3
+ "version": "2.0.0-dev.9",
4
4
  "description": "Shared UI theme and components for Lateralus shipping applications",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.esm.js",
@@ -11,26 +11,37 @@ import { cn } from "../utils/cn";
11
11
 
12
12
  export type TabsType = "tabs" | "pills";
13
13
 
14
+ /** Soft = search filters (filled idle). Solid = workflow shell (ghost idle, blue active). */
15
+ export type TabsAppearance = "soft" | "solid";
16
+
14
17
  type TabsContextValue = {
15
18
  type: TabsType;
19
+ appearance: TabsAppearance;
16
20
  };
17
21
 
18
- const TabsContext = createContext<TabsContextValue>({ type: "tabs" });
22
+ const TabsContext = createContext<TabsContextValue>({
23
+ type: "tabs",
24
+ appearance: "soft",
25
+ });
19
26
 
20
27
  export type TabsProps = ComponentPropsWithoutRef<typeof TabsPrimitive.Root> & {
21
28
  type?: TabsType;
29
+ /** Only applies when `type="pills"`. Defaults to `soft`. */
30
+ appearance?: TabsAppearance;
22
31
  };
23
32
 
24
33
  export const Tabs = ({
25
34
  type = "tabs",
35
+ appearance = "soft",
26
36
  className,
27
37
  children,
28
38
  ...props
29
39
  }: TabsProps) => (
30
- <TabsContext.Provider value={{ type }}>
40
+ <TabsContext.Provider value={{ type, appearance }}>
31
41
  <TabsPrimitive.Root
32
42
  className={cn("flex flex-col", className)}
33
43
  data-type={type}
44
+ data-appearance={type === "pills" ? appearance : undefined}
34
45
  {...props}
35
46
  >
36
47
  {children}
@@ -64,22 +75,20 @@ TabsList.displayName = TabsPrimitive.List.displayName;
64
75
  export type TabsTriggerProps = ComponentPropsWithoutRef<
65
76
  typeof TabsPrimitive.Trigger
66
77
  > & {
67
- /** Optional count badge (pill variant / search filters). */
68
- count?: number;
69
78
  children: ReactNode;
70
79
  };
71
80
 
72
81
  export const TabsTrigger = forwardRef<
73
82
  ElementRef<typeof TabsPrimitive.Trigger>,
74
83
  TabsTriggerProps
75
- >(({ className, count, children, ...props }, ref) => {
76
- const { type } = useContext(TabsContext);
84
+ >(({ className, children, ...props }, ref) => {
85
+ const { type, appearance } = useContext(TabsContext);
77
86
 
78
87
  return (
79
88
  <TabsPrimitive.Trigger
80
89
  ref={ref}
81
90
  className={cn(
82
- "inline-flex items-center justify-center transition-colors outline-none",
91
+ "inline-flex items-center justify-center gap-2.5 transition-colors outline-none",
83
92
  "disabled:pointer-events-none disabled:opacity-50",
84
93
  type === "tabs" && [
85
94
  "relative h-12 gap-2 px-0 py-0 text-caption-2 text-display-on-light-secondary",
@@ -88,37 +97,26 @@ export const TabsTrigger = forwardRef<
88
97
  "data-[state=active]:after:absolute data-[state=active]:after:inset-x-0 data-[state=active]:after:-bottom-px",
89
98
  "data-[state=active]:after:h-0.5 data-[state=active]:after:rounded-full data-[state=active]:after:bg-grey-900",
90
99
  ],
91
- type === "pills" && [
92
- "group min-h-9 gap-2.5 rounded-full px-3 py-1 text-caption-2-em",
93
- "bg-grey-100 text-display-on-light-secondary",
94
- "hover:bg-grey-200",
95
- "data-[state=active]:bg-accent-bg-light data-[state=active]:text-display-on-light-primary",
96
- ],
100
+ type === "pills" &&
101
+ appearance === "soft" && [
102
+ "min-h-9 rounded-full px-3 py-1 text-caption-2-em",
103
+ "bg-grey-100 text-display-on-light-secondary",
104
+ "hover:bg-grey-200",
105
+ "data-[state=active]:bg-accent-bg-light data-[state=active]:text-display-on-light-primary",
106
+ ],
107
+ type === "pills" &&
108
+ appearance === "solid" && [
109
+ "min-h-9 rounded-full px-3 py-1 text-caption-2-em",
110
+ "bg-transparent text-display-on-light-primary",
111
+ "hover:bg-grey-900/[0.04]",
112
+ "data-[state=active]:bg-blue-600 data-[state=active]:text-white",
113
+ "data-[state=active]:hover:bg-blue-600",
114
+ ],
97
115
  className,
98
116
  )}
99
117
  {...props}
100
118
  >
101
119
  {children}
102
- {typeof count === "number" &&
103
- (type === "pills" ? (
104
- <span
105
- className={cn(
106
- "inline-flex shrink-0 items-center justify-center rounded-full px-1.5 py-0.5 text-footnote-em leading-none",
107
- "bg-accent-bg-light text-display-on-light-secondary",
108
- "group-data-[state=active]:text-display-on-light-tertiary",
109
- )}
110
- aria-label={`Count: ${count}`}
111
- >
112
- {count > 99 ? "99+" : count}
113
- </span>
114
- ) : (
115
- <span
116
- className="px-1 text-caption-2 text-display-on-light-secondary"
117
- aria-label={`Count: ${count}`}
118
- >
119
- {count > 99 ? "99+" : count}
120
- </span>
121
- ))}
122
120
  </TabsPrimitive.Trigger>
123
121
  );
124
122
  });
@@ -15,6 +15,7 @@ export {
15
15
  type TabsContentProps,
16
16
  type TabsItem,
17
17
  type TabsType,
18
+ type TabsAppearance,
18
19
  } from "./Tabs";
19
20
  export { Header, type HeaderProps, type HeaderVariant } from "./Header";
20
21
  export { Entry, type EntryProps, type EntryType, type EntryState, type EntryVariant } from "./Entry";
package/src/index.ts CHANGED
@@ -56,6 +56,7 @@ export type {
56
56
  TabsContentProps,
57
57
  TabsItem,
58
58
  TabsType,
59
+ TabsAppearance,
59
60
  HeaderProps,
60
61
  HeaderVariant,
61
62
  EntryProps,
@@ -13,6 +13,7 @@ import {
13
13
  type ModalProps,
14
14
  } from "../../components/Modal";
15
15
  import { Tabs, TabsContent, TabsList, TabsTrigger } from "../../components/Tabs";
16
+ import { Badge } from "../../primitives/Badge";
16
17
  import { cn } from "../../utils/cn";
17
18
  import { ResultRow, type ResultRowProps } from "./ResultRow";
18
19
  import { SectionHeader } from "./SectionHeader";
@@ -176,8 +177,13 @@ export const SearchModalFilters = ({
176
177
  )}
177
178
  >
178
179
  {tabs.map((tab) => (
179
- <TabsTrigger key={tab.value} value={tab.value} count={tab.count}>
180
+ <TabsTrigger key={tab.value} value={tab.value}>
180
181
  {tab.label}
182
+ {typeof tab.count === "number" && (
183
+ <Badge color="blue">
184
+ {tab.count > 99 ? "99+" : tab.count}
185
+ </Badge>
186
+ )}
181
187
  </TabsTrigger>
182
188
  ))}
183
189
  </TabsList>
@@ -1,11 +1,12 @@
1
1
  import { type ReactNode } from "react";
2
2
  import { cn } from "../utils/cn";
3
3
 
4
- type BadgeColor = "blue" | "green" | "red" | "orange" | "purple" | "grey";
5
- type BadgeType = "label" | "icon";
4
+ export type BadgeColor = "blue" | "green" | "red" | "orange" | "purple" | "grey";
5
+ export type BadgeType = "label" | "icon";
6
6
 
7
7
  export type BadgeProps = {
8
8
  color: BadgeColor;
9
+ /** `label` grows with content (pill). `icon` is a compact circle for a glyph/digit. */
9
10
  type?: BadgeType;
10
11
  children: ReactNode;
11
12
  className?: string;
@@ -20,11 +21,20 @@ const colorStyles: Record<BadgeColor, string> = {
20
21
  grey: "bg-grey-100 text-display-on-light-secondary",
21
22
  };
22
23
 
23
- export const Badge = ({ color, type = "label", children, className }: BadgeProps) => (
24
+ /**
25
+ * Figma Badge (4365:74363) — padding + rounded-full; no fixed width on labels.
26
+ */
27
+ export const Badge = ({
28
+ color,
29
+ type = "label",
30
+ children,
31
+ className,
32
+ }: BadgeProps) => (
24
33
  <span
25
34
  className={cn(
26
- "inline-flex shrink-0 items-center justify-center text-footnote-em",
27
- type === "label" ? "rounded-control px-2 py-0.5" : "size-6 rounded-full",
35
+ "inline-flex shrink-0 items-center justify-center text-footnote-em leading-none",
36
+ type === "label" && "rounded-full px-1.5 py-0.5",
37
+ type === "icon" && "size-5 rounded-full [&>svg]:size-3",
28
38
  colorStyles[color],
29
39
  className,
30
40
  )}
@@ -14,5 +14,5 @@ export { Tooltip, TooltipProvider, type TooltipProps, type TooltipSide } from ".
14
14
  export { ThinkingDot, type ThinkingDotProps } from "./ThinkingDot";
15
15
  export { Count, type CountProps } from "./Count";
16
16
  export { Switch, type SwitchProps } from "./Switch";
17
- export { Badge, type BadgeProps } from "./Badge";
17
+ export { Badge, type BadgeProps, type BadgeColor, type BadgeType } from "./Badge";
18
18
  export { Callout, type CalloutProps } from "./Callout";
@@ -1,4 +1,4 @@
1
- import { Button } from "../../primitives";
1
+ import { Badge, Button } from "../../primitives";
2
2
  import {
3
3
  EmptyState,
4
4
  Entry,
@@ -9,6 +9,7 @@ import {
9
9
  TabsList,
10
10
  TabsTrigger,
11
11
  } from "../../components";
12
+ import { TickIcon } from "../../icons";
12
13
  import { WorkflowsIllustration } from "../../illustrations";
13
14
  import {
14
15
  FigmaContent,
@@ -50,12 +51,13 @@ export const ContentCanvas = () => (
50
51
  </TabsContent>
51
52
  </Tabs>
52
53
  </FigmaVariant>
53
- <FigmaVariant label="Pills">
54
- <Tabs defaultValue="active" type="pills">
54
+ <FigmaVariant label="Pills · soft">
55
+ <Tabs defaultValue="active" type="pills" appearance="soft">
55
56
  <TabsList>
56
57
  <TabsTrigger value="active">Active</TabsTrigger>
57
- <TabsTrigger value="completed" count={3}>
58
+ <TabsTrigger value="completed">
58
59
  Completed
60
+ <Badge color="blue">3</Badge>
59
61
  </TabsTrigger>
60
62
  </TabsList>
61
63
  <TabsContent value="active" className="pt-3 text-caption-2 text-display-on-light-secondary">
@@ -66,6 +68,27 @@ export const ContentCanvas = () => (
66
68
  </TabsContent>
67
69
  </Tabs>
68
70
  </FigmaVariant>
71
+ <FigmaVariant label="Pills · solid">
72
+ <Tabs defaultValue="chat" type="pills" appearance="solid">
73
+ <TabsList>
74
+ <TabsTrigger value="chat">Chat</TabsTrigger>
75
+ <TabsTrigger value="questions">
76
+ Questions
77
+ <Badge color="grey">208</Badge>
78
+ </TabsTrigger>
79
+ <TabsTrigger value="review">
80
+ Review
81
+ <Badge color="green" type="icon">
82
+ <TickIcon size="xs" />
83
+ </Badge>
84
+ </TabsTrigger>
85
+ <TabsTrigger value="gaps">
86
+ Gaps
87
+ <Badge color="grey">47</Badge>
88
+ </TabsTrigger>
89
+ </TabsList>
90
+ </Tabs>
91
+ </FigmaVariant>
69
92
  </div>
70
93
  </FigmaSection>
71
94