@pablozaiden/webapp 0.3.0 → 0.3.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pablozaiden/webapp",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Opinionated Bun + React webapp framework for single-server apps",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1002,16 +1002,28 @@ export function WebAppRoot({ appName, homeRoute, sidebar, routes, header, onRout
1002
1002
  const headerTitle = header?.renderTitle?.(headerContext) ?? defaultTitle;
1003
1003
  const primaryHeaderActions = header?.renderActions?.(headerContext);
1004
1004
  const headerActionLabel = typeof headerTitle === "string" ? headerTitle : defaultTitle;
1005
+ const navigateFromSidebarHeader = (nextRoute: WebAppRoute) => {
1006
+ navigate(nextRoute);
1007
+ setSidebarOpen(false);
1008
+ };
1009
+ const runSidebarHeaderAction = (action: SidebarAction) => {
1010
+ if (action.onAction) {
1011
+ action.onAction();
1012
+ } else if (action.route) {
1013
+ navigate(action.route);
1014
+ }
1015
+ setSidebarOpen(false);
1016
+ };
1005
1017
 
1006
1018
  return (
1007
1019
  <main className={`wapp-shell ${sidebarCollapsed ? "sidebar-collapsed" : ""} ${sidebarOpen ? "sidebar-open" : ""}`}>
1008
1020
  <div className="wapp-mobile-backdrop" onClick={() => setSidebarOpen(false)} />
1009
1021
  <aside className="wapp-sidebar">
1010
1022
  <div className="wapp-sidebar-header">
1011
- <button type="button" className="wapp-brand" onClick={() => navigate(homeRoute)}>{appName}</button>
1023
+ <button type="button" className="wapp-brand" onClick={() => navigateFromSidebarHeader(homeRoute)}>{appName}</button>
1012
1024
  <div className="wapp-sidebar-actions">
1013
- {topActions.map((action) => <IconButton key={action.id} className="wapp-sidebar-top-button" title={action.title} aria-label={action.title} onClick={action.onAction ?? (() => action.route && navigate(action.route))}><ActionIcon icon={action.icon} /></IconButton>)}
1014
- <IconButton className="wapp-sidebar-top-button" title="Settings" aria-label="Open settings" active={route.view === "settings"} onClick={() => navigate({ view: "settings" })}><Icon name="settings" /></IconButton>
1025
+ {topActions.map((action) => <IconButton key={action.id} className="wapp-sidebar-top-button" title={action.title} aria-label={action.title} onClick={() => runSidebarHeaderAction(action)}><ActionIcon icon={action.icon} /></IconButton>)}
1026
+ <IconButton className="wapp-sidebar-top-button" title="Settings" aria-label="Open settings" active={route.view === "settings"} onClick={() => navigateFromSidebarHeader({ view: "settings" })}><Icon name="settings" /></IconButton>
1015
1027
  <IconButton className="wapp-sidebar-top-button" title="Collapse sidebar" aria-label="Collapse sidebar" onClick={() => { setSidebarCollapsed(true); setSidebarOpen(false); }}><Icon name="sidebar" /></IconButton>
1016
1028
  </div>
1017
1029
  </div>
@@ -30,6 +30,10 @@ export function Badge({ variant = "default", className = "", children, ...props
30
30
  return <span {...props} className={`wapp-badge wapp-badge-${variant} ${className}`}>{children}</span>;
31
31
  }
32
32
 
33
+ export function Page({ className = "", children, ...props }: HTMLAttributes<HTMLDivElement> & { children: ReactNode }) {
34
+ return <div {...props} className={`wapp-page ${className}`}>{children}</div>;
35
+ }
36
+
33
37
  export function Panel({ title, description, actions, children, className = "" }: { title?: string; description?: string; actions?: ReactNode; children?: ReactNode; className?: string }) {
34
38
  return (
35
39
  <section className={`wapp-panel ${className}`}>
@@ -1,6 +1,6 @@
1
1
  :root {
2
2
  color-scheme: light;
3
- --wapp-bg: #f3f4f6;
3
+ --wapp-bg: var(--wapp-shell-bg);
4
4
  --wapp-shell-bg: rgb(249 250 251 / 0.95);
5
5
  --wapp-surface: #ffffff;
6
6
  --wapp-surface-muted: #f9fafb;
@@ -18,7 +18,7 @@
18
18
 
19
19
  :root.dark {
20
20
  color-scheme: dark;
21
- --wapp-bg: #0a0a0a;
21
+ --wapp-bg: var(--wapp-shell-bg);
22
22
  --wapp-shell-bg: rgb(23 23 23 / 0.95);
23
23
  --wapp-surface: #262626;
24
24
  --wapp-surface-muted: #171717;
@@ -550,6 +550,12 @@ textarea::placeholder {
550
550
  min-height: 0;
551
551
  overflow: auto;
552
552
  overflow-x: hidden;
553
+ padding: 0;
554
+ }
555
+
556
+ .wapp-page {
557
+ width: 100%;
558
+ min-width: 0;
553
559
  padding: 1.5rem 2rem 2rem;
554
560
  }
555
561
 
@@ -1765,11 +1771,14 @@ textarea::placeholder {
1765
1771
  }
1766
1772
 
1767
1773
  .wapp-main-content {
1768
- padding: 1rem;
1769
1774
  overflow: auto;
1770
1775
  overflow-x: hidden;
1771
1776
  }
1772
1777
 
1778
+ .wapp-page {
1779
+ padding: 1rem;
1780
+ }
1781
+
1773
1782
  .wapp-panel-header,
1774
1783
  .wapp-entity-header {
1775
1784
  flex-wrap: wrap;