@exxatdesignux/ui 0.2.8 → 0.2.10

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 (125) hide show
  1. package/consumer-extras/cursor-skills/exxat-card-vs-list-rows/SKILL.md +20 -0
  2. package/consumer-extras/cursor-skills/exxat-collaboration-access/SKILL.md +33 -0
  3. package/consumer-extras/cursor-skills/exxat-dedicated-search-surfaces/SKILL.md +45 -0
  4. package/consumer-extras/cursor-skills/exxat-drawer-vs-dialog/SKILL.md +20 -0
  5. package/consumer-extras/cursor-skills/exxat-ds-skill/SKILL.md +31 -5
  6. package/consumer-extras/cursor-skills/exxat-kpi-max-four/SKILL.md +19 -0
  7. package/consumer-extras/cursor-skills/exxat-kpi-trends/SKILL.md +27 -0
  8. package/consumer-extras/cursor-skills/exxat-primary-nav-secondary-panel/SKILL.md +1 -0
  9. package/consumer-extras/patterns/collaboration-access-pattern.md +114 -0
  10. package/consumer-extras/patterns/data-views-pattern.md +12 -4
  11. package/package.json +17 -4
  12. package/src/components/ui/banner.tsx +20 -7
  13. package/src/components/ui/date-picker-field.tsx +3 -3
  14. package/src/components/ui/dropdown-menu.tsx +17 -6
  15. package/src/components/ui/input-group.tsx +1 -1
  16. package/src/components/ui/input.tsx +1 -1
  17. package/src/components/ui/select.tsx +1 -1
  18. package/src/components/ui/separator.tsx +2 -2
  19. package/src/components/ui/sidebar.tsx +31 -3
  20. package/src/components/ui/textarea.tsx +1 -1
  21. package/src/globals.css +0 -1
  22. package/src/index.ts +1 -0
  23. package/src/lib/date-filter.ts +13 -4
  24. package/src/lib/dropdown-menu-surface.ts +13 -0
  25. package/template/.claude/skills/exxat-ds-skill/SKILL.md +27 -9
  26. package/template/.cursor/rules/exxat-data-tables.mdc +1 -0
  27. package/template/AGENTS.md +82 -27
  28. package/template/app/(app)/examples/page.tsx +2 -1
  29. package/template/app/(app)/help/page.tsx +6 -0
  30. package/template/app/(app)/layout.tsx +7 -4
  31. package/template/app/(app)/question-bank/find/page.tsx +12 -0
  32. package/template/app/(app)/question-bank/layout.tsx +46 -0
  33. package/template/app/(app)/question-bank/library/page.tsx +11 -0
  34. package/template/app/(app)/question-bank/list/page.tsx +12 -0
  35. package/template/app/(app)/question-bank/page.tsx +4 -3
  36. package/template/app/globals.css +1 -2
  37. package/template/components/app-sidebar.tsx +51 -13
  38. package/template/components/ask-leo-composer.tsx +173 -45
  39. package/template/components/ask-leo-sidebar.tsx +9 -1
  40. package/template/components/chart-area-interactive.tsx +3 -13
  41. package/template/components/charts-overview.tsx +33 -6
  42. package/template/components/collaboration-access-flow.tsx +144 -0
  43. package/template/components/compliance-page-header.tsx +1 -1
  44. package/template/components/compliance-table.tsx +2 -2
  45. package/template/components/dashboard-tabs.tsx +4 -3
  46. package/template/components/data-list-table-cells.tsx +1 -1
  47. package/template/components/data-list-table.tsx +1 -1
  48. package/template/components/data-table/index.tsx +5 -5
  49. package/template/components/data-table/use-table-state.ts +18 -2
  50. package/template/components/data-view-dashboard-charts-compliance.tsx +8 -5
  51. package/template/components/data-view-dashboard-charts-team.tsx +8 -5
  52. package/template/components/data-view-dashboard-charts.tsx +62 -227
  53. package/template/components/dedicated-search-recents.tsx +96 -0
  54. package/template/components/dedicated-search-url-composer.tsx +112 -0
  55. package/template/components/getting-started.tsx +1 -1
  56. package/template/components/hub-tree-panel-view.tsx +10 -26
  57. package/template/components/invite-collaborators-drawer.tsx +453 -0
  58. package/template/components/key-metrics.tsx +54 -8
  59. package/template/components/nav-documents.tsx +1 -1
  60. package/template/components/new-placement-form.tsx +3 -3
  61. package/template/components/page-header.tsx +76 -59
  62. package/template/components/placements-board-view.tsx +3 -3
  63. package/template/components/placements-page-header.tsx +1 -1
  64. package/template/components/placements-table-columns.tsx +3 -2
  65. package/template/components/product-switcher.tsx +0 -1
  66. package/template/components/question-bank-board-view.tsx +35 -47
  67. package/template/components/question-bank-client.tsx +293 -81
  68. package/template/components/question-bank-dashboard-charts.tsx +174 -0
  69. package/template/components/question-bank-favorite-button.tsx +46 -0
  70. package/template/components/question-bank-hub-client.tsx +436 -0
  71. package/template/components/question-bank-list-view.tsx +26 -19
  72. package/template/components/question-bank-new-folder-sheet.tsx +56 -42
  73. package/template/components/question-bank-os-folder-view.tsx +3 -14
  74. package/template/components/question-bank-page-header.tsx +85 -53
  75. package/template/components/question-bank-panel-activator.tsx +3 -4
  76. package/template/components/question-bank-secondary-nav.tsx +523 -65
  77. package/template/components/question-bank-table.tsx +125 -343
  78. package/template/components/secondary-panel.tsx +130 -63
  79. package/template/components/settings-client.tsx +3 -1
  80. package/template/components/sidebar-shell.tsx +2 -0
  81. package/template/components/sites-all-client.tsx +1 -1
  82. package/template/components/sites-table.tsx +1 -1
  83. package/template/components/system-banner-slot.tsx +2 -1
  84. package/template/components/table-properties/drawer.tsx +3 -3
  85. package/template/components/table-properties/sort-card.tsx +1 -1
  86. package/template/components/team-page-header.tsx +1 -1
  87. package/template/components/team-table.tsx +8 -4
  88. package/template/components/templates/dedicated-search-landing-template.tsx +58 -0
  89. package/template/components/templates/dedicated-search-results-template.tsx +19 -0
  90. package/template/components/templates/discovery-hub-template.tsx +273 -0
  91. package/template/components/templates/list-page.tsx +11 -4
  92. package/template/components/templates/nested-secondary-panel-shell.tsx +57 -0
  93. package/template/components/templates/secondary-panel-hub-template.tsx +54 -0
  94. package/template/docs/card-vs-rows-pattern.md +36 -0
  95. package/template/docs/collaboration-access-pattern.md +114 -0
  96. package/template/docs/data-views-pattern.md +12 -4
  97. package/template/docs/drawer-vs-dialog-pattern.md +50 -0
  98. package/template/docs/kpi-strip-max-four-pattern.md +29 -0
  99. package/template/docs/kpi-trend-pattern.md +43 -0
  100. package/template/fontawesome-subset.manifest.json +2 -2
  101. package/template/hooks/use-location-hash.ts +14 -8
  102. package/template/hooks/use-secondary-panel-hub-nav.ts +98 -0
  103. package/template/lib/ask-leo-route-context.ts +24 -0
  104. package/template/lib/collaborator-access.ts +92 -0
  105. package/template/lib/command-menu-config.ts +8 -1
  106. package/template/lib/command-menu-search-data.ts +11 -8
  107. package/template/lib/data-list-display-options.ts +1 -1
  108. package/template/lib/data-view-dashboard-placements-layout.ts +215 -0
  109. package/template/lib/date-filter.ts +1 -0
  110. package/template/lib/dedicated-search-recents.ts +76 -0
  111. package/template/lib/dedicated-search-url.ts +23 -0
  112. package/template/lib/discovery-hub.ts +15 -0
  113. package/template/lib/list-status-badges.ts +1 -21
  114. package/template/lib/mock/navigation.tsx +4 -2
  115. package/template/lib/mock/placements.ts +9 -9
  116. package/template/lib/mock/question-bank-folders.ts +7 -0
  117. package/template/lib/mock/question-bank-header-collaborators.ts +45 -5
  118. package/template/lib/mock/question-bank-inspector.ts +1 -2
  119. package/template/lib/mock/question-bank-kpi.ts +38 -26
  120. package/template/lib/mock/question-bank.ts +43 -16
  121. package/template/lib/question-bank-dedicated-search.ts +19 -0
  122. package/template/lib/question-bank-hub-search.ts +90 -0
  123. package/template/lib/question-bank-nav.ts +322 -6
  124. package/template/lib/question-bank-recent-searches.ts +22 -0
  125. package/template/package.json +0 -1
@@ -11,10 +11,10 @@ import {
11
11
  DropdownMenu,
12
12
  DropdownMenuContent,
13
13
  DropdownMenuItem,
14
- DropdownMenuSeparator,
15
14
  DropdownMenuTrigger,
16
15
  } from "@/components/ui/dropdown-menu"
17
16
  import { Tip } from "@/components/ui/tip"
17
+ import { COLLABORATION_HEADER_ADD_LABEL } from "@/lib/collaborator-access"
18
18
  import { QUESTION_BANK_HEADER_COLLABORATORS } from "@/lib/mock/question-bank-header-collaborators"
19
19
 
20
20
  export interface QuestionBankPageHeaderProps {
@@ -23,17 +23,27 @@ export interface QuestionBankPageHeaderProps {
23
23
  questionCount: number
24
24
  onNewQuestion: () => void
25
25
  onExport: () => void
26
- showMetrics: boolean
27
- onToggleMetrics: () => void
26
+ /** Omitted on surfaces without a metric strip (e.g. dedicated search). */
27
+ showMetrics?: boolean
28
+ onToggleMetrics?: () => void
28
29
  showTitleBlock?: boolean
29
- /** `collaboration` adds access line + collaborator stack + invite before CTAs. */
30
+ /** `collaboration` adds access line + collaborator stack before CTAs. */
30
31
  variant?: PageHeaderVariant
31
32
  /** Optional role / access row when `variant="collaboration"` (badge + copy). */
32
33
  accessInfo?: React.ReactNode
33
34
  collaborators?: PageHeaderCollaborator[]
34
35
  collaboratorDisplayLimit?: number
35
36
  onAddCollaborator?: () => void
37
+ onCollaboratorsOpen?: () => void
38
+ /** Empty-roster header CTA — default **Add collaborator**. */
39
+ collaborationAddLabel?: string
36
40
  addCollaboratorLabel?: string
41
+ /** When false, the primary “New question” button is omitted (e.g. search landing). */
42
+ hideNewQuestion?: boolean
43
+ /** Replaces the default “N questions · Last updated…” subtitle when set. */
44
+ subtitleOverride?: string
45
+ /** Omits the action column (e.g. search landing before first query). */
46
+ hideActions?: boolean
37
47
  }
38
48
 
39
49
  export function QuestionBankPageHeader({
@@ -49,10 +59,17 @@ export function QuestionBankPageHeader({
49
59
  collaborators = QUESTION_BANK_HEADER_COLLABORATORS,
50
60
  collaboratorDisplayLimit = 4,
51
61
  onAddCollaborator = () => {},
62
+ onCollaboratorsOpen,
63
+ collaborationAddLabel = COLLABORATION_HEADER_ADD_LABEL,
52
64
  addCollaboratorLabel = "Invite people",
65
+ hideNewQuestion = false,
66
+ subtitleOverride,
67
+ hideActions = false,
53
68
  }: QuestionBankPageHeaderProps) {
54
69
  const [moreOpen, setMoreOpen] = React.useState(false)
55
- const countLine = `${questionCount} ${questionCount === 1 ? "question" : "questions"} · Last updated now`
70
+ const countLine =
71
+ subtitleOverride ??
72
+ `${questionCount} ${questionCount === 1 ? "question" : "questions"} · Last updated now`
56
73
  const resolvedAccess = variant === "collaboration" ? accessInfo : undefined
57
74
 
58
75
  return (
@@ -63,56 +80,71 @@ export function QuestionBankPageHeader({
63
80
  accessInfo={resolvedAccess}
64
81
  collaborators={variant === "collaboration" ? collaborators : undefined}
65
82
  collaboratorDisplayLimit={collaboratorDisplayLimit}
66
- onAddCollaborator={variant === "collaboration" ? onAddCollaborator : undefined}
67
- addCollaboratorLabel={addCollaboratorLabel}
83
+ onCollaboratorsOpen={onCollaboratorsOpen ?? onAddCollaborator}
84
+ addCollaboratorLabel={collaborationAddLabel}
68
85
  showTitleBlock={showTitleBlock}
69
- actions={(
70
- <div className="flex items-center gap-2" role="group" aria-label="Question bank actions">
71
- <Tip side="bottom" label="Create a new question (demo)">
72
- <Button type="button" size="lg" onClick={onNewQuestion}>
73
- <i className="fa-light fa-plus" aria-hidden="true" />
74
- New question
75
- </Button>
76
- </Tip>
77
- <DropdownMenu open={moreOpen} onOpenChange={setMoreOpen}>
78
- <Tip side="bottom" label="More actions">
79
- <DropdownMenuTrigger asChild>
80
- <Button
81
- type="button"
82
- size="lg"
83
- variant="outline"
84
- className="aspect-square px-0"
85
- aria-label="More actions"
86
- >
87
- <i className="fa-light fa-ellipsis text-base" aria-hidden="true" />
86
+ actions={
87
+ hideActions ? undefined : (
88
+ <div className="flex items-center gap-2" role="group" aria-label="Question bank actions">
89
+ {!hideNewQuestion ? (
90
+ <Tip side="bottom" label="Create a new question (demo)">
91
+ <Button type="button" size="lg" onClick={onNewQuestion}>
92
+ <i className="fa-light fa-plus" aria-hidden="true" />
93
+ New question
88
94
  </Button>
89
- </DropdownMenuTrigger>
90
- </Tip>
91
- <DropdownMenuContent align="end" className="w-52">
92
- <DropdownMenuItem
93
- onSelect={() => {
94
- window.setTimeout(() => onExport(), 0)
95
- }}
96
- >
97
- <i className="fa-light fa-arrow-down-to-line" aria-hidden="true" />
98
- Export
99
- </DropdownMenuItem>
100
- <DropdownMenuSeparator />
101
- <DropdownMenuItem
102
- onSelect={() => {
103
- window.setTimeout(() => onToggleMetrics(), 0)
104
- }}
105
- >
106
- <i
107
- className={`fa-light ${showMetrics ? "fa-eye-slash" : "fa-eye"}`}
108
- aria-hidden="true"
109
- />
110
- {showMetrics ? "Hide metric section" : "Show metric section"}
111
- </DropdownMenuItem>
112
- </DropdownMenuContent>
113
- </DropdownMenu>
114
- </div>
115
- )}
95
+ </Tip>
96
+ ) : null}
97
+ <DropdownMenu open={moreOpen} onOpenChange={setMoreOpen}>
98
+ <Tip side="bottom" label="More actions">
99
+ <DropdownMenuTrigger asChild>
100
+ <Button
101
+ type="button"
102
+ size="lg"
103
+ variant="outline"
104
+ className="aspect-square px-0"
105
+ aria-label="More actions"
106
+ >
107
+ <i className="fa-light fa-ellipsis text-base" aria-hidden="true" />
108
+ </Button>
109
+ </DropdownMenuTrigger>
110
+ </Tip>
111
+ <DropdownMenuContent align="end">
112
+ {variant === "collaboration" ? (
113
+ <DropdownMenuItem
114
+ onSelect={() => {
115
+ window.setTimeout(() => onAddCollaborator(), 0)
116
+ }}
117
+ >
118
+ <i className="fa-light fa-user-plus" aria-hidden="true" />
119
+ {addCollaboratorLabel}
120
+ </DropdownMenuItem>
121
+ ) : null}
122
+ <DropdownMenuItem
123
+ onSelect={() => {
124
+ window.setTimeout(() => onExport(), 0)
125
+ }}
126
+ >
127
+ <i className="fa-light fa-arrow-down-to-line" aria-hidden="true" />
128
+ Export
129
+ </DropdownMenuItem>
130
+ {onToggleMetrics != null ? (
131
+ <DropdownMenuItem
132
+ onSelect={() => {
133
+ window.setTimeout(() => onToggleMetrics(), 0)
134
+ }}
135
+ >
136
+ <i
137
+ className={`fa-light ${(showMetrics ?? false) ? "fa-eye-slash" : "fa-eye"}`}
138
+ aria-hidden="true"
139
+ />
140
+ {(showMetrics ?? false) ? "Hide metric section" : "Show metric section"}
141
+ </DropdownMenuItem>
142
+ ) : null}
143
+ </DropdownMenuContent>
144
+ </DropdownMenu>
145
+ </div>
146
+ )
147
+ }
116
148
  />
117
149
  )
118
150
  }
@@ -1,9 +1,8 @@
1
1
  "use client"
2
2
 
3
- import { useAutoPanel } from "@/components/secondary-panel"
3
+ import { SecondaryPanelHubActivator } from "@/components/templates/secondary-panel-hub-template"
4
4
 
5
- /** Opens the Question bank secondary panel while this route is mounted (same pattern as rotations). */
5
+ /** Opens the Question bank secondary panel while this route is mounted. */
6
6
  export function QuestionBankPanelActivator() {
7
- useAutoPanel("question-bank")
8
- return null
7
+ return <SecondaryPanelHubActivator panelId="question-bank" />
9
8
  }