@checkstack/announcement-frontend 0.3.4 → 0.3.6

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,69 @@
1
1
  # @checkstack/announcement-frontend
2
2
 
3
+ ## 0.3.6
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [e2d6f25]
8
+ - Updated dependencies [41c77f4]
9
+ - Updated dependencies [41c77f4]
10
+ - Updated dependencies [41c77f4]
11
+ - Updated dependencies [41c77f4]
12
+ - Updated dependencies [4832e33]
13
+ - Updated dependencies [6d52276]
14
+ - Updated dependencies [35bc682]
15
+ - Updated dependencies [c39ee69]
16
+ - @checkstack/frontend-api@0.6.0
17
+ - @checkstack/ui@1.11.0
18
+ - @checkstack/common@0.12.0
19
+ - @checkstack/auth-frontend@0.6.6
20
+ - @checkstack/tips-frontend@0.2.6
21
+ - @checkstack/announcement-common@0.4.2
22
+ - @checkstack/signal-frontend@0.1.5
23
+
24
+ ## 0.3.5
25
+
26
+ ### Patch Changes
27
+
28
+ - f23f3c9: Gate decorative motion and blur effects behind
29
+ `usePerformance().isLowPower` on a focused set of high-traffic plugin
30
+ pages (Dashboard, Dependency map, System node, Notification bell,
31
+ Announcement banner / cards, Anomaly field overrides editor, SLO
32
+ attribution chart, Catalog droppable group). Hover scales, backdrop
33
+ blurs, `animate-pulse`/`animate-ping` accents, and entry transitions
34
+ now drop to static states on low-power devices; functional UX
35
+ transitions (Drawer/Dialog open-close, colour transitions) are left
36
+ alone.
37
+
38
+ Standardise the post-mutation error-toast voice on plugin pages by
39
+ migrating multi-clause `toast.error(extractErrorMessage(error, "Failed
40
+ to X"))` call sites onto the `toastError(toast, "Failed to X", error)`
41
+ helper from `@checkstack/ui`. The helper applies the canonical
42
+ `"action: message"` prefix and 100-character truncation in one place,
43
+ and the now-orphaned `extractErrorMessage` imports are dropped from
44
+ the affected files. No business logic or component APIs changed.
45
+
46
+ - f23f3c9: Standardise the empty / loading / error story on key list pages using
47
+ the shared `ListEmptyState`, `QueryErrorState`, and `Skeleton`
48
+ primitives from `@checkstack/ui`. Each affected page now branches
49
+ through the same `isLoading -> isError -> empty -> data` ladder, so
50
+ failed queries surface a retry-able inline error instead of silently
51
+ rendering an empty table, and loading states match the final layout
52
+ rather than flashing a generic spinner. No layout, business logic, or
53
+ query input shapes changed.
54
+ - Updated dependencies [f23f3c9]
55
+ - Updated dependencies [f23f3c9]
56
+ - Updated dependencies [f23f3c9]
57
+ - Updated dependencies [f23f3c9]
58
+ - Updated dependencies [f23f3c9]
59
+ - @checkstack/common@0.11.0
60
+ - @checkstack/auth-frontend@0.6.5
61
+ - @checkstack/frontend-api@0.5.2
62
+ - @checkstack/ui@1.10.0
63
+ - @checkstack/announcement-common@0.4.1
64
+ - @checkstack/tips-frontend@0.2.5
65
+ - @checkstack/signal-frontend@0.1.4
66
+
3
67
  ## 0.3.4
4
68
 
5
69
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@checkstack/announcement-frontend",
3
- "version": "0.3.4",
3
+ "version": "0.3.6",
4
4
  "license": "Elastic-2.0",
5
5
  "type": "module",
6
6
  "main": "src/index.tsx",
@@ -13,13 +13,13 @@
13
13
  "lint:code": "eslint . --max-warnings 0"
14
14
  },
15
15
  "dependencies": {
16
- "@checkstack/announcement-common": "0.4.0",
17
- "@checkstack/auth-frontend": "0.6.3",
18
- "@checkstack/common": "0.10.0",
19
- "@checkstack/frontend-api": "0.5.1",
20
- "@checkstack/signal-frontend": "0.1.3",
21
- "@checkstack/tips-frontend": "0.2.3",
22
- "@checkstack/ui": "1.8.3",
16
+ "@checkstack/announcement-common": "0.4.1",
17
+ "@checkstack/auth-frontend": "0.6.5",
18
+ "@checkstack/common": "0.11.0",
19
+ "@checkstack/frontend-api": "0.5.2",
20
+ "@checkstack/signal-frontend": "0.1.4",
21
+ "@checkstack/tips-frontend": "0.2.5",
22
+ "@checkstack/ui": "1.10.0",
23
23
  "date-fns": "^4.1.0",
24
24
  "lucide-react": "^0.344.0",
25
25
  "react": "^18.2.0",
@@ -29,6 +29,6 @@
29
29
  "typescript": "^5.0.0",
30
30
  "@types/react": "^18.2.0",
31
31
  "@checkstack/tsconfig": "0.0.7",
32
- "@checkstack/scripts": "0.3.2"
32
+ "@checkstack/scripts": "0.3.3"
33
33
  }
34
34
  }
@@ -4,7 +4,7 @@ import {
4
4
  AnnouncementApi,
5
5
  type Announcement,
6
6
  } from "@checkstack/announcement-common";
7
- import { MarkdownBlock } from "@checkstack/ui";
7
+ import { MarkdownBlock, cn, usePerformance } from "@checkstack/ui";
8
8
  import {
9
9
  Info,
10
10
  AlertTriangle,
@@ -106,6 +106,7 @@ function BannerItem({
106
106
  announcement: Announcement;
107
107
  onDismiss: (id: string) => void;
108
108
  }) {
109
+ const { isLowPower } = usePerformance();
109
110
  const [expanded, setExpanded] = useState(false);
110
111
  const styles = getSeverityStyles(announcement.severity);
111
112
 
@@ -114,7 +115,12 @@ function BannerItem({
114
115
 
115
116
  return (
116
117
  <div
117
- className={`${styles.bg} ${styles.border} border-b px-4 py-2 transition-all duration-200`}
118
+ className={cn(
119
+ styles.bg,
120
+ styles.border,
121
+ "border-b px-4 py-2",
122
+ !isLowPower && "transition-all duration-200",
123
+ )}
118
124
  >
119
125
  <div className="flex items-center gap-3 max-w-7xl mx-auto">
120
126
  <SeverityIcon severity={announcement.severity} />
@@ -1,7 +1,7 @@
1
1
  import React, { useState } from "react";
2
2
  import { usePluginClient } from "@checkstack/frontend-api";
3
3
  import { AnnouncementApi, type Announcement } from "@checkstack/announcement-common";
4
- import { MarkdownBlock } from "@checkstack/ui";
4
+ import { MarkdownBlock, cn, usePerformance } from "@checkstack/ui";
5
5
  import {
6
6
  Info,
7
7
  AlertTriangle,
@@ -55,13 +55,18 @@ function getSeverityColor(severity: Announcement["severity"]): string {
55
55
  * A single compact announcement card with expand/collapse.
56
56
  */
57
57
  function AnnouncementCard({ announcement }: { announcement: Announcement }) {
58
+ const { isLowPower } = usePerformance();
58
59
  const [expanded, setExpanded] = useState(false);
59
60
  const severityColor = getSeverityColor(announcement.severity);
60
61
  const [borderClass, textClass] = severityColor.split(" ");
61
62
 
62
63
  return (
63
64
  <div
64
- className={`bg-card border border-border rounded-lg border-l-4 ${borderClass} transition-all duration-200`}
65
+ className={cn(
66
+ "bg-card border border-border rounded-lg border-l-4",
67
+ borderClass,
68
+ !isLowPower && "transition-all duration-200",
69
+ )}
65
70
  >
66
71
  <button
67
72
  type="button"
@@ -83,7 +88,12 @@ function AnnouncementCard({ announcement }: { announcement: Announcement }) {
83
88
  </button>
84
89
 
85
90
  {expanded && (
86
- <div className="px-4 pb-3 pl-11 animate-in slide-in-from-top-1 duration-200">
91
+ <div
92
+ className={cn(
93
+ "px-4 pb-3 pl-11",
94
+ !isLowPower && "animate-in slide-in-from-top-1 duration-200",
95
+ )}
96
+ >
87
97
  <div className="text-sm text-muted-foreground">
88
98
  <MarkdownBlock size="sm">{announcement.message}</MarkdownBlock>
89
99
  </div>
@@ -99,6 +109,7 @@ function AnnouncementCard({ announcement }: { announcement: Announcement }) {
99
109
  * Only shows when there are active dashboard-mode announcements.
100
110
  */
101
111
  export const DashboardAnnouncements: React.FC = () => {
112
+ const { isLowPower } = usePerformance();
102
113
  const announcementClient = usePluginClient(AnnouncementApi);
103
114
 
104
115
  // Always refetch on mount so the dashboard shows fresh data when navigated to.
@@ -121,7 +132,9 @@ export const DashboardAnnouncements: React.FC = () => {
121
132
  }
122
133
 
123
134
  return (
124
- <section className="animate-in fade-in duration-300">
135
+ <section
136
+ className={cn(!isLowPower && "animate-in fade-in duration-300")}
137
+ >
125
138
  <div className="flex items-center gap-2 mb-3">
126
139
  <Megaphone className="w-4 h-4 text-muted-foreground" />
127
140
  <h3 className="text-sm font-medium text-muted-foreground">
@@ -25,6 +25,7 @@ import {
25
25
  Badge,
26
26
  LoadingSpinner,
27
27
  EmptyState,
28
+ QueryErrorState,
28
29
  Table,
29
30
  TableHeader,
30
31
  TableRow,
@@ -47,6 +48,7 @@ import {
47
48
  Input,
48
49
  Label,
49
50
  Textarea,
51
+ toastError,
50
52
  } from "@checkstack/ui";
51
53
  import {
52
54
  Plus,
@@ -61,7 +63,6 @@ import {
61
63
  Columns,
62
64
  } from "lucide-react";
63
65
  import { formatDistanceToNow, format } from "date-fns";
64
- import { extractErrorMessage } from "@checkstack/common";
65
66
 
66
67
  // ---------------------------------------------------------------------------
67
68
  // Editor Dialog
@@ -136,7 +137,7 @@ const AnnouncementEditor: React.FC<AnnouncementEditorProps> = ({
136
137
  onSave();
137
138
  },
138
139
  onError: (error) => {
139
- toast.error(extractErrorMessage(error, "Failed to create"));
140
+ toastError(toast, "Failed to create announcement", error);
140
141
  },
141
142
  });
142
143
 
@@ -147,7 +148,7 @@ const AnnouncementEditor: React.FC<AnnouncementEditorProps> = ({
147
148
  onSave();
148
149
  },
149
150
  onError: (error) => {
150
- toast.error(extractErrorMessage(error, "Failed to update"));
151
+ toastError(toast, "Failed to update announcement", error);
151
152
  },
152
153
  });
153
154
 
@@ -457,11 +458,8 @@ const AnnouncementManageContent: React.FC = () => {
457
458
  >();
458
459
  const [deleteId, setDeleteId] = useState<string | undefined>();
459
460
 
460
- const {
461
- data: announcementsData,
462
- isLoading,
463
- refetch,
464
- } = announcementClient.listAllAnnouncements.useQuery();
461
+ const announcementsQuery = announcementClient.listAllAnnouncements.useQuery();
462
+ const { data: announcementsData, isLoading, refetch } = announcementsQuery;
465
463
 
466
464
  const deleteMutation = announcementClient.deleteAnnouncement.useMutation({
467
465
  onSuccess: () => {
@@ -470,7 +468,7 @@ const AnnouncementManageContent: React.FC = () => {
470
468
  setDeleteId(undefined);
471
469
  },
472
470
  onError: (error) => {
473
- toast.error(extractErrorMessage(error, "Failed to delete"));
471
+ toastError(toast, "Failed to delete announcement", error);
474
472
  },
475
473
  });
476
474
 
@@ -530,6 +528,14 @@ const AnnouncementManageContent: React.FC = () => {
530
528
  <div className="p-12 flex justify-center">
531
529
  <LoadingSpinner />
532
530
  </div>
531
+ ) : announcementsQuery.isError ? (
532
+ <div className="p-4">
533
+ <QueryErrorState
534
+ error={announcementsQuery.error}
535
+ onRetry={() => void announcementsQuery.refetch()}
536
+ resource="announcements"
537
+ />
538
+ </div>
533
539
  ) : announcements.length === 0 ? (
534
540
  <EmptyState
535
541
  icon={<Megaphone className="size-10" />}