@1889ca/ui 0.1.0 → 0.2.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 +1 -1
- package/src/components/LoginCard.css +98 -0
- package/src/components/LoginCard.jsx +46 -0
- package/src/index.js +2 -0
package/package.json
CHANGED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/** Contract: contracts/packages-ui-components/rules.md */
|
|
2
|
+
|
|
3
|
+
.ui-login-card {
|
|
4
|
+
position: relative;
|
|
5
|
+
display: flex;
|
|
6
|
+
flex-direction: column;
|
|
7
|
+
gap: 1rem;
|
|
8
|
+
width: 100%;
|
|
9
|
+
max-width: 400px;
|
|
10
|
+
padding: 2rem;
|
|
11
|
+
background: rgba(18, 18, 24, 0.7);
|
|
12
|
+
backdrop-filter: blur(var(--ui-glass-blur-heavy));
|
|
13
|
+
border: 1px solid var(--ui-border);
|
|
14
|
+
border-top-color: var(--ui-border-strong);
|
|
15
|
+
border-radius: var(--ui-radius-lg);
|
|
16
|
+
box-shadow: var(--ui-shadow-float);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/* Dev mode corner badge */
|
|
20
|
+
.ui-login-dev-badge {
|
|
21
|
+
position: absolute;
|
|
22
|
+
top: -1px;
|
|
23
|
+
right: -1px;
|
|
24
|
+
background: linear-gradient(135deg, #f59e0b, #f97316);
|
|
25
|
+
color: #000;
|
|
26
|
+
font-size: 0.65rem;
|
|
27
|
+
font-weight: 700;
|
|
28
|
+
letter-spacing: 0.08em;
|
|
29
|
+
padding: 0.2rem 0.65rem;
|
|
30
|
+
border-radius: 0 var(--ui-radius-lg) 0 var(--ui-radius);
|
|
31
|
+
box-shadow: 0 0 12px rgba(245, 158, 11, 0.3);
|
|
32
|
+
text-transform: uppercase;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* Gradient title */
|
|
36
|
+
.ui-login-title {
|
|
37
|
+
font-size: 2rem;
|
|
38
|
+
font-weight: 700;
|
|
39
|
+
letter-spacing: -0.03em;
|
|
40
|
+
line-height: 1.2;
|
|
41
|
+
background: linear-gradient(135deg, #fff 0%, var(--ui-accent) 100%);
|
|
42
|
+
-webkit-background-clip: text;
|
|
43
|
+
-webkit-text-fill-color: transparent;
|
|
44
|
+
background-clip: text;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.ui-login-subtitle {
|
|
48
|
+
color: var(--ui-text-muted);
|
|
49
|
+
font-size: 0.88rem;
|
|
50
|
+
margin-top: -0.5rem;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* Tab switcher */
|
|
54
|
+
.ui-login-tabs {
|
|
55
|
+
display: flex;
|
|
56
|
+
border: 1px solid var(--ui-border);
|
|
57
|
+
border-radius: var(--ui-radius);
|
|
58
|
+
overflow: hidden;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.ui-login-tab {
|
|
62
|
+
flex: 1;
|
|
63
|
+
background: transparent;
|
|
64
|
+
border: none;
|
|
65
|
+
color: var(--ui-text-muted);
|
|
66
|
+
padding: 0.55rem 0.5rem;
|
|
67
|
+
font-size: 0.85rem;
|
|
68
|
+
font-weight: 500;
|
|
69
|
+
cursor: pointer;
|
|
70
|
+
transition: all 0.2s var(--ui-ease);
|
|
71
|
+
font-family: inherit;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.ui-login-tab:hover {
|
|
75
|
+
color: var(--ui-text);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.ui-login-tab--active {
|
|
79
|
+
background: var(--ui-surface-raised);
|
|
80
|
+
color: var(--ui-text);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* Body / form area */
|
|
84
|
+
.ui-login-body {
|
|
85
|
+
display: flex;
|
|
86
|
+
flex-direction: column;
|
|
87
|
+
gap: 0.75rem;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/* Error display */
|
|
91
|
+
.ui-login-error {
|
|
92
|
+
color: var(--ui-danger);
|
|
93
|
+
font-size: 0.82rem;
|
|
94
|
+
padding: 0.5rem 0.75rem;
|
|
95
|
+
background: rgba(240, 96, 104, 0.08);
|
|
96
|
+
border: 1px solid rgba(240, 96, 104, 0.2);
|
|
97
|
+
border-radius: var(--ui-radius);
|
|
98
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** Contract: contracts/packages-ui-components/rules.md */
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Styled login card with optional dev-mode badge, gradient title,
|
|
6
|
+
* tab switcher, and form layout. Presentational only — consumers
|
|
7
|
+
* supply callbacks for auth logic.
|
|
8
|
+
*
|
|
9
|
+
* @param {string} title - App name / heading
|
|
10
|
+
* @param {string} subtitle - Short tagline
|
|
11
|
+
* @param {boolean} devMode - Show "DEV MODE" corner badge
|
|
12
|
+
* @param {Array} tabs - [{label, id}] for mode switcher (omit for single-mode)
|
|
13
|
+
* @param {string} activeTab - Currently active tab id
|
|
14
|
+
* @param {function} onTabChange - Called with tab id
|
|
15
|
+
* @param {string} error - Error message to display
|
|
16
|
+
* @param {ReactNode} children - Form content
|
|
17
|
+
*/
|
|
18
|
+
export default function LoginCard({ title, subtitle, devMode, tabs, activeTab, onTabChange, error, children }) {
|
|
19
|
+
return (
|
|
20
|
+
<div className="ui-login-card">
|
|
21
|
+
{devMode && <div className="ui-login-dev-badge">DEV MODE</div>}
|
|
22
|
+
{title && <h1 className="ui-login-title">{title}</h1>}
|
|
23
|
+
{subtitle && <p className="ui-login-subtitle">{subtitle}</p>}
|
|
24
|
+
{tabs && tabs.length > 0 && (
|
|
25
|
+
<div className="ui-login-tabs">
|
|
26
|
+
{tabs.map((tab) => (
|
|
27
|
+
<button
|
|
28
|
+
key={tab.id}
|
|
29
|
+
type="button"
|
|
30
|
+
className={`ui-login-tab${activeTab === tab.id ? ' ui-login-tab--active' : ''}`}
|
|
31
|
+
onClick={() => onTabChange?.(tab.id)}
|
|
32
|
+
>
|
|
33
|
+
{tab.label}
|
|
34
|
+
</button>
|
|
35
|
+
))}
|
|
36
|
+
</div>
|
|
37
|
+
)}
|
|
38
|
+
<div className="ui-login-body">
|
|
39
|
+
{error && (
|
|
40
|
+
<p className="ui-login-error">{error}</p>
|
|
41
|
+
)}
|
|
42
|
+
{children}
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
);
|
|
46
|
+
}
|
package/src/index.js
CHANGED
|
@@ -16,6 +16,7 @@ import './components/ItemGrid.css';
|
|
|
16
16
|
import './components/ItemCard.css';
|
|
17
17
|
import './components/FolderCard.css';
|
|
18
18
|
import './components/SlidePanel.css';
|
|
19
|
+
import './components/LoginCard.css';
|
|
19
20
|
|
|
20
21
|
/* Components */
|
|
21
22
|
export { default as ContextMenu } from './components/ContextMenu.jsx';
|
|
@@ -30,6 +31,7 @@ export { default as ItemGrid } from './components/ItemGrid.jsx';
|
|
|
30
31
|
export { default as ItemCard } from './components/ItemCard.jsx';
|
|
31
32
|
export { default as FolderCard } from './components/FolderCard.jsx';
|
|
32
33
|
export { default as SlidePanel } from './components/SlidePanel.jsx';
|
|
34
|
+
export { default as LoginCard } from './components/LoginCard.jsx';
|
|
33
35
|
|
|
34
36
|
/* Hooks */
|
|
35
37
|
export { default as useMultiSelect } from './hooks/useMultiSelect.js';
|