@checkstack/notification-frontend 0.3.1 → 0.4.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,102 @@
1
1
  # @checkstack/notification-frontend
2
2
 
3
+ ## 0.4.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [9016526]
8
+ - @checkstack/common@0.10.0
9
+ - @checkstack/notification-common@1.1.0
10
+ - @checkstack/auth-frontend@0.6.1
11
+ - @checkstack/frontend-api@0.5.1
12
+ - @checkstack/tips-frontend@0.2.1
13
+ - @checkstack/ui@1.8.1
14
+ - @checkstack/signal-frontend@0.1.3
15
+
16
+ ## 0.4.0
17
+
18
+ ### Minor Changes
19
+
20
+ - 3547670: Wire the new tips infrastructure across the frontends:
21
+
22
+ **Empty-state coaching.** Replace generic "no items" copy with onboarding
23
+ guidance — short description, three numbered steps and a primary CTA — on
24
+ every EmptyState that has a meaningful next action. Affects: catalog
25
+ (systems + groups), dashboard, health-check page, integrations (subscriptions
26
+
27
+ - provider connections), GitOps providers + secrets, GitOps provenance,
28
+ SLO config + overview, maintenance config, satellites, plugin manager,
29
+ incident config, announcements. Read-only EmptyStates (incident history,
30
+ maintenance history, plugin events) get clearer descriptions explaining
31
+ what would populate them.
32
+
33
+ **First-run anchored tips.** Add `<Tip>` popovers to the most important
34
+ "Create" affordances so first-time users see a one-line explanation of
35
+ what they're about to make and why it matters: catalog “Add System” /
36
+ “Add Group”, healthcheck “Create Check”, integrations “New Subscription”,
37
+ GitOps “Add Provider”, SLO “Create SLO”, maintenance “Create Maintenance”,
38
+ satellite “Create Satellite”, plugin-manager “Install plugin”, incident
39
+ “Report Incident”, announcement “New Announcement”. Each tip is dismissed
40
+ per user (server-backed when signed in, localStorage otherwise) and
41
+ namespaced through `qualifyTipId(plugin, …)` so it cannot escape the
42
+ plugin's own namespace.
43
+
44
+ **Welcome banner on the dashboard.** A `<TipBanner>` at the top of the
45
+ dashboard introduces Checkstack's main flow ("add a system, then a health
46
+ check") with a one-click jump into the catalog.
47
+
48
+ ### Patch Changes
49
+
50
+ - 3547670: Add a `<Tip>` next to the title in the notification-subscriptions modal
51
+ that explains the two things that confuse first-time users: (1) the
52
+ difference between subscribing to an individual system vs. subscribing
53
+ to a whole group (groups auto-include systems added later), and (2) the
54
+ difference between "Subscribe to all" and toggling specific rows for
55
+ just the event types they care about. Tip id:
56
+ `notification.subscriptions.intro`.
57
+ - 950d6ec: Fix mobile UserMenu items rendering at zero height, group menu items by
58
+ section, and unstack cramped card headers on small viewports.
59
+
60
+ - **UserMenu mobile bug**: On mobile, the user-menu Sheet rendered every
61
+ menu item as a grid row, which combined with `flex-shrink: 1` on each
62
+ item collapsed the buttons whose internal layout uses `display: flex`
63
+ (the items registered with `useNavigate` rather than `<Link>`) to zero
64
+ content height. Switched the mobile container to a flex column with
65
+ `[&>*]:shrink-0` and added `min-h-0` so the sheet scrolls correctly
66
+ when the list overflows.
67
+
68
+ - **UserMenu grouping**: Slot extensions now accept an optional `group`
69
+ field. The user menu buckets `UserMenuItemsSlot` extensions by `group`
70
+ and renders each group under a labeled header (`Workspace`,
71
+ `Reliability`, `Configuration`, `Documentation`, `Account`). Existing
72
+ core plugins are tagged with the appropriate group; third-party plugins
73
+ can pick any of these or supply their own label. Untagged extensions
74
+ render last with no header. `UserMenuItemsBottomSlot` is unaffected.
75
+
76
+ - **Card header responsiveness**: `CardHeaderRow` (the primitive shared by
77
+ Incident, Maintenance, Auth, Catalog, GitOps and other config cards) now
78
+ stacks vertically on narrow viewports and only switches to a single row
79
+ at the `sm` breakpoint, so titles and adjacent filter controls (e.g.
80
+ status `Select`, "Show resolved" checkbox) no longer cram together on
81
+ mobile. Refactored the Incident and Maintenance config pages to use the
82
+ primitive instead of a hand-rolled `flex items-center justify-between`
83
+ row, and made their `Select` triggers full-width on mobile.
84
+
85
+ - Updated dependencies [42abfff]
86
+ - Updated dependencies [3547670]
87
+ - Updated dependencies [1ef2e79]
88
+ - Updated dependencies [aa89bc5]
89
+ - Updated dependencies [3547670]
90
+ - Updated dependencies [950d6ec]
91
+ - Updated dependencies [3547670]
92
+ - @checkstack/common@0.9.0
93
+ - @checkstack/ui@1.8.0
94
+ - @checkstack/frontend-api@0.5.0
95
+ - @checkstack/tips-frontend@0.2.0
96
+ - @checkstack/auth-frontend@0.6.0
97
+ - @checkstack/notification-common@1.0.2
98
+ - @checkstack/signal-frontend@0.1.2
99
+
3
100
  ## 0.3.1
4
101
 
5
102
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@checkstack/notification-frontend",
3
- "version": "0.3.1",
3
+ "version": "0.4.1",
4
4
  "license": "Elastic-2.0",
5
5
  "type": "module",
6
6
  "main": "src/index.tsx",
@@ -13,20 +13,21 @@
13
13
  "lint:code": "eslint . --max-warnings 0"
14
14
  },
15
15
  "dependencies": {
16
- "@checkstack/notification-common": "1.0.0",
17
- "@checkstack/frontend-api": "0.4.1",
18
- "@checkstack/auth-frontend": "0.5.32",
19
- "@checkstack/signal-frontend": "0.1.0",
20
- "@checkstack/common": "0.7.0",
21
- "@checkstack/ui": "1.7.0",
16
+ "@checkstack/auth-frontend": "0.6.0",
17
+ "@checkstack/common": "0.9.0",
18
+ "@checkstack/frontend-api": "0.5.0",
19
+ "@checkstack/notification-common": "1.0.2",
20
+ "@checkstack/signal-frontend": "0.1.2",
21
+ "@checkstack/tips-frontend": "0.2.0",
22
+ "@checkstack/ui": "1.8.0",
23
+ "lucide-react": "^0.344.0",
22
24
  "react": "^18.2.0",
23
- "react-router-dom": "^6.22.0",
24
- "lucide-react": "^0.344.0"
25
+ "react-router-dom": "^6.22.0"
25
26
  },
26
27
  "devDependencies": {
27
28
  "typescript": "^5.0.0",
28
29
  "@types/react": "^18.2.0",
29
- "@checkstack/tsconfig": "0.0.6",
30
- "@checkstack/scripts": "0.1.2"
30
+ "@checkstack/tsconfig": "0.0.7",
31
+ "@checkstack/scripts": "0.3.1"
31
32
  }
32
33
  }
@@ -15,9 +15,11 @@ import { usePluginClient } from "@checkstack/frontend-api";
15
15
  import {
16
16
  NotificationApi,
17
17
  subscriptionGroupId,
18
+ pluginMetadata as notificationPluginMetadata,
18
19
  type NotificationTarget,
19
20
  } from "@checkstack/notification-common";
20
21
  import { extractErrorMessage } from "@checkstack/common";
22
+ import { Tip } from "@checkstack/tips-frontend";
21
23
  import { SubscriptionRow } from "./SubscriptionRow";
22
24
 
23
25
  export interface NotificationSubscriptionsManagerProps<TResource> {
@@ -111,14 +113,10 @@ export function NotificationSubscriptionsManager<TResource>({
111
113
  .filter((id) => statusMap[id])
112
114
  .map((groupId) => unsubscribeMutation.mutateAsync({ groupId })),
113
115
  );
114
- toast.success(
115
- `Unsubscribed from all notifications for ${resourceLabel}`,
116
- );
116
+ toast.success(`Unsubscribed from all notifications for ${resourceLabel}`);
117
117
  void refetchStatus();
118
118
  } catch (error) {
119
- toast.error(
120
- extractErrorMessage(error, "Failed to unsubscribe from all"),
121
- );
119
+ toast.error(extractErrorMessage(error, "Failed to unsubscribe from all"));
122
120
  }
123
121
  };
124
122
 
@@ -148,25 +146,58 @@ export function NotificationSubscriptionsManager<TResource>({
148
146
  <DialogContent size="lg">
149
147
  <DialogHeader>
150
148
  <DialogTitle className="flex items-center gap-2">
151
- <Bell className="h-4 w-4" />
149
+ <Bell className="w-4 h-4" />
152
150
  Notifications for {resourceLabel}
151
+ <Tip
152
+ plugin={notificationPluginMetadata}
153
+ id="subscriptions.intro"
154
+ title="How notification subscriptions work"
155
+ description={
156
+ <div className="space-y-2">
157
+ <p>
158
+ <strong>System vs. group.</strong> Subscribing to a system
159
+ means you'll only hear about that one thing. Subscribing
160
+ to a group means you'll hear about every system inside
161
+ that group — useful if a teammate adds new systems later,
162
+ since the group covers them automatically.
163
+ </p>
164
+ <p>
165
+ <strong>All vs. specific types.</strong> Each row below is
166
+ a different kind of event (incidents, anomalies, …). Use
167
+ “Subscribe to all” at the top to opt in to everything, or
168
+ toggle rows individually if you only care about, say,
169
+ critical incidents.
170
+ </p>
171
+ <p>
172
+ Where things actually reach you (Slack, email, Telegram,
173
+ …) is configured once in <em>Notification Settings</em>{" "}
174
+ and applies to every subscription.
175
+ </p>
176
+ </div>
177
+ }
178
+ side="bottom"
179
+ align="start"
180
+ contentClassName="w-96"
181
+ >
182
+ <span className="sr-only">Subscription help</span>
183
+ </Tip>
153
184
  </DialogTitle>
154
185
  <DialogDescription>
155
- Choose which notification types you want to receive for
156
- this {target.resourceKind}.
186
+ Choose which notification types you want to receive for this{" "}
187
+ {target.resourceKind}.
157
188
  </DialogDescription>
158
189
  </DialogHeader>
159
190
 
160
191
  <div className="space-y-3">
161
192
  {totalCount === 0 ? (
162
- <div className="rounded-md border border-border bg-muted/20 p-4 text-sm text-muted-foreground">
193
+ <div className="p-4 text-sm border rounded-md border-border bg-muted/20 text-muted-foreground">
163
194
  No notification types are available for this{" "}
164
195
  {target.resourceKind} yet.
165
196
  </div>
166
197
  ) : (
167
198
  <>
168
- <div className="flex items-center justify-between gap-3 rounded-md border border-border bg-muted/20 p-3">
169
- <div className="text-sm min-w-0">
199
+ <div className="flex items-center justify-between gap-3 p-3 border rounded-md border-border bg-muted/20">
200
+ <div className="min-w-0 text-sm">
170
201
  <div className="font-medium">
171
202
  {subscribedCount} of {totalCount} subscribed
172
203
  </div>
@@ -183,7 +214,7 @@ export function NotificationSubscriptionsManager<TResource>({
183
214
  disabled={isPending}
184
215
  onClick={handleUnsubscribeAll}
185
216
  >
186
- <BellOff className="mr-1 h-3 w-3" />
217
+ <BellOff className="w-3 h-3 mr-1" />
187
218
  Unsubscribe from all
188
219
  </Button>
189
220
  ) : (
@@ -194,13 +225,13 @@ export function NotificationSubscriptionsManager<TResource>({
194
225
  disabled={isPending}
195
226
  onClick={handleSubscribeAll}
196
227
  >
197
- <BellRing className="mr-1 h-3 w-3" />
228
+ <BellRing className="w-3 h-3 mr-1" />
198
229
  Subscribe to all
199
230
  </Button>
200
231
  )}
201
232
  </div>
202
233
  </div>
203
- <div className="overflow-hidden rounded-md border border-border">
234
+ <div className="overflow-hidden border rounded-md border-border">
204
235
  {specs.map((spec) => {
205
236
  const groupId = subscriptionGroupId(spec, resourceKey);
206
237
  return (
package/src/index.tsx CHANGED
@@ -57,6 +57,7 @@ export const notificationPlugin = createFrontendPlugin({
57
57
  createSlotExtension(UserMenuItemsSlot, {
58
58
  id: "notification.user.setting",
59
59
  component: NotificationUserMenuItems,
60
+ metadata: { group: "Configuration" },
60
61
  }),
61
62
  ],
62
63
  });
@@ -17,7 +17,9 @@ import type { EnrichedSubscription } from "@checkstack/notification-common";
17
17
  import {
18
18
  NotificationApi,
19
19
  notificationAccess,
20
+ pluginMetadata as notificationPluginMetadata,
20
21
  } from "@checkstack/notification-common";
22
+ import { TipBanner } from "@checkstack/tips-frontend";
21
23
  import {
22
24
  StrategyCard,
23
25
  type DeliveryStrategy,
@@ -246,6 +248,13 @@ export const NotificationSettingsPage = () => {
246
248
  return (
247
249
  <PageLayout title="Notification Settings" icon={Bell} loading={subsLoading}>
248
250
  <div className="space-y-8">
251
+ <TipBanner
252
+ plugin={notificationPluginMetadata}
253
+ id="settings.intro"
254
+ title="Two pieces fit together: channels and subscriptions"
255
+ description="A channel is how you'd like to be reached (Slack DM, email, Telegram, etc.). A subscription is what you want to be reached about (a system group, a specific incident severity). Connect at least one channel here, then subscribe from the dashboard or the system detail pages."
256
+ />
257
+
249
258
  {/* Your Notification Channels - All users */}
250
259
  <section>
251
260
  <SectionHeader
package/tsconfig.json CHANGED
@@ -19,6 +19,9 @@
19
19
  {
20
20
  "path": "../signal-frontend"
21
21
  },
22
+ {
23
+ "path": "../tips-frontend"
24
+ },
22
25
  {
23
26
  "path": "../ui"
24
27
  }