@peers-app/peers-ui 0.8.2 → 0.8.4

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.
@@ -48,6 +48,8 @@ const color_mode_dropdown_1 = require("../settings/color-mode-dropdown");
48
48
  const log_display_1 = require("./log-display");
49
49
  const log_filters_1 = require("./log-filters");
50
50
  const resizable_table_header_1 = require("./resizable-table-header");
51
+ const globals_1 = require("../../globals");
52
+ const mobile_log_card_1 = require("./mobile-log-card");
51
53
  const windowHeight = () => window.innerHeight;
52
54
  const DEFAULT_COLUMNS = [
53
55
  { key: 'timestamp', label: 'Timestamp', width: 150 },
@@ -68,6 +70,8 @@ const ConsoleLogsList = () => {
68
70
  const [_colorMode] = (0, hooks_1.useObservable)(color_mode_dropdown_1.colorMode);
69
71
  const logsEndRef = react_1.default.useRef(null);
70
72
  const containerRef = react_1.default.useRef(null);
73
+ (0, hooks_1.useObservable)(globals_1.isDesktop);
74
+ const isMobile = !(0, globals_1.isDesktop)();
71
75
  const batchSize = 50;
72
76
  // Track fixed column widths to trigger message column recalculation
73
77
  const fixedColumnsWidthKey = (0, react_1.useMemo)(() => {
@@ -225,7 +229,7 @@ const ConsoleLogsList = () => {
225
229
  marginBottom: '50px',
226
230
  overflow: 'hidden',
227
231
  } },
228
- react_1.default.createElement(resizable_table_header_1.ResizableTableHeader, { columns: columns, onColumnsChange: setColumns, colorMode: _colorMode }),
232
+ !isMobile && (react_1.default.createElement(resizable_table_header_1.ResizableTableHeader, { columns: columns, onColumnsChange: setColumns, colorMode: _colorMode })),
229
233
  react_1.default.createElement("div", { id: "scrollableLogsDiv", style: {
230
234
  flex: 1,
231
235
  overflow: 'auto',
@@ -239,10 +243,12 @@ const ConsoleLogsList = () => {
239
243
  react_1.default.createElement("div", { ref: logsEndRef }),
240
244
  _logs.length === 0 && allLogsLoaded ? (react_1.default.createElement("div", { className: "text-center p-5 text-muted" },
241
245
  react_1.default.createElement("i", { className: "bi bi-inbox display-1" }),
242
- react_1.default.createElement("p", { className: "mt-2" }, "No logs found"))) : (react_1.default.createElement("table", { className: "table table-sm table-hover mb-0", style: { fontSize: '0.85rem', tableLayout: 'fixed', width: '100%' } },
243
- react_1.default.createElement("tbody", null, _logs.map((log) => (
244
- // log.logId
245
- react_1.default.createElement(log_display_1.LogDisplay, { key: log.logId, log: log, columns: columns }))))))))),
246
+ react_1.default.createElement("p", { className: "mt-2" }, "No logs found"))) : isMobile ? (
247
+ /* Mobile: Card-based layout */
248
+ react_1.default.createElement("div", null, _logs.map((log) => (react_1.default.createElement(mobile_log_card_1.MobileLogCard, { key: log.logId, log: log, colorMode: _colorMode }))))) : (
249
+ /* Desktop: Table layout */
250
+ react_1.default.createElement("table", { className: "table table-sm table-hover mb-0", style: { fontSize: '0.85rem', tableLayout: 'fixed', width: '100%' } },
251
+ react_1.default.createElement("tbody", null, _logs.map((log) => (react_1.default.createElement(log_display_1.LogDisplay, { key: log.logId, log: log, columns: columns }))))))))),
246
252
  react_1.default.createElement("div", { style: {
247
253
  position: 'fixed',
248
254
  bottom: 0,
@@ -0,0 +1,8 @@
1
+ import { IConsoleLog } from "@peers-app/peers-sdk";
2
+ import React from 'react';
3
+ interface MobileLogCardProps {
4
+ log: IConsoleLog;
5
+ colorMode: string;
6
+ }
7
+ export declare const MobileLogCard: ({ log, colorMode }: MobileLogCardProps) => React.JSX.Element;
8
+ export {};
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.MobileLogCard = void 0;
7
+ const peers_sdk_1 = require("@peers-app/peers-sdk");
8
+ const moment_1 = __importDefault(require("moment"));
9
+ const react_1 = __importDefault(require("react"));
10
+ const getLevelColor = (level) => {
11
+ switch (level) {
12
+ case 'error': return '#dc3545';
13
+ case 'warn': return '#ffc107';
14
+ case 'info': return '#0dcaf0';
15
+ case 'log': return '#6c757d';
16
+ case 'debug': return '#6c757d';
17
+ default: return '#6c757d';
18
+ }
19
+ };
20
+ const getProcessColor = (process) => {
21
+ switch (process) {
22
+ case 'ui':
23
+ case 'renderer': return '#0dcaf0';
24
+ case 'electron':
25
+ case 'main': return '#d946ef';
26
+ case 'react-native': return '#61dafb';
27
+ default: return '#6c757d';
28
+ }
29
+ };
30
+ const getLevelIcon = (level) => {
31
+ switch (level) {
32
+ case 'error': return 'bi-x-circle-fill';
33
+ case 'warn': return 'bi-exclamation-triangle-fill';
34
+ case 'info': return 'bi-info-circle-fill';
35
+ case 'debug': return 'bi-bug-fill';
36
+ default: return 'bi-chat-square-text';
37
+ }
38
+ };
39
+ const MobileLogCard = ({ log, colorMode }) => {
40
+ const isDark = colorMode === 'dark';
41
+ // Parse context if it's a string
42
+ let context = log.context;
43
+ if (typeof context === 'string') {
44
+ try {
45
+ context = (0, peers_sdk_1.fromJSONString)(context);
46
+ }
47
+ catch (err) { }
48
+ }
49
+ return (react_1.default.createElement("div", { style: {
50
+ padding: '10px 12px',
51
+ borderBottom: `1px solid ${isDark ? '#333' : '#e9ecef'}`,
52
+ backgroundColor: isDark ? '#1a1a1a' : '#fff',
53
+ } },
54
+ react_1.default.createElement("div", { className: "d-flex align-items-center gap-2 mb-1", style: { flexWrap: 'wrap' } },
55
+ react_1.default.createElement("span", { style: { fontSize: '0.7rem', color: isDark ? '#888' : '#666' } }, (0, moment_1.default)(log.timestamp).format('HH:mm:ss.SSS')),
56
+ react_1.default.createElement("span", { className: "badge text-white", style: {
57
+ backgroundColor: getLevelColor(log.level),
58
+ fontSize: '0.65rem',
59
+ padding: '2px 6px'
60
+ } },
61
+ react_1.default.createElement("i", { className: `${getLevelIcon(log.level)} me-1` }),
62
+ log.level),
63
+ react_1.default.createElement("span", { className: "badge text-white", style: {
64
+ backgroundColor: getProcessColor(log.process),
65
+ fontSize: '0.65rem',
66
+ padding: '2px 6px'
67
+ } }, log.process),
68
+ log.source && (react_1.default.createElement("span", { style: { fontSize: '0.65rem', color: isDark ? '#666' : '#999' } }, log.source))),
69
+ react_1.default.createElement("div", { style: {
70
+ fontSize: '0.8rem',
71
+ wordBreak: 'break-word',
72
+ color: isDark ? '#e0e0e0' : '#333'
73
+ } }, log.message),
74
+ context && (react_1.default.createElement("details", { className: "mt-1" },
75
+ react_1.default.createElement("summary", { className: "text-muted", style: { cursor: 'pointer', fontSize: '0.7rem' } },
76
+ react_1.default.createElement("i", { className: "bi bi-code-square me-1" }),
77
+ "Context"),
78
+ react_1.default.createElement("pre", { className: "mt-1 p-2 rounded", style: {
79
+ fontSize: '0.65rem',
80
+ backgroundColor: isDark ? '#252525' : '#f8f9fa',
81
+ color: isDark ? '#aaa' : '#333',
82
+ overflow: 'auto',
83
+ maxHeight: '150px'
84
+ } }, JSON.stringify(context, null, 2)))),
85
+ log.stackTrace && (react_1.default.createElement("details", { className: "mt-1" },
86
+ react_1.default.createElement("summary", { className: "text-danger", style: { cursor: 'pointer', fontSize: '0.7rem' } },
87
+ react_1.default.createElement("i", { className: "bi bi-bug me-1" }),
88
+ "Stack Trace"),
89
+ react_1.default.createElement("pre", { className: "mt-1 p-2 rounded text-danger", style: {
90
+ fontSize: '0.6rem',
91
+ backgroundColor: isDark ? '#2a1a1a' : '#fff0f0',
92
+ overflow: 'auto',
93
+ maxHeight: '150px'
94
+ } }, log.stackTrace)))));
95
+ };
96
+ exports.MobileLogCard = MobileLogCard;
@@ -100,7 +100,7 @@ function TabsLayoutInternal() {
100
100
  sub = userContext.currentlyActiveGroupId.subscribe(async (groupId) => {
101
101
  setCurrentlyActiveGroupId(userContext.currentlyActiveGroupId() || userContext.userId);
102
102
  // below reloading logic is a kludge to deal with different groups having different packages installed
103
- await (0, peers_sdk_1.sleep)(100);
103
+ await (0, peers_sdk_1.sleep)(250);
104
104
  window.location.reload();
105
105
  });
106
106
  });
@@ -177,28 +177,28 @@ function MobileTabsHeader({ tabs, activeTab, onSwitch, onClose, colorMode }) {
177
177
  react_1.default.createElement("button", { className: `btn btn-sm ${colorMode === 'light' ? 'btn-outline-dark' : 'btn-outline-light'}`, onClick: () => setShowMenuDropdown(!showMenuDropdown), style: { minWidth: '36px' } },
178
178
  react_1.default.createElement("i", { className: "bi-list" }),
179
179
  nonLauncherTabs.length > 0 && (react_1.default.createElement("span", { className: "ms-1" }, nonLauncherTabs.length))),
180
- showMenuDropdown && (react_1.default.createElement("div", { className: `dropdown-menu show position-absolute ${colorMode === 'light' ? '' : 'dropdown-menu-dark'}`, style: { right: 0, top: '100%', zIndex: 1000, minWidth: '250px' } },
181
- react_1.default.createElement("div", { className: `dropdown-item d-flex align-items-center ${activeTab === 'launcher' ? 'active' : ''}`, style: { cursor: 'pointer' }, onClick: () => {
180
+ showMenuDropdown && (react_1.default.createElement("div", { className: `dropdown-menu show position-absolute ${colorMode === 'light' ? '' : 'dropdown-menu-dark'}`, style: { right: 0, top: '100%', zIndex: 1000, minWidth: '280px', maxHeight: 'calc(100vh - 60px)', overflowY: 'auto' } },
181
+ react_1.default.createElement("div", { className: `dropdown-item d-flex align-items-center ${activeTab === 'launcher' ? 'active' : ''}`, style: { cursor: 'pointer', padding: '14px 18px', fontSize: '17px' }, onClick: () => {
182
182
  onSwitch('launcher');
183
183
  setShowMenuDropdown(false);
184
184
  } },
185
- react_1.default.createElement("i", { className: "bi-grid-3x3-gap me-2" }),
185
+ react_1.default.createElement("i", { className: "bi-grid-3x3-gap me-3", style: { fontSize: '20px' } }),
186
186
  react_1.default.createElement("span", null, "Apps")),
187
- react_1.default.createElement("div", { className: "dropdown-item d-flex align-items-center", style: { cursor: 'pointer' }, onClick: () => {
187
+ react_1.default.createElement("div", { className: "dropdown-item d-flex align-items-center", style: { cursor: 'pointer', padding: '14px 18px', fontSize: '17px' }, onClick: () => {
188
188
  (0, command_palette_1.openCommandPalette)();
189
189
  setShowMenuDropdown(false);
190
190
  } },
191
- react_1.default.createElement("i", { className: "bi-search me-2" }),
191
+ react_1.default.createElement("i", { className: "bi-search me-3", style: { fontSize: '20px' } }),
192
192
  react_1.default.createElement("span", null, "Search")),
193
- nonLauncherTabs.length > 0 && (react_1.default.createElement("div", { className: "dropdown-divider" })),
194
- nonLauncherTabs.slice().reverse().map(tab => (react_1.default.createElement("div", { key: tab.tabId, className: `dropdown-item d-flex align-items-center justify-content-between ${activeTab === tab.tabId ? 'active' : ''}`, style: { cursor: 'pointer' }, onClick: () => {
193
+ nonLauncherTabs.length > 0 && (react_1.default.createElement("div", { className: "dropdown-divider", style: { margin: '8px 0' } })),
194
+ nonLauncherTabs.slice().reverse().map(tab => (react_1.default.createElement("div", { key: tab.tabId, className: `dropdown-item d-flex align-items-center justify-content-between ${activeTab === tab.tabId ? 'active' : ''}`, style: { cursor: 'pointer', padding: '14px 18px', fontSize: '17px' }, onClick: () => {
195
195
  onSwitch(tab.tabId);
196
196
  setShowMenuDropdown(false);
197
197
  } },
198
198
  react_1.default.createElement("div", { className: "d-flex align-items-center" },
199
- tab.iconClassName && react_1.default.createElement("i", { className: `${tab.iconClassName} me-2` }),
199
+ tab.iconClassName && react_1.default.createElement("i", { className: `${tab.iconClassName} me-3`, style: { fontSize: '20px' } }),
200
200
  react_1.default.createElement("span", null, tab.title)),
201
- react_1.default.createElement("button", { className: "btn btn-sm p-0 ms-2", style: { width: '20px', height: '20px' }, onClick: (e) => {
201
+ react_1.default.createElement("button", { className: "btn btn-sm p-0 ms-3", style: { width: '32px', height: '32px', fontSize: '20px' }, onClick: (e) => {
202
202
  e.stopPropagation();
203
203
  onClose(tab.tabId);
204
204
  } },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peers-app/peers-ui",
3
- "version": "0.8.2",
3
+ "version": "0.8.4",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/peers-app/peers-ui.git"
@@ -27,7 +27,7 @@
27
27
  },
28
28
  "peerDependencies": {
29
29
  "bootstrap": "^5.3.3",
30
- "@peers-app/peers-sdk": "^0.8.2",
30
+ "@peers-app/peers-sdk": "^0.8.4",
31
31
  "react": "^18.0.0",
32
32
  "react-dom": "^18.0.0"
33
33
  },
@@ -57,7 +57,7 @@
57
57
  "jest": "^29.7.0",
58
58
  "jest-environment-jsdom": "^30.0.5",
59
59
  "path-browserify": "^1.0.1",
60
- "@peers-app/peers-sdk": "0.8.2",
60
+ "@peers-app/peers-sdk": "0.8.4",
61
61
  "react": "^18.0.0",
62
62
  "react-dom": "^18.0.0",
63
63
  "string-width": "^7.1.0",
@@ -9,6 +9,8 @@ import { colorMode } from '../settings/color-mode-dropdown';
9
9
  import { LogDisplay } from './log-display';
10
10
  import { LogFilters } from './log-filters';
11
11
  import { ResizableTableHeader } from './resizable-table-header';
12
+ import { isDesktop } from '../../globals';
13
+ import { MobileLogCard } from './mobile-log-card';
12
14
 
13
15
  const windowHeight = () => window.innerHeight;
14
16
 
@@ -37,7 +39,9 @@ export const ConsoleLogsList = () => {
37
39
  const [totalLogCount, setTotalLogCount] = useState<number>(0);
38
40
  const [_colorMode] = useObservable(colorMode);
39
41
  const logsEndRef = React.useRef<HTMLDivElement>(null);
40
- const containerRef = React.useRef<HTMLDivElement>(null);
42
+ const containerRef = React.useRef<HTMLDivElement>(null);
43
+ useObservable(isDesktop);
44
+ const isMobile = !isDesktop();
41
45
 
42
46
  const batchSize = 50;
43
47
 
@@ -226,12 +230,14 @@ export const ConsoleLogsList = () => {
226
230
  overflow: 'hidden',
227
231
  }}
228
232
  >
229
- {/* Resizable table header outside scroll area */}
230
- <ResizableTableHeader
231
- columns={columns}
232
- onColumnsChange={setColumns}
233
- colorMode={_colorMode}
234
- />
233
+ {/* Desktop: Resizable table header outside scroll area */}
234
+ {!isMobile && (
235
+ <ResizableTableHeader
236
+ columns={columns}
237
+ onColumnsChange={setColumns}
238
+ colorMode={_colorMode}
239
+ />
240
+ )}
235
241
 
236
242
  {/* Scrollable content area */}
237
243
  <div
@@ -267,11 +273,18 @@ export const ConsoleLogsList = () => {
267
273
  <i className="bi bi-inbox display-1"></i>
268
274
  <p className="mt-2">No logs found</p>
269
275
  </div>
276
+ ) : isMobile ? (
277
+ /* Mobile: Card-based layout */
278
+ <div>
279
+ {_logs.map((log) => (
280
+ <MobileLogCard key={log.logId} log={log} colorMode={_colorMode} />
281
+ ))}
282
+ </div>
270
283
  ) : (
284
+ /* Desktop: Table layout */
271
285
  <table className="table table-sm table-hover mb-0" style={{ fontSize: '0.85rem', tableLayout: 'fixed', width: '100%' }}>
272
286
  <tbody>
273
287
  {_logs.map((log) => (
274
- // log.logId
275
288
  <LogDisplay key={log.logId} log={log} columns={columns} />
276
289
  ))}
277
290
  </tbody>
@@ -0,0 +1,154 @@
1
+ import { fromJSONString, IConsoleLog } from "@peers-app/peers-sdk";
2
+ import moment from 'moment';
3
+ import React from 'react';
4
+
5
+ interface MobileLogCardProps {
6
+ log: IConsoleLog;
7
+ colorMode: string;
8
+ }
9
+
10
+ const getLevelColor = (level: string) => {
11
+ switch (level) {
12
+ case 'error': return '#dc3545';
13
+ case 'warn': return '#ffc107';
14
+ case 'info': return '#0dcaf0';
15
+ case 'log': return '#6c757d';
16
+ case 'debug': return '#6c757d';
17
+ default: return '#6c757d';
18
+ }
19
+ };
20
+
21
+ const getProcessColor = (process: string) => {
22
+ switch (process) {
23
+ case 'ui':
24
+ case 'renderer': return '#0dcaf0';
25
+ case 'electron':
26
+ case 'main': return '#d946ef';
27
+ case 'react-native': return '#61dafb';
28
+ default: return '#6c757d';
29
+ }
30
+ };
31
+
32
+ const getLevelIcon = (level: string) => {
33
+ switch (level) {
34
+ case 'error': return 'bi-x-circle-fill';
35
+ case 'warn': return 'bi-exclamation-triangle-fill';
36
+ case 'info': return 'bi-info-circle-fill';
37
+ case 'debug': return 'bi-bug-fill';
38
+ default: return 'bi-chat-square-text';
39
+ }
40
+ };
41
+
42
+ export const MobileLogCard = ({ log, colorMode }: MobileLogCardProps) => {
43
+ const isDark = colorMode === 'dark';
44
+
45
+ // Parse context if it's a string
46
+ let context = log.context;
47
+ if (typeof context === 'string') {
48
+ try {
49
+ context = fromJSONString(context);
50
+ } catch (err) {}
51
+ }
52
+
53
+ return (
54
+ <div
55
+ style={{
56
+ padding: '10px 12px',
57
+ borderBottom: `1px solid ${isDark ? '#333' : '#e9ecef'}`,
58
+ backgroundColor: isDark ? '#1a1a1a' : '#fff',
59
+ }}
60
+ >
61
+ {/* Header row: timestamp, level, process */}
62
+ <div className="d-flex align-items-center gap-2 mb-1" style={{ flexWrap: 'wrap' }}>
63
+ <span style={{ fontSize: '0.7rem', color: isDark ? '#888' : '#666' }}>
64
+ {moment(log.timestamp).format('HH:mm:ss.SSS')}
65
+ </span>
66
+ <span
67
+ className="badge text-white"
68
+ style={{
69
+ backgroundColor: getLevelColor(log.level),
70
+ fontSize: '0.65rem',
71
+ padding: '2px 6px'
72
+ }}
73
+ >
74
+ <i className={`${getLevelIcon(log.level)} me-1`}></i>
75
+ {log.level}
76
+ </span>
77
+ <span
78
+ className="badge text-white"
79
+ style={{
80
+ backgroundColor: getProcessColor(log.process),
81
+ fontSize: '0.65rem',
82
+ padding: '2px 6px'
83
+ }}
84
+ >
85
+ {log.process}
86
+ </span>
87
+ {log.source && (
88
+ <span style={{ fontSize: '0.65rem', color: isDark ? '#666' : '#999' }}>
89
+ {log.source}
90
+ </span>
91
+ )}
92
+ </div>
93
+
94
+ {/* Message */}
95
+ <div style={{
96
+ fontSize: '0.8rem',
97
+ wordBreak: 'break-word',
98
+ color: isDark ? '#e0e0e0' : '#333'
99
+ }}>
100
+ {log.message}
101
+ </div>
102
+
103
+ {/* Context (collapsible) */}
104
+ {context && (
105
+ <details className="mt-1">
106
+ <summary
107
+ className="text-muted"
108
+ style={{ cursor: 'pointer', fontSize: '0.7rem' }}
109
+ >
110
+ <i className="bi bi-code-square me-1"></i>
111
+ Context
112
+ </summary>
113
+ <pre
114
+ className="mt-1 p-2 rounded"
115
+ style={{
116
+ fontSize: '0.65rem',
117
+ backgroundColor: isDark ? '#252525' : '#f8f9fa',
118
+ color: isDark ? '#aaa' : '#333',
119
+ overflow: 'auto',
120
+ maxHeight: '150px'
121
+ }}
122
+ >
123
+ {JSON.stringify(context, null, 2)}
124
+ </pre>
125
+ </details>
126
+ )}
127
+
128
+ {/* Stack trace (collapsible) */}
129
+ {log.stackTrace && (
130
+ <details className="mt-1">
131
+ <summary
132
+ className="text-danger"
133
+ style={{ cursor: 'pointer', fontSize: '0.7rem' }}
134
+ >
135
+ <i className="bi bi-bug me-1"></i>
136
+ Stack Trace
137
+ </summary>
138
+ <pre
139
+ className="mt-1 p-2 rounded text-danger"
140
+ style={{
141
+ fontSize: '0.6rem',
142
+ backgroundColor: isDark ? '#2a1a1a' : '#fff0f0',
143
+ overflow: 'auto',
144
+ maxHeight: '150px'
145
+ }}
146
+ >
147
+ {log.stackTrace}
148
+ </pre>
149
+ </details>
150
+ )}
151
+ </div>
152
+ );
153
+ };
154
+
@@ -74,7 +74,7 @@ function TabsLayoutInternal() {
74
74
  sub = userContext.currentlyActiveGroupId.subscribe(async groupId => {
75
75
  setCurrentlyActiveGroupId(userContext.currentlyActiveGroupId() || userContext.userId);
76
76
  // below reloading logic is a kludge to deal with different groups having different packages installed
77
- await sleep(100);
77
+ await sleep(250);
78
78
  window.location.reload();
79
79
  });
80
80
  });
@@ -252,37 +252,37 @@ function MobileTabsHeader({ tabs, activeTab, onSwitch, onClose, colorMode }: Mob
252
252
  {showMenuDropdown && (
253
253
  <div
254
254
  className={`dropdown-menu show position-absolute ${colorMode === 'light' ? '' : 'dropdown-menu-dark'}`}
255
- style={{ right: 0, top: '100%', zIndex: 1000, minWidth: '250px' }}
255
+ style={{ right: 0, top: '100%', zIndex: 1000, minWidth: '280px', maxHeight: 'calc(100vh - 60px)', overflowY: 'auto' }}
256
256
  >
257
257
  {/* Apps Option */}
258
258
  <div
259
259
  className={`dropdown-item d-flex align-items-center ${activeTab === 'launcher' ? 'active' : ''}`}
260
- style={{ cursor: 'pointer' }}
260
+ style={{ cursor: 'pointer', padding: '14px 18px', fontSize: '17px' }}
261
261
  onClick={() => {
262
262
  onSwitch('launcher');
263
263
  setShowMenuDropdown(false);
264
264
  }}
265
265
  >
266
- <i className="bi-grid-3x3-gap me-2" />
266
+ <i className="bi-grid-3x3-gap me-3" style={{ fontSize: '20px' }} />
267
267
  <span>Apps</span>
268
268
  </div>
269
269
 
270
270
  {/* Search Option */}
271
271
  <div
272
272
  className="dropdown-item d-flex align-items-center"
273
- style={{ cursor: 'pointer' }}
273
+ style={{ cursor: 'pointer', padding: '14px 18px', fontSize: '17px' }}
274
274
  onClick={() => {
275
275
  openCommandPalette();
276
276
  setShowMenuDropdown(false);
277
277
  }}
278
278
  >
279
- <i className="bi-search me-2" />
279
+ <i className="bi-search me-3" style={{ fontSize: '20px' }} />
280
280
  <span>Search</span>
281
281
  </div>
282
282
 
283
283
  {/* Divider if there are open tabs */}
284
284
  {nonLauncherTabs.length > 0 && (
285
- <div className="dropdown-divider" />
285
+ <div className="dropdown-divider" style={{ margin: '8px 0' }} />
286
286
  )}
287
287
 
288
288
  {/* Open Tabs */}
@@ -290,19 +290,19 @@ function MobileTabsHeader({ tabs, activeTab, onSwitch, onClose, colorMode }: Mob
290
290
  <div
291
291
  key={tab.tabId}
292
292
  className={`dropdown-item d-flex align-items-center justify-content-between ${activeTab === tab.tabId ? 'active' : ''}`}
293
- style={{ cursor: 'pointer' }}
293
+ style={{ cursor: 'pointer', padding: '14px 18px', fontSize: '17px' }}
294
294
  onClick={() => {
295
295
  onSwitch(tab.tabId);
296
296
  setShowMenuDropdown(false);
297
297
  }}
298
298
  >
299
299
  <div className="d-flex align-items-center">
300
- {tab.iconClassName && <i className={`${tab.iconClassName} me-2`} />}
300
+ {tab.iconClassName && <i className={`${tab.iconClassName} me-3`} style={{ fontSize: '20px' }} />}
301
301
  <span>{tab.title}</span>
302
302
  </div>
303
303
  <button
304
- className="btn btn-sm p-0 ms-2"
305
- style={{ width: '20px', height: '20px' }}
304
+ className="btn btn-sm p-0 ms-3"
305
+ style={{ width: '32px', height: '32px', fontSize: '20px' }}
306
306
  onClick={(e) => {
307
307
  e.stopPropagation();
308
308
  onClose(tab.tabId);