From 7092e69d0eb1e4a4477444532117af9eab9736ed Mon Sep 17 00:00:00 2001 From: Louis Escher <66965600+louisescher@users.noreply.github.com> Date: Tue, 1 Oct 2024 23:04:39 +0200 Subject: [PATCH] Add a new `@studiocms/ui` package (#296) * Initial commit for `@studiocms/ui` * Add new components & UI playground - Adjust button, divider, input styles - Added "Center" component, UI playground - Moved all CSS files into a global CSS file with imports - Added the font to the playground & UI library * Add .editorconfig, update biome.json * Add textboxes & checkboxes, ID gen function & more - Added the utils folder to the package's exports - Format the TODO's in the README - Buttons can now be disabled - Added a textarea component - Added a checkbox component - Added a function to generate random names & IDs if not provided - Added a default gap size to the row component - Added an icon component to easily grab icons in a type-safe manner - Added new components to playground * Linted files & added completed components to readme * Add cards, radio inputs, toggles, toasts, warning color - Added a new Card component. - Added a radio group component. - Added a toggle component. - Added a Toaster component and a toast function to create toasts. - Added a new "warning" colorway to all components that support colored variants. * Add modals, new button variant, change CSS vars - Added a Modal component. - Added a new, "flat" button variant. - All color variables now come in hsl format and need to be wrapped in hsl(). This allows for easier opacity management - Some fixes in regards to textarea sizing on small devices * Forgot to fucking lint again :skull: Windows decided now would be a good idea to change 190 files on it's own so yeah * Add a select component, fix various bugs - Added a new select component. - Some changes to input & textarea transitions - Modals now show overflow to allow for selects to be used - Fixed radio inputs not actually being disabled * Add dropdown & user components - Added a dropdown component. - Added a user component. - Moved all colorways into a shared type. - Removed the transparent backgrounds from select elements for better visibility. - Adjusted the shadows for select dropdowns & toasts. * Can windows please stop formatting my files in fucked up ways I swear to god * Add sidebar, double sidebar, root layout component - Added new sidebar & double sidebar components. - Added a new RootLayout component. * Add right click trigger to dropdowns - Added right click (and both mouse buttons) triggers to dropdowns - Added option to register buttons for opening and closing single sidebar individually * Update package.json * Update DropdownTests.astro * Lint :skull: * Update & dedupe packages * Update package.json * update deployment action * Update package.json * Update package.json * Add changeset * Update README.md * Add is:global to styles to eliminate race condition - Added is:global to all component css style tags because css is being a cascading bitch * Remove experimental directRenderScript * Fix dropdown options not filling parent element * Adjust modal and dropdown paddings * Changes to folder structure & accessibility fixes - Moved all components into their own folders and moved all CSS to CSS files. This should help eliminate the race condition pointed out by @hkbertoson in #296 . - All buttons *should* now follow the web accessibility guidelines for colors and should pass WCAG Level AAA. * Add pseudo-docs to README, option to disable radios - Wrote pseudo-docs for the README file of the UI library. - It's now possible to pass a class to the User component's container. - Radio options can not be disabled individually. - Improved the helper for the single sidebar a bit. * Change icons for dropdowns to slots * Update README.md * Update README.md * Update Modal.css - Fixed the modal backdrop animation taking a whole second to complete * Improve double sidebar helper API * Update packages/studiocms_ui/README.md Co-authored-by: Adam Matthiesen * Fix navbar toggle for single sidebar not showing * Remove unused BaseHead component Seriously this is a UI lib why did I think putting this here would benefit the UI lib. * Revert "Remove unused BaseHead component" This reverts commit 308d332d50a4d879011270d6676220b1b86fc291. --------- Co-authored-by: Adam Matthiesen --- .changeset/config.json | 5 +- .changeset/pre.json | 2 + .changeset/rotten-dancers-trade.md | 5 + .moon/workspace.yml | 2 + package.json | 3 + packages/studiocms/tsconfig.json | 70 ++- packages/studiocms_assets/tsconfig.json | 8 +- packages/studiocms_auth/tsconfig.json | 30 +- .../studiocms_betaresources/tsconfig.json | 22 +- packages/studiocms_blog/tsconfig.json | 24 +- packages/studiocms_core/tsconfig.json | 16 +- packages/studiocms_dashboard/tsconfig.json | 34 +- packages/studiocms_frontend/tsconfig.json | 22 +- packages/studiocms_imagehandler/tsconfig.json | 16 +- packages/studiocms_renderers/tsconfig.json | 16 +- packages/studiocms_robotstxt/tsconfig.json | 8 +- packages/studiocms_ui/.gitignore | 1 + packages/studiocms_ui/README.md | 564 ++++++++++++++++++ packages/studiocms_ui/moon.yml | 7 + packages/studiocms_ui/package.json | 48 ++ packages/studiocms_ui/src/components.ts | 22 + .../src/components/BaseHead.astro | 22 + .../src/components/Button/Button.astro | 45 ++ .../src/components/Button/Button.css | 292 +++++++++ .../src/components/Card/Card.astro | 25 + .../studiocms_ui/src/components/Card/Card.css | 37 ++ .../src/components/Center/Center.astro | 7 + .../src/components/Center/Center.css | 10 + .../src/components/Checkbox/Checkbox.astro | 63 ++ .../src/components/Checkbox/Checkbox.css | 117 ++++ .../src/components/Divider/Divider.astro | 9 + .../src/components/Divider/Divider.css | 25 + .../src/components/Dropdown/Dropdown.astro | 47 ++ .../src/components/Dropdown/Dropdown.css | 183 ++++++ .../src/components/Dropdown/dropdown.ts | 159 +++++ .../src/components/Input/Input.astro | 43 ++ .../src/components/Input/Input.css | 46 ++ .../src/components/Modal/Modal.astro | 54 ++ .../src/components/Modal/Modal.css | 109 ++++ .../src/components/Modal/modal.ts | 125 ++++ .../components/RadioGroup/RadioGroup.astro | 74 +++ .../src/components/RadioGroup/RadioGroup.css | 100 ++++ .../studiocms_ui/src/components/Row/Row.astro | 14 + .../studiocms_ui/src/components/Row/Row.css | 22 + .../src/components/Select/Select.astro | 179 ++++++ .../src/components/Select/Select.css | 113 ++++ .../src/components/Sidebar/Double.astro | 11 + .../src/components/Sidebar/Double.css | 142 +++++ .../src/components/Sidebar/Single.astro | 6 + .../src/components/Sidebar/Single.css | 38 ++ .../src/components/Sidebar/helpers.ts | 120 ++++ .../src/components/Textarea/Textarea.astro | 49 ++ .../src/components/Textarea/Textarea.css | 53 ++ .../src/components/Toast/Toaster.astro | 155 +++++ .../src/components/Toast/Toaster.css | 160 +++++ .../src/components/Toast/toast.ts | 11 + .../src/components/Toggle/Toggle.astro | 51 ++ .../src/components/Toggle/Toggle.css | 95 +++ .../src/components/User/User.astro | 28 + .../studiocms_ui/src/components/User/User.css | 40 ++ packages/studiocms_ui/src/components/index.ts | 23 + packages/studiocms_ui/src/css/colors.css | 106 ++++ packages/studiocms_ui/src/css/global.css | 4 + packages/studiocms_ui/src/css/resets.css | 56 ++ packages/studiocms_ui/src/css/sizes.css | 0 packages/studiocms_ui/src/css/spacings.css | 0 packages/studiocms_ui/src/env.d.ts | 17 + .../studiocms_ui/src/icons/Checkmark.astro | 13 + .../src/icons/ChevronUpDown.astro | 13 + packages/studiocms_ui/src/icons/User.astro | 13 + packages/studiocms_ui/src/icons/X-Mark.astro | 13 + packages/studiocms_ui/src/layouts.ts | 1 + .../studiocms_ui/src/layouts/RootLayout.astro | 34 ++ packages/studiocms_ui/src/layouts/index.ts | 2 + packages/studiocms_ui/src/types/index.ts | 16 + packages/studiocms_ui/src/utils/Icon.astro | 27 + packages/studiocms_ui/src/utils/colors.ts | 1 + packages/studiocms_ui/src/utils/generateID.ts | 5 + packages/studiocms_ui/src/utils/headers.ts | 190 ++++++ .../studiocms_ui/src/utils/iconStrings.ts | 29 + packages/studiocms_ui/tsconfig.json | 27 + playgrounds/ui/.gitignore | 26 + playgrounds/ui/.vscode/extensions.json | 4 + playgrounds/ui/.vscode/launch.json | 11 + playgrounds/ui/README.md | 16 + playgrounds/ui/astro.config.mts | 7 + playgrounds/ui/moon.yml | 30 + playgrounds/ui/package.json | 23 + playgrounds/ui/public/favicon.svg | 41 ++ playgrounds/ui/public/studiocms.svg | 5 + .../ui/src/components/ButtonTests.astro | 225 +++++++ playgrounds/ui/src/components/CardTests.astro | 29 + .../ui/src/components/CheckboxTests.astro | 77 +++ .../ui/src/components/DropdownTests.astro | 116 ++++ .../ui/src/components/ModalTests.astro | 70 +++ .../ui/src/components/RadioGroupTests.astro | 77 +++ .../ui/src/components/SelectTests.astro | 50 ++ .../ui/src/components/ToastTests.astro | 66 ++ .../ui/src/components/ToggleTests.astro | 77 +++ playgrounds/ui/src/env.d.ts | 4 + playgrounds/ui/src/icons/ArrowLeft.astro | 13 + playgrounds/ui/src/icons/Hamburger.astro | 13 + playgrounds/ui/src/icons/Moon.astro | 13 + playgrounds/ui/src/icons/Sun.astro | 13 + .../ui/src/ideas/folder-system-client-side.ts | 24 + .../ui/src/layouts/DoubleSidebarLayout.astro | 89 +++ .../ui/src/layouts/SidebarLayout.astro | 44 ++ playgrounds/ui/src/pages/double-sidebar.astro | 39 ++ playgrounds/ui/src/pages/index.astro | 181 ++++++ playgrounds/ui/src/pages/sidebar.astro | 34 ++ playgrounds/ui/src/utils/Icon.astro | 29 + playgrounds/ui/tsconfig.json | 26 + pnpm-lock.yaml | 299 +++------- tsconfig.json | 47 +- www/docs/tsconfig.json | 3 +- www/web/tsconfig.json | 5 +- 116 files changed, 5986 insertions(+), 234 deletions(-) create mode 100644 .changeset/rotten-dancers-trade.md create mode 100644 packages/studiocms_ui/.gitignore create mode 100644 packages/studiocms_ui/README.md create mode 100644 packages/studiocms_ui/moon.yml create mode 100644 packages/studiocms_ui/package.json create mode 100644 packages/studiocms_ui/src/components.ts create mode 100644 packages/studiocms_ui/src/components/BaseHead.astro create mode 100644 packages/studiocms_ui/src/components/Button/Button.astro create mode 100644 packages/studiocms_ui/src/components/Button/Button.css create mode 100644 packages/studiocms_ui/src/components/Card/Card.astro create mode 100644 packages/studiocms_ui/src/components/Card/Card.css create mode 100644 packages/studiocms_ui/src/components/Center/Center.astro create mode 100644 packages/studiocms_ui/src/components/Center/Center.css create mode 100644 packages/studiocms_ui/src/components/Checkbox/Checkbox.astro create mode 100644 packages/studiocms_ui/src/components/Checkbox/Checkbox.css create mode 100644 packages/studiocms_ui/src/components/Divider/Divider.astro create mode 100644 packages/studiocms_ui/src/components/Divider/Divider.css create mode 100644 packages/studiocms_ui/src/components/Dropdown/Dropdown.astro create mode 100644 packages/studiocms_ui/src/components/Dropdown/Dropdown.css create mode 100644 packages/studiocms_ui/src/components/Dropdown/dropdown.ts create mode 100644 packages/studiocms_ui/src/components/Input/Input.astro create mode 100644 packages/studiocms_ui/src/components/Input/Input.css create mode 100644 packages/studiocms_ui/src/components/Modal/Modal.astro create mode 100644 packages/studiocms_ui/src/components/Modal/Modal.css create mode 100644 packages/studiocms_ui/src/components/Modal/modal.ts create mode 100644 packages/studiocms_ui/src/components/RadioGroup/RadioGroup.astro create mode 100644 packages/studiocms_ui/src/components/RadioGroup/RadioGroup.css create mode 100644 packages/studiocms_ui/src/components/Row/Row.astro create mode 100644 packages/studiocms_ui/src/components/Row/Row.css create mode 100644 packages/studiocms_ui/src/components/Select/Select.astro create mode 100644 packages/studiocms_ui/src/components/Select/Select.css create mode 100644 packages/studiocms_ui/src/components/Sidebar/Double.astro create mode 100644 packages/studiocms_ui/src/components/Sidebar/Double.css create mode 100644 packages/studiocms_ui/src/components/Sidebar/Single.astro create mode 100644 packages/studiocms_ui/src/components/Sidebar/Single.css create mode 100644 packages/studiocms_ui/src/components/Sidebar/helpers.ts create mode 100644 packages/studiocms_ui/src/components/Textarea/Textarea.astro create mode 100644 packages/studiocms_ui/src/components/Textarea/Textarea.css create mode 100644 packages/studiocms_ui/src/components/Toast/Toaster.astro create mode 100644 packages/studiocms_ui/src/components/Toast/Toaster.css create mode 100644 packages/studiocms_ui/src/components/Toast/toast.ts create mode 100644 packages/studiocms_ui/src/components/Toggle/Toggle.astro create mode 100644 packages/studiocms_ui/src/components/Toggle/Toggle.css create mode 100644 packages/studiocms_ui/src/components/User/User.astro create mode 100644 packages/studiocms_ui/src/components/User/User.css create mode 100644 packages/studiocms_ui/src/components/index.ts create mode 100644 packages/studiocms_ui/src/css/colors.css create mode 100644 packages/studiocms_ui/src/css/global.css create mode 100644 packages/studiocms_ui/src/css/resets.css create mode 100644 packages/studiocms_ui/src/css/sizes.css create mode 100644 packages/studiocms_ui/src/css/spacings.css create mode 100644 packages/studiocms_ui/src/env.d.ts create mode 100644 packages/studiocms_ui/src/icons/Checkmark.astro create mode 100644 packages/studiocms_ui/src/icons/ChevronUpDown.astro create mode 100644 packages/studiocms_ui/src/icons/User.astro create mode 100644 packages/studiocms_ui/src/icons/X-Mark.astro create mode 100644 packages/studiocms_ui/src/layouts.ts create mode 100644 packages/studiocms_ui/src/layouts/RootLayout.astro create mode 100644 packages/studiocms_ui/src/layouts/index.ts create mode 100644 packages/studiocms_ui/src/types/index.ts create mode 100644 packages/studiocms_ui/src/utils/Icon.astro create mode 100644 packages/studiocms_ui/src/utils/colors.ts create mode 100644 packages/studiocms_ui/src/utils/generateID.ts create mode 100644 packages/studiocms_ui/src/utils/headers.ts create mode 100644 packages/studiocms_ui/src/utils/iconStrings.ts create mode 100644 packages/studiocms_ui/tsconfig.json create mode 100644 playgrounds/ui/.gitignore create mode 100644 playgrounds/ui/.vscode/extensions.json create mode 100644 playgrounds/ui/.vscode/launch.json create mode 100644 playgrounds/ui/README.md create mode 100644 playgrounds/ui/astro.config.mts create mode 100644 playgrounds/ui/moon.yml create mode 100644 playgrounds/ui/package.json create mode 100644 playgrounds/ui/public/favicon.svg create mode 100644 playgrounds/ui/public/studiocms.svg create mode 100644 playgrounds/ui/src/components/ButtonTests.astro create mode 100644 playgrounds/ui/src/components/CardTests.astro create mode 100644 playgrounds/ui/src/components/CheckboxTests.astro create mode 100644 playgrounds/ui/src/components/DropdownTests.astro create mode 100644 playgrounds/ui/src/components/ModalTests.astro create mode 100644 playgrounds/ui/src/components/RadioGroupTests.astro create mode 100644 playgrounds/ui/src/components/SelectTests.astro create mode 100644 playgrounds/ui/src/components/ToastTests.astro create mode 100644 playgrounds/ui/src/components/ToggleTests.astro create mode 100644 playgrounds/ui/src/env.d.ts create mode 100644 playgrounds/ui/src/icons/ArrowLeft.astro create mode 100644 playgrounds/ui/src/icons/Hamburger.astro create mode 100644 playgrounds/ui/src/icons/Moon.astro create mode 100644 playgrounds/ui/src/icons/Sun.astro create mode 100644 playgrounds/ui/src/ideas/folder-system-client-side.ts create mode 100644 playgrounds/ui/src/layouts/DoubleSidebarLayout.astro create mode 100644 playgrounds/ui/src/layouts/SidebarLayout.astro create mode 100644 playgrounds/ui/src/pages/double-sidebar.astro create mode 100644 playgrounds/ui/src/pages/index.astro create mode 100644 playgrounds/ui/src/pages/sidebar.astro create mode 100644 playgrounds/ui/src/utils/Icon.astro create mode 100644 playgrounds/ui/tsconfig.json diff --git a/.changeset/config.json b/.changeset/config.json index 7148a21da..a5b44a41e 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -13,12 +13,13 @@ "@studiocms/frontend", "@studiocms/imagehandler", "@studiocms/renderers", - "@studiocms/robotstxt" + "@studiocms/robotstxt", + "@studiocms/ui" ] ], "linked": [], "access": "public", "baseBranch": "main", "updateInternalDependencies": "patch", - "ignore": ["web", "docs", "node-playground"] + "ignore": ["web", "docs", "node-playground", "ui-playground"] } diff --git a/.changeset/pre.json b/.changeset/pre.json index 971b9530a..f58d87d23 100644 --- a/.changeset/pre.json +++ b/.changeset/pre.json @@ -13,7 +13,9 @@ "@studiocms/renderers": "0.1.0-beta.4", "@studiocms/robotstxt": "0.1.0-beta.4", "@studiocms/blog": "0.1.0-beta.1", + "@studiocms/ui": "0.1.0-beta.7", "node-playground": "0.0.1", + "ui-playground": "0.0.1", "docs": "0.0.1", "web": "0.0.1" }, diff --git a/.changeset/rotten-dancers-trade.md b/.changeset/rotten-dancers-trade.md new file mode 100644 index 000000000..960cc7f00 --- /dev/null +++ b/.changeset/rotten-dancers-trade.md @@ -0,0 +1,5 @@ +--- +"@studiocms/ui": patch +--- + +Added a new UI library for the dashboard rework diff --git a/.moon/workspace.yml b/.moon/workspace.yml index c896abda6..3c3d1cadd 100644 --- a/.moon/workspace.yml +++ b/.moon/workspace.yml @@ -15,9 +15,11 @@ projects: studiocms_imagehandler: 'packages/studiocms_imagehandler' studiocms_renderers: 'packages/studiocms_renderers' studiocms_robotstxt: 'packages/studiocms_robotstxt' + studiocms_ui: 'packages/studiocms_ui' # Playgrounds playground: 'playgrounds/node' + ui-playground: 'playgrounds/ui' # cloudflare-playground: 'playgrounds/cloudflare' - Removed for now till we start experimenting with Cloudflare again. # Web Sites & Docs diff --git a/package.json b/package.json index df2d8cd46..cf11e2335 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,9 @@ "playground:login": "pnpm --filter node-playground db:login", "playground:link": "pnpm --filter node-playground db:link", "playground:push": "pnpm --filter node-playground db:push", + "ui:dev": "pnpm --filter ui-playground dev", + "ui:build": "pnpm --filter ui-playground build", + "ui:preview": "pnpm --filter ui-playground preview", "build": "pnpm --filter node-playground build", "lint": "biome check .", "lint:fix": "biome check --write .", diff --git a/packages/studiocms/tsconfig.json b/packages/studiocms/tsconfig.json index 121fd8f5d..73fb2bc44 100644 --- a/packages/studiocms/tsconfig.json +++ b/packages/studiocms/tsconfig.json @@ -8,13 +8,79 @@ "allowImportingTsExtensions": false, "emitDeclarationOnly": false, "paths": { - "node-playground/*": ["../../playgrounds/node/src/*"] + "node-playground/*": ["../../playgrounds/node/src/*"], + "@studiocms/assets": ["../studiocms_assets/src/index.ts"], + "@studiocms/assets/*": ["../studiocms_assets/src/*"], + "@studiocms/auth": ["../studiocms_auth/src/index.ts"], + "@studiocms/auth/*": ["../studiocms_auth/src/*"], + "@studiocms/betaresources": ["../studiocms_betaresources/src/index.ts"], + "@studiocms/betaresources/*": ["../studiocms_betaresources/src/*"], + "@studiocms/blog": ["../studiocms_blog/index.ts"], + "@studiocms/blog/*": ["../studiocms_blog/src/*"], + "@studiocms/core": ["../studiocms_core/src/index.ts"], + "@studiocms/core/*": ["../studiocms_core/src/*"], + "@studiocms/dashboard": ["../studiocms_dashboard/src/index.ts"], + "@studiocms/dashboard/*": ["../studiocms_dashboard/src/*"], + "@studiocms/frontend": ["../studiocms_frontend/src/index.ts"], + "@studiocms/frontend/*": ["../studiocms_frontend/src/*"], + "@studiocms/imagehandler": ["../studiocms_imagehandler/src/index.ts"], + "@studiocms/imagehandler/*": ["../studiocms_imagehandler/src/*"], + "@studiocms/renderers": ["../studiocms_renderers/src/index.ts"], + "@studiocms/renderers/*": ["../studiocms_renderers/src/*"], + "@studiocms/robotstxt": ["../studiocms_robotstxt/src/index.ts"], + "@studiocms/robotstxt/*": ["../studiocms_robotstxt/src/*"] } }, "references": [ { "path": "../../playgrounds/node" + }, + { + "path": "../studiocms_assets" + }, + { + "path": "../studiocms_auth" + }, + { + "path": "../studiocms_betaresources" + }, + { + "path": "../studiocms_blog" + }, + { + "path": "../studiocms_core" + }, + { + "path": "../studiocms_dashboard" + }, + { + "path": "../studiocms_frontend" + }, + { + "path": "../studiocms_imagehandler" + }, + { + "path": "../studiocms_renderers" + }, + { + "path": "../studiocms_robotstxt" } ], - "include": ["./package.json", "../../playgrounds/node/.astro/**/*", "./**/*", "./src/**/*.json"] + "include": [ + "./package.json", + "../../playgrounds/node/**/*", + "../../playgrounds/node/.astro/**/*", + "../studiocms_assets/**/*", + "../studiocms_auth/**/*", + "../studiocms_betaresources/**/*", + "../studiocms_blog/**/*", + "../studiocms_core/**/*", + "../studiocms_dashboard/**/*", + "../studiocms_frontend/**/*", + "../studiocms_imagehandler/**/*", + "../studiocms_renderers/**/*", + "../studiocms_robotstxt/**/*", + "./**/*", + "./src/**/*.json" + ] } diff --git a/packages/studiocms_assets/tsconfig.json b/packages/studiocms_assets/tsconfig.json index 735e1558c..c2c3dc4d8 100644 --- a/packages/studiocms_assets/tsconfig.json +++ b/packages/studiocms_assets/tsconfig.json @@ -16,5 +16,11 @@ "path": "../../playgrounds/node" } ], - "include": ["./package.json", "../../playgrounds/node/.astro/**/*", "./**/*", "./src/**/*.json"] + "include": [ + "./package.json", + "../../playgrounds/node/**/*", + "../../playgrounds/node/.astro/**/*", + "./**/*", + "./src/**/*.json" + ] } diff --git a/packages/studiocms_auth/tsconfig.json b/packages/studiocms_auth/tsconfig.json index 293461caa..eef2ee650 100644 --- a/packages/studiocms_auth/tsconfig.json +++ b/packages/studiocms_auth/tsconfig.json @@ -2,19 +2,43 @@ "extends": "astro/tsconfigs/strictest", "files": [], "compilerOptions": { - "outDir": "../../.moon/cache/types/packages/studiocms_renderers", + "outDir": "../../.moon/cache/types/packages/studiocms_auth", "composite": true, "noEmit": false, "allowImportingTsExtensions": false, "emitDeclarationOnly": false, "paths": { - "node-playground/*": ["../../playgrounds/node/src/*"] + "node-playground/*": ["../../playgrounds/node/src/*"], + "@studiocms/assets": ["../studiocms_assets/src/index.ts"], + "@studiocms/assets/*": ["../studiocms_assets/src/*"], + "@studiocms/core": ["../studiocms_core/src/index.ts"], + "@studiocms/core/*": ["../studiocms_core/src/*"], + "@studiocms/dashboard": ["../studiocms_dashboard/src/index.ts"], + "@studiocms/dashboard/*": ["../studiocms_dashboard/src/*"] } }, "references": [ { "path": "../../playgrounds/node" + }, + { + "path": "../studiocms_assets" + }, + { + "path": "../studiocms_core" + }, + { + "path": "../studiocms_dashboard" } ], - "include": ["./package.json", "../../playgrounds/node/.astro/**/*", "./**/*", "./src/**/*.json"] + "include": [ + "./package.json", + "../../playgrounds/node/**/*", + "../../playgrounds/node/.astro/**/*", + "../studiocms_assets/**/*", + "../studiocms_core/**/*", + "../studiocms_dashboard/**/*", + "./**/*", + "./src/**/*.json" + ] } diff --git a/packages/studiocms_betaresources/tsconfig.json b/packages/studiocms_betaresources/tsconfig.json index fb6bf44b9..54435a1f1 100644 --- a/packages/studiocms_betaresources/tsconfig.json +++ b/packages/studiocms_betaresources/tsconfig.json @@ -8,13 +8,31 @@ "allowImportingTsExtensions": false, "emitDeclarationOnly": false, "paths": { - "node-playground/*": ["../../playgrounds/node/src/*"] + "node-playground/*": ["../../playgrounds/node/src/*"], + "@studiocms/assets": ["../studiocms_assets/src/index.ts"], + "@studiocms/assets/*": ["../studiocms_assets/src/*"], + "@studiocms/core": ["../studiocms_core/src/index.ts"], + "@studiocms/core/*": ["../studiocms_core/src/*"] } }, "references": [ { "path": "../../playgrounds/node" + }, + { + "path": "../studiocms_assets" + }, + { + "path": "../studiocms_core" } ], - "include": ["./package.json", "../../playgrounds/node/.astro/**/*", "./**/*", "./src/**/*.json"] + "include": [ + "./package.json", + "../../playgrounds/node/**/*", + "../../playgrounds/node/.astro/**/*", + "../studiocms_assets/**/*", + "../studiocms_core/**/*", + "./**/*", + "./src/**/*.json" + ] } diff --git a/packages/studiocms_blog/tsconfig.json b/packages/studiocms_blog/tsconfig.json index 4530d9b26..13aee4d58 100644 --- a/packages/studiocms_blog/tsconfig.json +++ b/packages/studiocms_blog/tsconfig.json @@ -6,7 +6,27 @@ "composite": true, "noEmit": false, "emitDeclarationOnly": true, - "allowImportingTsExtensions": false + "allowImportingTsExtensions": false, + "paths": { + "@studiocms/core": ["../studiocms_core/src/index.ts"], + "@studiocms/core/*": ["../studiocms_core/src/*"], + "@studiocms/frontend": ["../studiocms_frontend/src/index.ts"], + "@studiocms/frontend/*": ["../studiocms_frontend/src/*"] + } }, - "include": ["../../playgrounds/node/.astro/**/*", "./**/*", "./**/*.json"] + "include": [ + "../../playgrounds/node/.astro/**/*", + "../studiocms_core/**/*", + "../studiocms_frontend/**/*", + "./**/*", + "./**/*.json" + ], + "references": [ + { + "path": "../studiocms_core" + }, + { + "path": "../studiocms_frontend" + } + ] } diff --git a/packages/studiocms_core/tsconfig.json b/packages/studiocms_core/tsconfig.json index dd8ad4811..19d1e8e7c 100644 --- a/packages/studiocms_core/tsconfig.json +++ b/packages/studiocms_core/tsconfig.json @@ -8,13 +8,25 @@ "allowImportingTsExtensions": false, "emitDeclarationOnly": false, "paths": { - "node-playground/*": ["../../playgrounds/node/src/*"] + "node-playground/*": ["../../playgrounds/node/src/*"], + "@studiocms/robotstxt": ["../studiocms_robotstxt/src/index.ts"], + "@studiocms/robotstxt/*": ["../studiocms_robotstxt/src/*"] } }, "references": [ { "path": "../../playgrounds/node" + }, + { + "path": "../studiocms_robotstxt" } ], - "include": ["./package.json", "../../playgrounds/node/.astro/**/*", "./**/*", "./src/**/*.json"] + "include": [ + "./package.json", + "../../playgrounds/node/**/*", + "../../playgrounds/node/.astro/**/*", + "../studiocms_robotstxt/**/*", + "./**/*", + "./src/**/*.json" + ] } diff --git a/packages/studiocms_dashboard/tsconfig.json b/packages/studiocms_dashboard/tsconfig.json index fa748cf2f..a98360473 100644 --- a/packages/studiocms_dashboard/tsconfig.json +++ b/packages/studiocms_dashboard/tsconfig.json @@ -8,13 +8,43 @@ "allowImportingTsExtensions": false, "emitDeclarationOnly": false, "paths": { - "node-playground/*": ["../../playgrounds/node/src/*"] + "node-playground/*": ["../../playgrounds/node/src/*"], + "@studiocms/assets": ["../studiocms_assets/src/index.ts"], + "@studiocms/assets/*": ["../studiocms_assets/src/*"], + "@studiocms/betaresources": ["../studiocms_betaresources/src/index.ts"], + "@studiocms/betaresources/*": ["../studiocms_betaresources/src/*"], + "@studiocms/core": ["../studiocms_core/src/index.ts"], + "@studiocms/core/*": ["../studiocms_core/src/*"], + "@studiocms/renderers": ["../studiocms_renderers/src/index.ts"], + "@studiocms/renderers/*": ["../studiocms_renderers/src/*"] } }, "references": [ { "path": "../../playgrounds/node" + }, + { + "path": "../studiocms_assets" + }, + { + "path": "../studiocms_betaresources" + }, + { + "path": "../studiocms_core" + }, + { + "path": "../studiocms_renderers" } ], - "include": ["./package.json", "../../playgrounds/node/.astro/**/*", "./**/*", "./src/**/*.json"] + "include": [ + "./package.json", + "../../playgrounds/node/**/*", + "../../playgrounds/node/.astro/**/*", + "../studiocms_assets/**/*", + "../studiocms_betaresources/**/*", + "../studiocms_core/**/*", + "../studiocms_renderers/**/*", + "./**/*", + "./src/**/*.json" + ] } diff --git a/packages/studiocms_frontend/tsconfig.json b/packages/studiocms_frontend/tsconfig.json index 507f44c2f..124e2e005 100644 --- a/packages/studiocms_frontend/tsconfig.json +++ b/packages/studiocms_frontend/tsconfig.json @@ -8,13 +8,31 @@ "allowImportingTsExtensions": false, "emitDeclarationOnly": false, "paths": { - "node-playground/*": ["../../playgrounds/node/src/*"] + "node-playground/*": ["../../playgrounds/node/src/*"], + "@studiocms/core": ["../studiocms_core/src/index.ts"], + "@studiocms/core/*": ["../studiocms_core/src/*"], + "@studiocms/renderers": ["../studiocms_renderers/src/index.ts"], + "@studiocms/renderers/*": ["../studiocms_renderers/src/*"] } }, "references": [ { "path": "../../playgrounds/node" + }, + { + "path": "../studiocms_core" + }, + { + "path": "../studiocms_renderers" } ], - "include": ["./package.json", "../../playgrounds/node/.astro/**/*", "./**/*", "./src/**/*.json"] + "include": [ + "./package.json", + "../../playgrounds/node/**/*", + "../../playgrounds/node/.astro/**/*", + "../studiocms_core/**/*", + "../studiocms_renderers/**/*", + "./**/*", + "./src/**/*.json" + ] } diff --git a/packages/studiocms_imagehandler/tsconfig.json b/packages/studiocms_imagehandler/tsconfig.json index b058bec2a..740b2031f 100644 --- a/packages/studiocms_imagehandler/tsconfig.json +++ b/packages/studiocms_imagehandler/tsconfig.json @@ -8,13 +8,25 @@ "allowImportingTsExtensions": false, "emitDeclarationOnly": false, "paths": { - "node-playground/*": ["../../playgrounds/node/src/*"] + "node-playground/*": ["../../playgrounds/node/src/*"], + "@studiocms/core": ["../studiocms_core/src/index.ts"], + "@studiocms/core/*": ["../studiocms_core/src/*"] } }, "references": [ { "path": "../../playgrounds/node" + }, + { + "path": "../studiocms_core" } ], - "include": ["./package.json", "../../playgrounds/node/.astro/**/*", "./**/*", "./src/**/*.json"] + "include": [ + "./package.json", + "../../playgrounds/node/**/*", + "../../playgrounds/node/.astro/**/*", + "../studiocms_core/**/*", + "./**/*", + "./src/**/*.json" + ] } diff --git a/packages/studiocms_renderers/tsconfig.json b/packages/studiocms_renderers/tsconfig.json index 293461caa..d8530b08e 100644 --- a/packages/studiocms_renderers/tsconfig.json +++ b/packages/studiocms_renderers/tsconfig.json @@ -8,13 +8,25 @@ "allowImportingTsExtensions": false, "emitDeclarationOnly": false, "paths": { - "node-playground/*": ["../../playgrounds/node/src/*"] + "node-playground/*": ["../../playgrounds/node/src/*"], + "@studiocms/core": ["../studiocms_core/src/index.ts"], + "@studiocms/core/*": ["../studiocms_core/src/*"] } }, "references": [ { "path": "../../playgrounds/node" + }, + { + "path": "../studiocms_core" } ], - "include": ["./package.json", "../../playgrounds/node/.astro/**/*", "./**/*", "./src/**/*.json"] + "include": [ + "./package.json", + "../../playgrounds/node/**/*", + "../../playgrounds/node/.astro/**/*", + "../studiocms_core/**/*", + "./**/*", + "./src/**/*.json" + ] } diff --git a/packages/studiocms_robotstxt/tsconfig.json b/packages/studiocms_robotstxt/tsconfig.json index 28200ffd8..803f32d0a 100644 --- a/packages/studiocms_robotstxt/tsconfig.json +++ b/packages/studiocms_robotstxt/tsconfig.json @@ -16,5 +16,11 @@ "path": "../../playgrounds/node" } ], - "include": ["./package.json", "../../playgrounds/node/.astro/**/*", "./**/*", "./src/**/*.json"] + "include": [ + "./package.json", + "../../playgrounds/node/**/*", + "../../playgrounds/node/.astro/**/*", + "./**/*", + "./src/**/*.json" + ] } diff --git a/packages/studiocms_ui/.gitignore b/packages/studiocms_ui/.gitignore new file mode 100644 index 000000000..b512c09d4 --- /dev/null +++ b/packages/studiocms_ui/.gitignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/packages/studiocms_ui/README.md b/packages/studiocms_ui/README.md new file mode 100644 index 000000000..1b265edb5 --- /dev/null +++ b/packages/studiocms_ui/README.md @@ -0,0 +1,564 @@ +# @studiocms/ui + +This is the UI library that we use to build StudioCMS. + +All of these components can be tested [here](https://ui-testing.studiocms.xyz). + +## Components & how to use them +All components are exported from `@studiocms/ui/components`. + +### Button +A simple button component. Use it like this: + +```html + +``` + +You can pass the following props: +```ts +type Props = { + as?: As; // What the button should be rendered as. Set to "a" for an anchor tag, etc. + size?: 'sm' | 'md' | 'lg'; + fullWidth?: boolean; // Make the button take up full width + color?: 'default' | 'primary' | 'success' | 'warning' | 'danger'; + variant?: 'solid' | 'outlined' | 'flat'; + class?: string; + disabled?: boolean; + // Note: you can pass all other HTML attributes and they will be applied. +}; +``` + +### Card +A simple card component with support for a header and footer. Use it like this: +```html + +
Header Content
+
Body Content
+
Footer Content
+
+``` + +You can pass the following props: +```ts +type Props = { + as?: As; + class?: string; + fullWidth?: boolean; + fullHeight?: boolean; +}; +``` + +### Center +A component that automatically centers all of it's content. Use it like this: +```html +
Content in here will be centered!
+``` + +### Checkbox +A checkbox component. Use it like this: +```html + +``` + +You can pass the following props: +```ts +type Props = { + label: string; + size?: 'sm' | 'md' | 'lg'; + color?: 'default' | 'primary' | 'success' | 'warning' | 'danger'; + defaultChecked?: boolean; + disabled?: boolean; + name?: string; // If you want to use this in forms. If unset, a name will be auto-generated. + isRequired?: boolean; +}; +``` + +### Divider +A simple divider. Use it like this: +```html +Divider Label +``` + +### Dropdown +A dropdown component. Use it like this: +```html + +
+
Your Trigger goes here!
+
+
+``` +**This component needs a helper to function.** Add it in a script tag: +```html + +``` +You can pass the following props: +```ts +type Option = { + label: string; + value: string; + disabled?: boolean; + color?: 'default' | 'primary' | 'success' | 'warning' | 'danger'; +}; + +type Props = { + id: string; + options: Option[]; + disabled?: boolean; + align?: 'start' | 'center' | 'end'; + triggerOn?: 'left' | 'right' | 'both'; +}; +``` + +### Input +A text input. Use it like this: +```html + +``` +You can pass the following props: +```ts +type Props = { + label?: string; + type?: 'text' | 'password'; + placeholder?: string; + isRequired?: boolean; + name?: string; + disabled?: boolean; + defaultValue?: string; + class?: string; +}; +``` + +### Modal +A modal component with form support. Use it like this: +```html + + +

Header content

+
Modal content
+
+ +``` +**This component needs a helper to function.** Add it in a script tag: +```html + +``` +You can make the modal a form and also display "confirm" and "cancel" buttons individually: +```html + +

Header content

+
Modal content
+
+ +``` +*Note: The order in which you supply the buttons does not change the buttons order in the modal.* + +After adding a button, you can register a callback that will be fired when a button is clicked. If you made the modal a form, this will also give you a way to access the form data: +```html + +``` +You can pass the following props: +```ts +type Props = { + id: string; + size?: 'sm' | 'md' | 'lg'; + dismissable?: boolean; + buttons?: ('confirm' | 'cancel')[]; + isForm?: boolean; +}; +``` + +### RadioGroup +A radio group. Use it like this: +```html + +``` +You can pass the following props: +```ts +type Option = { + label: string; + value: string; + disabled?: boolean; +}; + +type Props = { + label: string; + options: Option[]; + color?: 'default' | 'primary' | 'success' | 'warning' | 'danger'; + defaultValue?: string; // Needs to be the value of an option! + disabled?: boolean; + name?: string; + isRequired?: boolean; + horizontal?: boolean; + class?: string; +}; +``` + +### Row +A simple row component, essentially a flex div to wrap stuff in. Use it like this: +```html + + + + +``` +You can pass the following props: +```ts +type Props = { + alignCenter?: boolean; + gapSize?: 'sm' | 'md' | 'lg'; +}; +``` + +### Select +A select component. Use it like this: +```html + + \ No newline at end of file diff --git a/packages/studiocms_ui/src/components/Textarea/Textarea.css b/packages/studiocms_ui/src/components/Textarea/Textarea.css new file mode 100644 index 000000000..52ebf39b8 --- /dev/null +++ b/packages/studiocms_ui/src/components/Textarea/Textarea.css @@ -0,0 +1,53 @@ +.textarea-label { + display: flex; + flex-direction: column; + gap: .25rem; + margin-top: .5rem; + max-width: 80ch; +} + +.textarea-label.disabled { + opacity: 0.5; + pointer-events: none; + color: hsl(var(--text-muted)); +} + +.textarea-label.full { + width: 100%; + max-width: none; +} + +.label { + font-size: 14px; +} + +.textarea { + padding: .65rem 1rem; + border-radius: 8px; + border: 1px solid hsl(var(--border)); + background: hsl(var(--background-step-2)); + color: hsl(var(--text-normal)); + transition: all .15s ease; + resize: none; + min-height: 12ch; +} + +.textarea:hover { + background: hsl(var(--background-step-3)); +} + +.resize .textarea { + resize: both; +} + +.textarea:active, +.textarea:focus { + border: 1px solid hsl(var(--primary-base)); + outline: none; + background: hsl(var(--background-step-2)); +} + +.req-star { + color: hsl(var(--danger-base)); + font-weight: 700; +} diff --git a/packages/studiocms_ui/src/components/Toast/Toaster.astro b/packages/studiocms_ui/src/components/Toast/Toaster.astro new file mode 100644 index 000000000..acddd29f7 --- /dev/null +++ b/packages/studiocms_ui/src/components/Toast/Toaster.astro @@ -0,0 +1,155 @@ +--- +import './Toaster.css'; + +type Props = { + position?: + | 'top-left' + | 'top-right' + | 'top-center' + | 'bottom-left' + | 'bottom-right' + | 'bottom-center'; + class?: string; + duration?: number; + expand?: boolean; + closeButton?: boolean; + offset?: number; + gap?: number; +}; + +const { + position = 'top-center', + class: className, + duration = 4000, + expand = false, + closeButton = false, + offset = 32, + gap = 8, +} = Astro.props; +--- +
+
+
+ \ No newline at end of file diff --git a/packages/studiocms_ui/src/components/Toast/Toaster.css b/packages/studiocms_ui/src/components/Toast/Toaster.css new file mode 100644 index 000000000..1a8b72963 --- /dev/null +++ b/packages/studiocms_ui/src/components/Toast/Toaster.css @@ -0,0 +1,160 @@ +#toaster { + width: 100vw; + height: 100vh; + position: fixed; + top: 0; + left: 0; + z-index: 100; + pointer-events: none; +} + +#toast-drawer { + max-width: 420px; + width: 100%; + height: fit-content; + position: absolute; + display: flex; + flex-direction: column; +} + +#toaster.top-left #toast-drawer, +#toaster.bottom-left #toast-drawer { + left: 50%; + transform: translateX(-50%); +} + +.toast-container { + pointer-events: all; + padding: 1rem; + border-radius: .5rem; + border: 1px solid hsl(var(--border)); + background-color: hsl(var(--background-base)); + box-shadow: 0px 4px 8px hsl(var(--shadow), 0.5); + display: flex; + flex-direction: column; + gap: .5rem; + position: relative; + overflow: hidden; + margin-bottom: var(--gap); + animation: toast-pop-in .25s ease forwards; +} + +.toast-header { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; +} + +.toast-header-left-side { + display: flex; + flex-direction: row; + gap: .5rem; + align-items: center; + font-weight: 500; + font-size: 1.125em; +} + +.toast-header-left-side svg { + color: hsl(var(--primary-base)); +} + +.toast-container.success .toast-header-left-side svg { + color: hsl(var(--success-base)); +} + +.toast-container.warning .toast-header-left-side svg { + color: hsl(var(--warning-base)); +} + +.toast-container.danger .toast-header-left-side svg { + color: hsl(var(--danger-base)); +} + +.toast-progress-bar { + position: absolute; + height: 4px; + width: 100%; + bottom: 0; + left: 0%; + background-color: hsl(var(--primary-base)); + animation: toast-progress forwards linear; +} + +.toast-container.success .toast-progress-bar { + background-color: hsl(var(--success-base)); +} + +.toast-container.warning .toast-progress-bar { + background-color: hsl(var(--warning-base)); +} + +.toast-container.danger .toast-progress-bar { + background-color: hsl(var(--danger-base)); +} + +.close-icon-container { + cursor: pointer; + height: 1.5rem; + width: 1.5rem; + display: flex; + align-items: center; + justify-content: center; + transition: background-color .15s ease; + border-radius: .25rem; +} + +.close-icon-container:hover { + background-color: hsl(var(--default-base)); +} + +.toast-container.closing { + animation: toast-closing .25s ease forwards; +} + +@keyframes toast-pop-in { + 0% { + opacity: 0; + scale: 0.75; + } + 100% { + opacity: 1; + scale: 1; + } +} + +@keyframes toast-closing { + 0% { + opacity: 1; + scale: 1; + max-height: 500px; + margin-bottom: var(--gap); + padding: 1rem; + border: 1px solid hsl(var(--border)); + } + 62.5% { + scale: 0.75; + opacity: 0; + max-height: 500px; + margin-bottom: var(--gap); + padding: 1rem; + border: 1px solid hsl(var(--border)); + } + 100% { + scale: 0.75; + opacity: 0; + max-height: 0px; + margin-bottom: 0; + padding: 0; + border: 0px solid hsl(var(--border)); + } +} + +@keyframes toast-progress { + 0% { + left: 0%; + } + 100% { + left: -100%; + } +} diff --git a/packages/studiocms_ui/src/components/Toast/toast.ts b/packages/studiocms_ui/src/components/Toast/toast.ts new file mode 100644 index 000000000..ca20402b3 --- /dev/null +++ b/packages/studiocms_ui/src/components/Toast/toast.ts @@ -0,0 +1,11 @@ +import type { ToastProps } from '../../types'; + +function toast(props: ToastProps) { + const createToast = new CustomEvent('createtoast', { + detail: props, + }); + + document.dispatchEvent(createToast); +} + +export { toast }; diff --git a/packages/studiocms_ui/src/components/Toggle/Toggle.astro b/packages/studiocms_ui/src/components/Toggle/Toggle.astro new file mode 100644 index 000000000..7f9928cb7 --- /dev/null +++ b/packages/studiocms_ui/src/components/Toggle/Toggle.astro @@ -0,0 +1,51 @@ +--- +import './Toggle.css'; + +import type { StudioCMSColorway } from '../../utils/colors'; +import { generateID } from '../../utils/generateID'; + +type Props = { + label: string; + size?: 'sm' | 'md' | 'lg'; + color?: StudioCMSColorway; + defaultChecked?: boolean; + disabled?: boolean; + name?: string; + isRequired?: boolean; +}; + +const { + size = 'md', + color = 'default', + defaultChecked, + disabled, + name = generateID('checkbox'), + label, + isRequired, +} = Astro.props; +--- +