feat: modular dashboards - widgets
You can test the feature by running pnpm dev dashboard on this branch.
Old (obsolete) example
See the comment below explaining the change in approach we took
https://github.com/user-attachments/assets/96157f83-c5d7-4350-9f31-c014daedb2a8
New demo
https://github.com/user-attachments/assets/6c08d8d6-c989-4845-b56f-6d3fbd30b1af
Future Work
The following improvements are planned but will be added in the future:
- fields: You'll be able to define
fieldsthat a widget receives, which will serve as props in the component. Why might this be useful? Imagine a chart widget that can have a weekly, daily, or yearly view. Or a "count" widget that shows how many documents there are in a collection (the collection could be a field). - A11y (EDITED): Okay, I finally went the extra mile here, and you can reorder and resize it with the keyboard. The screen reader works, although there's room for improvement.
- Dashboard presets: we're planning to add the ability to create and share dashboard presets, similar to how query presets work today. For example, you could build dashboards that adjust based on a variable, such as a "daily, weekly, or monthly" interval. You could also create dashboards tailored to different focus areas, like "marketing, sales, or product."
📦 esbuild Bundle Analysis for payload
This analysis was generated by esbuild-bundle-analyzer. 🤖
| Meta File | Out File | Size (raw) | Note |
|---|---|---|---|
| packages/next/meta_index.json | esbuild/index.js | 883.73 KB | ⚠️ +119.16 KB (+15.6%) |
| packages/payload/meta_index.json | esbuild/index.js | 1.23 MB | ⚠️ +544 B (+0.0%) |
| packages/payload/meta_shared.json | esbuild/exports/shared.js | 163.07 KB | ✅ No change |
| packages/richtext-lexical/meta_client.json | esbuild/exports/client_optimized/index.js | 280.71 KB | ✅ No change |
| packages/ui/meta_client.json | esbuild/exports/client_optimized/index.js | 1.16 MB | ⚠️ +2.58 KB (+0.2%) |
| packages/ui/meta_shared.json | esbuild/exports/shared_optimized/index.js | 15.62 KB | ⚠️ +1.22 KB (+8.5%) |
Largest paths
These visualization shows top 20 largest paths in the bundle.Meta file: packages/next/meta_index.json, Out file: esbuild/index.js
| Path | Size |
|---|---|
| ../../node_modules | ${{\color{Goldenrod}{ ████████████████████▍ }}}$ 81.8%, 719.30 KB |
| dist/views/Version | ${{\color{Goldenrod}{ █▍ }}}$ 5.7%, 50.20 KB |
| dist/views/Document | ${{\color{Goldenrod}{ ▍ }}}$ 1.8%, 15.51 KB |
| dist/views/Dashboard | ${{\color{Goldenrod}{ ▍ }}}$ 1.5%, 12.86 KB |
| dist/views/List | ${{\color{Goldenrod}{ ▎ }}}$ 1.3%, 11.27 KB |
| dist/views/Root | ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 9.03 KB |
| dist/views/API | ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 5.98 KB |
| dist/views/Versions | ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 5.96 KB |
| dist/elements/Nav | ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 5.53 KB |
| dist/views/Account | ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 5.32 KB |
| dist/elements/DocumentHeader | ${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 4.81 KB |
| dist/views/Login | ${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 4.39 KB |
| dist/views/ForgotPassword | ${{\color{Goldenrod}{ }}}$ 0.4%, 3.09 KB |
| dist/layouts/Root | ${{\color{Goldenrod}{ }}}$ 0.3%, 2.91 KB |
| dist/templates/Default | ${{\color{Goldenrod}{ }}}$ 0.3%, 2.83 KB |
| dist/views/CreateFirstUser | ${{\color{Goldenrod}{ }}}$ 0.3%, 2.76 KB |
| dist/views/BrowseByFolder | ${{\color{Goldenrod}{ }}}$ 0.3%, 2.60 KB |
| dist/views/CollectionFolders | ${{\color{Goldenrod}{ }}}$ 0.3%, 2.46 KB |
| dist/views/ResetPassword | ${{\color{Goldenrod}{ }}}$ 0.3%, 2.41 KB |
| dist/views/Logout | ${{\color{Goldenrod}{ }}}$ 0.2%, 1.92 KB |
| (other) | ${{\color{Goldenrod}{ ████▌ }}}$ 18.2%, 159.76 KB |
Meta file: packages/payload/meta_index.json, Out file: esbuild/index.js
| Path | Size |
|---|---|
| ../../node_modules | ${{\color{Goldenrod}{ █████████████████▏ }}}$ 68.6%, 841.09 KB |
| dist/fields/hooks | ${{\color{Goldenrod}{ ▉ }}}$ 3.5%, 43.31 KB |
| dist/collections/operations | ${{\color{Goldenrod}{ ▊ }}}$ 3.0%, 37.29 KB |
| dist/auth/operations | ${{\color{Goldenrod}{ ▎ }}}$ 1.3%, 15.65 KB |
| dist/queues/operations | ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 12.11 KB |
| dist/globals/operations | ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 12.04 KB |
| dist/fields/config | ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 11.95 KB |
| dist/utilities/configToJSONSchema.js | ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 11.83 KB |
| dist/fields/validations.js | ${{\color{Goldenrod}{ ▏ }}}$ 0.8%, 10.21 KB |
| dist/bin/generateImportMap | ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 8.47 KB |
| dist/database/migrations | ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 8.07 KB |
| dist/collections/config | ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.88 KB |
| dist/uploads/fetchAPI-multipart | ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.74 KB |
| dist/index.js | ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.59 KB |
| dist/config/orderable | ${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 6.27 KB |
| dist/collections/endpoints | ${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 6.00 KB |
| dist/config/sanitize.js | ${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 5.76 KB |
| dist/auth/strategies | ${{\color{Goldenrod}{ }}}$ 0.4%, 5.50 KB |
| dist/auth/endpoints | ${{\color{Goldenrod}{ }}}$ 0.4%, 5.42 KB |
| dist/utilities/telemetry | ${{\color{Goldenrod}{ }}}$ 0.4%, 5.31 KB |
| (other) | ${{\color{Goldenrod}{ ███████▊ }}}$ 31.4%, 384.12 KB |
Meta file: packages/payload/meta_shared.json, Out file: esbuild/exports/shared.js
| Path | Size |
|---|---|
| ../../node_modules | ${{\color{Goldenrod}{ ███████████████████▉ }}}$ 79.5%, 126.93 KB |
| dist/fields/validations.js | ${{\color{Goldenrod}{ █▌ }}}$ 6.4%, 10.21 KB |
| dist/fields/baseFields | ${{\color{Goldenrod}{ ▍ }}}$ 1.7%, 2.79 KB |
| dist/utilities/deepCopyObject.js | ${{\color{Goldenrod}{ ▍ }}}$ 1.6%, 2.48 KB |
| dist/auth/cookies.js | ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 1.55 KB |
| dist/utilities/flattenTopLevelFields.js | ${{\color{Goldenrod}{ ▏ }}}$ 0.9%, 1.42 KB |
| dist/fields/config | ${{\color{Goldenrod}{ ▏ }}}$ 0.8%, 1.28 KB |
| dist/utilities/flattenAllFields.js | ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 943 B |
| dist/folders/utils | ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 916 B |
| dist/utilities/unflatten.js | ${{\color{Goldenrod}{ ▏ }}}$ 0.5%, 779 B |
| dist/utilities/sanitizeUserDataForEmail.js | ${{\color{Goldenrod}{ }}}$ 0.4%, 713 B |
| dist/utilities/getFieldPermissions.js | ${{\color{Goldenrod}{ }}}$ 0.4%, 651 B |
| dist/collections/config | ${{\color{Goldenrod}{ }}}$ 0.4%, 570 B |
| dist/bin/generateImportMap | ${{\color{Goldenrod}{ }}}$ 0.4%, 561 B |
| dist/auth/sessions.js | ${{\color{Goldenrod}{ }}}$ 0.3%, 525 B |
| dist/utilities/getSafeRedirect.js | ${{\color{Goldenrod}{ }}}$ 0.3%, 423 B |
| dist/utilities/deepMerge.js | ${{\color{Goldenrod}{ }}}$ 0.3%, 413 B |
| dist/utilities/formatLabels.js | ${{\color{Goldenrod}{ }}}$ 0.2%, 380 B |
| dist/utilities/appendUploadSelectFields.js | ${{\color{Goldenrod}{ }}}$ 0.2%, 360 B |
| dist/utilities/transformColumnPreferences.js | ${{\color{Goldenrod}{ }}}$ 0.2%, 348 B |
| (other) | ${{\color{Goldenrod}{ █████▏ }}}$ 20.5%, 32.80 KB |
Meta file: packages/richtext-lexical/meta_client.json, Out file: esbuild/exports/client_optimized/index.js
| Path | Size |
|---|---|
| dist/features/blocks | ${{\color{Goldenrod}{ ███▏ }}}$ 12.6%, 35.02 KB |
| dist/lexical/plugins | ${{\color{Goldenrod}{ ██▊ }}}$ 11.4%, 31.68 KB |
| dist/lexical/ui | ${{\color{Goldenrod}{ ██▏ }}}$ 8.8%, 24.36 KB |
| dist/features/experimental_table | ${{\color{Goldenrod}{ ██▏ }}}$ 8.5%, 23.70 KB |
| dist/packages/@lexical | ${{\color{Goldenrod}{ █▋ }}}$ 6.8%, 18.99 KB |
| dist/features/link | ${{\color{Goldenrod}{ █▋ }}}$ 6.5%, 18.04 KB |
| dist/features/toolbars | ${{\color{Goldenrod}{ █▌ }}}$ 6.4%, 17.75 KB |
| dist/features/upload | ${{\color{Goldenrod}{ █▏ }}}$ 4.9%, 13.73 KB |
| dist/features/textState | ${{\color{Goldenrod}{ █ }}}$ 4.0%, 11.08 KB |
| dist/features/relationship | ${{\color{Goldenrod}{ ▊ }}}$ 3.2%, 8.96 KB |
| dist/lexical/utils | ${{\color{Goldenrod}{ ▊ }}}$ 3.0%, 8.22 KB |
| dist/features/debug | ${{\color{Goldenrod}{ ▋ }}}$ 2.7%, 7.39 KB |
| dist/utilities/fieldsDrawer | ${{\color{Goldenrod}{ ▋ }}}$ 2.6%, 7.12 KB |
| dist/features/converters | ${{\color{Goldenrod}{ ▋ }}}$ 2.5%, 7.04 KB |
| dist/lexical/config | ${{\color{Goldenrod}{ ▍ }}}$ 1.8%, 5.08 KB |
| dist/features/lists | ${{\color{Goldenrod}{ ▍ }}}$ 1.8%, 5.00 KB |
| dist/features/format | ${{\color{Goldenrod}{ ▎ }}}$ 1.2%, 3.46 KB |
| dist/lexical/LexicalEditor.js | ${{\color{Goldenrod}{ ▎ }}}$ 1.1%, 3.17 KB |
| dist/lexical/theme | ${{\color{Goldenrod}{ ▏ }}}$ 0.9%, 2.62 KB |
| dist/features/indent | ${{\color{Goldenrod}{ ▏ }}}$ 0.9%, 2.50 KB |
| (other) | ${{\color{Goldenrod}{ █████████████████████▊ }}}$ 87.4%, 242.43 KB |
Meta file: packages/ui/meta_client.json, Out file: esbuild/exports/client_optimized/index.js
| Path | Size |
|---|---|
| ../../node_modules | ${{\color{Goldenrod}{ ████████████▍ }}}$ 49.8%, 572.85 KB |
| dist/elements/FolderView | ${{\color{Goldenrod}{ ▋ }}}$ 2.5%, 29.18 KB |
| dist/elements/BulkUpload | ${{\color{Goldenrod}{ ▌ }}}$ 2.4%, 27.14 KB |
| dist/elements/WhereBuilder | ${{\color{Goldenrod}{ ▍ }}}$ 1.5%, 16.85 KB |
| dist/views/Edit | ${{\color{Goldenrod}{ ▎ }}}$ 1.4%, 16.08 KB |
| dist/fields/Relationship | ${{\color{Goldenrod}{ ▎ }}}$ 1.4%, 15.74 KB |
| dist/elements/Table | ${{\color{Goldenrod}{ ▎ }}}$ 1.3%, 15.46 KB |
| dist/forms/Form | ${{\color{Goldenrod}{ ▎ }}}$ 1.3%, 15.13 KB |
| dist/fields/Upload | ${{\color{Goldenrod}{ ▎ }}}$ 1.2%, 14.06 KB |
| dist/fields/Blocks | ${{\color{Goldenrod}{ ▎ }}}$ 1.2%, 13.70 KB |
| dist/elements/PublishButton | ${{\color{Goldenrod}{ ▏ }}}$ 0.8%, 8.73 KB |
| dist/elements/QueryPresets | ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 8.58 KB |
| dist/providers/Folders | ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 8.49 KB |
| dist/elements/LivePreview | ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 8.38 KB |
| dist/elements/ListHeader | ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 7.83 KB |
| dist/elements/HTMLDiff | ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 7.81 KB |
| dist/fields/Array | ${{\color{Goldenrod}{ ▏ }}}$ 0.7%, 7.55 KB |
| dist/views/CollectionFolder | ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.37 KB |
| dist/elements/ReactSelect | ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 7.31 KB |
| dist/views/List | ${{\color{Goldenrod}{ ▏ }}}$ 0.6%, 6.96 KB |
| (other) | ${{\color{Goldenrod}{ ████████████▌ }}}$ 50.2%, 576.57 KB |
Meta file: packages/ui/meta_shared.json, Out file: esbuild/exports/shared_optimized/index.js
| Path | Size |
|---|---|
| dist/graphics/Logo | ${{\color{Goldenrod}{ █████▏ }}}$ 20.9%, 3.12 KB |
| ../../node_modules | ${{\color{Goldenrod}{ ████▍ }}}$ 17.7%, 2.65 KB |
| dist/graphics/Icon | ${{\color{Goldenrod}{ ██▌ }}}$ 10.2%, 1.52 KB |
| dist/utilities/formatDocTitle | ${{\color{Goldenrod}{ ██▏ }}}$ 8.9%, 1.32 KB |
| dist/providers/TableColumns | ${{\color{Goldenrod}{ █▍ }}}$ 5.8%, 862 B |
| dist/utilities/groupNavItems.js | ${{\color{Goldenrod}{ █▎ }}}$ 5.4%, 812 B |
| dist/utilities/api.js | ${{\color{Goldenrod}{ █▎ }}}$ 5.1%, 756 B |
| dist/utilities/getGlobalData.js | ${{\color{Goldenrod}{ ▉ }}}$ 3.5%, 528 B |
| dist/elements/Translation | ${{\color{Goldenrod}{ ▊ }}}$ 3.3%, 493 B |
| dist/utilities/handleTakeOver.js | ${{\color{Goldenrod}{ ▋ }}}$ 2.9%, 440 B |
| dist/elements/withMergedProps | ${{\color{Goldenrod}{ ▌ }}}$ 2.3%, 339 B |
| dist/utilities/getVisibleEntities.js | ${{\color{Goldenrod}{ ▌ }}}$ 2.2%, 329 B |
| dist/utilities/getNavGroups.js | ${{\color{Goldenrod}{ ▌ }}}$ 2.0%, 301 B |
| dist/elements/WithServerSideProps | ${{\color{Goldenrod}{ ▍ }}}$ 1.6%, 232 B |
| dist/utilities/handleGoBack.js | ${{\color{Goldenrod}{ ▎ }}}$ 1.1%, 168 B |
| dist/fields/mergeFieldStyles.js | ${{\color{Goldenrod}{ ▎ }}}$ 1.1%, 159 B |
| dist/forms/Form | ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 147 B |
| dist/utilities/abortAndIgnore.js | ${{\color{Goldenrod}{ ▎ }}}$ 1.0%, 146 B |
| dist/utilities/hasSavePermission.js | ${{\color{Goldenrod}{ ▏ }}}$ 0.9%, 136 B |
| dist/utilities/handleBackToDashboard.js | ${{\color{Goldenrod}{ ▏ }}}$ 0.9%, 129 B |
| (other) | ${{\color{Goldenrod}{ ███████████████████▊ }}}$ 79.1%, 11.84 KB |
Details
Next to the size is how much the size has increased or decreased compared with the base branch of this PR.
- ‼️: Size increased by 20% or more. Special attention should be given to this.
- ⚠️: Size increased in acceptable range (lower than 20%).
- ✅: No change or even downsized.
- 🗑️: The out file is deleted: not found in base branch.
- 🆕: The out file is newly found: will be added to base branch.
Pumped to start playing with this feature!
I might even try pulling down the feature branch for a test/toy project - given the PR, I suppose the config is relatively stable at this point?
edit: perhaps a little eager on my behalf. Looks like this is an initial commit to scaffold the feature - great news regardless!
Feature discussion thread at https://github.com/payloadcms/payload/discussions/11862#discussioncomment-14297611
hey @jmcapra maybe you could take a second look now. The feature is quite advanced, and if you'd like to try it out and give me your feedback, I'd be very grateful!
hey @jmcapra maybe you could take a second look now. The feature is quite advanced, and if you'd like to try it out and give me your feedback, I'd be very grateful!
Amazing, thanks for the ping! I will check it out it this weekend and let you know how I go.
I’m leaving this comment for the record as a separator.
I’m about to merge changes from another branch because we went with a different approach.
Before, we used react grid layout and widget height was determined by how many rows it occupied. Now it is just a flex layout. Widgets have dynamic height based on the tallest widget in the same row.
One possible downside is that layouts like the one shown in the PR description won’t be possible.
The upside is that it will now be easier to prevent widget height from creating empty gaps or hidden overflow.