@_linked/cli 1.4.5 → 1.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/CHANGELOG.md +12 -0
- package/defaults/app-with-backend/package.json +1 -0
- package/defaults/app-with-backend/src/App.module.css +51 -0
- package/defaults/app-with-backend/src/pages/Page1.module.css +88 -4
- package/defaults/app-with-backend/src/pages/Page1.tsx +178 -6
- package/lib/cjs/package.json +1 -1
- package/lib/esm/package.json +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.5.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#34](https://github.com/linked-cm/cli/pull/34) [`4138d8f`](https://github.com/linked-cm/cli/commit/4138d8fbbee6c5def8538d2297bedd5c0ed3e4e7) Thanks [@flyon](https://github.com/flyon)! - Template visual upgrade: animated background + primitives showcase.
|
|
8
|
+
|
|
9
|
+
**Animated background.** `App.module.css` now renders a fixed-position layer underneath all content with three soft radial-gradient blobs that drift and gently pulse on a 22s loop. Brand-colored via `--color-primary-300` / `--color-secondary-300` / `--color-tertiary-200`, so the look re-tints automatically when an app overrides theme tokens. Honors `prefers-reduced-motion: reduce`.
|
|
10
|
+
|
|
11
|
+
**Protected page** (`/page1`) reworked into a `@_linked/primitives` showcase, organized into `Tabs` (Forms / Display / Buttons). Exercises `Button` (variants, colors, sizes), `Input`, `Switch`, `Checkbox`, `RadioGroup`, `Slider`, `Progress`, `Avatar`, `Label`, `Separator` — useful both as a visual smoke-test of the active theme and as starter code showing how to reach for each primitive.
|
|
12
|
+
|
|
13
|
+
`@_linked/primitives` added as a template dep (`^1.0.6`).
|
|
14
|
+
|
|
3
15
|
## 1.4.5
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -5,10 +5,61 @@
|
|
|
5
5
|
background: var(--bg-page);
|
|
6
6
|
color: var(--color-gray-900);
|
|
7
7
|
margin: 0;
|
|
8
|
+
overflow-x: hidden;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/* Animated background: soft radial-gradient "blobs" drifting and pulsing
|
|
12
|
+
underneath the content. Brand-colored via @_linked/css tokens — recolors
|
|
13
|
+
automatically when --color-primary-* / --color-secondary-* change in theme.css. */
|
|
14
|
+
:global(body)::before {
|
|
15
|
+
content: '';
|
|
16
|
+
position: fixed;
|
|
17
|
+
inset: 0;
|
|
18
|
+
z-index: -1;
|
|
19
|
+
pointer-events: none;
|
|
20
|
+
background:
|
|
21
|
+
radial-gradient(
|
|
22
|
+
circle at 18% 22%,
|
|
23
|
+
var(--color-primary-300) 0%,
|
|
24
|
+
transparent 38%
|
|
25
|
+
),
|
|
26
|
+
radial-gradient(
|
|
27
|
+
circle at 82% 76%,
|
|
28
|
+
var(--color-secondary-300) 0%,
|
|
29
|
+
transparent 42%
|
|
30
|
+
),
|
|
31
|
+
radial-gradient(
|
|
32
|
+
circle at 55% 58%,
|
|
33
|
+
var(--color-tertiary-200) 0%,
|
|
34
|
+
transparent 50%
|
|
35
|
+
);
|
|
36
|
+
opacity: 0.35;
|
|
37
|
+
filter: blur(40px);
|
|
38
|
+
animation: drift 22s ease-in-out infinite;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@keyframes drift {
|
|
42
|
+
0%,
|
|
43
|
+
100% {
|
|
44
|
+
transform: translate3d(0, 0, 0) scale(1);
|
|
45
|
+
}
|
|
46
|
+
33% {
|
|
47
|
+
transform: translate3d(-3%, 2%, 0) scale(1.05);
|
|
48
|
+
}
|
|
49
|
+
66% {
|
|
50
|
+
transform: translate3d(3%, -2%, 0) scale(0.97);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
@media (prefers-reduced-motion: reduce) {
|
|
55
|
+
:global(body)::before {
|
|
56
|
+
animation: none;
|
|
57
|
+
}
|
|
8
58
|
}
|
|
9
59
|
|
|
10
60
|
.App {
|
|
11
61
|
min-height: 100vh;
|
|
62
|
+
position: relative;
|
|
12
63
|
}
|
|
13
64
|
|
|
14
65
|
:global(h1) {
|
|
@@ -1,18 +1,102 @@
|
|
|
1
1
|
@import '@_linked/css/package.css';
|
|
2
2
|
|
|
3
|
-
.
|
|
3
|
+
.Page {
|
|
4
|
+
display: flex;
|
|
5
|
+
flex-direction: column;
|
|
6
|
+
gap: --spacing(5);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.Header {
|
|
4
10
|
background: var(--bg-card);
|
|
5
11
|
border-radius: var(--radius-card);
|
|
6
12
|
box-shadow: var(--shadow-card);
|
|
7
13
|
padding: --spacing(6);
|
|
8
14
|
}
|
|
9
15
|
|
|
10
|
-
.
|
|
11
|
-
margin: 0 0 --spacing(
|
|
16
|
+
.Header h2 {
|
|
17
|
+
margin: 0 0 --spacing(2);
|
|
12
18
|
}
|
|
13
19
|
|
|
14
|
-
.
|
|
20
|
+
.Header p {
|
|
15
21
|
color: var(--color-gray-700);
|
|
16
22
|
line-height: 1.5;
|
|
17
23
|
margin: 0;
|
|
18
24
|
}
|
|
25
|
+
|
|
26
|
+
.Header code {
|
|
27
|
+
background: var(--bg-section);
|
|
28
|
+
padding: 0 --spacing(1);
|
|
29
|
+
border-radius: var(--radius-element);
|
|
30
|
+
font-family: var(--font-mono);
|
|
31
|
+
font-size: 0.85em;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.Tabs {
|
|
35
|
+
background: var(--bg-card);
|
|
36
|
+
border-radius: var(--radius-card);
|
|
37
|
+
box-shadow: var(--shadow-card);
|
|
38
|
+
padding: --spacing(5);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.TabPanel {
|
|
42
|
+
display: grid;
|
|
43
|
+
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
|
44
|
+
gap: --spacing(4);
|
|
45
|
+
margin-top: --spacing(5);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.Card {
|
|
49
|
+
background: var(--bg-section);
|
|
50
|
+
border-radius: var(--radius-element);
|
|
51
|
+
padding: --spacing(4);
|
|
52
|
+
display: flex;
|
|
53
|
+
flex-direction: column;
|
|
54
|
+
gap: --spacing(3);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.Card h3 {
|
|
58
|
+
margin: 0;
|
|
59
|
+
font-size: 0.85rem;
|
|
60
|
+
font-weight: 600;
|
|
61
|
+
letter-spacing: 0.04em;
|
|
62
|
+
text-transform: uppercase;
|
|
63
|
+
color: var(--color-gray-600);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.Field {
|
|
67
|
+
display: flex;
|
|
68
|
+
flex-direction: column;
|
|
69
|
+
gap: --spacing(2);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.Stack {
|
|
73
|
+
display: flex;
|
|
74
|
+
flex-direction: column;
|
|
75
|
+
gap: --spacing(2);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.Row {
|
|
79
|
+
display: flex;
|
|
80
|
+
align-items: center;
|
|
81
|
+
gap: --spacing(2);
|
|
82
|
+
flex-wrap: wrap;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.ButtonRow {
|
|
86
|
+
display: flex;
|
|
87
|
+
align-items: center;
|
|
88
|
+
gap: --spacing(2);
|
|
89
|
+
flex-wrap: wrap;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.AvatarRow {
|
|
93
|
+
display: flex;
|
|
94
|
+
gap: --spacing(3);
|
|
95
|
+
align-items: center;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.Hint {
|
|
99
|
+
color: var(--color-gray-600);
|
|
100
|
+
font-size: 0.875rem;
|
|
101
|
+
margin: 0;
|
|
102
|
+
}
|
|
@@ -1,15 +1,187 @@
|
|
|
1
|
+
// Components showcase — demonstrates a slice of @_linked/primitives against
|
|
2
|
+
// the active @_linked/css theme. Open this page after signing in to see the
|
|
3
|
+
// design tokens in action. Replace with your own protected content.
|
|
4
|
+
import React, { useState } from 'react';
|
|
1
5
|
import { DefaultLayout } from '../layout/DefaultLayout';
|
|
6
|
+
import { Button } from '@_linked/primitives/components/Button';
|
|
7
|
+
import { Input } from '@_linked/primitives/components/Input';
|
|
8
|
+
import { Switch } from '@_linked/primitives/components/Switch';
|
|
9
|
+
import { Checkbox } from '@_linked/primitives/components/Checkbox';
|
|
10
|
+
import { Slider } from '@_linked/primitives/components/Slider';
|
|
11
|
+
import { Progress } from '@_linked/primitives/components/Progress';
|
|
12
|
+
import { Avatar } from '@_linked/primitives/components/Avatar';
|
|
13
|
+
import { Tabs } from '@_linked/primitives/components/Tabs';
|
|
14
|
+
import { RadioGroup } from '@_linked/primitives/components/RadioGroup';
|
|
15
|
+
import { Label } from '@_linked/primitives/components/Label';
|
|
16
|
+
import { Separator } from '@_linked/primitives/components/Separator';
|
|
2
17
|
import style from './Page1.module.css';
|
|
3
18
|
|
|
4
19
|
export default function Page1() {
|
|
20
|
+
const [progress, setProgress] = useState(60);
|
|
21
|
+
const [sliderValue, setSliderValue] = useState([40]);
|
|
22
|
+
const [checked, setChecked] = useState(true);
|
|
23
|
+
const [switchOn, setSwitchOn] = useState(true);
|
|
24
|
+
const [radio, setRadio] = useState('comfy');
|
|
25
|
+
const [text, setText] = useState('');
|
|
26
|
+
|
|
5
27
|
return (
|
|
6
28
|
<DefaultLayout>
|
|
7
|
-
<div className={style.
|
|
8
|
-
<
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
29
|
+
<div className={style.Page}>
|
|
30
|
+
<header className={style.Header}>
|
|
31
|
+
<h2>Components</h2>
|
|
32
|
+
<p>
|
|
33
|
+
A small tour of <code>@_linked/primitives</code> rendered against
|
|
34
|
+
the active <code>@_linked/css</code> theme. Tweak{' '}
|
|
35
|
+
<code>src/theme.css</code> tokens to re-skin every component on
|
|
36
|
+
this page.
|
|
37
|
+
</p>
|
|
38
|
+
</header>
|
|
39
|
+
|
|
40
|
+
<Tabs.Root defaultValue="forms" className={style.Tabs}>
|
|
41
|
+
<Tabs.List>
|
|
42
|
+
<Tabs.Trigger value="forms">Forms</Tabs.Trigger>
|
|
43
|
+
<Tabs.Trigger value="display">Display</Tabs.Trigger>
|
|
44
|
+
<Tabs.Trigger value="buttons">Buttons</Tabs.Trigger>
|
|
45
|
+
</Tabs.List>
|
|
46
|
+
|
|
47
|
+
<Tabs.Content value="forms" className={style.TabPanel}>
|
|
48
|
+
<section className={style.Card}>
|
|
49
|
+
<h3>Inputs</h3>
|
|
50
|
+
<div className={style.Field}>
|
|
51
|
+
<Label htmlFor="demo-name">Name</Label>
|
|
52
|
+
<Input
|
|
53
|
+
id="demo-name"
|
|
54
|
+
placeholder="Ada Lovelace"
|
|
55
|
+
value={text}
|
|
56
|
+
onChange={(e) => setText(e.target.value)}
|
|
57
|
+
/>
|
|
58
|
+
</div>
|
|
59
|
+
<Separator />
|
|
60
|
+
<div className={style.Row}>
|
|
61
|
+
<Switch
|
|
62
|
+
checked={switchOn}
|
|
63
|
+
onCheckedChange={(v) => setSwitchOn(Boolean(v))}
|
|
64
|
+
/>
|
|
65
|
+
<Label>Enable notifications</Label>
|
|
66
|
+
</div>
|
|
67
|
+
<div className={style.Row}>
|
|
68
|
+
<Checkbox
|
|
69
|
+
checked={checked}
|
|
70
|
+
onCheckedChange={(v) => setChecked(Boolean(v))}
|
|
71
|
+
/>
|
|
72
|
+
<Label>I agree to the terms</Label>
|
|
73
|
+
</div>
|
|
74
|
+
</section>
|
|
75
|
+
|
|
76
|
+
<section className={style.Card}>
|
|
77
|
+
<h3>Density</h3>
|
|
78
|
+
<RadioGroup.Root
|
|
79
|
+
value={radio}
|
|
80
|
+
onValueChange={setRadio}
|
|
81
|
+
className={style.Stack}
|
|
82
|
+
>
|
|
83
|
+
<div className={style.Row}>
|
|
84
|
+
<RadioGroup.Item value="compact" id="r-compact" />
|
|
85
|
+
<Label htmlFor="r-compact">Compact</Label>
|
|
86
|
+
</div>
|
|
87
|
+
<div className={style.Row}>
|
|
88
|
+
<RadioGroup.Item value="comfy" id="r-comfy" />
|
|
89
|
+
<Label htmlFor="r-comfy">Comfortable</Label>
|
|
90
|
+
</div>
|
|
91
|
+
<div className={style.Row}>
|
|
92
|
+
<RadioGroup.Item value="spacious" id="r-spacious" />
|
|
93
|
+
<Label htmlFor="r-spacious">Spacious</Label>
|
|
94
|
+
</div>
|
|
95
|
+
</RadioGroup.Root>
|
|
96
|
+
</section>
|
|
97
|
+
|
|
98
|
+
<section className={style.Card}>
|
|
99
|
+
<h3>Slider</h3>
|
|
100
|
+
<Slider.Root
|
|
101
|
+
value={sliderValue}
|
|
102
|
+
onValueChange={setSliderValue}
|
|
103
|
+
min={0}
|
|
104
|
+
max={100}
|
|
105
|
+
step={1}
|
|
106
|
+
>
|
|
107
|
+
<Slider.Track>
|
|
108
|
+
<Slider.Range />
|
|
109
|
+
</Slider.Track>
|
|
110
|
+
<Slider.Thumb />
|
|
111
|
+
</Slider.Root>
|
|
112
|
+
<p className={style.Hint}>Value: {sliderValue[0]}</p>
|
|
113
|
+
</section>
|
|
114
|
+
</Tabs.Content>
|
|
115
|
+
|
|
116
|
+
<Tabs.Content value="display" className={style.TabPanel}>
|
|
117
|
+
<section className={style.Card}>
|
|
118
|
+
<h3>Avatar</h3>
|
|
119
|
+
<div className={style.AvatarRow}>
|
|
120
|
+
<Avatar.Root>
|
|
121
|
+
<Avatar.Fallback>AL</Avatar.Fallback>
|
|
122
|
+
</Avatar.Root>
|
|
123
|
+
<Avatar.Root>
|
|
124
|
+
<Avatar.Fallback>GH</Avatar.Fallback>
|
|
125
|
+
</Avatar.Root>
|
|
126
|
+
<Avatar.Root>
|
|
127
|
+
<Avatar.Fallback>RV</Avatar.Fallback>
|
|
128
|
+
</Avatar.Root>
|
|
129
|
+
</div>
|
|
130
|
+
</section>
|
|
131
|
+
|
|
132
|
+
<section className={style.Card}>
|
|
133
|
+
<h3>Progress</h3>
|
|
134
|
+
<Progress.Root value={progress} />
|
|
135
|
+
<div className={style.Row}>
|
|
136
|
+
<Button
|
|
137
|
+
size="small"
|
|
138
|
+
variant="outline"
|
|
139
|
+
onClick={() => setProgress((p) => Math.max(0, p - 10))}
|
|
140
|
+
>
|
|
141
|
+
−10
|
|
142
|
+
</Button>
|
|
143
|
+
<Button
|
|
144
|
+
size="small"
|
|
145
|
+
variant="outline"
|
|
146
|
+
onClick={() => setProgress((p) => Math.min(100, p + 10))}
|
|
147
|
+
>
|
|
148
|
+
+10
|
|
149
|
+
</Button>
|
|
150
|
+
<span className={style.Hint}>{progress}%</span>
|
|
151
|
+
</div>
|
|
152
|
+
</section>
|
|
153
|
+
</Tabs.Content>
|
|
154
|
+
|
|
155
|
+
<Tabs.Content value="buttons" className={style.TabPanel}>
|
|
156
|
+
<section className={style.Card}>
|
|
157
|
+
<h3>Variants</h3>
|
|
158
|
+
<div className={style.ButtonRow}>
|
|
159
|
+
<Button variant="solid">Solid</Button>
|
|
160
|
+
<Button variant="outline">Outline</Button>
|
|
161
|
+
<Button variant="ghost">Ghost</Button>
|
|
162
|
+
<Button variant="link">Link</Button>
|
|
163
|
+
</div>
|
|
164
|
+
</section>
|
|
165
|
+
|
|
166
|
+
<section className={style.Card}>
|
|
167
|
+
<h3>Colors</h3>
|
|
168
|
+
<div className={style.ButtonRow}>
|
|
169
|
+
<Button color="primary">Primary</Button>
|
|
170
|
+
<Button color="secondary">Secondary</Button>
|
|
171
|
+
<Button color="tertiary">Tertiary</Button>
|
|
172
|
+
</div>
|
|
173
|
+
</section>
|
|
174
|
+
|
|
175
|
+
<section className={style.Card}>
|
|
176
|
+
<h3>Sizes</h3>
|
|
177
|
+
<div className={style.ButtonRow}>
|
|
178
|
+
<Button size="small">Small</Button>
|
|
179
|
+
<Button size="medium">Medium</Button>
|
|
180
|
+
<Button size="large">Large</Button>
|
|
181
|
+
</div>
|
|
182
|
+
</section>
|
|
183
|
+
</Tabs.Content>
|
|
184
|
+
</Tabs.Root>
|
|
13
185
|
</div>
|
|
14
186
|
</DefaultLayout>
|
|
15
187
|
);
|
package/lib/cjs/package.json
CHANGED
package/lib/esm/package.json
CHANGED