Skip to content

Commit 10cd114

Browse files
authored
feat: improve the doc picker modal (#828)
1 parent 19f95b7 commit 10cd114

20 files changed

Lines changed: 772 additions & 160 deletions

.changeset/clean-dingos-develop.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@blinkk/root-cms': patch
3+
---
4+
5+
feat: improve doc picker modal

AGENTS.md

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,24 @@ The project is a monorepo managed with `pnpm` and `turbo`.
2020
- **@blinkk/root-cms** (`packages/root-cms`): The CMS integration for Root.js.
2121
- **@blinkk/create-root** (`packages/create-root`): CLI tool to scaffold new Root.js projects.
2222
- **Other Packages**:
23-
- `eslint-config-root`: Shared ESLint configuration.
24-
- `rds`: Likely related to data services or storage (needs verification).
25-
- `root-core`: Core logic/utilities.
26-
- `root-db`: Database abstraction/layer.
27-
- `root-form`: Form handling utilities.
28-
- `root-password-protect`: Middleware/utility for password protection.
29-
- `root-webui`: UI components or interface for the system.
23+
- `eslint-config-root`: Shared ESLint configuration.
24+
- `rds`: Likely related to data services or storage (needs verification).
25+
- `root-core`: Core logic/utilities.
26+
- `root-db`: Database abstraction/layer.
27+
- `root-form`: Form handling utilities.
28+
- `root-password-protect`: Middleware/utility for password protection.
29+
- `root-webui`: UI components or interface for the system.
3030

3131
### Apps (`apps/`)
3232

3333
- **gci**: An application built within the monorepo.
3434

3535
### Documentation (`docs/`)
36+
3637
Contains documentation for the project, likely powering `rootjs.dev`.
3738

3839
### Examples (`examples/`)
40+
3941
Contains example projects demonstrating various features of Root.js.
4042

4143
## Development
@@ -49,20 +51,26 @@ Contains example projects demonstrating various features of Root.js.
4951
When working on this project, please adhere to the following guidelines:
5052

5153
### Package Management
54+
5255
- **Always use `pnpm`**: This project uses `pnpm` for package management. Do not use `npm` or `yarn`.
5356
- **Install dependencies**: Run `pnpm install` at the root to install dependencies for all packages.
5457

5558
### Build & Test
59+
5660
- **Use Turbo**: Use `turbo run build` or `turbo run test` to run tasks across the monorepo efficiently.
5761
- **Dev Server**: Use `pnpm dev` in specific package or app directories for development.
5862

5963
### Version Control & Contributions
64+
6065
- **Changesets**: If your changes require a release (version bump), you must create a changeset. Run `pnpm changeset` and follow the prompts.
6166
- **Commit Messages**: Follow the conventional commit format (e.g., `feat: add new feature`, `fix: resolve issue`).
6267
- **Linting**: Ensure code passes linting rules by running `pnpm lint`.
6368

6469
### Documentation
70+
6571
- **Update Docs**: If you change functionality, check if `docs/` needs updating. The documentation is a Root.js app itself.
72+
- **Comment Style**: All comments should end in punctuation. Use block comments to describe interfaces and their fields. Avoid adding superfluous comments.
73+
- **Comment Requirements**: When creating new classes, hooks, or components that have medium-to-complex functionality, ensure you write at least a brief block comment describing what it is for. For complex functionality, provide an example of how to use it in the comment.
6674

6775
## Contribution
6876

packages/root-cms/ui/components/DocEditor/fields/ReferencesField.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ import {useState} from 'preact/hooks';
1212
import * as schema from '../../../../core/schema.js';
1313
import {useDraftDoc, useDraftDocField} from '../../../hooks/useDraftDoc.js';
1414
import {joinClassNames} from '../../../utils/classes.js';
15+
import {useDocPickerModal} from '../../DocPickerModal/DocPickerModal.js';
1516
import {DocPreviewCard} from '../../DocPreviewCard/DocPreviewCard.js';
16-
import {useDocSelectModal} from '../../DocSelectModal/DocSelectModal.js';
1717
import {FieldProps} from './FieldProps.js';
1818
import {ReferenceFieldValue} from './ReferenceField.js';
1919

@@ -43,14 +43,15 @@ export function ReferencesField(props: FieldProps) {
4343
}
4444
});
4545

46-
const docSelectModal = useDocSelectModal();
46+
const docPickerModal = useDocPickerModal();
4747

48-
function openDocSelectModal() {
49-
docSelectModal.open({
48+
function openDocPickerModal() {
49+
docPickerModal.open({
5050
collections: field.collections,
5151
initialCollection: field.initialCollection,
52+
multiSelect: true,
5253
selectedDocIds: refIds,
53-
onChange: (docId: string, selected: boolean) => {
54+
onChangeMulti: (docId: string, selected: boolean) => {
5455
setRefIds((old) => {
5556
const next = [...old];
5657
if (selected) {
@@ -146,7 +147,7 @@ export function ReferencesField(props: FieldProps) {
146147
) : (
147148
<div className="ReferencesField__none">None selected</div>
148149
)}
149-
<Button color="dark" size="xs" onClick={() => openDocSelectModal()}>
150+
<Button color="dark" size="xs" onClick={() => openDocPickerModal()}>
150151
{field.buttonLabel || 'Select'}
151152
</Button>
152153
</div>

packages/root-cms/ui/components/DocPickerModal/DocPickerModal.css

Lines changed: 117 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
.DocPickerModal {
2+
padding-right: 20px;
3+
}
4+
15
.DocPickerModal__collection__select {
26
display: flex;
37
gap: 8px;
@@ -10,29 +14,87 @@
1014
font-weight: 600;
1115
}
1216

17+
.DocPickerModal__DocsList__controls {
18+
display: flex;
19+
gap: 12px;
20+
align-items: center;
21+
margin-bottom: 12px;
22+
padding-bottom: 12px;
23+
border-bottom: 1px solid var(--color-border);
24+
}
25+
26+
.DocPickerModal__DocsList__controls:last-child {
27+
border-bottom: 0;
28+
margin-bottom: 0;
29+
}
30+
31+
.DocPickerModal__DocsList__controls__search {
32+
flex: 1;
33+
min-width: 200px;
34+
}
35+
36+
.DocPickerModal__DocsList__controls__sort {
37+
min-width: 140px;
38+
}
39+
40+
.DocPickerModal__DocsList {
41+
display: flex;
42+
flex-direction: column;
43+
height: 100%;
44+
}
45+
46+
.DocPickerModal__DocsList__stickyHeader {
47+
position: sticky;
48+
top: 0;
49+
background: white;
50+
z-index: 1;
51+
margin-bottom: 8px;
52+
border-bottom: 1px solid var(--color-border);
53+
}
54+
55+
.DocPickerModal__DocsList__docsContainer {
56+
flex: 1;
57+
overflow-y: auto;
58+
min-height: 0;
59+
}
60+
1361
.DocPickerModal__DocCard {
1462
display: flex;
1563
align-items: center;
16-
padding: 8px 0;
64+
padding: 8px 8px 8px 0;
1765
border-top: 1px solid var(--color-border);
1866
overflow: hidden;
1967
}
2068

69+
.DocPickerModal__DocCard:first-child {
70+
border-top: none;
71+
}
72+
2173
.DocPickerModal__DocCard__image {
2274
border: 1px solid var(--color-border);
2375
flex-shrink: 0;
76+
cursor: pointer;
2477
}
2578

2679
.DocPickerModal__DocCard__content {
27-
display: block;
80+
display: flex;
2881
padding: 0 12px;
2982
text-decoration: none;
3083
flex: 1;
84+
flex-direction: column;
85+
}
86+
87+
.DocPickerModal__DocCard__content__header {
88+
display: flex;
89+
gap: 8px;
90+
align-items: center;
91+
flex-wrap: wrap;
3192
}
3293

3394
.DocPickerModal__DocCard__content__header__docId {
3495
font-size: 14px;
3596
font-weight: 500;
97+
cursor: pointer;
3698
}
3799

38100
.DocPickerModal__DocCard__content__title {
@@ -43,16 +105,65 @@
43105
display: -webkit-box;
44106
-webkit-box-orient: vertical;
45107
-webkit-line-clamp: 1;
108+
cursor: pointer;
46109
}
47110

48-
.DocPickerModal__DocCard__content__url {
49-
font-size: 12px;
50-
font-weight: 500;
51-
color: #ababab;
111+
.DocPickerModal__DocCard__content__link {
112+
display: inline-block;
113+
cursor: pointer;
114+
}
115+
116+
.DocPickerModal__DocCard__content__badges {
117+
display: flex;
118+
align-items: center;
119+
gap: 4px;
120+
margin-top: 4px;
121+
}
122+
123+
.DocPickerModal__DocCard__content__badges .mantine-Tooltip-root {
124+
display: block;
125+
}
126+
127+
.DocPickerModal__DocCard__content__badges .mantine-Badge-root {
128+
display: flex;
52129
}
53130

54131
.DocPickerModal__DocCard__controls {
55132
display: flex;
56133
gap: 8px;
57134
align-items: center;
135+
flex-direction: column;
136+
}
137+
138+
.DocPickerModal__DocCard__controls__buttons {
139+
display: flex;
140+
gap: 8px;
141+
align-items: center;
142+
}
143+
144+
.DocPickerModal__DocsList__loading {
145+
display: flex;
146+
justify-content: center;
147+
padding: 40px 0;
148+
}
149+
150+
.DocPickerModal__DocsList__empty {
151+
padding: 40px 20px;
152+
text-align: center;
153+
color: #999;
154+
font-size: 14px;
155+
}
156+
157+
.DocPickerModal__noCollections {
158+
padding: 20px;
159+
text-align: center;
160+
color: #999;
161+
font-size: 14px;
162+
}
163+
164+
.DocPickerModal__DocsList__count {
165+
font-size: 12px;
166+
color: #666;
167+
margin-bottom: 12px;
168+
padding: 0 4px;
58169
}

0 commit comments

Comments
 (0)