@1889ca/ui 0.3.4 → 0.5.0

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": "@1889ca/ui",
3
- "version": "0.3.4",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "main": "src/index.js",
6
6
  "module": "src/index.js",
@@ -0,0 +1,65 @@
1
+ /** Contract: contracts/packages-ui-components/rules.md */
2
+
3
+ .ui-panel {
4
+ background: rgba(18, 18, 24, 0.8);
5
+ backdrop-filter: blur(var(--ui-glass-blur-heavy));
6
+ border: 1px solid var(--ui-border);
7
+ border-top-color: var(--ui-border-strong);
8
+ border-radius: var(--ui-radius-lg);
9
+ box-shadow: var(--ui-shadow-float);
10
+ display: flex;
11
+ flex-direction: column;
12
+ min-width: 120px;
13
+ overflow: hidden;
14
+ }
15
+
16
+ .ui-panel-titlebar {
17
+ display: flex;
18
+ align-items: center;
19
+ justify-content: space-between;
20
+ padding: 0.4rem 0.65rem;
21
+ border-bottom: 1px solid var(--ui-border);
22
+ flex-shrink: 0;
23
+ }
24
+
25
+ .ui-panel-title {
26
+ font-size: 0.7rem;
27
+ font-weight: 600;
28
+ color: var(--ui-text-muted);
29
+ text-transform: uppercase;
30
+ letter-spacing: 0.06em;
31
+ }
32
+
33
+ .ui-panel-actions {
34
+ display: flex;
35
+ align-items: center;
36
+ gap: 0.35rem;
37
+ }
38
+
39
+ .ui-panel-close {
40
+ background: none;
41
+ border: none;
42
+ color: var(--ui-text-subtle);
43
+ font-size: 0.9rem;
44
+ cursor: pointer;
45
+ line-height: 1;
46
+ padding: 0.1rem 0.2rem;
47
+ border-radius: var(--ui-radius-sm);
48
+ transition: color 0.15s, background 0.15s;
49
+ }
50
+
51
+ .ui-panel-close:hover {
52
+ color: var(--ui-text);
53
+ background: var(--ui-surface-raised);
54
+ }
55
+
56
+ .ui-panel-body {
57
+ flex: 1;
58
+ min-height: 0;
59
+ padding: 0.5rem 0.65rem;
60
+ overflow: auto;
61
+ }
62
+
63
+ .ui-panel-body--flush {
64
+ padding: 0;
65
+ }
@@ -0,0 +1,31 @@
1
+ /** Contract: contracts/packages-ui-components/rules.md */
2
+
3
+ /**
4
+ * Static glass panel — same chrome as DraggablePanel but positioned in flow.
5
+ * Use for sidebar sections, inspector panels, toolboxes, etc.
6
+ *
7
+ * @param {string} title - Titlebar text
8
+ * @param {ReactNode} children - Panel body content
9
+ * @param {ReactNode} actions - Extra elements in the titlebar (right side, before close)
10
+ * @param {function} onClose - Close button handler (omit to hide close button)
11
+ * @param {string} className - Additional class names
12
+ * @param {boolean} flush - If true, removes body padding (for custom layouts)
13
+ */
14
+ export default function Panel({ title, children, actions, onClose, className, flush }) {
15
+ return (
16
+ <div className={`ui-panel${className ? ` ${className}` : ''}`}>
17
+ {title && (
18
+ <div className="ui-panel-titlebar">
19
+ <span className="ui-panel-title">{title}</span>
20
+ <div className="ui-panel-actions">
21
+ {actions}
22
+ {onClose && <button className="ui-panel-close" type="button" onClick={onClose}>&times;</button>}
23
+ </div>
24
+ </div>
25
+ )}
26
+ <div className={`ui-panel-body${flush ? ' ui-panel-body--flush' : ''}`}>
27
+ {children}
28
+ </div>
29
+ </div>
30
+ );
31
+ }
@@ -0,0 +1,118 @@
1
+ /** Contract: contracts/packages-ui-components/rules.md */
2
+
3
+ .ui-statusbar {
4
+ display: flex;
5
+ align-items: center;
6
+ justify-content: space-between;
7
+ padding: 0 1rem;
8
+ height: 28px;
9
+ border-top: 1px solid var(--ui-border);
10
+ background: rgba(8, 8, 12, 0.75);
11
+ backdrop-filter: blur(var(--ui-glass-blur-heavy));
12
+ box-shadow: 0 -1px 0 rgba(255, 255, 255, 0.03);
13
+ position: fixed;
14
+ bottom: 0;
15
+ left: 0;
16
+ right: 0;
17
+ z-index: 10;
18
+ font-size: 0.72rem;
19
+ color: var(--ui-text-muted);
20
+ gap: 0.5rem;
21
+ }
22
+
23
+ .ui-statusbar-left,
24
+ .ui-statusbar-right,
25
+ .ui-statusbar-center {
26
+ display: flex;
27
+ align-items: center;
28
+ gap: 0.6rem;
29
+ min-width: 0;
30
+ }
31
+
32
+ .ui-statusbar-left { justify-content: flex-start; }
33
+ .ui-statusbar-center { justify-content: center; flex: 1; }
34
+ .ui-statusbar-right { justify-content: flex-end; }
35
+
36
+ /* Chunks — shared label style */
37
+
38
+ .ui-sb-label {
39
+ color: var(--ui-text-subtle);
40
+ margin-right: 0.3rem;
41
+ }
42
+
43
+ /* Text */
44
+
45
+ .ui-sb-text {
46
+ white-space: nowrap;
47
+ font-variant-numeric: tabular-nums;
48
+ }
49
+
50
+ .ui-sb-text--muted {
51
+ color: var(--ui-text-subtle);
52
+ }
53
+
54
+ /* Spinner */
55
+
56
+ .ui-sb-spinner {
57
+ display: inline-flex;
58
+ align-items: center;
59
+ gap: 0.35rem;
60
+ }
61
+
62
+ .ui-sb-spinner-icon {
63
+ animation: ui-sb-spin 0.8s linear infinite;
64
+ color: var(--ui-accent);
65
+ }
66
+
67
+ @keyframes ui-sb-spin {
68
+ to { transform: rotate(360deg); }
69
+ }
70
+
71
+ /* Progress */
72
+
73
+ .ui-sb-progress {
74
+ display: inline-flex;
75
+ align-items: center;
76
+ gap: 0.4rem;
77
+ }
78
+
79
+ .ui-sb-progress-track {
80
+ height: 4px;
81
+ background: var(--ui-surface-raised);
82
+ border-radius: 2px;
83
+ overflow: hidden;
84
+ display: inline-block;
85
+ }
86
+
87
+ .ui-sb-progress-fill {
88
+ display: block;
89
+ height: 100%;
90
+ background: var(--ui-accent);
91
+ border-radius: 2px;
92
+ transition: width 0.3s var(--ui-ease);
93
+ }
94
+
95
+ /* Badge */
96
+
97
+ .ui-sb-badge {
98
+ display: inline-flex;
99
+ align-items: center;
100
+ gap: 0.3rem;
101
+ white-space: nowrap;
102
+ }
103
+
104
+ .ui-sb-badge-dot {
105
+ width: 6px;
106
+ height: 6px;
107
+ border-radius: 50%;
108
+ flex-shrink: 0;
109
+ }
110
+
111
+ /* Separator */
112
+
113
+ .ui-sb-sep {
114
+ width: 1px;
115
+ height: 14px;
116
+ background: var(--ui-border);
117
+ flex-shrink: 0;
118
+ }
@@ -0,0 +1,78 @@
1
+ /** Contract: contracts/packages-ui-components/rules.md */
2
+
3
+ /**
4
+ * Fixed footer status bar with composable data chunks.
5
+ * Mirrors PageHeader as a bottom counterpart with glass blur.
6
+ *
7
+ * @param {ReactNode} left - Left-aligned chunks
8
+ * @param {ReactNode} right - Right-aligned chunks
9
+ * @param {ReactNode} center - Center-aligned chunks (optional)
10
+ * @param {string} className - Additional class names
11
+ */
12
+ export default function StatusBar({ left, right, center, className }) {
13
+ return (
14
+ <footer className={`ui-statusbar${className ? ` ${className}` : ''}`}>
15
+ <div className="ui-statusbar-left">{left}</div>
16
+ {center && <div className="ui-statusbar-center">{center}</div>}
17
+ <div className="ui-statusbar-right">{right}</div>
18
+ </footer>
19
+ );
20
+ }
21
+
22
+ /** Text chunk — label with optional muted prefix */
23
+ function Text({ label, value, muted }) {
24
+ return (
25
+ <span className={`ui-sb-text${muted ? ' ui-sb-text--muted' : ''}`}>
26
+ {label && <span className="ui-sb-label">{label}</span>}
27
+ {value}
28
+ </span>
29
+ );
30
+ }
31
+
32
+ /** Spinner chunk — small rotating indicator with optional label */
33
+ function Spinner({ label, size = 14 }) {
34
+ return (
35
+ <span className="ui-sb-spinner">
36
+ <svg className="ui-sb-spinner-icon" width={size} height={size} viewBox="0 0 16 16" fill="none">
37
+ <circle cx="8" cy="8" r="6" stroke="currentColor" strokeWidth="2" opacity="0.25" />
38
+ <path d="M14 8a6 6 0 0 0-6-6" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
39
+ </svg>
40
+ {label && <span className="ui-sb-label">{label}</span>}
41
+ </span>
42
+ );
43
+ }
44
+
45
+ /** Progress chunk — thin inline progress bar */
46
+ function Progress({ value, max = 100, label, width = 80 }) {
47
+ const pct = Math.min(100, Math.max(0, (value / max) * 100));
48
+ return (
49
+ <span className="ui-sb-progress">
50
+ {label && <span className="ui-sb-label">{label}</span>}
51
+ <span className="ui-sb-progress-track" style={{ width }}>
52
+ <span className="ui-sb-progress-fill" style={{ width: `${pct}%` }} />
53
+ </span>
54
+ <span className="ui-sb-text ui-sb-text--muted">{Math.round(pct)}%</span>
55
+ </span>
56
+ );
57
+ }
58
+
59
+ /** Badge chunk — colored indicator dot with label */
60
+ function Badge({ label, color = 'var(--ui-success)' }) {
61
+ return (
62
+ <span className="ui-sb-badge">
63
+ <span className="ui-sb-badge-dot" style={{ background: color }} />
64
+ {label}
65
+ </span>
66
+ );
67
+ }
68
+
69
+ /** Separator — vertical divider between chunks */
70
+ function Separator() {
71
+ return <span className="ui-sb-sep" />;
72
+ }
73
+
74
+ StatusBar.Text = Text;
75
+ StatusBar.Spinner = Spinner;
76
+ StatusBar.Progress = Progress;
77
+ StatusBar.Badge = Badge;
78
+ StatusBar.Separator = Separator;
package/src/index.js CHANGED
@@ -19,6 +19,8 @@ import './components/SlidePanel.css';
19
19
  import './components/LoginCard.css';
20
20
  import './components/PasskeyLoginPage.css';
21
21
  import './components/UserMenu.css';
22
+ import './components/StatusBar.css';
23
+ import './components/Panel.css';
22
24
 
23
25
  /* Components */
24
26
  export { default as ContextMenu } from './components/ContextMenu.jsx';
@@ -36,6 +38,8 @@ export { default as SlidePanel } from './components/SlidePanel.jsx';
36
38
  export { default as LoginCard } from './components/LoginCard.jsx';
37
39
  export { default as PasskeyLoginPage } from './components/PasskeyLoginPage.jsx';
38
40
  export { default as UserMenu } from './components/UserMenu.jsx';
41
+ export { default as StatusBar } from './components/StatusBar.jsx';
42
+ export { default as Panel } from './components/Panel.jsx';
39
43
 
40
44
  /* Auth */
41
45
  export { AuthProvider, useAuth } from './auth/AuthProvider.jsx';
@@ -124,11 +124,11 @@
124
124
  position: fixed;
125
125
  inset: 0;
126
126
  background:
127
- radial-gradient(ellipse 80% 60% at 15% 10%, rgba(124, 108, 240, 0.12), transparent),
128
- radial-gradient(ellipse 60% 50% at 85% 20%, rgba(56, 189, 248, 0.08), transparent),
129
- radial-gradient(ellipse 50% 60% at 40% 90%, rgba(168, 85, 247, 0.10), transparent),
130
- radial-gradient(ellipse 70% 40% at 75% 75%, rgba(34, 211, 153, 0.06), transparent),
131
- radial-gradient(ellipse 40% 30% at 50% 50%, rgba(244, 114, 182, 0.04), transparent);
127
+ radial-gradient(ellipse 80% 60% at 15% 10%, rgba(124, 108, 240, 0.084), transparent),
128
+ radial-gradient(ellipse 60% 50% at 85% 20%, rgba(56, 189, 248, 0.056), transparent),
129
+ radial-gradient(ellipse 50% 60% at 40% 90%, rgba(168, 85, 247, 0.07), transparent),
130
+ radial-gradient(ellipse 70% 40% at 75% 75%, rgba(34, 211, 153, 0.042), transparent),
131
+ radial-gradient(ellipse 40% 30% at 50% 50%, rgba(244, 114, 182, 0.028), transparent);
132
132
  pointer-events: none;
133
133
  z-index: 0;
134
134
  }