@jetbrains/ring-ui-built 7.0.123-beta.0 → 7.0.124
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 +0 -4
- package/components/_helpers/caption.js +1 -1
- package/components/_helpers/icon-svg.js +50 -35
- package/components/alert/alert.js +1 -1
- package/components/alert-service/alert-service.js +1 -1
- package/components/auth/auth-core.js +1 -1
- package/components/auth/auth.js +1 -1
- package/components/auth/down-notification.js +1 -1
- package/components/auth/storage.js +1 -1
- package/components/avatar-stack/avatar-stack.js +1 -1
- package/components/banner/banner.js +1 -1
- package/components/button/button.js +1 -1
- package/components/button-toolbar/button-toolbar.js +1 -1
- package/components/checkbox/checkbox.js +1 -0
- package/components/clipboard/clipboard.js +1 -1
- package/components/collapsible-group/collapsible-group.js +1 -0
- package/components/confirm-service/confirm-service.js +1 -1
- package/components/contenteditable/contenteditable.js +4 -3
- package/components/data-list/data-list.js +1 -1
- package/components/data-list/data-list.mock.js +1 -1
- package/components/data-list/item.js +1 -1
- package/components/data-list/title.js +1 -0
- package/components/date-picker/date-popup.js +1 -1
- package/components/dialog/dialog.js +1 -1
- package/components/dropdown/anchor.js +1 -1
- package/components/dropdown/dropdown.js +1 -1
- package/components/dropdown-menu/dropdown-menu.js +1 -1
- package/components/editable-heading/editable-heading.js +1 -1
- package/components/error-message/error-message.js +1 -0
- package/components/expand/collapsible-group.js +1 -0
- package/components/global/configuration.d.ts +5 -0
- package/components/global/configuration.js +10 -2
- package/components/global/controls-height.js +1 -1
- package/components/header/header-icon.js +1 -1
- package/components/header/header.js +1 -1
- package/components/header/logo.js +1 -0
- package/components/header/profile.js +1 -1
- package/components/header/services.js +1 -1
- package/components/header/smart-profile.js +1 -1
- package/components/header/smart-services.js +1 -1
- package/components/icon/icon-svg.js +1 -0
- package/components/icon/icon.js +1 -0
- package/components/icon/index.js +1 -0
- package/components/input/input.js +1 -1
- package/components/list/list-item.js +1 -0
- package/components/list/list-users-groups-source.js +1 -0
- package/components/list/list.js +1 -0
- package/components/login-dialog/login-dialog.js +1 -1
- package/components/old-browsers-message/white-list.js +2 -2
- package/components/query-assist/query-assist-suggestions.js +1 -0
- package/components/select/chevron-button.js +1 -1
- package/components/select/select-filter.js +1 -1
- package/components/storage/storage-local.js +1 -1
- package/components/storage/storage.js +1 -1
- package/components/style.css +1 -1
- package/components/table/header-cell.js +1 -0
- package/components/table/header.js +1 -0
- package/components/table/row-with-focus-sensor.js +1 -1
- package/components/table/row.js +1 -1
- package/components/table/simple-table.js +1 -1
- package/components/table/smart-table.js +1 -1
- package/components/table/table.js +1 -1
- package/components/tags-input/tags-input.js +1 -1
- package/components/tags-list/tags-list.js +1 -1
- package/components/upload/upload.js +1 -0
- package/components/user-agreement/service.js +1 -1
- package/components/user-card/smart-user-card-tooltip.js +1 -1
- package/components/user-card/tooltip.js +1 -1
- package/components/user-card/user-card.js +1 -1
- package/package.json +5 -7
- package/skills/ring-ui/SKILL.md +0 -43
- package/skills/ring-ui/references/forms-and-feedback.md +0 -261
- package/skills/ring-ui/references/page-layouts.md +0 -324
|
@@ -1,324 +0,0 @@
|
|
|
1
|
-
# Page layouts
|
|
2
|
-
|
|
3
|
-
Ring UI supplies controls, surfaces, and tokens. It does not replace page geometry: semantic HTML defines the document, while native CSS Grid/Flexbox defines the shell, widths, responsive behavior, sticky regions, and scroll ownership.
|
|
4
|
-
|
|
5
|
-
The examples and consumer imports use `@jetbrains/ring-ui-built`.
|
|
6
|
-
|
|
7
|
-
## Contents
|
|
8
|
-
|
|
9
|
-
- [App setup](#app-setup)
|
|
10
|
-
- [Complete page shell](#complete-page-shell)
|
|
11
|
-
- [Geometry rules](#geometry-rules)
|
|
12
|
-
- [Sticky offsets and nested scopes](#sticky-offsets-and-nested-scopes)
|
|
13
|
-
- [Theme, semantics, and accessibility](#theme-semantics-and-accessibility)
|
|
14
|
-
|
|
15
|
-
## App setup
|
|
16
|
-
|
|
17
|
-
Use the repository's package manager to install the built package. For example, with npm:
|
|
18
|
-
|
|
19
|
-
```shell
|
|
20
|
-
npm install @jetbrains/ring-ui-built
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
Import the consolidated stylesheet exactly once at the application entry point. Import components from the same package, and put `ThemeProvider` near the application root with `Theme.AUTO` and `passToPopups`:
|
|
24
|
-
|
|
25
|
-
```tsx
|
|
26
|
-
import {createRoot} from 'react-dom/client';
|
|
27
|
-
import '@jetbrains/ring-ui-built/components/style.css';
|
|
28
|
-
import Theme, {ThemeProvider} from '@jetbrains/ring-ui-built/components/global/theme';
|
|
29
|
-
|
|
30
|
-
import App from './App';
|
|
31
|
-
|
|
32
|
-
const rootElement = document.getElementById('root');
|
|
33
|
-
if (!rootElement) {
|
|
34
|
-
throw new Error('Root element #root was not found.');
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const root = createRoot(rootElement);
|
|
38
|
-
|
|
39
|
-
root.render(
|
|
40
|
-
<ThemeProvider theme={Theme.AUTO} passToPopups target={document.body}>
|
|
41
|
-
<App />
|
|
42
|
-
</ThemeProvider>,
|
|
43
|
-
);
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
Add `class="plugin"` to `<body>`:
|
|
47
|
-
|
|
48
|
-
```html
|
|
49
|
-
<body class="plugin">
|
|
50
|
-
<div id="root"></div>
|
|
51
|
-
</body>
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
Add the baseline page styles to application CSS:
|
|
55
|
-
|
|
56
|
-
```css
|
|
57
|
-
body.plugin {
|
|
58
|
-
padding: 0 16px;
|
|
59
|
-
background-color: var(--ring-content-background-color);
|
|
60
|
-
color: var(--ring-text-color);
|
|
61
|
-
font-size: var(--ring-font-size);
|
|
62
|
-
}
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
A deliberately full-bleed shell can override the body padding in application CSS.
|
|
66
|
-
|
|
67
|
-
## Complete page shell
|
|
68
|
-
|
|
69
|
-
`page-shell.tsx`:
|
|
70
|
-
|
|
71
|
-
```tsx
|
|
72
|
-
import type {ReactNode} from 'react';
|
|
73
|
-
import Button from '@jetbrains/ring-ui-built/components/button/button';
|
|
74
|
-
import {H1} from '@jetbrains/ring-ui-built/components/heading/heading';
|
|
75
|
-
|
|
76
|
-
import styles from './page-shell.module.css';
|
|
77
|
-
|
|
78
|
-
type PageShellProps = {
|
|
79
|
-
children: ReactNode;
|
|
80
|
-
currentPath: string;
|
|
81
|
-
onCreateProject: () => void;
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
const primaryNavigation = [
|
|
85
|
-
{href: '/projects', label: 'Projects'},
|
|
86
|
-
{href: '/teams', label: 'Teams'},
|
|
87
|
-
];
|
|
88
|
-
|
|
89
|
-
const settingsNavigation = [
|
|
90
|
-
{href: '/projects/settings/general', label: 'General'},
|
|
91
|
-
{href: '/projects/settings/access', label: 'Access'},
|
|
92
|
-
{href: '/projects/settings/integrations', label: 'Integrations'},
|
|
93
|
-
];
|
|
94
|
-
|
|
95
|
-
export function PageShell({children, currentPath, onCreateProject}: PageShellProps) {
|
|
96
|
-
return (
|
|
97
|
-
<div className={styles.shell}>
|
|
98
|
-
<a className={styles.skipLink} href="#main-content">
|
|
99
|
-
Skip to content
|
|
100
|
-
</a>
|
|
101
|
-
|
|
102
|
-
<header className={styles.topBar}>
|
|
103
|
-
<a className={styles.brand} href="/" aria-label="Acme home">
|
|
104
|
-
Acme
|
|
105
|
-
</a>
|
|
106
|
-
<nav className={styles.topNavigation} aria-label="Primary">
|
|
107
|
-
{primaryNavigation.map(item => (
|
|
108
|
-
<a
|
|
109
|
-
key={item.href}
|
|
110
|
-
className={styles.navigationLink}
|
|
111
|
-
href={item.href}
|
|
112
|
-
aria-current={currentPath === item.href ? 'page' : undefined}
|
|
113
|
-
>
|
|
114
|
-
{item.label}
|
|
115
|
-
</a>
|
|
116
|
-
))}
|
|
117
|
-
</nav>
|
|
118
|
-
<Button primary onClick={onCreateProject}>
|
|
119
|
-
New project
|
|
120
|
-
</Button>
|
|
121
|
-
</header>
|
|
122
|
-
|
|
123
|
-
<div className={styles.workspace}>
|
|
124
|
-
<aside className={styles.sidebar}>
|
|
125
|
-
<nav className={styles.sidebarNavigation} aria-label="Project settings">
|
|
126
|
-
{settingsNavigation.map(item => (
|
|
127
|
-
<a
|
|
128
|
-
key={item.href}
|
|
129
|
-
className={styles.sidebarLink}
|
|
130
|
-
href={item.href}
|
|
131
|
-
aria-current={currentPath === item.href ? 'page' : undefined}
|
|
132
|
-
>
|
|
133
|
-
{item.label}
|
|
134
|
-
</a>
|
|
135
|
-
))}
|
|
136
|
-
</nav>
|
|
137
|
-
</aside>
|
|
138
|
-
|
|
139
|
-
<main id="main-content" className={styles.main} tabIndex={-1}>
|
|
140
|
-
<div className={styles.content}>
|
|
141
|
-
<H1>Project settings</H1>
|
|
142
|
-
{children}
|
|
143
|
-
</div>
|
|
144
|
-
</main>
|
|
145
|
-
</div>
|
|
146
|
-
</div>
|
|
147
|
-
);
|
|
148
|
-
}
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
`page-shell.module.css`:
|
|
152
|
-
|
|
153
|
-
```css
|
|
154
|
-
.shell {
|
|
155
|
-
--page-top-offset: calc(var(--ring-unit) * 8);
|
|
156
|
-
|
|
157
|
-
min-height: 100dvh;
|
|
158
|
-
color: var(--ring-text-color);
|
|
159
|
-
background: var(--ring-content-background-color);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
.skipLink {
|
|
163
|
-
position: absolute;
|
|
164
|
-
z-index: 20;
|
|
165
|
-
inset-block-start: var(--ring-unit);
|
|
166
|
-
inset-inline-start: var(--ring-unit);
|
|
167
|
-
padding: var(--ring-unit) calc(var(--ring-unit) * 2);
|
|
168
|
-
color: var(--ring-link-color);
|
|
169
|
-
background: var(--ring-content-background-color);
|
|
170
|
-
border: 1px solid var(--ring-borders-color);
|
|
171
|
-
transform: translateY(-200%);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
.skipLink:focus {
|
|
175
|
-
transform: none;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
.topBar {
|
|
179
|
-
position: sticky;
|
|
180
|
-
z-index: 10;
|
|
181
|
-
inset-block-start: 0;
|
|
182
|
-
display: flex;
|
|
183
|
-
min-height: var(--page-top-offset);
|
|
184
|
-
align-items: center;
|
|
185
|
-
gap: calc(var(--ring-unit) * 2);
|
|
186
|
-
padding-inline: calc(var(--ring-unit) * 4);
|
|
187
|
-
background: var(--ring-navigation-background-color);
|
|
188
|
-
border-block-end: 1px solid var(--ring-line-color);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
.brand {
|
|
192
|
-
flex: none;
|
|
193
|
-
color: var(--ring-text-color);
|
|
194
|
-
font-weight: bold;
|
|
195
|
-
text-decoration: none;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
.topNavigation {
|
|
199
|
-
display: flex;
|
|
200
|
-
flex: 1;
|
|
201
|
-
flex-wrap: wrap;
|
|
202
|
-
gap: var(--ring-unit) calc(var(--ring-unit) * 2);
|
|
203
|
-
min-width: 0;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
.navigationLink,
|
|
207
|
-
.sidebarLink {
|
|
208
|
-
color: var(--ring-link-color);
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
.navigationLink[aria-current='page'],
|
|
212
|
-
.sidebarLink[aria-current='page'] {
|
|
213
|
-
color: var(--ring-text-color);
|
|
214
|
-
font-weight: bold;
|
|
215
|
-
text-decoration: none;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
.workspace {
|
|
219
|
-
display: grid;
|
|
220
|
-
grid-template-columns: calc(var(--ring-unit) * 30) minmax(0, 1fr);
|
|
221
|
-
min-height: calc(100dvh - var(--page-top-offset));
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
.sidebar {
|
|
225
|
-
position: sticky;
|
|
226
|
-
inset-block-start: var(--page-top-offset);
|
|
227
|
-
align-self: start;
|
|
228
|
-
padding: calc(var(--ring-unit) * 3);
|
|
229
|
-
background: var(--ring-sidebar-background-color);
|
|
230
|
-
border-inline-end: 1px solid var(--ring-line-color);
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
.sidebarNavigation {
|
|
234
|
-
display: flex;
|
|
235
|
-
flex-direction: column;
|
|
236
|
-
gap: var(--ring-unit);
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
.main {
|
|
240
|
-
min-width: 0;
|
|
241
|
-
padding: calc(var(--ring-unit) * 4);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
.content {
|
|
245
|
-
width: min(100%, calc(var(--ring-unit) * 120));
|
|
246
|
-
margin-inline: auto;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
@media (max-width: 760px) {
|
|
250
|
-
.shell {
|
|
251
|
-
--page-top-offset: 0px;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
.topBar {
|
|
255
|
-
position: static;
|
|
256
|
-
flex-wrap: wrap;
|
|
257
|
-
padding: calc(var(--ring-unit) * 2);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
.topNavigation {
|
|
261
|
-
order: 3;
|
|
262
|
-
flex-basis: 100%;
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
.workspace {
|
|
266
|
-
grid-template-columns: minmax(0, 1fr);
|
|
267
|
-
min-height: 0;
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
.sidebar {
|
|
271
|
-
position: static;
|
|
272
|
-
min-width: 0;
|
|
273
|
-
padding: var(--ring-unit) calc(var(--ring-unit) * 2);
|
|
274
|
-
overflow-x: auto;
|
|
275
|
-
border-inline-end: 0;
|
|
276
|
-
border-block-end: 1px solid var(--ring-line-color);
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
.sidebarNavigation {
|
|
280
|
-
width: max-content;
|
|
281
|
-
flex-direction: row;
|
|
282
|
-
gap: calc(var(--ring-unit) * 2);
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
.main {
|
|
286
|
-
padding: calc(var(--ring-unit) * 2);
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
## Geometry rules
|
|
292
|
-
|
|
293
|
-
- Use `--ring-unit` as the spacing base and semantic tokens such as `--ring-content-background-color`, `--ring-sidebar-background-color`, `--ring-text-color`, and `--ring-line-color`. Do not paste their current pixel or color values into application CSS.
|
|
294
|
-
- In Grid/Flexbox, `min-width: auto` can stop content from shrinking and `min-height: auto` can stop vertical children from scrolling. Put `min-width: 0` or `min-height: 0` on the child that must shrink.
|
|
295
|
-
- Assign exactly one scroll owner per axis and scope. Prefer document scrolling for a page; use a named inner owner only for a deliberate viewport-like region. The mobile sidebar above owns only its horizontal overflow. A dialog or portal is a separate scroll scope.
|
|
296
|
-
- Bound long-form reading content rather than stretching it across the viewport. Choose a product-appropriate token-multiple maximum; allow tables, canvases, and dense dashboards to use a wider explicit region.
|
|
297
|
-
- Use CSS media queries when only geometry changes. Branch in React when narrow layouts need different interaction, focus order, or content—not to reproduce `display`, wrapping, or column changes.
|
|
298
|
-
- Use container queries for reusable widgets whose layout depends on their allocated panel width. Give the wrapper `container-type: inline-size` and keep viewport queries for the outer application shell.
|
|
299
|
-
|
|
300
|
-
## Sticky offsets and nested scopes
|
|
301
|
-
|
|
302
|
-
Prefer a simple inherited CSS variable when sticky heights are known:
|
|
303
|
-
|
|
304
|
-
```css
|
|
305
|
-
.page {
|
|
306
|
-
--sticky-offset: calc(var(--ring-unit) * 8);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
.localToolbar {
|
|
310
|
-
position: sticky;
|
|
311
|
-
inset-block-start: var(--sticky-offset);
|
|
312
|
-
}
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
Measure in JavaScript only when the preceding sticky height is genuinely dynamic; publish the measured value as a CSS variable instead of calculating every child position in React. Keep portal and dialog scroll containers isolated: their sticky offsets begin at that scope's top, not the document header.
|
|
316
|
-
|
|
317
|
-
## Theme, semantics, and accessibility
|
|
318
|
-
|
|
319
|
-
- Put `ThemeProvider` near the application root and use `Theme.AUTO`; use `passToPopups` when popup content must inherit the theme. Keep token-based application CSS inside the same themed subtree.
|
|
320
|
-
- Keep one real `h1` in `main`. Use `header`, labelled `nav`, `aside`, and `main` landmarks; do not use visual heading styles as a substitute for heading order.
|
|
321
|
-
- Use native anchors for navigation so open-in-new-tab, copy-link, and browser history continue to work. Use buttons for actions.
|
|
322
|
-
- Preserve visible focus, keyboard order, skip navigation, accessible names, and `aria-current="page"`. Ensure sticky content does not obscure focused targets or anchor destinations; use `scroll-margin-block-start` where needed.
|
|
323
|
-
|
|
324
|
-
Avoid deprecated `Grid`/`Row`/`Col` and `ContentLayout`, hardcoded copies of token values, fixed positioning where sticky works, JavaScript viewport checks for pure layout, styling Ring internals or `data-test`, and product-specific frameworks or portal conventions.
|