@keenmate/pure-admin-core 2.3.6 → 2.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/README.md +23 -29
- package/dist/css/main.css +68 -148
- package/package.json +1 -5
- package/snippets/AUDIT.md +94 -0
- package/snippets/alerts.html +264 -89
- package/snippets/badges.html +193 -61
- package/snippets/buttons.html +178 -0
- package/snippets/callouts.html +210 -129
- package/snippets/cards.html +383 -200
- package/snippets/checkbox-lists.html +199 -65
- package/snippets/code.html +55 -11
- package/snippets/command-palette.html +401 -111
- package/snippets/comparison.html +144 -93
- package/snippets/customization.html +311 -104
- package/snippets/data-display.html +584 -0
- package/snippets/detail-panel.html +470 -138
- package/snippets/filter-card.html +246 -0
- package/snippets/forms.html +408 -308
- package/snippets/grid.html +253 -141
- package/snippets/layout.html +379 -480
- package/snippets/lists.html +144 -47
- package/snippets/loaders.html +64 -39
- package/snippets/manifest.json +330 -280
- package/snippets/modal-dialogs.html +137 -64
- package/snippets/modals.html +221 -151
- package/snippets/notifications.html +285 -0
- package/snippets/popconfirm.html +213 -19
- package/snippets/profile.html +290 -330
- package/snippets/statistics.html +247 -0
- package/snippets/tables.html +359 -150
- package/snippets/tabs.html +129 -45
- package/snippets/timeline.html +123 -56
- package/snippets/toasts.html +179 -31
- package/snippets/tooltips.html +199 -81
- package/snippets/typography.html +183 -58
- package/snippets/utilities.html +511 -415
- package/snippets/virtual-scroll.html +201 -75
- package/snippets/web-daterangepicker.html +369 -189
- package/snippets/web-multiselect.html +360 -124
- package/src/scss/core-components/_alerts.scss +51 -12
- package/src/scss/core-components/_pagers.scss +1 -1
- package/src/scss/core-components/_popconfirm.scss +35 -13
- package/src/scss/core-components/_profile.scss +18 -8
- package/src/scss/core-components/_statistics.scss +12 -12
- package/src/scss/core-components/_tables.scss +2 -134
- package/src/scss/variables/_components.scss +17 -2
- package/scripts/download-themes.js +0 -351
package/snippets/profile.html
CHANGED
|
@@ -1,41 +1,63 @@
|
|
|
1
1
|
<!-- ================================
|
|
2
2
|
PROFILE PANEL SNIPPETS
|
|
3
3
|
Pure Admin Visual Framework
|
|
4
|
+
|
|
5
|
+
A slide-in side panel anchored to the inline-end edge of the
|
|
6
|
+
viewport. Toggled via JS by swapping a --open modifier on the
|
|
7
|
+
container. Width is driven by two CSS custom properties exposed
|
|
8
|
+
at :root, so utility classes can override without specificity
|
|
9
|
+
battles.
|
|
4
10
|
================================ -->
|
|
5
11
|
|
|
12
|
+
|
|
6
13
|
<!-- ================================
|
|
7
|
-
PROFILE BUTTON (
|
|
14
|
+
PROFILE BUTTON (in the navbar)
|
|
15
|
+
Shows the avatar + user name next to the burger/brand; acts as
|
|
16
|
+
the trigger for the panel. Hidden text on mobile (only icon shows).
|
|
8
17
|
================================ -->
|
|
9
18
|
|
|
10
|
-
<!-- Profile Button (goes in header/navbar) -->
|
|
11
19
|
<button class="pa-header__profile-btn" onclick="toggleProfilePanel()" aria-label="User Profile">
|
|
12
20
|
<span class="pa-btn__icon">👤</span>
|
|
13
21
|
<span class="pa-header__profile-name">John Doe</span>
|
|
14
22
|
</button>
|
|
15
23
|
|
|
16
|
-
<!--
|
|
24
|
+
<!-- With Font Awesome -->
|
|
17
25
|
<button class="pa-header__profile-btn" onclick="toggleProfilePanel()" aria-label="User Profile">
|
|
18
26
|
<span class="pa-btn__icon"><i class="fa-solid fa-user"></i></span>
|
|
19
27
|
<span class="pa-header__profile-name">John Doe</span>
|
|
20
28
|
</button>
|
|
21
29
|
|
|
30
|
+
<!--
|
|
31
|
+
Responsive: below $mobile-breakpoint (768px), .pa-header__profile-name
|
|
32
|
+
is hidden via `display: none` — the button collapses to just the icon
|
|
33
|
+
to save horizontal space in the navbar.
|
|
34
|
+
-->
|
|
35
|
+
|
|
22
36
|
|
|
23
37
|
<!-- ================================
|
|
24
|
-
PROFILE PANEL
|
|
38
|
+
BASIC PROFILE PANEL
|
|
39
|
+
Place the panel markup near </body> (outside the layout), because
|
|
40
|
+
it's position: fixed and shouldn't inherit layout container state.
|
|
41
|
+
The `id="profilePanel"` is what the example JS below looks up;
|
|
42
|
+
any id works as long as your toggle/close functions match.
|
|
25
43
|
================================ -->
|
|
26
44
|
|
|
27
|
-
<!-- Complete Profile Panel (place before closing </body> tag) -->
|
|
28
|
-
<!-- Note: Use title attributes on name/email for tooltips when text may be truncated -->
|
|
29
45
|
<div class="pa-profile-panel" id="profilePanel">
|
|
46
|
+
<!-- Click-to-close overlay (fills the viewport behind the content) -->
|
|
30
47
|
<div class="pa-profile-panel__overlay" onclick="closeProfilePanel()"></div>
|
|
48
|
+
|
|
49
|
+
<!-- The panel body; width is driven by --pa-local-profile-panel-* vars -->
|
|
31
50
|
<div class="pa-profile-panel__content">
|
|
51
|
+
|
|
52
|
+
<!-- Header: avatar + info + close button -->
|
|
32
53
|
<div class="pa-profile-panel__header">
|
|
33
54
|
<div class="pa-profile-panel__avatar">
|
|
34
55
|
<span class="pa-profile-panel__avatar-icon">👤</span>
|
|
35
56
|
</div>
|
|
36
57
|
<div class="pa-profile-panel__info">
|
|
37
|
-
|
|
38
|
-
<
|
|
58
|
+
<!-- title= attrs give a tooltip when the text truncates with ellipsis -->
|
|
59
|
+
<h3 class="pa-profile-panel__name" title="John Doe">John Doe</h3>
|
|
60
|
+
<p class="pa-profile-panel__email" title="john.doe@company.com">john.doe@company.com</p>
|
|
39
61
|
<span class="pa-profile-panel__role">Administrator</span>
|
|
40
62
|
</div>
|
|
41
63
|
<button class="pa-profile-panel__close" onclick="closeProfilePanel()" aria-label="Close Profile">
|
|
@@ -43,6 +65,7 @@
|
|
|
43
65
|
</button>
|
|
44
66
|
</div>
|
|
45
67
|
|
|
68
|
+
<!-- Body: scrollable; nav items + in-body actions -->
|
|
46
69
|
<div class="pa-profile-panel__body">
|
|
47
70
|
<nav class="pa-profile-panel__nav">
|
|
48
71
|
<ul>
|
|
@@ -64,18 +87,15 @@
|
|
|
64
87
|
</a></li>
|
|
65
88
|
<li><a href="#help" class="pa-profile-panel__nav-item">
|
|
66
89
|
<span class="pa-profile-panel__nav-icon">❓</span>
|
|
67
|
-
Help & Support
|
|
90
|
+
Help & Support
|
|
68
91
|
</a></li>
|
|
69
92
|
</ul>
|
|
70
93
|
</nav>
|
|
71
94
|
|
|
95
|
+
<!-- Actions inside __body: scroll with the nav above them -->
|
|
72
96
|
<div class="pa-profile-panel__actions">
|
|
73
|
-
<button class="pa-btn pa-btn--secondary pa-btn--block">
|
|
74
|
-
|
|
75
|
-
</button>
|
|
76
|
-
<button class="pa-btn pa-btn--danger pa-btn--block">
|
|
77
|
-
Sign Out
|
|
78
|
-
</button>
|
|
97
|
+
<button class="pa-btn pa-btn--secondary pa-btn--block">Switch Account</button>
|
|
98
|
+
<button class="pa-btn pa-btn--danger pa-btn--block">Sign Out</button>
|
|
79
99
|
</div>
|
|
80
100
|
</div>
|
|
81
101
|
</div>
|
|
@@ -83,76 +103,63 @@
|
|
|
83
103
|
|
|
84
104
|
|
|
85
105
|
<!-- ================================
|
|
86
|
-
|
|
87
|
-
|
|
106
|
+
PANEL WITH A FIXED FOOTER
|
|
107
|
+
Moves the action buttons out of __body into __footer, which sits
|
|
108
|
+
outside the scroll area and stays pinned to the bottom of the
|
|
109
|
+
panel regardless of content length.
|
|
110
|
+
|
|
111
|
+
Rule of thumb:
|
|
112
|
+
- Short nav + actions that shouldn't scroll away → __footer
|
|
113
|
+
- Long nav + related actions at end of the list → __actions
|
|
88
114
|
================================ -->
|
|
89
115
|
|
|
90
116
|
<div class="pa-profile-panel" id="profilePanel">
|
|
91
117
|
<div class="pa-profile-panel__overlay" onclick="closeProfilePanel()"></div>
|
|
92
118
|
<div class="pa-profile-panel__content">
|
|
119
|
+
|
|
93
120
|
<div class="pa-profile-panel__header">
|
|
94
121
|
<div class="pa-profile-panel__avatar">
|
|
95
122
|
<span class="pa-profile-panel__avatar-icon">👤</span>
|
|
96
123
|
</div>
|
|
97
124
|
<div class="pa-profile-panel__info">
|
|
98
|
-
<h3 class="pa-profile-panel__name"
|
|
99
|
-
<p
|
|
125
|
+
<h3 class="pa-profile-panel__name">John Doe</h3>
|
|
126
|
+
<p class="pa-profile-panel__email">john.doe@company.com</p>
|
|
100
127
|
<span class="pa-profile-panel__role">Administrator</span>
|
|
101
128
|
</div>
|
|
102
|
-
<button class="pa-profile-panel__close" onclick="closeProfilePanel()" aria-label="Close Profile">
|
|
103
|
-
✕
|
|
104
|
-
</button>
|
|
129
|
+
<button class="pa-profile-panel__close" onclick="closeProfilePanel()" aria-label="Close Profile">✕</button>
|
|
105
130
|
</div>
|
|
106
131
|
|
|
132
|
+
<!-- Scrolls -->
|
|
107
133
|
<div class="pa-profile-panel__body">
|
|
108
|
-
<!-- Body content scrolls -->
|
|
109
134
|
<nav class="pa-profile-panel__nav">
|
|
110
135
|
<ul>
|
|
111
136
|
<li><a href="#profile" class="pa-profile-panel__nav-item">
|
|
112
|
-
<span class="pa-profile-panel__nav-icon">👤</span>
|
|
113
|
-
Profile Settings
|
|
137
|
+
<span class="pa-profile-panel__nav-icon">👤</span> Profile
|
|
114
138
|
</a></li>
|
|
115
139
|
<li><a href="#security" class="pa-profile-panel__nav-item">
|
|
116
|
-
<span class="pa-profile-panel__nav-icon">🔒</span>
|
|
117
|
-
Security
|
|
118
|
-
</a></li>
|
|
119
|
-
<li><a href="#notifications" class="pa-profile-panel__nav-item">
|
|
120
|
-
<span class="pa-profile-panel__nav-icon">🔔</span>
|
|
121
|
-
Notifications
|
|
122
|
-
</a></li>
|
|
123
|
-
<li><a href="#preferences" class="pa-profile-panel__nav-item">
|
|
124
|
-
<span class="pa-profile-panel__nav-icon">⚙️</span>
|
|
125
|
-
Preferences
|
|
126
|
-
</a></li>
|
|
127
|
-
<li><a href="#help" class="pa-profile-panel__nav-item">
|
|
128
|
-
<span class="pa-profile-panel__nav-icon">❓</span>
|
|
129
|
-
Help & Support
|
|
140
|
+
<span class="pa-profile-panel__nav-icon">🔒</span> Security
|
|
130
141
|
</a></li>
|
|
142
|
+
<!-- … many items … -->
|
|
131
143
|
</ul>
|
|
132
144
|
</nav>
|
|
133
|
-
<!-- NO __actions here - they go in __footer -->
|
|
134
145
|
</div>
|
|
135
146
|
|
|
136
|
-
<!--
|
|
147
|
+
<!-- Stays pinned to the bottom of the panel -->
|
|
137
148
|
<div class="pa-profile-panel__footer">
|
|
138
|
-
<button class="pa-btn pa-btn--secondary pa-btn--block">
|
|
139
|
-
|
|
140
|
-
</button>
|
|
141
|
-
<button class="pa-btn pa-btn--danger pa-btn--block">
|
|
142
|
-
Sign Out
|
|
143
|
-
</button>
|
|
149
|
+
<button class="pa-btn pa-btn--secondary pa-btn--block">Switch Account</button>
|
|
150
|
+
<button class="pa-btn pa-btn--danger pa-btn--block">Sign Out</button>
|
|
144
151
|
</div>
|
|
145
152
|
</div>
|
|
146
153
|
</div>
|
|
147
154
|
|
|
148
155
|
|
|
149
156
|
<!-- ================================
|
|
150
|
-
|
|
151
|
-
|
|
157
|
+
NO-AVATAR VARIANT (corporate apps)
|
|
158
|
+
Some apps don't have user photos. Add --no-avatar to __header and
|
|
159
|
+
the SCSS hides the avatar element entirely. Keep the avatar markup
|
|
160
|
+
in place so you can re-enable it later by removing the modifier.
|
|
152
161
|
================================ -->
|
|
153
162
|
|
|
154
|
-
<!-- Profile Panel without avatar (for corporate apps that don't have user photos) -->
|
|
155
|
-
<!-- Add --no-avatar modifier to header to hide the avatar -->
|
|
156
163
|
<div class="pa-profile-panel" id="profilePanel">
|
|
157
164
|
<div class="pa-profile-panel__overlay" onclick="closeProfilePanel()"></div>
|
|
158
165
|
<div class="pa-profile-panel__content">
|
|
@@ -161,25 +168,20 @@
|
|
|
161
168
|
<span class="pa-profile-panel__avatar-icon">👤</span>
|
|
162
169
|
</div>
|
|
163
170
|
<div class="pa-profile-panel__info">
|
|
164
|
-
<h3 class="pa-profile-panel__name"
|
|
165
|
-
<p
|
|
166
|
-
<span class="pa-profile-panel__role">
|
|
171
|
+
<h3 class="pa-profile-panel__name">Jane Smith</h3>
|
|
172
|
+
<p class="pa-profile-panel__email">jane.smith@corp.example</p>
|
|
173
|
+
<span class="pa-profile-panel__role">Analyst</span>
|
|
167
174
|
</div>
|
|
168
|
-
<button class="pa-profile-panel__close" onclick="closeProfilePanel()" aria-label="Close Profile">
|
|
169
|
-
✕
|
|
170
|
-
</button>
|
|
175
|
+
<button class="pa-profile-panel__close" onclick="closeProfilePanel()" aria-label="Close Profile">✕</button>
|
|
171
176
|
</div>
|
|
172
|
-
|
|
173
177
|
<div class="pa-profile-panel__body">
|
|
174
178
|
<nav class="pa-profile-panel__nav">
|
|
175
179
|
<ul>
|
|
176
180
|
<li><a href="#profile" class="pa-profile-panel__nav-item">
|
|
177
|
-
<span class="pa-profile-panel__nav-icon">👤</span>
|
|
178
|
-
Profile Settings
|
|
181
|
+
<span class="pa-profile-panel__nav-icon">👤</span> Profile
|
|
179
182
|
</a></li>
|
|
180
183
|
<li><a href="#logout" class="pa-profile-panel__nav-item">
|
|
181
|
-
<span class="pa-profile-panel__nav-icon">🚪</span>
|
|
182
|
-
Sign Out
|
|
184
|
+
<span class="pa-profile-panel__nav-icon">🚪</span> Sign Out
|
|
183
185
|
</a></li>
|
|
184
186
|
</ul>
|
|
185
187
|
</nav>
|
|
@@ -189,27 +191,28 @@
|
|
|
189
191
|
|
|
190
192
|
|
|
191
193
|
<!-- ================================
|
|
192
|
-
|
|
194
|
+
PANEL WITH TABS (Profile + Favorites)
|
|
195
|
+
Uses the shared .pa-tabs component (see tabs.html for full details).
|
|
196
|
+
Tab buttons carry `data-profile-tab="foo"`, matching panels carry
|
|
197
|
+
`data-profile-panel="foo"`. The JS at the bottom wires up the
|
|
198
|
+
switching by toggling --active on both.
|
|
193
199
|
================================ -->
|
|
194
200
|
|
|
195
201
|
<div class="pa-profile-panel" id="profilePanel">
|
|
196
202
|
<div class="pa-profile-panel__overlay" onclick="closeProfilePanel()"></div>
|
|
197
203
|
<div class="pa-profile-panel__content">
|
|
204
|
+
|
|
198
205
|
<div class="pa-profile-panel__header">
|
|
199
|
-
<div class="pa-profile-panel__avatar">
|
|
200
|
-
<span class="pa-profile-panel__avatar-icon">👤</span>
|
|
201
|
-
</div>
|
|
206
|
+
<div class="pa-profile-panel__avatar"><span class="pa-profile-panel__avatar-icon">👤</span></div>
|
|
202
207
|
<div class="pa-profile-panel__info">
|
|
203
208
|
<h3 class="pa-profile-panel__name">John Doe</h3>
|
|
204
|
-
<p
|
|
209
|
+
<p class="pa-profile-panel__email">john.doe@company.com</p>
|
|
205
210
|
<span class="pa-profile-panel__role">Administrator</span>
|
|
206
211
|
</div>
|
|
207
|
-
<button class="pa-profile-panel__close" onclick="closeProfilePanel()" aria-label="Close Profile">
|
|
208
|
-
✕
|
|
209
|
-
</button>
|
|
212
|
+
<button class="pa-profile-panel__close" onclick="closeProfilePanel()" aria-label="Close Profile">✕</button>
|
|
210
213
|
</div>
|
|
211
214
|
|
|
212
|
-
<!--
|
|
215
|
+
<!-- Tab strip — sits between header and body -->
|
|
213
216
|
<div class="pa-profile-panel__tabs">
|
|
214
217
|
<div class="pa-tabs pa-tabs--full">
|
|
215
218
|
<button class="pa-tabs__item pa-tabs__item--active" data-profile-tab="profile">
|
|
@@ -224,47 +227,32 @@
|
|
|
224
227
|
</div>
|
|
225
228
|
|
|
226
229
|
<div class="pa-profile-panel__body">
|
|
227
|
-
<!-- Profile
|
|
230
|
+
<!-- Profile tab -->
|
|
228
231
|
<div class="pa-tabs__panel pa-tabs__panel--active" data-profile-panel="profile">
|
|
229
232
|
<nav class="pa-profile-panel__nav">
|
|
230
233
|
<ul>
|
|
231
234
|
<li><a href="#profile" class="pa-profile-panel__nav-item">
|
|
232
|
-
<span class="pa-profile-panel__nav-icon">👤</span>
|
|
233
|
-
Profile Settings
|
|
235
|
+
<span class="pa-profile-panel__nav-icon">👤</span> Profile Settings
|
|
234
236
|
</a></li>
|
|
235
237
|
<li><a href="#security" class="pa-profile-panel__nav-item">
|
|
236
|
-
<span class="pa-profile-panel__nav-icon">🔒</span>
|
|
237
|
-
Security
|
|
238
|
-
</a></li>
|
|
239
|
-
<li><a href="#notifications" class="pa-profile-panel__nav-item">
|
|
240
|
-
<span class="pa-profile-panel__nav-icon">🔔</span>
|
|
241
|
-
Notifications
|
|
242
|
-
</a></li>
|
|
243
|
-
<li><a href="#preferences" class="pa-profile-panel__nav-item">
|
|
244
|
-
<span class="pa-profile-panel__nav-icon">⚙️</span>
|
|
245
|
-
Preferences
|
|
246
|
-
</a></li>
|
|
247
|
-
<li><a href="#help" class="pa-profile-panel__nav-item">
|
|
248
|
-
<span class="pa-profile-panel__nav-icon">❓</span>
|
|
249
|
-
Help & Support
|
|
238
|
+
<span class="pa-profile-panel__nav-icon">🔒</span> Security
|
|
250
239
|
</a></li>
|
|
251
240
|
</ul>
|
|
252
241
|
</nav>
|
|
253
|
-
|
|
254
242
|
<div class="pa-profile-panel__actions">
|
|
255
|
-
<button class="pa-btn pa-btn--
|
|
256
|
-
Switch Account
|
|
257
|
-
</button>
|
|
258
|
-
<button class="pa-btn pa-btn--danger pa-btn--block">
|
|
259
|
-
Sign Out
|
|
260
|
-
</button>
|
|
243
|
+
<button class="pa-btn pa-btn--danger pa-btn--block">Sign Out</button>
|
|
261
244
|
</div>
|
|
262
245
|
</div>
|
|
263
246
|
|
|
264
|
-
<!-- Favorites
|
|
247
|
+
<!-- Favorites tab -->
|
|
265
248
|
<div class="pa-tabs__panel" data-profile-panel="favorites">
|
|
266
249
|
<div class="pa-profile-panel__favorites">
|
|
267
250
|
<ul>
|
|
251
|
+
<!-- __favorite-item is a <div> (not an <a>) because the
|
|
252
|
+
whole row is clickable via data-href + JS. The
|
|
253
|
+
__favorite-remove button is opacity: 0 until the
|
|
254
|
+
row is hovered — it fades in when a user is over
|
|
255
|
+
the favorite. -->
|
|
268
256
|
<li>
|
|
269
257
|
<div class="pa-profile-panel__favorite-item" data-href="/dashboard">
|
|
270
258
|
<span class="pa-profile-panel__favorite-icon">📊</span>
|
|
@@ -279,19 +267,10 @@
|
|
|
279
267
|
<button class="pa-profile-panel__favorite-remove" title="Remove from favorites">✕</button>
|
|
280
268
|
</div>
|
|
281
269
|
</li>
|
|
282
|
-
<li>
|
|
283
|
-
<div class="pa-profile-panel__favorite-item" data-href="/settings">
|
|
284
|
-
<span class="pa-profile-panel__favorite-icon">⚙️</span>
|
|
285
|
-
<span class="pa-profile-panel__favorite-label">Settings</span>
|
|
286
|
-
<button class="pa-profile-panel__favorite-remove" title="Remove from favorites">✕</button>
|
|
287
|
-
</div>
|
|
288
|
-
</li>
|
|
289
270
|
</ul>
|
|
290
271
|
</div>
|
|
291
272
|
<div class="pa-profile-panel__favorites-add">
|
|
292
|
-
<button class="pa-btn pa-btn--sm pa-btn--outline-secondary pa-btn--block">
|
|
293
|
-
+ Add Current Page
|
|
294
|
-
</button>
|
|
273
|
+
<button class="pa-btn pa-btn--sm pa-btn--outline-secondary pa-btn--block">+ Add Current Page</button>
|
|
295
274
|
</div>
|
|
296
275
|
</div>
|
|
297
276
|
</div>
|
|
@@ -299,214 +278,115 @@
|
|
|
299
278
|
</div>
|
|
300
279
|
|
|
301
280
|
|
|
302
|
-
<!--
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
<
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
</
|
|
314
|
-
|
|
315
|
-
<h3 class="pa-profile-panel__name">John Doe</h3>
|
|
316
|
-
<p class="pa-profile-panel__email">john.doe@company.com</p>
|
|
317
|
-
<span class="pa-profile-panel__role">Administrator</span>
|
|
318
|
-
</div>
|
|
319
|
-
<button class="pa-profile-panel__close" onclick="closeProfilePanel()" aria-label="Close Profile">
|
|
320
|
-
<i class="fa-solid fa-xmark"></i>
|
|
321
|
-
</button>
|
|
322
|
-
</div>
|
|
323
|
-
|
|
324
|
-
<!-- Profile Panel Tabs (icon-only) - add --icon-only modifier -->
|
|
325
|
-
<div class="pa-profile-panel__tabs pa-profile-panel__tabs--icon-only">
|
|
326
|
-
<div class="pa-tabs pa-tabs--full">
|
|
327
|
-
<button class="pa-tabs__item pa-tabs__item--active" data-profile-tab="profile" title="Profile">
|
|
328
|
-
<i class="fa-solid fa-user"></i>
|
|
329
|
-
<span class="pa-profile-panel__tab-text">Profile</span>
|
|
330
|
-
</button>
|
|
331
|
-
<button class="pa-tabs__item" data-profile-tab="favorites" title="Favorites">
|
|
332
|
-
<i class="fa-solid fa-star"></i>
|
|
333
|
-
<span class="pa-profile-panel__tab-text">Favorites</span>
|
|
334
|
-
</button>
|
|
335
|
-
</div>
|
|
336
|
-
</div>
|
|
337
|
-
|
|
338
|
-
<div class="pa-profile-panel__body">
|
|
339
|
-
<!-- Content same as regular tabs variant -->
|
|
340
|
-
</div>
|
|
281
|
+
<!-- Icon-only tab variant — hides the .pa-profile-panel__tab-text via
|
|
282
|
+
--icon-only on the tabs container. Keep the <span class="__tab-text">
|
|
283
|
+
markup in place so removing the modifier re-enables labels. -->
|
|
284
|
+
<div class="pa-profile-panel__tabs pa-profile-panel__tabs--icon-only">
|
|
285
|
+
<div class="pa-tabs pa-tabs--full">
|
|
286
|
+
<button class="pa-tabs__item pa-tabs__item--active" data-profile-tab="profile" title="Profile">
|
|
287
|
+
<i class="fa-solid fa-user"></i>
|
|
288
|
+
<span class="pa-profile-panel__tab-text">Profile</span>
|
|
289
|
+
</button>
|
|
290
|
+
<button class="pa-tabs__item" data-profile-tab="favorites" title="Favorites">
|
|
291
|
+
<i class="fa-solid fa-star"></i>
|
|
292
|
+
<span class="pa-profile-panel__tab-text">Favorites</span>
|
|
293
|
+
</button>
|
|
341
294
|
</div>
|
|
342
295
|
</div>
|
|
343
296
|
|
|
344
297
|
|
|
345
298
|
<!-- ================================
|
|
346
|
-
|
|
299
|
+
WIDTH CONTROL
|
|
300
|
+
The panel's content width is driven by two CSS custom properties
|
|
301
|
+
set at :root by the framework. The rule that applies them uses
|
|
302
|
+
:where() so the selector has ZERO specificity — any utility class
|
|
303
|
+
applied to .pa-profile-panel__content will win.
|
|
304
|
+
|
|
305
|
+
Default values:
|
|
306
|
+
--pa-local-profile-panel-width (set from $profile-panel-width)
|
|
307
|
+
--pa-local-profile-panel-max-width (set from $profile-panel-max-width)
|
|
308
|
+
|
|
309
|
+
Override strategies:
|
|
310
|
+
1. Utility class on __content — wr-*, minwr-*, maxwr-*
|
|
311
|
+
2. Inline style on __content — quick one-offs
|
|
312
|
+
3. Update the root CSS variable — app-wide change
|
|
347
313
|
================================ -->
|
|
348
314
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
<div class="pa-profile-panel__header">
|
|
353
|
-
<div class="pa-profile-panel__avatar">
|
|
354
|
-
<span class="pa-profile-panel__avatar-icon"><i class="fa-solid fa-user"></i></span>
|
|
355
|
-
</div>
|
|
356
|
-
<div class="pa-profile-panel__info">
|
|
357
|
-
<h3 class="pa-profile-panel__name">John Doe</h3>
|
|
358
|
-
<p class="pa-profile-panel__email">john.doe@company.com</p>
|
|
359
|
-
<span class="pa-profile-panel__role">Administrator</span>
|
|
360
|
-
</div>
|
|
361
|
-
<button class="pa-profile-panel__close" onclick="closeProfilePanel()" aria-label="Close Profile">
|
|
362
|
-
<i class="fa-solid fa-xmark"></i>
|
|
363
|
-
</button>
|
|
364
|
-
</div>
|
|
365
|
-
|
|
366
|
-
<div class="pa-profile-panel__body">
|
|
367
|
-
<nav class="pa-profile-panel__nav">
|
|
368
|
-
<ul>
|
|
369
|
-
<li><a href="#profile" class="pa-profile-panel__nav-item">
|
|
370
|
-
<span class="pa-profile-panel__nav-icon"><i class="fa-solid fa-user"></i></span>
|
|
371
|
-
Profile Settings
|
|
372
|
-
</a></li>
|
|
373
|
-
<li><a href="#security" class="pa-profile-panel__nav-item">
|
|
374
|
-
<span class="pa-profile-panel__nav-icon"><i class="fa-solid fa-lock"></i></span>
|
|
375
|
-
Security
|
|
376
|
-
</a></li>
|
|
377
|
-
<li><a href="#notifications" class="pa-profile-panel__nav-item">
|
|
378
|
-
<span class="pa-profile-panel__nav-icon"><i class="fa-solid fa-bell"></i></span>
|
|
379
|
-
Notifications
|
|
380
|
-
</a></li>
|
|
381
|
-
<li><a href="#preferences" class="pa-profile-panel__nav-item">
|
|
382
|
-
<span class="pa-profile-panel__nav-icon"><i class="fa-solid fa-gear"></i></span>
|
|
383
|
-
Preferences
|
|
384
|
-
</a></li>
|
|
385
|
-
<li><a href="#help" class="pa-profile-panel__nav-item">
|
|
386
|
-
<span class="pa-profile-panel__nav-icon"><i class="fa-solid fa-circle-question"></i></span>
|
|
387
|
-
Help & Support
|
|
388
|
-
</a></li>
|
|
389
|
-
</ul>
|
|
390
|
-
</nav>
|
|
391
|
-
|
|
392
|
-
<div class="pa-profile-panel__actions">
|
|
393
|
-
<button class="pa-btn pa-btn--secondary pa-btn--block">
|
|
394
|
-
<i class="fa-solid fa-right-left"></i> Switch Account
|
|
395
|
-
</button>
|
|
396
|
-
<button class="pa-btn pa-btn--danger pa-btn--block">
|
|
397
|
-
<i class="fa-solid fa-right-from-bracket"></i> Sign Out
|
|
398
|
-
</button>
|
|
399
|
-
</div>
|
|
400
|
-
</div>
|
|
401
|
-
</div>
|
|
315
|
+
<!-- 1. Fixed width — 30rem (300px). Wins because :where() = 0 specificity. -->
|
|
316
|
+
<div class="pa-profile-panel__content wr-30">
|
|
317
|
+
<!-- … -->
|
|
402
318
|
</div>
|
|
403
319
|
|
|
320
|
+
<!-- 2. Clamp between floor and ceiling — good for resizable panels -->
|
|
321
|
+
<div class="pa-profile-panel__content minwr-25 maxwr-50">
|
|
322
|
+
<!-- width is free between 25rem and 50rem -->
|
|
323
|
+
</div>
|
|
404
324
|
|
|
405
|
-
<!--
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
<div class="pa-profile-panel__header">
|
|
413
|
-
<div class="pa-profile-panel__avatar">
|
|
414
|
-
<span class="pa-profile-panel__avatar-icon">👤</span>
|
|
415
|
-
</div>
|
|
416
|
-
<div class="pa-profile-panel__info">
|
|
417
|
-
<h3 class="pa-profile-panel__name">John Doe</h3>
|
|
418
|
-
<p class="pa-profile-panel__email">john.doe@company.com</p>
|
|
419
|
-
<span class="pa-profile-panel__role">Administrator</span>
|
|
420
|
-
</div>
|
|
421
|
-
<button class="pa-profile-panel__close" onclick="closeProfilePanel()" aria-label="Close Profile">
|
|
422
|
-
✕
|
|
423
|
-
</button>
|
|
424
|
-
</div>
|
|
325
|
+
<!-- 3. App-wide default — set the CSS variable at :root (or on <html>) -->
|
|
326
|
+
<style>
|
|
327
|
+
:root {
|
|
328
|
+
--pa-local-profile-panel-width: 36rem;
|
|
329
|
+
--pa-local-profile-panel-max-width: 56rem;
|
|
330
|
+
}
|
|
331
|
+
</style>
|
|
425
332
|
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
<li><a href="#logout" class="pa-profile-panel__nav-item">
|
|
434
|
-
<span class="pa-profile-panel__nav-icon">🚪</span>
|
|
435
|
-
Sign Out
|
|
436
|
-
</a></li>
|
|
437
|
-
</ul>
|
|
438
|
-
</nav>
|
|
439
|
-
</div>
|
|
440
|
-
</div>
|
|
441
|
-
</div>
|
|
333
|
+
<!--
|
|
334
|
+
Responsive behaviour (automatic, below $mobile-breakpoint / 768px):
|
|
335
|
+
.pa-profile-panel__content → width: 85vw
|
|
336
|
+
max-width: $profile-panel-mobile-max-width
|
|
337
|
+
On mobile the panel fills most of the viewport regardless of the
|
|
338
|
+
desktop width-control setting.
|
|
339
|
+
-->
|
|
442
340
|
|
|
443
341
|
|
|
444
342
|
<!-- ================================
|
|
445
|
-
JAVASCRIPT
|
|
343
|
+
JAVASCRIPT — toggle, close, tabs, favorites
|
|
446
344
|
================================ -->
|
|
447
345
|
|
|
448
346
|
<script>
|
|
449
|
-
/**
|
|
450
|
-
* Toggle profile panel open/closed
|
|
451
|
-
*/
|
|
452
347
|
function toggleProfilePanel() {
|
|
453
|
-
|
|
454
|
-
profilePanel.classList.toggle('pa-profile-panel--open');
|
|
348
|
+
document.getElementById('profilePanel').classList.toggle('pa-profile-panel--open');
|
|
455
349
|
}
|
|
456
350
|
|
|
457
|
-
/**
|
|
458
|
-
* Close profile panel
|
|
459
|
-
*/
|
|
460
351
|
function closeProfilePanel() {
|
|
461
|
-
|
|
462
|
-
profilePanel.classList.remove('pa-profile-panel--open');
|
|
352
|
+
document.getElementById('profilePanel').classList.remove('pa-profile-panel--open');
|
|
463
353
|
}
|
|
464
354
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
355
|
+
// Click-outside-to-close — checks against the profile BUTTON as well
|
|
356
|
+
// as the panel itself so toggling via the button doesn't immediately
|
|
357
|
+
// re-close it.
|
|
468
358
|
document.addEventListener('click', (e) => {
|
|
469
|
-
const
|
|
470
|
-
const
|
|
471
|
-
|
|
472
|
-
if (!profilePanel || !profileBtn) return;
|
|
359
|
+
const panel = document.getElementById('profilePanel');
|
|
360
|
+
const btn = document.querySelector('.pa-header__profile-btn');
|
|
361
|
+
if (!panel || !btn) return;
|
|
473
362
|
|
|
474
|
-
if (!
|
|
475
|
-
|
|
363
|
+
if (!panel.contains(e.target) && !btn.contains(e.target) &&
|
|
364
|
+
panel.classList.contains('pa-profile-panel--open')) {
|
|
476
365
|
closeProfilePanel();
|
|
477
366
|
}
|
|
478
367
|
});
|
|
479
368
|
|
|
480
|
-
|
|
481
|
-
* Profile panel tab switching
|
|
482
|
-
*/
|
|
369
|
+
// Tab switching — flips --active on buttons + panels in lockstep.
|
|
483
370
|
document.querySelectorAll('[data-profile-tab]').forEach(tab => {
|
|
484
371
|
tab.addEventListener('click', () => {
|
|
485
|
-
const
|
|
486
|
-
// Update active tab
|
|
372
|
+
const id = tab.dataset.profileTab;
|
|
487
373
|
document.querySelectorAll('[data-profile-tab]').forEach(t =>
|
|
488
|
-
t.classList.toggle('pa-tabs__item--active', t.dataset.profileTab ===
|
|
489
|
-
// Update active panel
|
|
374
|
+
t.classList.toggle('pa-tabs__item--active', t.dataset.profileTab === id));
|
|
490
375
|
document.querySelectorAll('[data-profile-panel]').forEach(p =>
|
|
491
|
-
p.classList.toggle('pa-tabs__panel--active', p.dataset.profilePanel ===
|
|
376
|
+
p.classList.toggle('pa-tabs__panel--active', p.dataset.profilePanel === id));
|
|
492
377
|
});
|
|
493
378
|
});
|
|
494
379
|
|
|
495
|
-
|
|
496
|
-
* Favorite item click - navigate using data-href
|
|
497
|
-
*/
|
|
380
|
+
// Favorite click → navigate via data-href (unless the remove button was clicked)
|
|
498
381
|
document.querySelectorAll('.pa-profile-panel__favorite-item').forEach(item => {
|
|
499
382
|
item.addEventListener('click', (e) => {
|
|
500
|
-
// Skip if clicking the remove button
|
|
501
383
|
if (e.target.closest('.pa-profile-panel__favorite-remove')) return;
|
|
502
384
|
const href = item.dataset.href;
|
|
503
385
|
if (href) window.location.href = href;
|
|
504
386
|
});
|
|
505
387
|
});
|
|
506
388
|
|
|
507
|
-
|
|
508
|
-
* Favorite remove button - remove item from list
|
|
509
|
-
*/
|
|
389
|
+
// Favorite remove → drop the <li>
|
|
510
390
|
document.querySelectorAll('.pa-profile-panel__favorite-remove').forEach(btn => {
|
|
511
391
|
btn.addEventListener('click', (e) => {
|
|
512
392
|
e.stopPropagation();
|
|
@@ -517,67 +397,147 @@ document.querySelectorAll('.pa-profile-panel__favorite-remove').forEach(btn => {
|
|
|
517
397
|
|
|
518
398
|
|
|
519
399
|
<!-- ================================
|
|
520
|
-
|
|
400
|
+
COMPONENT REFERENCE
|
|
521
401
|
================================ -->
|
|
522
402
|
|
|
523
403
|
<!--
|
|
524
|
-
|
|
525
|
-
- .pa-header__profile-btn
|
|
526
|
-
- .pa-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
-
|
|
532
|
-
-
|
|
533
|
-
|
|
534
|
-
- .pa-profile-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
- .pa-profile-
|
|
542
|
-
- .pa-profile-
|
|
543
|
-
- .pa-profile-
|
|
544
|
-
- .pa-profile-
|
|
545
|
-
- .pa-profile-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
- .pa-profile-
|
|
549
|
-
- .pa-profile-
|
|
550
|
-
|
|
551
|
-
-
|
|
552
|
-
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
- .pa-profile-
|
|
567
|
-
|
|
568
|
-
- .pa-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
-
|
|
574
|
-
-
|
|
575
|
-
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
-
|
|
582
|
-
-
|
|
404
|
+
HEADER BUTTON:
|
|
405
|
+
- .pa-header__profile-btn The trigger button; lives in .pa-header__end.
|
|
406
|
+
- .pa-header__profile-name User's name text inside the button.
|
|
407
|
+
Hidden via `display: none` below 768px so
|
|
408
|
+
only the icon shows on mobile.
|
|
409
|
+
|
|
410
|
+
PANEL STRUCTURE:
|
|
411
|
+
- .pa-profile-panel Fixed-position container. Anchored to
|
|
412
|
+
inline-end (right in LTR, left in RTL).
|
|
413
|
+
Hidden by default (opacity: 0 + visibility).
|
|
414
|
+
- .pa-profile-panel--open Set by JS to reveal the panel.
|
|
415
|
+
- .pa-profile-panel__overlay Click-to-close backdrop (fills viewport).
|
|
416
|
+
- .pa-profile-panel__content The visible panel surface. Slides in
|
|
417
|
+
from the inline-end (translateX 100% → 0;
|
|
418
|
+
[dir="rtl"] flips to -100%).
|
|
419
|
+
|
|
420
|
+
HEADER:
|
|
421
|
+
- .pa-profile-panel__header Flex row: avatar + info + close.
|
|
422
|
+
- .pa-profile-panel__header--no-avatar Hides the avatar element (corporate apps).
|
|
423
|
+
- .pa-profile-panel__avatar Circular avatar wrapper.
|
|
424
|
+
- .pa-profile-panel__avatar-icon Emoji / FA icon inside the avatar.
|
|
425
|
+
- .pa-profile-panel__info Text column (name + email + role).
|
|
426
|
+
- .pa-profile-panel__name User name (ellipsis on overflow).
|
|
427
|
+
- .pa-profile-panel__email Email (ellipsis on overflow).
|
|
428
|
+
- .pa-profile-panel__role Role badge (uppercase, tinted bg).
|
|
429
|
+
- .pa-profile-panel__close Close button (top-end corner).
|
|
430
|
+
|
|
431
|
+
Theme-colour design choices (why they're like this):
|
|
432
|
+
- __name and __email use var(--pa-header-profile-name-color) — the same
|
|
433
|
+
colour the header uses for the user's name. This guarantees contrast
|
|
434
|
+
against dark / coloured header backgrounds across all themes (body
|
|
435
|
+
text colours would read wrong on a dark header).
|
|
436
|
+
- __role paints its background with color-mix(in srgb,
|
|
437
|
+
var(--pa-header-profile-name-color) 15%, transparent) so the tint is
|
|
438
|
+
derived from the header colour and works on any theme. An older
|
|
439
|
+
--pa-accent-light fallback is declared first for browsers without
|
|
440
|
+
color-mix.
|
|
441
|
+
|
|
442
|
+
TABS (optional — sits between __header and __body):
|
|
443
|
+
- .pa-profile-panel__tabs Tabs container (border-bottom + header-bg).
|
|
444
|
+
- .pa-profile-panel__tabs--icon-only Hide text labels, keep icons (tooltips
|
|
445
|
+
via `title` attrs recommended).
|
|
446
|
+
- .pa-profile-panel__tab-text Text label element inside a tab
|
|
447
|
+
(kept in markup; hidden by --icon-only).
|
|
448
|
+
- Uses the shared .pa-tabs / .pa-tabs--full / .pa-tabs__item / .pa-tabs__panel
|
|
449
|
+
component — see tabs.html for the full tab reference.
|
|
450
|
+
|
|
451
|
+
BODY + NAV:
|
|
452
|
+
- .pa-profile-panel__body flex: 1; overflow-y: auto. Scrollable.
|
|
453
|
+
- .pa-profile-panel__nav Navigation menu wrapper (ul reset).
|
|
454
|
+
- .pa-profile-panel__nav-item Menu item link (flex icon + label).
|
|
455
|
+
- .pa-profile-panel__nav-icon Fixed-width icon slot (sidebar icon size).
|
|
456
|
+
|
|
457
|
+
ACTIONS — two placements, mutually exclusive per action:
|
|
458
|
+
- .pa-profile-panel__actions Inside __body. Scrolls with the nav
|
|
459
|
+
above. Use for actions that belong to
|
|
460
|
+
the end of a list.
|
|
461
|
+
- .pa-profile-panel__footer Sibling of __body inside __content;
|
|
462
|
+
flex-shrink: 0. Always visible at the
|
|
463
|
+
bottom of the panel regardless of body
|
|
464
|
+
scroll position.
|
|
465
|
+
|
|
466
|
+
FAVORITES (inside a tab panel):
|
|
467
|
+
- .pa-profile-panel__favorites Wrapper (ul reset).
|
|
468
|
+
- .pa-profile-panel__favorite-item Row <div> with data-href (JS
|
|
469
|
+
navigates on click). Hover
|
|
470
|
+
reveals the __favorite-remove
|
|
471
|
+
button.
|
|
472
|
+
- .pa-profile-panel__favorite-icon Fixed-width icon slot.
|
|
473
|
+
- .pa-profile-panel__favorite-label flex: 1 label text.
|
|
474
|
+
- .pa-profile-panel__favorite-remove × button; opacity: 0 by default,
|
|
475
|
+
fades in on __favorite-item:hover.
|
|
476
|
+
- .pa-profile-panel__favorites-add Bottom wrapper for the "+ Add" button.
|
|
477
|
+
|
|
478
|
+
WIDTH CONTROL:
|
|
479
|
+
Two CSS custom properties, applied via a :where() rule on __content so
|
|
480
|
+
utility classes beat the default:
|
|
481
|
+
|
|
482
|
+
:root {
|
|
483
|
+
--pa-local-profile-panel-width: $profile-panel-width;
|
|
484
|
+
--pa-local-profile-panel-max-width: $profile-panel-max-width;
|
|
485
|
+
}
|
|
486
|
+
:where(.pa-profile-panel__content) {
|
|
487
|
+
width: var(--pa-local-profile-panel-width);
|
|
488
|
+
max-width: var(--pa-local-profile-panel-max-width);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
Override options:
|
|
492
|
+
- Utility class on __content — .wr-{n}, .minwr-{n}, .maxwr-{n}
|
|
493
|
+
(n = 1..10, 15, 20, 25, 30, 35, 40, 45, 50 rem)
|
|
494
|
+
- Inline style — quick one-off width / max-width
|
|
495
|
+
- Root CSS variable override — app-wide default change
|
|
496
|
+
|
|
497
|
+
RESPONSIVE BEHAVIOUR (automatic):
|
|
498
|
+
Below $mobile-breakpoint (768px):
|
|
499
|
+
.pa-profile-panel__content → width: 85vw,
|
|
500
|
+
max-width: $profile-panel-mobile-max-width
|
|
501
|
+
.pa-header__profile-name → display: none (icon-only button)
|
|
502
|
+
|
|
503
|
+
JAVASCRIPT CONTRACT:
|
|
504
|
+
- toggleProfilePanel() — flips --open on the panel
|
|
505
|
+
- closeProfilePanel() — removes --open
|
|
506
|
+
- Click-outside-to-close — registered on document, checks both the
|
|
507
|
+
panel AND the trigger button so toggling
|
|
508
|
+
via the button doesn't immediately re-close.
|
|
509
|
+
- Tabs — [data-profile-tab] on buttons pairs with
|
|
510
|
+
[data-profile-panel] on panels; both get
|
|
511
|
+
--active toggled in lockstep.
|
|
512
|
+
- Favorite nav — data-href attribute on __favorite-item; JS
|
|
513
|
+
navigates on click except when the remove
|
|
514
|
+
button is the target.
|
|
515
|
+
|
|
516
|
+
STRUCTURE PATTERNS:
|
|
517
|
+
|
|
518
|
+
Minimal panel (basic nav + in-body actions):
|
|
519
|
+
<div class="pa-profile-panel" id="profilePanel">
|
|
520
|
+
<div class="pa-profile-panel__overlay" onclick="closeProfilePanel()"></div>
|
|
521
|
+
<div class="pa-profile-panel__content">
|
|
522
|
+
<div class="pa-profile-panel__header">
|
|
523
|
+
<div class="pa-profile-panel__avatar">…</div>
|
|
524
|
+
<div class="pa-profile-panel__info">…</div>
|
|
525
|
+
<button class="pa-profile-panel__close">✕</button>
|
|
526
|
+
</div>
|
|
527
|
+
<div class="pa-profile-panel__body">
|
|
528
|
+
<nav class="pa-profile-panel__nav">…</nav>
|
|
529
|
+
<div class="pa-profile-panel__actions">…</div>
|
|
530
|
+
</div>
|
|
531
|
+
</div>
|
|
532
|
+
</div>
|
|
533
|
+
|
|
534
|
+
With fixed footer (actions pinned, body scrolls):
|
|
535
|
+
<div class="pa-profile-panel__content">
|
|
536
|
+
<div class="pa-profile-panel__header">…</div>
|
|
537
|
+
<div class="pa-profile-panel__body">…</div>
|
|
538
|
+
<div class="pa-profile-panel__footer">…</div>
|
|
539
|
+
</div>
|
|
540
|
+
|
|
541
|
+
Width override (fixed 30rem):
|
|
542
|
+
<div class="pa-profile-panel__content wr-30">…</div>
|
|
583
543
|
-->
|