@shipfox/react-ui 0.13.0 → 0.15.0

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 (268) hide show
  1. package/.storybook/preview.tsx +7 -0
  2. package/.turbo/turbo-build.log +7 -7
  3. package/.turbo/turbo-check.log +2 -2
  4. package/.turbo/turbo-type.log +1 -1
  5. package/CHANGELOG.md +16 -0
  6. package/dist/components/avatar/avatar.js +1 -1
  7. package/dist/components/avatar/avatar.js.map +1 -1
  8. package/dist/components/button-group/button-group.d.ts +17 -0
  9. package/dist/components/button-group/button-group.d.ts.map +1 -0
  10. package/dist/components/button-group/button-group.js +74 -0
  11. package/dist/components/button-group/button-group.js.map +1 -0
  12. package/dist/components/button-group/button-group.stories.js +644 -0
  13. package/dist/components/button-group/button-group.stories.js.map +1 -0
  14. package/dist/components/button-group/index.d.ts +2 -0
  15. package/dist/components/button-group/index.d.ts.map +1 -0
  16. package/dist/components/button-group/index.js +3 -0
  17. package/dist/components/button-group/index.js.map +1 -0
  18. package/dist/components/code-block/code-block-footer.d.ts.map +1 -1
  19. package/dist/components/code-block/code-block-footer.js +13 -5
  20. package/dist/components/code-block/code-block-footer.js.map +1 -1
  21. package/dist/components/command/command.d.ts +28 -0
  22. package/dist/components/command/command.d.ts.map +1 -0
  23. package/dist/components/command/command.js +190 -0
  24. package/dist/components/command/command.js.map +1 -0
  25. package/dist/components/command/command.stories.js +228 -0
  26. package/dist/components/command/command.stories.js.map +1 -0
  27. package/dist/components/command/index.d.ts +2 -0
  28. package/dist/components/command/index.d.ts.map +1 -0
  29. package/dist/components/command/index.js +3 -0
  30. package/dist/components/command/index.js.map +1 -0
  31. package/dist/components/confetti/confetti.d.ts +21 -0
  32. package/dist/components/confetti/confetti.d.ts.map +1 -0
  33. package/dist/components/confetti/confetti.js +101 -0
  34. package/dist/components/confetti/confetti.js.map +1 -0
  35. package/dist/components/confetti/confetti.stories.js +41 -0
  36. package/dist/components/confetti/confetti.stories.js.map +1 -0
  37. package/dist/components/confetti/index.d.ts +2 -0
  38. package/dist/components/confetti/index.d.ts.map +1 -0
  39. package/dist/components/confetti/index.js +3 -0
  40. package/dist/components/confetti/index.js.map +1 -0
  41. package/dist/components/dashboard/components/analytics-content.d.ts +2 -0
  42. package/dist/components/dashboard/components/analytics-content.d.ts.map +1 -0
  43. package/dist/components/dashboard/components/analytics-content.js +180 -0
  44. package/dist/components/dashboard/components/analytics-content.js.map +1 -0
  45. package/dist/components/dashboard/components/animated-logo.d.ts +4 -0
  46. package/dist/components/dashboard/components/animated-logo.d.ts.map +1 -0
  47. package/dist/components/dashboard/components/animated-logo.js +23 -0
  48. package/dist/components/dashboard/components/animated-logo.js.map +1 -0
  49. package/dist/components/dashboard/components/complete-setup-button.d.ts +4 -0
  50. package/dist/components/dashboard/components/complete-setup-button.d.ts.map +1 -0
  51. package/dist/components/dashboard/components/complete-setup-button.js +28 -0
  52. package/dist/components/dashboard/components/complete-setup-button.js.map +1 -0
  53. package/dist/components/dashboard/components/jobs-content.d.ts +2 -0
  54. package/dist/components/dashboard/components/jobs-content.d.ts.map +1 -0
  55. package/dist/components/dashboard/components/jobs-content.js +69 -0
  56. package/dist/components/dashboard/components/jobs-content.js.map +1 -0
  57. package/dist/components/dashboard/components/mobile-menu.d.ts +2 -0
  58. package/dist/components/dashboard/components/mobile-menu.d.ts.map +1 -0
  59. package/dist/components/dashboard/components/mobile-menu.js +65 -0
  60. package/dist/components/dashboard/components/mobile-menu.js.map +1 -0
  61. package/dist/components/dashboard/components/organization-selector.d.ts +2 -0
  62. package/dist/components/dashboard/components/organization-selector.d.ts.map +1 -0
  63. package/dist/components/dashboard/components/organization-selector.js +92 -0
  64. package/dist/components/dashboard/components/organization-selector.js.map +1 -0
  65. package/dist/components/dashboard/components/top-menu.d.ts +5 -0
  66. package/dist/components/dashboard/components/top-menu.d.ts.map +1 -0
  67. package/dist/components/dashboard/components/top-menu.js +31 -0
  68. package/dist/components/dashboard/components/top-menu.js.map +1 -0
  69. package/dist/components/dashboard/components/topbar-button.d.ts +7 -0
  70. package/dist/components/dashboard/components/topbar-button.d.ts.map +1 -0
  71. package/dist/components/dashboard/components/topbar-button.js +18 -0
  72. package/dist/components/dashboard/components/topbar-button.js.map +1 -0
  73. package/dist/components/dashboard/components/topbar.d.ts +4 -0
  74. package/dist/components/dashboard/components/topbar.d.ts.map +1 -0
  75. package/dist/components/dashboard/components/topbar.js +62 -0
  76. package/dist/components/dashboard/components/topbar.js.map +1 -0
  77. package/dist/components/dashboard/components/user-profile.d.ts +2 -0
  78. package/dist/components/dashboard/components/user-profile.d.ts.map +1 -0
  79. package/dist/components/dashboard/components/user-profile.js +146 -0
  80. package/dist/components/dashboard/components/user-profile.js.map +1 -0
  81. package/dist/components/dashboard/dashboard.d.ts +2 -0
  82. package/dist/components/dashboard/dashboard.d.ts.map +1 -0
  83. package/dist/components/dashboard/dashboard.js +70 -0
  84. package/dist/components/dashboard/dashboard.js.map +1 -0
  85. package/dist/components/dashboard/dashboard.stories.js +23 -0
  86. package/dist/components/dashboard/dashboard.stories.js.map +1 -0
  87. package/dist/components/dashboard/index.d.ts +2 -0
  88. package/dist/components/dashboard/index.d.ts.map +1 -0
  89. package/dist/components/dashboard/index.js +3 -0
  90. package/dist/components/dashboard/index.js.map +1 -0
  91. package/dist/components/form/form.stories.js +6 -1
  92. package/dist/components/form/form.stories.js.map +1 -1
  93. package/dist/components/icon/icon.d.ts +3 -2
  94. package/dist/components/icon/icon.d.ts.map +1 -1
  95. package/dist/components/icon/icon.js +7 -2
  96. package/dist/components/icon/icon.js.map +1 -1
  97. package/dist/components/index.d.ts +9 -0
  98. package/dist/components/index.d.ts.map +1 -1
  99. package/dist/components/index.js +9 -0
  100. package/dist/components/index.js.map +1 -1
  101. package/dist/components/kbd/index.d.ts +2 -0
  102. package/dist/components/kbd/index.d.ts.map +1 -0
  103. package/dist/components/kbd/index.js +3 -0
  104. package/dist/components/kbd/index.js.map +1 -0
  105. package/dist/components/kbd/kbd.d.ts +7 -0
  106. package/dist/components/kbd/kbd.d.ts.map +1 -0
  107. package/dist/components/kbd/kbd.js +18 -0
  108. package/dist/components/kbd/kbd.js.map +1 -0
  109. package/dist/components/kbd/kbd.stories.js +119 -0
  110. package/dist/components/kbd/kbd.stories.js.map +1 -0
  111. package/dist/components/modal/modal.stories.js +227 -168
  112. package/dist/components/modal/modal.stories.js.map +1 -1
  113. package/dist/components/search/index.d.ts +7 -0
  114. package/dist/components/search/index.d.ts.map +1 -0
  115. package/dist/components/search/index.js +8 -0
  116. package/dist/components/search/index.js.map +1 -0
  117. package/dist/components/search/search-context.d.ts +11 -0
  118. package/dist/components/search/search-context.d.ts.map +1 -0
  119. package/dist/components/search/search-context.js +56 -0
  120. package/dist/components/search/search-context.js.map +1 -0
  121. package/dist/components/search/search-inline.d.ts +9 -0
  122. package/dist/components/search/search-inline.d.ts.map +1 -0
  123. package/dist/components/search/search-inline.js +85 -0
  124. package/dist/components/search/search-inline.js.map +1 -0
  125. package/dist/components/search/search-modal.d.ts +25 -0
  126. package/dist/components/search/search-modal.d.ts.map +1 -0
  127. package/dist/components/search/search-modal.js +162 -0
  128. package/dist/components/search/search-modal.js.map +1 -0
  129. package/dist/components/search/search-trigger.d.ts +9 -0
  130. package/dist/components/search/search-trigger.d.ts.map +1 -0
  131. package/dist/components/search/search-trigger.js +37 -0
  132. package/dist/components/search/search-trigger.js.map +1 -0
  133. package/dist/components/search/search-variants.d.ts +14 -0
  134. package/dist/components/search/search-variants.d.ts.map +1 -0
  135. package/dist/components/search/search-variants.js +90 -0
  136. package/dist/components/search/search-variants.js.map +1 -0
  137. package/dist/components/search/search.d.ts +11 -0
  138. package/dist/components/search/search.d.ts.map +1 -0
  139. package/dist/components/search/search.js +35 -0
  140. package/dist/components/search/search.js.map +1 -0
  141. package/dist/components/search/search.stories.js +630 -0
  142. package/dist/components/search/search.stories.js.map +1 -0
  143. package/dist/components/select/index.d.ts +2 -0
  144. package/dist/components/select/index.d.ts.map +1 -0
  145. package/dist/components/select/index.js +3 -0
  146. package/dist/components/select/index.js.map +1 -0
  147. package/dist/components/select/select.d.ts +25 -0
  148. package/dist/components/select/select.d.ts.map +1 -0
  149. package/dist/components/select/select.js +153 -0
  150. package/dist/components/select/select.js.map +1 -0
  151. package/dist/components/select/select.stories.js +393 -0
  152. package/dist/components/select/select.stories.js.map +1 -0
  153. package/dist/components/shiny-text/index.d.ts +2 -0
  154. package/dist/components/shiny-text/index.d.ts.map +1 -0
  155. package/dist/components/shiny-text/index.js +3 -0
  156. package/dist/components/shiny-text/index.js.map +1 -0
  157. package/dist/components/shiny-text/shiny-text.d.ts +10 -0
  158. package/dist/components/shiny-text/shiny-text.d.ts.map +1 -0
  159. package/dist/components/shiny-text/shiny-text.js +17 -0
  160. package/dist/components/shiny-text/shiny-text.js.map +1 -0
  161. package/dist/components/skeleton/index.d.ts +2 -0
  162. package/dist/components/skeleton/index.d.ts.map +1 -0
  163. package/dist/components/skeleton/index.js +3 -0
  164. package/dist/components/skeleton/index.js.map +1 -0
  165. package/dist/components/skeleton/skeleton.d.ts +5 -0
  166. package/dist/components/skeleton/skeleton.d.ts.map +1 -0
  167. package/dist/components/skeleton/skeleton.js +11 -0
  168. package/dist/components/skeleton/skeleton.js.map +1 -0
  169. package/dist/components/skeleton/skeleton.stories.js +345 -0
  170. package/dist/components/skeleton/skeleton.stories.js.map +1 -0
  171. package/dist/components/table/data-table.d.ts +70 -0
  172. package/dist/components/table/data-table.d.ts.map +1 -0
  173. package/dist/components/table/data-table.js +159 -0
  174. package/dist/components/table/data-table.js.map +1 -0
  175. package/dist/components/table/index.d.ts +6 -0
  176. package/dist/components/table/index.d.ts.map +1 -0
  177. package/dist/components/table/index.js +6 -0
  178. package/dist/components/table/index.js.map +1 -0
  179. package/dist/components/table/table-column-header.d.ts +79 -0
  180. package/dist/components/table/table-column-header.d.ts.map +1 -0
  181. package/dist/components/table/table-column-header.js +99 -0
  182. package/dist/components/table/table-column-header.js.map +1 -0
  183. package/dist/components/table/table-pagination.d.ts +53 -0
  184. package/dist/components/table/table-pagination.d.ts.map +1 -0
  185. package/dist/components/table/table-pagination.js +139 -0
  186. package/dist/components/table/table-pagination.js.map +1 -0
  187. package/dist/components/table/table.d.ts +11 -0
  188. package/dist/components/table/table.d.ts.map +1 -0
  189. package/dist/components/table/table.js +64 -0
  190. package/dist/components/table/table.js.map +1 -0
  191. package/dist/components/table/table.stories.columns.d.ts +24 -0
  192. package/dist/components/table/table.stories.columns.d.ts.map +1 -0
  193. package/dist/components/table/table.stories.columns.js +310 -0
  194. package/dist/components/table/table.stories.columns.js.map +1 -0
  195. package/dist/components/table/table.stories.components.d.ts +14 -0
  196. package/dist/components/table/table.stories.components.d.ts.map +1 -0
  197. package/dist/components/table/table.stories.components.js +107 -0
  198. package/dist/components/table/table.stories.components.js.map +1 -0
  199. package/dist/components/table/table.stories.data.d.ts +54 -0
  200. package/dist/components/table/table.stories.data.d.ts.map +1 -0
  201. package/dist/components/table/table.stories.data.js +122 -0
  202. package/dist/components/table/table.stories.data.js.map +1 -0
  203. package/dist/components/table/table.stories.js +302 -0
  204. package/dist/components/table/table.stories.js.map +1 -0
  205. package/dist/index.d.ts +1 -0
  206. package/dist/index.d.ts.map +1 -1
  207. package/dist/index.js +1 -0
  208. package/dist/index.js.map +1 -1
  209. package/dist/styles.css +1 -1
  210. package/index.css +79 -0
  211. package/package.json +6 -2
  212. package/src/components/avatar/avatar.tsx +1 -1
  213. package/src/components/button-group/button-group.stories.tsx +361 -0
  214. package/src/components/button-group/button-group.tsx +111 -0
  215. package/src/components/button-group/index.ts +1 -0
  216. package/src/components/code-block/code-block-footer.tsx +19 -2
  217. package/src/components/command/command.stories.tsx +133 -0
  218. package/src/components/command/command.tsx +265 -0
  219. package/src/components/command/index.ts +1 -0
  220. package/src/components/confetti/confetti.stories.tsx +38 -0
  221. package/src/components/confetti/confetti.tsx +140 -0
  222. package/src/components/confetti/index.ts +1 -0
  223. package/src/components/dashboard/components/analytics-content.tsx +102 -0
  224. package/src/components/dashboard/components/animated-logo.tsx +25 -0
  225. package/src/components/dashboard/components/complete-setup-button.tsx +30 -0
  226. package/src/components/dashboard/components/jobs-content.tsx +51 -0
  227. package/src/components/dashboard/components/mobile-menu.tsx +50 -0
  228. package/src/components/dashboard/components/organization-selector.tsx +51 -0
  229. package/src/components/dashboard/components/top-menu.tsx +26 -0
  230. package/src/components/dashboard/components/topbar-button.tsx +27 -0
  231. package/src/components/dashboard/components/topbar.tsx +40 -0
  232. package/src/components/dashboard/components/user-profile.tsx +90 -0
  233. package/src/components/dashboard/dashboard.stories.tsx +25 -0
  234. package/src/components/dashboard/dashboard.tsx +61 -0
  235. package/src/components/dashboard/index.ts +1 -0
  236. package/src/components/form/form.stories.tsx +5 -0
  237. package/src/components/icon/icon.tsx +7 -3
  238. package/src/components/index.ts +9 -0
  239. package/src/components/kbd/index.ts +1 -0
  240. package/src/components/kbd/kbd.stories.tsx +64 -0
  241. package/src/components/kbd/kbd.tsx +32 -0
  242. package/src/components/modal/modal.stories.tsx +58 -4
  243. package/src/components/search/index.ts +28 -0
  244. package/src/components/search/search-context.tsx +78 -0
  245. package/src/components/search/search-inline.tsx +107 -0
  246. package/src/components/search/search-modal.tsx +198 -0
  247. package/src/components/search/search-trigger.tsx +47 -0
  248. package/src/components/search/search-variants.ts +88 -0
  249. package/src/components/search/search.stories.tsx +392 -0
  250. package/src/components/search/search.tsx +47 -0
  251. package/src/components/select/index.ts +1 -0
  252. package/src/components/select/select.stories.tsx +207 -0
  253. package/src/components/select/select.tsx +220 -0
  254. package/src/components/shiny-text/index.ts +1 -0
  255. package/src/components/shiny-text/shiny-text.tsx +21 -0
  256. package/src/components/skeleton/index.ts +1 -0
  257. package/src/components/skeleton/skeleton.stories.tsx +178 -0
  258. package/src/components/skeleton/skeleton.tsx +14 -0
  259. package/src/components/table/data-table.tsx +254 -0
  260. package/src/components/table/index.ts +5 -0
  261. package/src/components/table/table-column-header.tsx +141 -0
  262. package/src/components/table/table-pagination.tsx +161 -0
  263. package/src/components/table/table.stories.columns.tsx +198 -0
  264. package/src/components/table/table.stories.components.tsx +104 -0
  265. package/src/components/table/table.stories.data.ts +117 -0
  266. package/src/components/table/table.stories.tsx +256 -0
  267. package/src/components/table/table.tsx +95 -0
  268. package/src/index.ts +1 -0
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Data types, generation functions, and sample data for Table stories
3
+ */
4
+
5
+ export type JobData = {
6
+ id: string;
7
+ name: string;
8
+ total: number;
9
+ success: number;
10
+ failed: number;
11
+ neutral: number;
12
+ flaked: number;
13
+ failureRate: string;
14
+ flakeRate: string;
15
+ repository?: string;
16
+ branch?: string;
17
+ };
18
+
19
+ export type SearchJobData = {
20
+ id: string;
21
+ name: string;
22
+ total: number;
23
+ success: number;
24
+ failed: number;
25
+ status: 'active' | 'completed' | 'failed';
26
+ repository: string;
27
+ branch: string;
28
+ };
29
+
30
+ export type User = {
31
+ id: string;
32
+ name: string;
33
+ email: string;
34
+ role: string;
35
+ status: 'active' | 'inactive';
36
+ };
37
+
38
+ /**
39
+ * Generate mock job data
40
+ */
41
+ export const generateJobData = (count: number): JobData[] => {
42
+ return Array.from({length: count}, (_, i) => {
43
+ const total = 40 + (i % 20); // keeps totals in a reasonable range
44
+ const failed = i % 7;
45
+ const flaked = i % 5;
46
+ const neutral = i % 3;
47
+ const success = total - failed - flaked - neutral;
48
+ const failureRate = `${Math.round((failed / total) * 100)}%`;
49
+ const flakeRate = `${Math.round((flaked / total) * 100)}%`;
50
+ return {
51
+ id: `job-${i + 1}`,
52
+ name: 'Dependabot updates',
53
+ total,
54
+ success,
55
+ failed,
56
+ neutral,
57
+ flaked,
58
+ failureRate,
59
+ flakeRate,
60
+ repository: 'shipfox/tooling',
61
+ branch: 'main',
62
+ };
63
+ });
64
+ };
65
+
66
+ /**
67
+ * Generate mock search job data with varied properties
68
+ */
69
+ export const generateSearchJobData = (count: number): SearchJobData[] => {
70
+ const jobNames = [
71
+ 'Build & Deploy',
72
+ 'Run Tests',
73
+ 'Code Quality Check',
74
+ 'Security Scan',
75
+ 'Integration Tests',
76
+ 'Performance Tests',
77
+ 'Deploy to Staging',
78
+ 'Deploy to Production',
79
+ 'Database Migration',
80
+ 'Cache Warm-up',
81
+ ];
82
+ const repositories = ['shipfox/tooling', 'shipfox/web', 'shipfox/api', 'shipfox/mobile'];
83
+ const branches = ['main', 'develop', 'staging', 'feat/new-feature'];
84
+ const statuses: Array<'active' | 'completed' | 'failed'> = ['active', 'completed', 'failed'];
85
+
86
+ return Array.from({length: count}, (_, i) => ({
87
+ id: `job-${i + 1}`,
88
+ name: jobNames[i % jobNames.length],
89
+ total: Math.floor(Math.random() * 100) + 20,
90
+ success: Math.floor(Math.random() * 80) + 10,
91
+ failed: Math.floor(Math.random() * 20),
92
+ status: statuses[i % statuses.length],
93
+ repository: repositories[i % repositories.length],
94
+ branch: branches[i % branches.length],
95
+ }));
96
+ };
97
+
98
+ /**
99
+ * Sample job data
100
+ */
101
+ export const jobsData = generateJobData(100);
102
+
103
+ /**
104
+ * Sample search job data
105
+ */
106
+ export const searchJobsData = generateSearchJobData(50);
107
+
108
+ /**
109
+ * Sample user data
110
+ */
111
+ export const users: User[] = [
112
+ {id: '1', name: 'John Doe', email: 'john@example.com', role: 'Admin', status: 'active'},
113
+ {id: '2', name: 'Jane Smith', email: 'jane@example.com', role: 'User', status: 'active'},
114
+ {id: '3', name: 'Bob Johnson', email: 'bob@example.com', role: 'User', status: 'inactive'},
115
+ {id: '4', name: 'Alice Williams', email: 'alice@example.com', role: 'Editor', status: 'active'},
116
+ {id: '5', name: 'Charlie Brown', email: 'charlie@example.com', role: 'User', status: 'active'},
117
+ ];
@@ -0,0 +1,256 @@
1
+ import type {Meta, StoryObj} from '@storybook/react';
2
+ import type {ColumnDef} from '@tanstack/react-table';
3
+ import {Search, SearchContent, SearchTrigger} from 'components/search';
4
+ import {Header, Text} from 'components/typography';
5
+ import {useMemo, useState} from 'react';
6
+ import {Button} from '../button';
7
+ import {Icon} from '../icon';
8
+ import {SearchInline} from '../search/search-inline';
9
+ import {DataTable} from './data-table';
10
+ import {jobColumns, searchJobColumns, userColumns} from './table.stories.columns';
11
+ import {JobsEmptyState, SearchModalContent} from './table.stories.components';
12
+ import {type JobData, jobsData, searchJobsData, users} from './table.stories.data';
13
+
14
+ const meta = {
15
+ title: 'Components/Table',
16
+ parameters: {
17
+ layout: 'padded',
18
+ },
19
+ tags: ['autodocs'],
20
+ } satisfies Meta;
21
+
22
+ export default meta;
23
+ type Story = StoryObj;
24
+
25
+ export const Simple: Story = {
26
+ parameters: {
27
+ viewport: {
28
+ defaultViewport: 'extraLarge',
29
+ },
30
+ },
31
+ render: () => (
32
+ <div className="w-full min-h-screen bg-background-neutral-background p-24">
33
+ <DataTable columns={jobColumns.slice(0, 4)} data={jobsData.slice(0, 5)} pagination={false} />
34
+ </div>
35
+ ),
36
+ };
37
+
38
+ export const WithPagination: Story = {
39
+ parameters: {
40
+ viewport: {
41
+ defaultViewport: 'extraLarge',
42
+ },
43
+ },
44
+ render: () => (
45
+ <div className="w-full min-h-screen bg-background-neutral-background p-24">
46
+ <DataTable
47
+ columns={jobColumns}
48
+ data={jobsData}
49
+ pagination={true}
50
+ pageSize={10}
51
+ pageSizeOptions={[5, 10, 20, 50]}
52
+ />
53
+ </div>
54
+ ),
55
+ };
56
+
57
+ export const EmptyState: Story = {
58
+ parameters: {
59
+ viewport: {
60
+ defaultViewport: 'extraLarge',
61
+ },
62
+ },
63
+ render: () => (
64
+ <div className="w-full min-h-screen bg-background-neutral-background p-24">
65
+ <DataTable columns={jobColumns} data={[]} pagination={true} emptyState={<JobsEmptyState />} />
66
+ </div>
67
+ ),
68
+ };
69
+
70
+ export const UserTable: Story = {
71
+ parameters: {
72
+ viewport: {
73
+ defaultViewport: 'extraLarge',
74
+ },
75
+ },
76
+ render: () => (
77
+ <div className="w-full min-h-screen bg-background-neutral-background p-24">
78
+ <DataTable columns={userColumns} data={users} pagination={false} />
79
+ </div>
80
+ ),
81
+ };
82
+
83
+ export const CompactTable: Story = {
84
+ parameters: {
85
+ viewport: {
86
+ defaultViewport: 'extraLarge',
87
+ },
88
+ },
89
+ render: () => {
90
+ const compactColumns: ColumnDef<JobData>[] = [
91
+ jobColumns[0], // name
92
+ jobColumns[1], // total
93
+ jobColumns[6], // failureRate
94
+ ];
95
+
96
+ return (
97
+ <div className="w-full min-h-screen bg-background-neutral-background p-24">
98
+ <DataTable columns={compactColumns} data={jobsData.slice(0, 5)} pagination={false} />
99
+ </div>
100
+ );
101
+ },
102
+ };
103
+
104
+ export const JobsOverview: Story = {
105
+ parameters: {
106
+ viewport: {
107
+ defaultViewport: 'extraLarge',
108
+ },
109
+ },
110
+ render: () => {
111
+ const [searchQuery, setSearchQuery] = useState('');
112
+
113
+ const filteredData = useMemo(
114
+ () => jobsData.filter((job) => job.name.toLowerCase().includes(searchQuery.toLowerCase())),
115
+ [searchQuery],
116
+ );
117
+
118
+ return (
119
+ <div className="w-full min-h-screen bg-background-neutral-background p-24">
120
+ <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-12 sm:gap-0 p-12 border-t border-x border-border-neutral-base rounded-t-8 rounded-b-none bg-background-neutral-base">
121
+ <Header variant="h3" className="text-foreground-neutral-base">
122
+ Jobs overview
123
+ </Header>
124
+
125
+ <div className="flex items-center gap-12 sm:gap-16 w-full sm:w-auto">
126
+ <SearchInline
127
+ placeholder="Search..."
128
+ value={searchQuery}
129
+ onChange={(e) => setSearchQuery(e.target.value)}
130
+ onClear={() => setSearchQuery('')}
131
+ className="flex-1 sm:w-240"
132
+ />
133
+ <Button variant="secondary" aria-label="Insert column left" className="shrink-0">
134
+ <Icon name="insertColumnLeft" className="size-16 text-foreground-neutral-subtle" />
135
+ </Button>
136
+ </div>
137
+ </div>
138
+
139
+ <DataTable
140
+ columns={jobColumns}
141
+ data={filteredData}
142
+ pagination={true}
143
+ pageSize={10}
144
+ pageSizeOptions={[10, 20, 50, 100]}
145
+ className="rounded-t-none"
146
+ />
147
+ </div>
148
+ );
149
+ },
150
+ };
151
+
152
+ export const WithSearchModal: Story = {
153
+ parameters: {
154
+ viewport: {
155
+ defaultViewport: 'extraLarge',
156
+ },
157
+ },
158
+ render: () => {
159
+ function SearchModalDemo() {
160
+ const [open, setOpen] = useState(false);
161
+ const [selectedJobId, setSelectedJobId] = useState<string | null>(null);
162
+
163
+ const filteredData = useMemo(
164
+ () =>
165
+ selectedJobId ? searchJobsData.filter((job) => job.id === selectedJobId) : searchJobsData,
166
+ [selectedJobId],
167
+ );
168
+
169
+ const selectedJob = useMemo(
170
+ () => (selectedJobId ? searchJobsData.find((job) => job.id === selectedJobId) : null),
171
+ [selectedJobId],
172
+ );
173
+
174
+ const handleSelectJob = (jobId: string) => {
175
+ setSelectedJobId(jobId);
176
+ setOpen(false);
177
+ };
178
+
179
+ const handleClearSelection = () => {
180
+ setSelectedJobId(null);
181
+ };
182
+
183
+ return (
184
+ <div className="w-full min-h-screen bg-background-neutral-background p-24">
185
+ <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-12 sm:gap-0 p-12 border-t border-x border-border-neutral-base rounded-t-8 rounded-b-none bg-background-neutral-base">
186
+ <Header variant="h3" className="text-foreground-neutral-base">
187
+ Jobs Breakdown
188
+ </Header>
189
+
190
+ <div className="flex flex-col sm:flex-row items-stretch sm:items-center gap-12 sm:gap-16 w-full sm:w-auto">
191
+ {selectedJob && (
192
+ <Button
193
+ variant="transparentMuted"
194
+ size="sm"
195
+ onClick={handleClearSelection}
196
+ className="text-foreground-neutral-muted gap-4 w-full sm:w-auto justify-center sm:justify-start"
197
+ iconRight="closeLine"
198
+ >
199
+ Clear filter
200
+ </Button>
201
+ )}
202
+ <Search open={open} onOpenChange={setOpen} shortcutKey="meta+k" shouldFilter={false}>
203
+ <SearchTrigger placeholder="Filter jobs..." className="w-full sm:w-280" />
204
+ <SearchContent aria-describedby={undefined}>
205
+ <SearchModalContent onSelectJob={handleSelectJob} />
206
+ </SearchContent>
207
+ </Search>
208
+ </div>
209
+ </div>
210
+
211
+ <DataTable
212
+ columns={searchJobColumns}
213
+ data={filteredData}
214
+ pagination={true}
215
+ pageSize={10}
216
+ pageSizeOptions={[10, 25, 50]}
217
+ className="rounded-t-none"
218
+ />
219
+ </div>
220
+ );
221
+ }
222
+
223
+ return <SearchModalDemo />;
224
+ },
225
+ };
226
+
227
+ export const WithRowSelection: Story = {
228
+ parameters: {
229
+ viewport: {
230
+ defaultViewport: 'extraLarge',
231
+ },
232
+ },
233
+ render: () => (
234
+ <div className="w-full min-h-screen bg-background-neutral-background p-24">
235
+ <div className="space-y-16">
236
+ <div>
237
+ <Header variant="h3" className="text-foreground-neutral-base mb-8">
238
+ Selectable Rows
239
+ </Header>
240
+ <Text size="sm" className="text-foreground-neutral-muted">
241
+ Use the checkboxes to select rows. The pagination footer shows the count of selected
242
+ rows.
243
+ </Text>
244
+ </div>
245
+ <DataTable
246
+ columns={jobColumns}
247
+ data={jobsData}
248
+ pagination={true}
249
+ pageSize={10}
250
+ pageSizeOptions={[5, 10, 20, 50]}
251
+ showSelectedCount={true}
252
+ />
253
+ </div>
254
+ </div>
255
+ ),
256
+ };
@@ -0,0 +1,95 @@
1
+ import type {ComponentProps} from 'react';
2
+ import {cn} from 'utils/cn';
3
+
4
+ function Table({className, ...props}: ComponentProps<'table'>) {
5
+ return (
6
+ <div className="relative w-full overflow-auto scrollbar">
7
+ <table
8
+ data-slot="table"
9
+ className={cn('w-full caption-bottom text-sm', className)}
10
+ {...props}
11
+ />
12
+ </div>
13
+ );
14
+ }
15
+
16
+ function TableHeader({className, ...props}: ComponentProps<'thead'>) {
17
+ return <thead data-slot="table-header" className={cn(className)} {...props} />;
18
+ }
19
+
20
+ function TableBody({className, ...props}: ComponentProps<'tbody'>) {
21
+ return <tbody data-slot="table-body" className={cn(className)} {...props} />;
22
+ }
23
+
24
+ function TableFooter({className, ...props}: ComponentProps<'tfoot'>) {
25
+ return (
26
+ <tfoot
27
+ data-slot="table-footer"
28
+ className={cn(
29
+ 'border-t border-border-neutral-base bg-background-neutral-base font-medium',
30
+ className,
31
+ )}
32
+ {...props}
33
+ />
34
+ );
35
+ }
36
+
37
+ function TableRow({className, ...props}: ComponentProps<'tr'>) {
38
+ return (
39
+ <tr
40
+ data-slot="table-row"
41
+ className={cn(
42
+ 'group/row border-b border-border-neutral-base transition-colors',
43
+ 'last:border-b-0',
44
+ 'hover:bg-background-neutral-hover',
45
+ 'data-[selected=true]:bg-background-neutral-pressed data-[selected=true]:hover:bg-background-neutral-pressed',
46
+ className,
47
+ )}
48
+ {...props}
49
+ />
50
+ );
51
+ }
52
+
53
+ function TableHead({className, ...props}: ComponentProps<'th'>) {
54
+ return (
55
+ <th
56
+ data-slot="table-head"
57
+ className={cn(
58
+ 'h-40 px-16 text-left align-middle text-xs font-medium leading-20 text-foreground-neutral-subtle',
59
+ 'bg-background-subtle-base',
60
+ '[&:has([role=checkbox])]:pr-0 [&:has([role=checkbox])]:px-12 [&:has([role=checkbox])]:w-0 [&:has([role=checkbox])]:pt-6',
61
+ className,
62
+ )}
63
+ {...props}
64
+ />
65
+ );
66
+ }
67
+
68
+ function TableCell({className, ...props}: ComponentProps<'td'>) {
69
+ return (
70
+ <td
71
+ data-slot="table-cell"
72
+ className={cn(
73
+ 'px-12 py-10 align-middle text-sm leading-20 text-foreground-neutral-base',
74
+ 'bg-background-neutral-base',
75
+ 'group-hover/row:bg-background-neutral-hover',
76
+ 'group-data-[selected=true]/row:bg-background-neutral-pressed!',
77
+ '[&:has([role=checkbox])]:pr-0 [&:has([role=checkbox])]:pt-14',
78
+ className,
79
+ )}
80
+ {...props}
81
+ />
82
+ );
83
+ }
84
+
85
+ function TableCaption({className, ...props}: ComponentProps<'caption'>) {
86
+ return (
87
+ <caption
88
+ data-slot="table-caption"
89
+ className={cn('mt-16 text-sm text-foreground-neutral-muted', className)}
90
+ {...props}
91
+ />
92
+ );
93
+ }
94
+
95
+ export {Table, TableHeader, TableBody, TableFooter, TableRow, TableHead, TableCell, TableCaption};
package/src/index.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export {ShipfoxLoader} from 'shipfox-loader-react';
1
2
  export * from './components';
2
3
  export * from './hooks';
3
4
  export * from './utils';