@equinor/cpl-top-bar-react 0.2.5 → 0.3.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/dist/index.d.mts CHANGED
@@ -1,16 +1,40 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as styled_components_dist_types from 'styled-components/dist/types';
3
+ import * as styled_components from 'styled-components';
4
+ import * as react from 'react';
5
+
6
+ interface FeedbackLinkProps {
7
+ link: string;
8
+ subject: string;
9
+ body: string;
10
+ }
11
+ /**
12
+ * `FeedbackLink`
13
+ * component renders a link that opens the user's email client
14
+ * with pre-filled subject and body for feedback. The email link should be the link to a Teams channel.
15
+ */
16
+ declare function FeedbackLink({ link, subject, body }: FeedbackLinkProps): react_jsx_runtime.JSX.Element;
2
17
 
3
18
  interface TopBarProps {
4
19
  appName: string;
5
20
  logoLink: string;
6
- documentationLink: string;
21
+ sideMenuOpen?: boolean;
22
+ setSideMenuOpen?: (open: boolean) => void;
23
+ documentationLink?: string;
7
24
  documentationName?: string;
25
+ feedbackLink?: React.ReactNode;
8
26
  userMenu?: React.ReactNode;
9
- darkMode?: boolean;
10
27
  logoPath?: string;
11
28
  logoAlt?: string;
12
29
  }
13
- declare function TopBar({ appName, logoLink, documentationLink, documentationName, userMenu, darkMode, logoPath, logoAlt, }: TopBarProps): react_jsx_runtime.JSX.Element;
30
+ /**
31
+ * `Dark mode usage`
32
+ *
33
+ * To use the Topbar component in dark mode, you need to wrap it in the `ThemeProvider` from `@equinor/cpl-theme-react`
34
+ * and set the theme to 'dark'.
35
+ */
36
+ declare function TopBar({ appName, logoLink, sideMenuOpen, setSideMenuOpen, feedbackLink, documentationLink, documentationName, userMenu, logoPath, logoAlt, }: TopBarProps): react_jsx_runtime.JSX.Element;
37
+ declare const StyledLink: styled_components_dist_types.IStyledComponentBase<"web", styled_components.FastOmit<react.DetailedHTMLProps<react.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, never>> & string;
14
38
 
15
39
  interface UserMenuProps {
16
40
  logout: string | (() => void);
@@ -18,10 +42,9 @@ interface UserMenuProps {
18
42
  name: string;
19
43
  email: string;
20
44
  };
21
- darkMode?: boolean;
22
45
  settingsLink?: string;
23
46
  children?: React.ReactNode;
24
47
  }
25
- declare function UserMenu({ user, logout, darkMode, settingsLink, children, }: UserMenuProps): react_jsx_runtime.JSX.Element;
48
+ declare function UserMenu({ user, logout, settingsLink, children }: UserMenuProps): react_jsx_runtime.JSX.Element;
26
49
 
27
- export { TopBar, UserMenu };
50
+ export { FeedbackLink, StyledLink, TopBar, UserMenu };
package/dist/index.d.ts CHANGED
@@ -1,16 +1,40 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as styled_components_dist_types from 'styled-components/dist/types';
3
+ import * as styled_components from 'styled-components';
4
+ import * as react from 'react';
5
+
6
+ interface FeedbackLinkProps {
7
+ link: string;
8
+ subject: string;
9
+ body: string;
10
+ }
11
+ /**
12
+ * `FeedbackLink`
13
+ * component renders a link that opens the user's email client
14
+ * with pre-filled subject and body for feedback. The email link should be the link to a Teams channel.
15
+ */
16
+ declare function FeedbackLink({ link, subject, body }: FeedbackLinkProps): react_jsx_runtime.JSX.Element;
2
17
 
3
18
  interface TopBarProps {
4
19
  appName: string;
5
20
  logoLink: string;
6
- documentationLink: string;
21
+ sideMenuOpen?: boolean;
22
+ setSideMenuOpen?: (open: boolean) => void;
23
+ documentationLink?: string;
7
24
  documentationName?: string;
25
+ feedbackLink?: React.ReactNode;
8
26
  userMenu?: React.ReactNode;
9
- darkMode?: boolean;
10
27
  logoPath?: string;
11
28
  logoAlt?: string;
12
29
  }
13
- declare function TopBar({ appName, logoLink, documentationLink, documentationName, userMenu, darkMode, logoPath, logoAlt, }: TopBarProps): react_jsx_runtime.JSX.Element;
30
+ /**
31
+ * `Dark mode usage`
32
+ *
33
+ * To use the Topbar component in dark mode, you need to wrap it in the `ThemeProvider` from `@equinor/cpl-theme-react`
34
+ * and set the theme to 'dark'.
35
+ */
36
+ declare function TopBar({ appName, logoLink, sideMenuOpen, setSideMenuOpen, feedbackLink, documentationLink, documentationName, userMenu, logoPath, logoAlt, }: TopBarProps): react_jsx_runtime.JSX.Element;
37
+ declare const StyledLink: styled_components_dist_types.IStyledComponentBase<"web", styled_components.FastOmit<react.DetailedHTMLProps<react.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, never>> & string;
14
38
 
15
39
  interface UserMenuProps {
16
40
  logout: string | (() => void);
@@ -18,10 +42,9 @@ interface UserMenuProps {
18
42
  name: string;
19
43
  email: string;
20
44
  };
21
- darkMode?: boolean;
22
45
  settingsLink?: string;
23
46
  children?: React.ReactNode;
24
47
  }
25
- declare function UserMenu({ user, logout, darkMode, settingsLink, children, }: UserMenuProps): react_jsx_runtime.JSX.Element;
48
+ declare function UserMenu({ user, logout, settingsLink, children }: UserMenuProps): react_jsx_runtime.JSX.Element;
26
49
 
27
- export { TopBar, UserMenu };
50
+ export { FeedbackLink, StyledLink, TopBar, UserMenu };
package/dist/index.js CHANGED
@@ -30,39 +30,60 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ FeedbackLink: () => FeedbackLink,
34
+ StyledLink: () => StyledLink,
33
35
  TopBar: () => TopBar,
34
36
  UserMenu: () => UserMenu
35
37
  });
36
38
  module.exports = __toCommonJS(index_exports);
37
39
 
40
+ // src/FeedbackLink/FeedbackLink.tsx
41
+ var import_eds_core_react2 = require("@equinor/eds-core-react");
42
+ var import_eds_icons2 = require("@equinor/eds-icons");
43
+
38
44
  // src/TopBar/TopBar.tsx
39
45
  var import_eds_core_react = require("@equinor/eds-core-react");
40
46
  var import_eds_icons = require("@equinor/eds-icons");
41
- var import_styled_components = __toESM(require("styled-components"));
42
47
  var import_eds_tokens = require("@equinor/eds-tokens");
48
+ var import_styled_components = __toESM(require("styled-components"));
43
49
  var import_jsx_runtime = require("react/jsx-runtime");
44
50
  function TopBar({
45
51
  appName,
46
52
  logoLink,
53
+ sideMenuOpen,
54
+ setSideMenuOpen,
55
+ feedbackLink,
47
56
  documentationLink,
48
57
  documentationName = "Documentation",
49
58
  userMenu,
50
- darkMode = false,
51
59
  logoPath = ".",
52
60
  logoAlt = "logo"
53
61
  }) {
54
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(StyledEDSTopBar, { $darkMode: darkMode, children: [
55
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_eds_core_react.TopBar.Header, { style: { padding: 0 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AppNameContainer, { children: [
56
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: logoPath, alt: logoAlt, height: 24, width: 22 }) }),
57
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: logoLink, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StyledTypography, { $darkMode: darkMode, children: appName }) })
58
- ] }) }),
59
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_eds_core_react.TopBar.Actions, { children: [
60
- documentationLink && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(DocumentationDiv, { $darkMode: darkMode, children: [
61
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: documentationLink, children: documentationName }),
62
+ const hasSideMenu = setSideMenuOpen && sideMenuOpen !== void 0;
63
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(StyledEDSTopBar, { children: [
64
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_eds_core_react.TopBar.Header, { style: { padding: 0 }, children: [
65
+ hasSideMenu && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
66
+ ThemedButton,
67
+ {
68
+ variant: "ghost_icon",
69
+ "aria-label": "menu action",
70
+ onClick: () => setSideMenuOpen(!sideMenuOpen),
71
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_eds_core_react.Icon, { data: import_eds_icons.menu, size: 24 })
72
+ }
73
+ ),
74
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(AppNameContainer, { children: [
75
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: logoPath, alt: logoAlt, height: 24, width: 22 }) }),
76
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: logoLink, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StyledTypography, { children: appName }) })
77
+ ] })
78
+ ] }),
79
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_eds_core_react.TopBar.Actions, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(LinkContainer, { children: [
80
+ feedbackLink && feedbackLink,
81
+ documentationLink && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(StyledLink, { href: documentationLink, children: [
82
+ documentationName,
62
83
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_eds_core_react.Icon, { data: import_eds_icons.external_link, size: 16 })
63
84
  ] }),
64
85
  userMenu
65
- ] })
86
+ ] }) })
66
87
  ] });
67
88
  }
68
89
  var StyledEDSTopBar = (0, import_styled_components.default)(import_eds_core_react.TopBar)`
@@ -70,10 +91,8 @@ var StyledEDSTopBar = (0, import_styled_components.default)(import_eds_core_reac
70
91
  gap: 0;
71
92
  padding: 0px 20px;
72
93
  margin: 0px;
73
- ${({ $darkMode }) => $darkMode ? import_styled_components.css`
74
- background: ${import_eds_tokens.tokens.colors.interactive.table__cell__fill_resting.hex};
75
- color: #fff;
76
- ` : ""}
94
+ background: var(--background-default, rgba(255, 255, 255, 1));
95
+ color: var(--color-text);
77
96
  `;
78
97
  var AppNameContainer = import_styled_components.default.div`
79
98
  display: flex;
@@ -81,42 +100,64 @@ var AppNameContainer = import_styled_components.default.div`
81
100
  align-items: center;
82
101
  `;
83
102
  var StyledTypography = (0, import_styled_components.default)(import_eds_core_react.Typography)`
84
- font-weight: 300;
85
- ${({ $darkMode }) => $darkMode ? import_styled_components.css`
86
- color: #fff;
87
- ` : ""}
103
+ color: var(--color-text);
104
+ `;
105
+ var LinkContainer = import_styled_components.default.div`
106
+ display: flex;
107
+ align-items: center;
108
+ gap: ${import_eds_tokens.tokens.spacings.comfortable.large};
88
109
  `;
89
- var DocumentationDiv = import_styled_components.default.div`
110
+ var StyledLink = import_styled_components.default.a`
90
111
  text-decoration: none;
91
112
  display: flex;
113
+ align-items: center;
92
114
  gap: 0.3rem;
93
- font-weight: 300;
94
- a {
95
- text-decoration: none;
96
- color: inherit;
115
+
116
+ text-decoration: none;
117
+ color: var(--color-text);
118
+ `;
119
+ var ThemedButton = (0, import_styled_components.default)(import_eds_core_react.Button)`
120
+ background-color: transparent;
121
+ color: var(--interactive-focus-border, ${import_eds_tokens.tokens.colors.interactive.primary__resting.hex});
122
+
123
+ &:focus-visible {
124
+ outline-color: var(--interactive-focus-border, ${import_eds_tokens.tokens.colors.interactive.focus.hex});
125
+ }
126
+
127
+ &:hover {
128
+ background-color: var(
129
+ --interactive-primary-hover-alt,
130
+ ${import_eds_tokens.tokens.colors.interactive.primary__hover_alt.hex}
131
+ );
132
+ color: var(--interactive-secondary-hover, ${import_eds_tokens.tokens.colors.interactive.primary__resting.hex});
97
133
  }
98
- ${({ $darkMode }) => $darkMode ? import_styled_components.css`
99
- color: ${import_eds_tokens.tokens.colors.interactive.table__cell__fill_resting.hex};
100
- a {
101
- color: #fff;
102
- }
103
- ` : ""}
104
134
  `;
105
135
 
136
+ // src/FeedbackLink/FeedbackLink.tsx
137
+ var import_jsx_runtime2 = require("react/jsx-runtime");
138
+ function FeedbackLink({ link, subject, body }) {
139
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
140
+ StyledLink,
141
+ {
142
+ href: `mailto:${link}?subject=${subject}&body=${body}`,
143
+ target: "_blank",
144
+ rel: "noreferrer",
145
+ children: [
146
+ "Feedback",
147
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_eds_core_react2.Icon, { data: import_eds_icons2.email, size: 16 })
148
+ ]
149
+ }
150
+ );
151
+ }
152
+
106
153
  // src/UserMenu/UserMenu.tsx
107
- var import_eds_core_react2 = require("@equinor/eds-core-react");
108
- var import_eds_icons2 = require("@equinor/eds-icons");
154
+ var import_eds_core_react3 = require("@equinor/eds-core-react");
155
+ var import_eds_icons3 = require("@equinor/eds-icons");
109
156
  var import_eds_tokens2 = require("@equinor/eds-tokens");
110
157
  var import_react = require("react");
111
158
  var import_styled_components2 = __toESM(require("styled-components"));
112
- var import_jsx_runtime2 = require("react/jsx-runtime");
113
- function UserMenu({
114
- user,
115
- logout,
116
- darkMode = false,
117
- settingsLink,
118
- children
119
- }) {
159
+ var import_jsx_runtime3 = require("react/jsx-runtime");
160
+ function UserMenu({ user, logout, settingsLink, children }) {
120
161
  var _a, _b, _c, _d, _e;
121
162
  const [isOpen, setIsOpen] = (0, import_react.useState)(false);
122
163
  const [anchorEl, setAnchorEl] = (0, import_react.useState)(null);
@@ -128,20 +169,20 @@ function UserMenu({
128
169
  };
129
170
  const LogOutMenuItem = () => {
130
171
  if (typeof logout === "string") {
131
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_eds_core_react2.Menu.Item, { as: "a", href: logout, className: "menu-item", id: "logout-button", children: [
132
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_eds_core_react2.Icon, { data: import_eds_icons2.log_out }),
133
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "Log out" })
172
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_eds_core_react3.Menu.Item, { as: "a", href: logout, className: "menu-item", id: "logout-button", children: [
173
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_eds_core_react3.Icon, { data: import_eds_icons3.log_out }),
174
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "Log out" })
134
175
  ] });
135
176
  } else {
136
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_eds_core_react2.Menu.Item, { as: "button", onClick: logout, className: "menu-item", id: "logout-button", children: [
137
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_eds_core_react2.Icon, { data: import_eds_icons2.log_out }),
138
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "Log out" })
177
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_eds_core_react3.Menu.Item, { as: "button", onClick: logout, className: "menu-item", id: "logout-button", children: [
178
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_eds_core_react3.Icon, { data: import_eds_icons3.log_out }),
179
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "Log out" })
139
180
  ] });
140
181
  }
141
182
  };
142
183
  const firstLetter = (_c = (_b = (_a = user == null ? void 0 : user.email) == null ? void 0 : _a[0]) == null ? void 0 : _b.toUpperCase()) != null ? _c : "-";
143
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
144
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
184
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
185
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
145
186
  StyledUserButton,
146
187
  {
147
188
  id: "user-button",
@@ -151,14 +192,12 @@ function UserMenu({
151
192
  "aria-expanded": isOpen,
152
193
  "aria-controls": "user-menu",
153
194
  onClick: () => isOpen ? closeMenu() : openMenu(),
154
- $darkMode: darkMode,
155
195
  children: firstLetter
156
196
  }
157
197
  ),
158
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
198
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
159
199
  MenuWrapper,
160
200
  {
161
- $darkMode: darkMode,
162
201
  id: "user-menu",
163
202
  "aria-labelledby": "user-button",
164
203
  open: isOpen,
@@ -166,16 +205,16 @@ function UserMenu({
166
205
  anchorEl,
167
206
  style: { padding: 0, paddingBottom: 2 },
168
207
  children: [
169
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(IconAndTextWrapper, { $darkMode: darkMode, children: [
170
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(LetterCircle, { $darkMode: darkMode, children: firstLetter }),
171
- isOpen && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
172
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { fontWeight: "bold", lineHeight: 0.9, marginBottom: 2 }, children: (_d = user == null ? void 0 : user.name) != null ? _d : "-" }),
173
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { children: (_e = user == null ? void 0 : user.email) != null ? _e : "-" })
208
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(IconAndTextWrapper, { children: [
209
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(LetterCircle, { children: firstLetter }),
210
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
211
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { fontWeight: "bold", lineHeight: 0.9, marginBottom: 2 }, children: (_d = user == null ? void 0 : user.name) != null ? _d : "-" }),
212
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: (_e = user == null ? void 0 : user.email) != null ? _e : "-" })
174
213
  ] })
175
214
  ] }),
176
- settingsLink && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_eds_core_react2.Menu.Item, { as: "a", href: settingsLink, className: "menu-item", children: [
177
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_eds_core_react2.Icon, { data: import_eds_icons2.settings }),
178
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "Settings" })
215
+ settingsLink && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_eds_core_react3.Menu.Item, { as: "a", href: settingsLink, className: "menu-item", children: [
216
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_eds_core_react3.Icon, { data: import_eds_icons3.settings }),
217
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "Settings" })
179
218
  ] }),
180
219
  LogOutMenuItem(),
181
220
  children
@@ -184,7 +223,7 @@ function UserMenu({
184
223
  )
185
224
  ] });
186
225
  }
187
- var MenuWrapper = (0, import_styled_components2.default)(import_eds_core_react2.Menu)`
226
+ var MenuWrapper = (0, import_styled_components2.default)(import_eds_core_react3.Menu)`
188
227
  border-radius: ${import_eds_tokens2.tokens.shape.corners.borderRadius};
189
228
  margin-top: ${import_eds_tokens2.tokens.spacings.comfortable.small};
190
229
  margin-bottom: -${import_eds_tokens2.tokens.spacings.comfortable.small};
@@ -194,32 +233,28 @@ var MenuWrapper = (0, import_styled_components2.default)(import_eds_core_react2.
194
233
  padding-top: ${import_eds_tokens2.tokens.spacings.comfortable.small};
195
234
  width: 315px;
196
235
 
236
+ background: var(--ui-background-temporary-nav, #fff);
237
+ color: var(--color-text);
238
+
197
239
  .menu-item {
198
240
  align-items: center;
199
241
  display: flex;
200
242
  gap: ${import_eds_tokens2.tokens.spacings.comfortable.medium};
201
243
  opacity: 0.85;
202
244
  padding: ${import_eds_tokens2.tokens.spacings.comfortable.small} ${import_eds_tokens2.tokens.spacings.comfortable.large};
245
+
246
+ color: var(--color-text);
203
247
  svg {
204
248
  opacity: 0.7;
205
249
  }
206
250
  &:hover {
207
251
  opacity: 1;
252
+ background: var(--menu-item-hover-color);
208
253
  svg {
209
254
  opacity: 1;
210
255
  }
211
256
  }
212
257
  }
213
- ${({ $darkMode }) => $darkMode ? import_styled_components2.css`
214
- background: #3e4f5c; //TODO: get color from token in the future
215
- color: #fff;
216
- .menu-item {
217
- color: #fff;
218
- &:hover {
219
- background: #305c75;
220
- }
221
- }
222
- ` : ``}
223
258
  `;
224
259
  var LetterCircle = import_styled_components2.default.span`
225
260
  align-items: center;
@@ -230,28 +265,25 @@ var LetterCircle = import_styled_components2.default.span`
230
265
  height: 32px;
231
266
  justify-content: center;
232
267
  width: 32px;
233
- background-color: ${import_eds_tokens2.tokens.colors.interactive.primary__resting.hex};
234
- color: #fff;
235
- ${({ $darkMode }) => $darkMode ? import_styled_components2.css`
236
- background: ${import_eds_tokens2.tokens.colors.interactive.link_in_snackbars.hex};
237
- color: ${import_eds_tokens2.tokens.colors.interactive.table__cell__fill_resting.hex};
238
- ` : ``};
268
+ background-color: var(
269
+ --interactive-focus-border,
270
+ ${import_eds_tokens2.tokens.colors.interactive.primary__resting.hex}
271
+ );
272
+ color: var(--color-text-inverse, #fff);
239
273
  `;
240
- var StyledUserButton = (0, import_styled_components2.default)(import_eds_core_react2.Button)`
274
+ var StyledUserButton = (0, import_styled_components2.default)(import_eds_core_react3.Button)`
241
275
  margin-left: 12px;
242
276
  font-weight: bold;
243
277
  width: 32px;
244
278
  height: 32px;
279
+ background: var(--interactive-focus-border, ${import_eds_tokens2.tokens.colors.interactive.primary__resting.hex});
280
+ color: var(--color-text-inverse, #fff);
245
281
 
246
- ${({ $darkMode }) => $darkMode && import_styled_components2.css`
247
- background: ${import_eds_tokens2.tokens.colors.interactive.link_in_snackbars.hex};
248
- color: ${import_eds_tokens2.tokens.colors.interactive.table__cell__fill_resting.hex};
249
- &:hover {
250
- background: #fff;
251
- }
252
- `}
282
+ &:hover {
283
+ background-color: var(--color-text, rgba(0, 79, 85, 1));
284
+ }
253
285
  `;
254
- var IconAndTextWrapper = (0, import_styled_components2.default)(import_eds_core_react2.Menu.Item)`
286
+ var IconAndTextWrapper = (0, import_styled_components2.default)(import_eds_core_react3.Menu.Item)`
255
287
  display: flex;
256
288
  gap: 12px;
257
289
  padding: 12px 20px;
@@ -266,6 +298,8 @@ var IconAndTextWrapper = (0, import_styled_components2.default)(import_eds_core_
266
298
  `;
267
299
  // Annotate the CommonJS export names for ESM import in node:
268
300
  0 && (module.exports = {
301
+ FeedbackLink,
302
+ StyledLink,
269
303
  TopBar,
270
304
  UserMenu
271
305
  });
package/dist/index.mjs CHANGED
@@ -1,31 +1,50 @@
1
+ // src/FeedbackLink/FeedbackLink.tsx
2
+ import { Icon as Icon2 } from "@equinor/eds-core-react";
3
+ import { email } from "@equinor/eds-icons";
4
+
1
5
  // src/TopBar/TopBar.tsx
2
- import { TopBar as EDSTopBar, Icon, Typography } from "@equinor/eds-core-react";
3
- import { external_link } from "@equinor/eds-icons";
4
- import styled, { css } from "styled-components";
6
+ import { Button, TopBar as EDSTopBar, Icon, Typography } from "@equinor/eds-core-react";
7
+ import { external_link, menu } from "@equinor/eds-icons";
5
8
  import { tokens } from "@equinor/eds-tokens";
9
+ import styled from "styled-components";
6
10
  import { jsx, jsxs } from "react/jsx-runtime";
7
11
  function TopBar({
8
12
  appName,
9
13
  logoLink,
14
+ sideMenuOpen,
15
+ setSideMenuOpen,
16
+ feedbackLink,
10
17
  documentationLink,
11
18
  documentationName = "Documentation",
12
19
  userMenu,
13
- darkMode = false,
14
20
  logoPath = ".",
15
21
  logoAlt = "logo"
16
22
  }) {
17
- return /* @__PURE__ */ jsxs(StyledEDSTopBar, { $darkMode: darkMode, children: [
18
- /* @__PURE__ */ jsx(EDSTopBar.Header, { style: { padding: 0 }, children: /* @__PURE__ */ jsxs(AppNameContainer, { children: [
19
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("img", { src: logoPath, alt: logoAlt, height: 24, width: 22 }) }),
20
- /* @__PURE__ */ jsx("a", { href: logoLink, children: /* @__PURE__ */ jsx(StyledTypography, { $darkMode: darkMode, children: appName }) })
21
- ] }) }),
22
- /* @__PURE__ */ jsxs(EDSTopBar.Actions, { children: [
23
- documentationLink && /* @__PURE__ */ jsxs(DocumentationDiv, { $darkMode: darkMode, children: [
24
- /* @__PURE__ */ jsx("a", { href: documentationLink, children: documentationName }),
23
+ const hasSideMenu = setSideMenuOpen && sideMenuOpen !== void 0;
24
+ return /* @__PURE__ */ jsxs(StyledEDSTopBar, { children: [
25
+ /* @__PURE__ */ jsxs(EDSTopBar.Header, { style: { padding: 0 }, children: [
26
+ hasSideMenu && /* @__PURE__ */ jsx(
27
+ ThemedButton,
28
+ {
29
+ variant: "ghost_icon",
30
+ "aria-label": "menu action",
31
+ onClick: () => setSideMenuOpen(!sideMenuOpen),
32
+ children: /* @__PURE__ */ jsx(Icon, { data: menu, size: 24 })
33
+ }
34
+ ),
35
+ /* @__PURE__ */ jsxs(AppNameContainer, { children: [
36
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx("img", { src: logoPath, alt: logoAlt, height: 24, width: 22 }) }),
37
+ /* @__PURE__ */ jsx("a", { href: logoLink, children: /* @__PURE__ */ jsx(StyledTypography, { children: appName }) })
38
+ ] })
39
+ ] }),
40
+ /* @__PURE__ */ jsx(EDSTopBar.Actions, { children: /* @__PURE__ */ jsxs(LinkContainer, { children: [
41
+ feedbackLink && feedbackLink,
42
+ documentationLink && /* @__PURE__ */ jsxs(StyledLink, { href: documentationLink, children: [
43
+ documentationName,
25
44
  /* @__PURE__ */ jsx(Icon, { data: external_link, size: 16 })
26
45
  ] }),
27
46
  userMenu
28
- ] })
47
+ ] }) })
29
48
  ] });
30
49
  }
31
50
  var StyledEDSTopBar = styled(EDSTopBar)`
@@ -33,10 +52,8 @@ var StyledEDSTopBar = styled(EDSTopBar)`
33
52
  gap: 0;
34
53
  padding: 0px 20px;
35
54
  margin: 0px;
36
- ${({ $darkMode }) => $darkMode ? css`
37
- background: ${tokens.colors.interactive.table__cell__fill_resting.hex};
38
- color: #fff;
39
- ` : ""}
55
+ background: var(--background-default, rgba(255, 255, 255, 1));
56
+ color: var(--color-text);
40
57
  `;
41
58
  var AppNameContainer = styled.div`
42
59
  display: flex;
@@ -44,42 +61,64 @@ var AppNameContainer = styled.div`
44
61
  align-items: center;
45
62
  `;
46
63
  var StyledTypography = styled(Typography)`
47
- font-weight: 300;
48
- ${({ $darkMode }) => $darkMode ? css`
49
- color: #fff;
50
- ` : ""}
64
+ color: var(--color-text);
51
65
  `;
52
- var DocumentationDiv = styled.div`
66
+ var LinkContainer = styled.div`
67
+ display: flex;
68
+ align-items: center;
69
+ gap: ${tokens.spacings.comfortable.large};
70
+ `;
71
+ var StyledLink = styled.a`
53
72
  text-decoration: none;
54
73
  display: flex;
74
+ align-items: center;
55
75
  gap: 0.3rem;
56
- font-weight: 300;
57
- a {
58
- text-decoration: none;
59
- color: inherit;
76
+
77
+ text-decoration: none;
78
+ color: var(--color-text);
79
+ `;
80
+ var ThemedButton = styled(Button)`
81
+ background-color: transparent;
82
+ color: var(--interactive-focus-border, ${tokens.colors.interactive.primary__resting.hex});
83
+
84
+ &:focus-visible {
85
+ outline-color: var(--interactive-focus-border, ${tokens.colors.interactive.focus.hex});
86
+ }
87
+
88
+ &:hover {
89
+ background-color: var(
90
+ --interactive-primary-hover-alt,
91
+ ${tokens.colors.interactive.primary__hover_alt.hex}
92
+ );
93
+ color: var(--interactive-secondary-hover, ${tokens.colors.interactive.primary__resting.hex});
60
94
  }
61
- ${({ $darkMode }) => $darkMode ? css`
62
- color: ${tokens.colors.interactive.table__cell__fill_resting.hex};
63
- a {
64
- color: #fff;
65
- }
66
- ` : ""}
67
95
  `;
68
96
 
97
+ // src/FeedbackLink/FeedbackLink.tsx
98
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
99
+ function FeedbackLink({ link, subject, body }) {
100
+ return /* @__PURE__ */ jsxs2(
101
+ StyledLink,
102
+ {
103
+ href: `mailto:${link}?subject=${subject}&body=${body}`,
104
+ target: "_blank",
105
+ rel: "noreferrer",
106
+ children: [
107
+ "Feedback",
108
+ /* @__PURE__ */ jsx2(Icon2, { data: email, size: 16 })
109
+ ]
110
+ }
111
+ );
112
+ }
113
+
69
114
  // src/UserMenu/UserMenu.tsx
70
- import { Button, Icon as Icon2, Menu } from "@equinor/eds-core-react";
115
+ import { Button as Button2, Icon as Icon3, Menu } from "@equinor/eds-core-react";
71
116
  import { log_out, settings } from "@equinor/eds-icons";
72
117
  import { tokens as tokens2 } from "@equinor/eds-tokens";
73
118
  import { useState } from "react";
74
- import styled2, { css as css2 } from "styled-components";
75
- import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
76
- function UserMenu({
77
- user,
78
- logout,
79
- darkMode = false,
80
- settingsLink,
81
- children
82
- }) {
119
+ import styled2 from "styled-components";
120
+ import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
121
+ function UserMenu({ user, logout, settingsLink, children }) {
83
122
  var _a, _b, _c, _d, _e;
84
123
  const [isOpen, setIsOpen] = useState(false);
85
124
  const [anchorEl, setAnchorEl] = useState(null);
@@ -91,20 +130,20 @@ function UserMenu({
91
130
  };
92
131
  const LogOutMenuItem = () => {
93
132
  if (typeof logout === "string") {
94
- return /* @__PURE__ */ jsxs2(Menu.Item, { as: "a", href: logout, className: "menu-item", id: "logout-button", children: [
95
- /* @__PURE__ */ jsx2(Icon2, { data: log_out }),
96
- /* @__PURE__ */ jsx2("span", { children: "Log out" })
133
+ return /* @__PURE__ */ jsxs3(Menu.Item, { as: "a", href: logout, className: "menu-item", id: "logout-button", children: [
134
+ /* @__PURE__ */ jsx3(Icon3, { data: log_out }),
135
+ /* @__PURE__ */ jsx3("span", { children: "Log out" })
97
136
  ] });
98
137
  } else {
99
- return /* @__PURE__ */ jsxs2(Menu.Item, { as: "button", onClick: logout, className: "menu-item", id: "logout-button", children: [
100
- /* @__PURE__ */ jsx2(Icon2, { data: log_out }),
101
- /* @__PURE__ */ jsx2("span", { children: "Log out" })
138
+ return /* @__PURE__ */ jsxs3(Menu.Item, { as: "button", onClick: logout, className: "menu-item", id: "logout-button", children: [
139
+ /* @__PURE__ */ jsx3(Icon3, { data: log_out }),
140
+ /* @__PURE__ */ jsx3("span", { children: "Log out" })
102
141
  ] });
103
142
  }
104
143
  };
105
144
  const firstLetter = (_c = (_b = (_a = user == null ? void 0 : user.email) == null ? void 0 : _a[0]) == null ? void 0 : _b.toUpperCase()) != null ? _c : "-";
106
- return /* @__PURE__ */ jsxs2(Fragment, { children: [
107
- /* @__PURE__ */ jsx2(
145
+ return /* @__PURE__ */ jsxs3(Fragment, { children: [
146
+ /* @__PURE__ */ jsx3(
108
147
  StyledUserButton,
109
148
  {
110
149
  id: "user-button",
@@ -114,14 +153,12 @@ function UserMenu({
114
153
  "aria-expanded": isOpen,
115
154
  "aria-controls": "user-menu",
116
155
  onClick: () => isOpen ? closeMenu() : openMenu(),
117
- $darkMode: darkMode,
118
156
  children: firstLetter
119
157
  }
120
158
  ),
121
- /* @__PURE__ */ jsxs2(
159
+ /* @__PURE__ */ jsxs3(
122
160
  MenuWrapper,
123
161
  {
124
- $darkMode: darkMode,
125
162
  id: "user-menu",
126
163
  "aria-labelledby": "user-button",
127
164
  open: isOpen,
@@ -129,16 +166,16 @@ function UserMenu({
129
166
  anchorEl,
130
167
  style: { padding: 0, paddingBottom: 2 },
131
168
  children: [
132
- /* @__PURE__ */ jsxs2(IconAndTextWrapper, { $darkMode: darkMode, children: [
133
- /* @__PURE__ */ jsx2(LetterCircle, { $darkMode: darkMode, children: firstLetter }),
134
- isOpen && /* @__PURE__ */ jsxs2("div", { children: [
135
- /* @__PURE__ */ jsx2("div", { style: { fontWeight: "bold", lineHeight: 0.9, marginBottom: 2 }, children: (_d = user == null ? void 0 : user.name) != null ? _d : "-" }),
136
- /* @__PURE__ */ jsx2("div", { children: (_e = user == null ? void 0 : user.email) != null ? _e : "-" })
169
+ /* @__PURE__ */ jsxs3(IconAndTextWrapper, { children: [
170
+ /* @__PURE__ */ jsx3(LetterCircle, { children: firstLetter }),
171
+ isOpen && /* @__PURE__ */ jsxs3("div", { children: [
172
+ /* @__PURE__ */ jsx3("div", { style: { fontWeight: "bold", lineHeight: 0.9, marginBottom: 2 }, children: (_d = user == null ? void 0 : user.name) != null ? _d : "-" }),
173
+ /* @__PURE__ */ jsx3("div", { children: (_e = user == null ? void 0 : user.email) != null ? _e : "-" })
137
174
  ] })
138
175
  ] }),
139
- settingsLink && /* @__PURE__ */ jsxs2(Menu.Item, { as: "a", href: settingsLink, className: "menu-item", children: [
140
- /* @__PURE__ */ jsx2(Icon2, { data: settings }),
141
- /* @__PURE__ */ jsx2("span", { children: "Settings" })
176
+ settingsLink && /* @__PURE__ */ jsxs3(Menu.Item, { as: "a", href: settingsLink, className: "menu-item", children: [
177
+ /* @__PURE__ */ jsx3(Icon3, { data: settings }),
178
+ /* @__PURE__ */ jsx3("span", { children: "Settings" })
142
179
  ] }),
143
180
  LogOutMenuItem(),
144
181
  children
@@ -157,32 +194,28 @@ var MenuWrapper = styled2(Menu)`
157
194
  padding-top: ${tokens2.spacings.comfortable.small};
158
195
  width: 315px;
159
196
 
197
+ background: var(--ui-background-temporary-nav, #fff);
198
+ color: var(--color-text);
199
+
160
200
  .menu-item {
161
201
  align-items: center;
162
202
  display: flex;
163
203
  gap: ${tokens2.spacings.comfortable.medium};
164
204
  opacity: 0.85;
165
205
  padding: ${tokens2.spacings.comfortable.small} ${tokens2.spacings.comfortable.large};
206
+
207
+ color: var(--color-text);
166
208
  svg {
167
209
  opacity: 0.7;
168
210
  }
169
211
  &:hover {
170
212
  opacity: 1;
213
+ background: var(--menu-item-hover-color);
171
214
  svg {
172
215
  opacity: 1;
173
216
  }
174
217
  }
175
218
  }
176
- ${({ $darkMode }) => $darkMode ? css2`
177
- background: #3e4f5c; //TODO: get color from token in the future
178
- color: #fff;
179
- .menu-item {
180
- color: #fff;
181
- &:hover {
182
- background: #305c75;
183
- }
184
- }
185
- ` : ``}
186
219
  `;
187
220
  var LetterCircle = styled2.span`
188
221
  align-items: center;
@@ -193,26 +226,23 @@ var LetterCircle = styled2.span`
193
226
  height: 32px;
194
227
  justify-content: center;
195
228
  width: 32px;
196
- background-color: ${tokens2.colors.interactive.primary__resting.hex};
197
- color: #fff;
198
- ${({ $darkMode }) => $darkMode ? css2`
199
- background: ${tokens2.colors.interactive.link_in_snackbars.hex};
200
- color: ${tokens2.colors.interactive.table__cell__fill_resting.hex};
201
- ` : ``};
229
+ background-color: var(
230
+ --interactive-focus-border,
231
+ ${tokens2.colors.interactive.primary__resting.hex}
232
+ );
233
+ color: var(--color-text-inverse, #fff);
202
234
  `;
203
- var StyledUserButton = styled2(Button)`
235
+ var StyledUserButton = styled2(Button2)`
204
236
  margin-left: 12px;
205
237
  font-weight: bold;
206
238
  width: 32px;
207
239
  height: 32px;
240
+ background: var(--interactive-focus-border, ${tokens2.colors.interactive.primary__resting.hex});
241
+ color: var(--color-text-inverse, #fff);
208
242
 
209
- ${({ $darkMode }) => $darkMode && css2`
210
- background: ${tokens2.colors.interactive.link_in_snackbars.hex};
211
- color: ${tokens2.colors.interactive.table__cell__fill_resting.hex};
212
- &:hover {
213
- background: #fff;
214
- }
215
- `}
243
+ &:hover {
244
+ background-color: var(--color-text, rgba(0, 79, 85, 1));
245
+ }
216
246
  `;
217
247
  var IconAndTextWrapper = styled2(Menu.Item)`
218
248
  display: flex;
@@ -228,6 +258,8 @@ var IconAndTextWrapper = styled2(Menu.Item)`
228
258
  }
229
259
  `;
230
260
  export {
261
+ FeedbackLink,
262
+ StyledLink,
231
263
  TopBar,
232
264
  UserMenu
233
265
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@equinor/cpl-top-bar-react",
3
- "version": "0.2.5",
3
+ "version": "0.3.1",
4
4
  "license": "MIT",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -14,8 +14,7 @@
14
14
  },
15
15
  "devDependencies": {
16
16
  "@equinor/eds-core-react": "^0.42.5",
17
- "@storybook/react": "^8.6.14",
18
- "@storybook/test": "^8.6.14",
17
+ "@storybook/react": "^9.0.12",
19
18
  "@types/react": "^18.3.18",
20
19
  "@types/react-dom": "^18.3.5",
21
20
  "@types/styled-components": "^5.1.34",