From 81b7cfc7b59130ca1be8cbf4e0c484db47a9cd8d Mon Sep 17 00:00:00 2001 From: VictoriaBeilstenEdmands Date: Tue, 16 Dec 2025 14:51:58 +0000 Subject: [PATCH 01/10] Add MUI Button story --- .storybook/main.ts | 35 +- .storybook/preview.tsx | 33 +- package.json | 26 +- pnpm-lock.yaml | 2410 ++++++++---------- src/components/MUI/Inputs/Button.stories.tsx | 237 ++ src/components/MUI/Inputs/Button.tsx | 15 + 6 files changed, 1296 insertions(+), 1460 deletions(-) create mode 100644 src/components/MUI/Inputs/Button.stories.tsx create mode 100644 src/components/MUI/Inputs/Button.tsx diff --git a/.storybook/main.ts b/.storybook/main.ts index 0656ad6..c8c5ac4 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -1,32 +1,35 @@ -import type { StorybookConfig } from "@storybook/react-webpack5"; +import type { StorybookConfig } from "@storybook/react-vite"; const config: StorybookConfig = { stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"], addons: [ - "@storybook/addon-webpack5-compiler-swc", "@storybook/addon-essentials", "@chromatic-com/storybook", "@storybook/addon-interactions", "@storybook/addon-links", "storybook-dark-mode", + "@storybook/addon-themes", + "@storybook/addon-a11y", ], - framework: { - name: "@storybook/react-webpack5", - options: { - builder: { - useSWC: true, + framework: { name: "@storybook/react-vite", options: {} }, + docs: { autodocs: true }, + typescript: { + check: false, + reactDocgen: "react-docgen", + reactDocgenTypescriptOptions: { + compilerOptions: { + allowSyntheticDefaultImports: false, + esModuleInterop: false, }, + shouldExtractLiteralValuesFromEnum: true, + shouldRemoveUndefinedFromOptional: true, + propFilter: (prop) => + prop.parent + ? !/node_modules\/(?!@mui)/.test(prop.parent.fileName) + : true, }, }, staticDirs: ["../src/public/"], - swc: () => ({ - jsc: { - transform: { - react: { - runtime: "automatic", - }, - }, - }, - }), }; + export default config; diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 4de2bdc..685d506 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -11,28 +11,24 @@ const TextThemeBase = "Theme: Generic"; const TextThemeDiamond = "Theme: Diamond"; export const decorators = [ - (StoriesWithPadding: React.FC) => { - return ( -
- -
- ); - }, - (StoriesWithThemeSwapping: React.FC, context: Context) => { - return ( - - - - ); - }, + (StoriesWithPadding: React.FC) => ( +
+ +
+ ), + (StoriesWithThemeSwapping: React.FC, context: Context) => ( + + + + ), (StoriesWithThemeProvider: React.FC, context: Context) => { const selectedTheme = context.globals.theme || TextThemeBase; const selectedThemeMode = context.globals.themeMode || TextLight; return ( @@ -68,6 +64,7 @@ const preview: Preview = { }, parameters: { controls: { + expanded: true, matchers: { color: /(background|color)$/i, date: /Date$/i, @@ -89,9 +86,7 @@ const preview: Preview = { }, }, argTypes: { - linkComponent: { - control: false, - }, + linkComponent: { control: false }, }, }; diff --git a/package.json b/package.json index 9eb2726..49e5aad 100644 --- a/package.json +++ b/package.json @@ -54,17 +54,18 @@ "@rollup/plugin-node-resolve": "^15.3.0", "@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-typescript": "^12.1.1", - "@storybook/addon-actions": "^8.4.4", - "@storybook/addon-controls": "^8.4.4", - "@storybook/addon-essentials": "^8.4.4", - "@storybook/addon-interactions": "^8.4.4", - "@storybook/addon-links": "^8.4.4", - "@storybook/addon-toolbars": "^8.4.4", - "@storybook/addon-webpack5-compiler-swc": "^1.0.5", - "@storybook/blocks": "^8.4.4", - "@storybook/react": "^8.4.4", - "@storybook/react-webpack5": "^8.4.4", - "@storybook/test": "^8.4.4", + "@storybook/addon-a11y": "^8.6.14", + "@storybook/addon-actions": "^8.4.7", + "@storybook/addon-controls": "^8.4.7", + "@storybook/addon-essentials": "^8.6.14", + "@storybook/addon-interactions": "^8.6.14", + "@storybook/addon-links": "^8.6.14", + "@storybook/addon-themes": "^8.6.14", + "@storybook/addon-toolbars": "^8.4.7", + "@storybook/blocks": "^8.4.7", + "@storybook/react": "^8.6.14", + "@storybook/react-vite": "^8.6.14", + "@storybook/test": "^8.6.14", "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.1.0", "@types/node": "^20.19.21", @@ -80,13 +81,14 @@ "eslint-plugin-react-hooks": "^5.1.0", "file-loader": "^6.2.0", "gh-pages": "^6.2.0", + "react-docgen": "^8.0.2", "react-dom": "^18.3.1", "react-router-dom": "^7.5.3", "rollup": "^4.27.3", "rollup-plugin-dts": "^6.1.1", "rollup-plugin-peer-deps-external": "^2.2.4", "rollup-plugin-postcss": "^4.0.2", - "storybook": "^8.4.4", + "storybook": "^8.6.14", "storybook-dark-mode": "^4.0.2", "tslib": "^2.8.1", "typedoc": "^0.28.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f3b6b6d..41c0aef 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -56,7 +56,7 @@ importers: version: 7.26.0(@babel/core@7.26.0) '@chromatic-com/storybook': specifier: ^3.2.2 - version: 3.2.3(react@18.3.1)(storybook@8.4.7(prettier@3.4.2)) + version: 3.2.3(react@18.3.1)(storybook@8.6.14(prettier@3.4.2)) '@eslint/eslintrc': specifier: ^3.2.0 version: 3.2.0 @@ -78,39 +78,42 @@ importers: '@rollup/plugin-typescript': specifier: ^12.1.1 version: 12.1.2(rollup@4.30.0)(tslib@2.8.1)(typescript@5.7.2) + '@storybook/addon-a11y': + specifier: ^8.6.14 + version: 8.6.14(storybook@8.6.14(prettier@3.4.2)) '@storybook/addon-actions': - specifier: ^8.4.4 - version: 8.4.7(storybook@8.4.7(prettier@3.4.2)) + specifier: ^8.4.7 + version: 8.4.7(storybook@8.6.14(prettier@3.4.2)) '@storybook/addon-controls': - specifier: ^8.4.4 - version: 8.4.7(storybook@8.4.7(prettier@3.4.2)) + specifier: ^8.4.7 + version: 8.4.7(storybook@8.6.14(prettier@3.4.2)) '@storybook/addon-essentials': - specifier: ^8.4.4 - version: 8.4.7(@types/react@18.3.18)(storybook@8.4.7(prettier@3.4.2)) + specifier: ^8.6.14 + version: 8.6.14(@types/react@18.3.18)(storybook@8.6.14(prettier@3.4.2)) '@storybook/addon-interactions': - specifier: ^8.4.4 - version: 8.4.7(storybook@8.4.7(prettier@3.4.2)) + specifier: ^8.6.14 + version: 8.6.14(storybook@8.6.14(prettier@3.4.2)) '@storybook/addon-links': - specifier: ^8.4.4 - version: 8.4.7(react@18.3.1)(storybook@8.4.7(prettier@3.4.2)) + specifier: ^8.6.14 + version: 8.6.14(react@18.3.1)(storybook@8.6.14(prettier@3.4.2)) + '@storybook/addon-themes': + specifier: ^8.6.14 + version: 8.6.14(storybook@8.6.14(prettier@3.4.2)) '@storybook/addon-toolbars': - specifier: ^8.4.4 - version: 8.4.7(storybook@8.4.7(prettier@3.4.2)) - '@storybook/addon-webpack5-compiler-swc': - specifier: ^1.0.5 - version: 1.0.6(webpack@5.97.1(@swc/core@1.10.4)(esbuild@0.24.2)) + specifier: ^8.4.7 + version: 8.4.7(storybook@8.6.14(prettier@3.4.2)) '@storybook/blocks': - specifier: ^8.4.4 - version: 8.4.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.7(prettier@3.4.2)) + specifier: ^8.4.7 + version: 8.4.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.6.14(prettier@3.4.2)) '@storybook/react': - specifier: ^8.4.4 - version: 8.4.7(@storybook/test@8.4.7(storybook@8.4.7(prettier@3.4.2)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.7(prettier@3.4.2))(typescript@5.7.2) - '@storybook/react-webpack5': - specifier: ^8.4.4 - version: 8.4.7(@storybook/test@8.4.7(storybook@8.4.7(prettier@3.4.2)))(@swc/core@1.10.4)(esbuild@0.24.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.7(prettier@3.4.2))(typescript@5.7.2) + specifier: ^8.6.14 + version: 8.6.14(@storybook/test@8.6.14(storybook@8.6.14(prettier@3.4.2)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.6.14(prettier@3.4.2))(typescript@5.7.2) + '@storybook/react-vite': + specifier: ^8.6.14 + version: 8.6.14(@storybook/test@8.6.14(storybook@8.6.14(prettier@3.4.2)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.30.0)(storybook@8.6.14(prettier@3.4.2))(typescript@5.7.2)(vite@7.1.10(@types/node@20.19.21)(jiti@1.21.7)(less@4.5.1)(terser@5.37.0)(yaml@2.8.0)) '@storybook/test': - specifier: ^8.4.4 - version: 8.4.7(storybook@8.4.7(prettier@3.4.2)) + specifier: ^8.6.14 + version: 8.6.14(storybook@8.6.14(prettier@3.4.2)) '@testing-library/jest-dom': specifier: ^6.9.1 version: 6.9.1 @@ -131,31 +134,34 @@ importers: version: 3.0.5 '@typescript-eslint/eslint-plugin': specifier: ^8.18.1 - version: 8.19.0(@typescript-eslint/parser@8.19.0(eslint@9.17.0)(typescript@5.7.2))(eslint@9.17.0)(typescript@5.7.2) + version: 8.19.0(@typescript-eslint/parser@8.19.0(eslint@9.17.0(jiti@1.21.7))(typescript@5.7.2))(eslint@9.17.0(jiti@1.21.7))(typescript@5.7.2) '@typescript-eslint/parser': specifier: ^8.18.1 - version: 8.19.0(eslint@9.17.0)(typescript@5.7.2) + version: 8.19.0(eslint@9.17.0(jiti@1.21.7))(typescript@5.7.2) eslint: specifier: ^9.17.0 - version: 9.17.0 + version: 9.17.0(jiti@1.21.7) eslint-config-prettier: specifier: ^9.1.0 - version: 9.1.0(eslint@9.17.0) + version: 9.1.0(eslint@9.17.0(jiti@1.21.7)) eslint-plugin-prettier: specifier: ^5.2.1 - version: 5.2.1(@types/eslint@9.6.1)(eslint-config-prettier@9.1.0(eslint@9.17.0))(eslint@9.17.0)(prettier@3.4.2) + version: 5.2.1(@types/eslint@9.6.1)(eslint-config-prettier@9.1.0(eslint@9.17.0(jiti@1.21.7)))(eslint@9.17.0(jiti@1.21.7))(prettier@3.4.2) eslint-plugin-react: specifier: ^7.37.2 - version: 7.37.3(eslint@9.17.0) + version: 7.37.3(eslint@9.17.0(jiti@1.21.7)) eslint-plugin-react-hooks: specifier: ^5.1.0 - version: 5.1.0(eslint@9.17.0) + version: 5.1.0(eslint@9.17.0(jiti@1.21.7)) file-loader: specifier: ^6.2.0 - version: 6.2.0(webpack@5.97.1(@swc/core@1.10.4)(esbuild@0.24.2)) + version: 6.2.0(webpack@5.97.1(esbuild@0.25.11)) gh-pages: specifier: ^6.2.0 version: 6.3.0 + react-docgen: + specifier: ^8.0.2 + version: 8.0.2 react-dom: specifier: ^18.3.1 version: 18.3.1(react@18.3.1) @@ -173,13 +179,13 @@ importers: version: 2.2.4(rollup@4.30.0) rollup-plugin-postcss: specifier: ^4.0.2 - version: 4.0.2(postcss@8.4.49) + version: 4.0.2(postcss@8.5.6) storybook: - specifier: ^8.4.4 - version: 8.4.7(prettier@3.4.2) + specifier: ^8.6.14 + version: 8.6.14(prettier@3.4.2) storybook-dark-mode: specifier: ^4.0.2 - version: 4.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.7(prettier@3.4.2)) + version: 4.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.6.14(prettier@3.4.2)) tslib: specifier: ^2.8.1 version: 2.8.1 @@ -191,10 +197,10 @@ importers: version: 5.7.2 typescript-eslint: specifier: ^8.15.0 - version: 8.19.0(eslint@9.17.0)(typescript@5.7.2) + version: 8.19.0(eslint@9.17.0(jiti@1.21.7))(typescript@5.7.2) vitest: specifier: ^3.2.4 - version: 3.2.4(@types/node@20.19.21)(jsdom@20.0.3)(terser@5.37.0)(yaml@2.8.0) + version: 3.2.4(@types/node@20.19.21)(jiti@1.21.7)(jsdom@20.0.3)(less@4.5.1)(terser@5.37.0)(yaml@2.8.0) packages: @@ -209,18 +215,34 @@ packages: resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + engines: {node: '>=6.9.0'} + '@babel/compat-data@7.26.3': resolution: {integrity: sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==} engines: {node: '>=6.9.0'} + '@babel/compat-data@7.28.5': + resolution: {integrity: sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==} + engines: {node: '>=6.9.0'} + '@babel/core@7.26.0': resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==} engines: {node: '>=6.9.0'} + '@babel/core@7.28.5': + resolution: {integrity: sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==} + engines: {node: '>=6.9.0'} + '@babel/generator@7.26.3': resolution: {integrity: sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==} engines: {node: '>=6.9.0'} + '@babel/generator@7.28.5': + resolution: {integrity: sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==} + engines: {node: '>=6.9.0'} + '@babel/helper-annotate-as-pure@7.25.9': resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} engines: {node: '>=6.9.0'} @@ -229,6 +251,10 @@ packages: resolution: {integrity: sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==} engines: {node: '>=6.9.0'} + '@babel/helper-compilation-targets@7.27.2': + resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} + engines: {node: '>=6.9.0'} + '@babel/helper-create-class-features-plugin@7.25.9': resolution: {integrity: sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==} engines: {node: '>=6.9.0'} @@ -246,6 +272,10 @@ packages: peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + '@babel/helper-member-expression-to-functions@7.25.9': resolution: {integrity: sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==} engines: {node: '>=6.9.0'} @@ -254,12 +284,22 @@ packages: resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} engines: {node: '>=6.9.0'} + '@babel/helper-module-imports@7.27.1': + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} + engines: {node: '>=6.9.0'} + '@babel/helper-module-transforms@7.26.0': resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 + '@babel/helper-module-transforms@7.28.3': + resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + '@babel/helper-optimise-call-expression@7.25.9': resolution: {integrity: sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==} engines: {node: '>=6.9.0'} @@ -288,14 +328,26 @@ packages: resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.25.9': resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@7.25.9': resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + '@babel/helper-wrap-function@7.25.9': resolution: {integrity: sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==} engines: {node: '>=6.9.0'} @@ -304,11 +356,20 @@ packages: resolution: {integrity: sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==} engines: {node: '>=6.9.0'} + '@babel/helpers@7.28.4': + resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==} + engines: {node: '>=6.9.0'} + '@babel/parser@7.26.3': resolution: {integrity: sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==} engines: {node: '>=6.0.0'} hasBin: true + '@babel/parser@7.28.5': + resolution: {integrity: sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==} + engines: {node: '>=6.0.0'} + hasBin: true + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9': resolution: {integrity: sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==} engines: {node: '>=6.9.0'} @@ -736,14 +797,26 @@ packages: resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==} engines: {node: '>=6.9.0'} + '@babel/template@7.27.2': + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} + engines: {node: '>=6.9.0'} + '@babel/traverse@7.26.4': resolution: {integrity: sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==} engines: {node: '>=6.9.0'} + '@babel/traverse@7.28.5': + resolution: {integrity: sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==} + engines: {node: '>=6.9.0'} + '@babel/types@7.26.3': resolution: {integrity: sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==} engines: {node: '>=6.9.0'} + '@babel/types@7.28.5': + resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} + engines: {node: '>=6.9.0'} + '@chromatic-com/storybook@3.2.3': resolution: {integrity: sha512-3+hfANx79kIjP1qrOSLxpoAXOiYUA0S7A0WI0A24kASrv7USFNNW8etR5TjUilMb0LmqKUn3wDwUK2h6aceQ9g==} engines: {node: '>=16.0.0', yarn: '>=1.22.18'} @@ -815,252 +888,126 @@ packages: '@emotion/weak-memoize@0.4.0': resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==} - '@esbuild/aix-ppc64@0.24.2': - resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - '@esbuild/aix-ppc64@0.25.11': resolution: {integrity: sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.24.2': - resolution: {integrity: sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - '@esbuild/android-arm64@0.25.11': resolution: {integrity: sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.24.2': - resolution: {integrity: sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - '@esbuild/android-arm@0.25.11': resolution: {integrity: sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.24.2': - resolution: {integrity: sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - '@esbuild/android-x64@0.25.11': resolution: {integrity: sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.24.2': - resolution: {integrity: sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - '@esbuild/darwin-arm64@0.25.11': resolution: {integrity: sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.24.2': - resolution: {integrity: sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - '@esbuild/darwin-x64@0.25.11': resolution: {integrity: sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.24.2': - resolution: {integrity: sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - '@esbuild/freebsd-arm64@0.25.11': resolution: {integrity: sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.24.2': - resolution: {integrity: sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - '@esbuild/freebsd-x64@0.25.11': resolution: {integrity: sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.24.2': - resolution: {integrity: sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - '@esbuild/linux-arm64@0.25.11': resolution: {integrity: sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.24.2': - resolution: {integrity: sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - '@esbuild/linux-arm@0.25.11': resolution: {integrity: sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.24.2': - resolution: {integrity: sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - '@esbuild/linux-ia32@0.25.11': resolution: {integrity: sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.24.2': - resolution: {integrity: sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - '@esbuild/linux-loong64@0.25.11': resolution: {integrity: sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.24.2': - resolution: {integrity: sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - '@esbuild/linux-mips64el@0.25.11': resolution: {integrity: sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.24.2': - resolution: {integrity: sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - '@esbuild/linux-ppc64@0.25.11': resolution: {integrity: sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.24.2': - resolution: {integrity: sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - '@esbuild/linux-riscv64@0.25.11': resolution: {integrity: sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.24.2': - resolution: {integrity: sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - '@esbuild/linux-s390x@0.25.11': resolution: {integrity: sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.24.2': - resolution: {integrity: sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - '@esbuild/linux-x64@0.25.11': resolution: {integrity: sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.24.2': - resolution: {integrity: sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - '@esbuild/netbsd-arm64@0.25.11': resolution: {integrity: sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.24.2': - resolution: {integrity: sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - '@esbuild/netbsd-x64@0.25.11': resolution: {integrity: sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.24.2': - resolution: {integrity: sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - '@esbuild/openbsd-arm64@0.25.11': resolution: {integrity: sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.24.2': - resolution: {integrity: sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - '@esbuild/openbsd-x64@0.25.11': resolution: {integrity: sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw==} engines: {node: '>=18'} @@ -1073,48 +1020,24 @@ packages: cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.24.2': - resolution: {integrity: sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - '@esbuild/sunos-x64@0.25.11': resolution: {integrity: sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.24.2': - resolution: {integrity: sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - '@esbuild/win32-arm64@0.25.11': resolution: {integrity: sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.24.2': - resolution: {integrity: sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - '@esbuild/win32-ia32@0.25.11': resolution: {integrity: sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.24.2': - resolution: {integrity: sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - '@esbuild/win32-x64@0.25.11': resolution: {integrity: sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA==} engines: {node: '>=18'} @@ -1178,10 +1101,29 @@ packages: resolution: {integrity: sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==} engines: {node: '>=18.18'} + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@joshwooding/vite-plugin-react-docgen-typescript@0.5.0': + resolution: {integrity: sha512-qYDdL7fPwLRI+bJNurVcis+tNgJmvWjH4YTBGXTA8xMuxFrnAz6E5o35iyzyKbq5J5Lr8mJGfrR5GXl+WGwhgQ==} + peerDependencies: + typescript: '>= 4.3.x' + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 + peerDependenciesMeta: + typescript: + optional: true + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + '@jridgewell/gen-mapping@0.3.8': resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} engines: {node: '>=6.0.0'} + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + '@jridgewell/resolve-uri@3.1.2': resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} engines: {node: '>=6.0.0'} @@ -1199,6 +1141,9 @@ packages: '@jridgewell/trace-mapping@0.3.25': resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@jsonforms/core@3.6.0': resolution: {integrity: sha512-Qz7qJPf/yP4ybqknZ500zggIDZRJfcufu+3efp/xNWf05mpXvxN9TdfmA++BdXi5Nr4UAgjos2kFmQpZpQaCDw==} @@ -1372,6 +1317,10 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + '@pkgr/core@0.1.1': resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} @@ -1666,73 +1615,94 @@ packages: '@shikijs/vscode-textmate@10.0.2': resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} + '@storybook/addon-a11y@8.6.14': + resolution: {integrity: sha512-fozv6enO9IgpWq2U8qqS8MZ21Nt+MVHiRQe3CjnCpBOejTyo/ATm690PeYYRVHVG6M/15TVePb0h3ngKQbrrzQ==} + peerDependencies: + storybook: ^8.6.14 + '@storybook/addon-actions@8.4.7': resolution: {integrity: sha512-mjtD5JxcPuW74T6h7nqMxWTvDneFtokg88p6kQ5OnC1M259iAXb//yiSZgu/quunMHPCXSiqn4FNOSgASTSbsA==} peerDependencies: storybook: ^8.4.7 - '@storybook/addon-backgrounds@8.4.7': - resolution: {integrity: sha512-I4/aErqtFiazcoWyKafOAm3bLpxTj6eQuH/woSbk1Yx+EzN+Dbrgx1Updy8//bsNtKkcrXETITreqHC+a57DHQ==} + '@storybook/addon-actions@8.6.14': + resolution: {integrity: sha512-mDQxylxGGCQSK7tJPkD144J8jWh9IU9ziJMHfB84PKpI/V5ZgqMDnpr2bssTrUaGDqU5e1/z8KcRF+Melhs9pQ==} peerDependencies: - storybook: ^8.4.7 + storybook: ^8.6.14 + + '@storybook/addon-backgrounds@8.6.14': + resolution: {integrity: sha512-l9xS8qWe5n4tvMwth09QxH2PmJbCctEvBAc1tjjRasAfrd69f7/uFK4WhwJAstzBTNgTc8VXI4w8ZR97i1sFbg==} + peerDependencies: + storybook: ^8.6.14 '@storybook/addon-controls@8.4.7': resolution: {integrity: sha512-377uo5IsJgXLnQLJixa47+11V+7Wn9KcDEw+96aGCBCfLbWNH8S08tJHHnSu+jXg9zoqCAC23MetntVp6LetHA==} peerDependencies: storybook: ^8.4.7 - '@storybook/addon-docs@8.4.7': - resolution: {integrity: sha512-NwWaiTDT5puCBSUOVuf6ME7Zsbwz7Y79WF5tMZBx/sLQ60vpmJVQsap6NSjvK1Ravhc21EsIXqemAcBjAWu80w==} + '@storybook/addon-controls@8.6.14': + resolution: {integrity: sha512-IiQpkNJdiRyA4Mq9mzjZlvQugL/aE7hNgVxBBGPiIZG6wb6Ht9hNnBYpap5ZXXFKV9p2qVI0FZK445ONmAa+Cw==} peerDependencies: - storybook: ^8.4.7 + storybook: ^8.6.14 - '@storybook/addon-essentials@8.4.7': - resolution: {integrity: sha512-+BtZHCBrYtQKILtejKxh0CDRGIgTl9PumfBOKRaihYb4FX1IjSAxoV/oo/IfEjlkF5f87vouShWsRa8EUauFDw==} + '@storybook/addon-docs@8.6.14': + resolution: {integrity: sha512-Obpd0OhAF99JyU5pp5ci17YmpcQtMNgqW2pTXV8jAiiipWpwO++hNDeQmLmlSXB399XjtRDOcDVkoc7rc6JzdQ==} peerDependencies: - storybook: ^8.4.7 + storybook: ^8.6.14 - '@storybook/addon-highlight@8.4.7': - resolution: {integrity: sha512-whQIDBd3PfVwcUCrRXvCUHWClXe9mQ7XkTPCdPo4B/tZ6Z9c6zD8JUHT76ddyHivixFLowMnA8PxMU6kCMAiNw==} + '@storybook/addon-essentials@8.6.14': + resolution: {integrity: sha512-5ZZSHNaW9mXMOFkoPyc3QkoNGdJHETZydI62/OASR0lmPlJ1065TNigEo5dJddmZNn0/3bkE8eKMAzLnO5eIdA==} peerDependencies: - storybook: ^8.4.7 + storybook: ^8.6.14 - '@storybook/addon-interactions@8.4.7': - resolution: {integrity: sha512-fnufT3ym8ht3HHUIRVXAH47iOJW/QOb0VSM+j269gDuvyDcY03D1civCu1v+eZLGaXPKJ8vtjr0L8zKQ/4P0JQ==} + '@storybook/addon-highlight@8.6.14': + resolution: {integrity: sha512-4H19OJlapkofiE9tM6K/vsepf4ir9jMm9T+zw5L85blJZxhKZIbJ6FO0TCG9PDc4iPt3L6+aq5B0X29s9zicNQ==} peerDependencies: - storybook: ^8.4.7 + storybook: ^8.6.14 - '@storybook/addon-links@8.4.7': - resolution: {integrity: sha512-L/1h4dMeMKF+MM0DanN24v5p3faNYbbtOApMgg7SlcBT/tgo3+cAjkgmNpYA8XtKnDezm+T2mTDhB8mmIRZpIQ==} + '@storybook/addon-interactions@8.6.14': + resolution: {integrity: sha512-8VmElhm2XOjh22l/dO4UmXxNOolGhNiSpBcls2pqWSraVh4a670EyYBZsHpkXqfNHo2YgKyZN3C91+9zfH79qQ==} + peerDependencies: + storybook: ^8.6.14 + + '@storybook/addon-links@8.6.14': + resolution: {integrity: sha512-DRlXHIyZzOruAZkxmXfVgTF+4d6K27pFcH4cUsm3KT1AXuZbr23lb5iZHpUZoG6lmU85Sru4xCEgewSTXBIe1w==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.4.7 + storybook: ^8.6.14 peerDependenciesMeta: react: optional: true - '@storybook/addon-measure@8.4.7': - resolution: {integrity: sha512-QfvqYWDSI5F68mKvafEmZic3SMiK7zZM8VA0kTXx55hF/+vx61Mm0HccApUT96xCXIgmwQwDvn9gS4TkX81Dmw==} + '@storybook/addon-measure@8.6.14': + resolution: {integrity: sha512-1Tlyb72NX8aAqm6I6OICsUuGOP6hgnXcuFlXucyhKomPa6j3Eu2vKu561t/f0oGtAK2nO93Z70kVaEh5X+vaGw==} peerDependencies: - storybook: ^8.4.7 + storybook: ^8.6.14 - '@storybook/addon-outline@8.4.7': - resolution: {integrity: sha512-6LYRqUZxSodmAIl8icr585Oi8pmzbZ90aloZJIpve+dBAzo7ydYrSQxxoQEVltXbKf3VeVcrs64ouAYqjisMYA==} + '@storybook/addon-outline@8.6.14': + resolution: {integrity: sha512-CW857JvN6OxGWElqjlzJO2S69DHf+xO3WsEfT5mT3ZtIjmsvRDukdWfDU9bIYUFyA2lFvYjncBGjbK+I91XR7w==} peerDependencies: - storybook: ^8.4.7 + storybook: ^8.6.14 + + '@storybook/addon-themes@8.6.14': + resolution: {integrity: sha512-/HJCgskA3OFGectuoLEBQ3JX1nQhE7lnpSv5gH13CWyyaMEk/mP8JYF1uO25YQqwGuSgL2gaEox+aK7UmglAmQ==} + peerDependencies: + storybook: ^8.6.14 '@storybook/addon-toolbars@8.4.7': resolution: {integrity: sha512-OSfdv5UZs+NdGB+nZmbafGUWimiweJ/56gShlw8Neo/4jOJl1R3rnRqqY7MYx8E4GwoX+i3GF5C3iWFNQqlDcw==} peerDependencies: storybook: ^8.4.7 - '@storybook/addon-viewport@8.4.7': - resolution: {integrity: sha512-hvczh/jjuXXcOogih09a663sRDDSATXwbE866al1DXgbDFraYD/LxX/QDb38W9hdjU9+Qhx8VFIcNWoMQns5HQ==} + '@storybook/addon-toolbars@8.6.14': + resolution: {integrity: sha512-W/wEXT8h3VyZTVfWK/84BAcjAxTdtRiAkT2KAN0nbSHxxB5KEM1MjKpKu2upyzzMa3EywITqbfy4dP6lpkVTwQ==} peerDependencies: - storybook: ^8.4.7 + storybook: ^8.6.14 - '@storybook/addon-webpack5-compiler-swc@1.0.6': - resolution: {integrity: sha512-QiZheKKYsUCAtPn9phwtmOBAWBNxnxyfu5E+HUSQIbX94pTwc3ROufJ3g1R/RMQZcklOYXpSI0V8FS1m6aUVkg==} - engines: {node: '>=18'} + '@storybook/addon-viewport@8.6.14': + resolution: {integrity: sha512-gNzVQbMqRC+/4uQTPI2ZrWuRHGquTMZpdgB9DrD88VTEjNudP+J6r8myLfr2VvGksBbUMHkGHMXHuIhrBEnXYA==} + peerDependencies: + storybook: ^8.6.14 '@storybook/blocks@8.4.7': resolution: {integrity: sha512-+QH7+JwXXXIyP3fRCxz/7E2VZepAanXJM7G8nbR3wWsqWgrRp4Wra6MvybxAYCxU7aNfJX5c+RW84SNikFpcIA==} @@ -1746,42 +1716,51 @@ packages: react-dom: optional: true - '@storybook/builder-webpack5@8.4.7': - resolution: {integrity: sha512-O8LpsQ+4g2x5kh7rI9+jEUdX8k1a5egBQU1lbudmHchqsV0IKiVqBD9LL5Gj3wpit4vB8coSW4ZWTFBw8FQb4Q==} + '@storybook/blocks@8.6.14': + resolution: {integrity: sha512-rBMHAfA39AGHgkrDze4RmsnQTMw1ND5fGWobr9pDcJdnDKWQWNRD7Nrlxj0gFlN3n4D9lEZhWGdFrCbku7FVAQ==} peerDependencies: - storybook: ^8.4.7 - typescript: '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + storybook: ^8.6.14 peerDependenciesMeta: - typescript: + react: + optional: true + react-dom: optional: true + '@storybook/builder-vite@8.6.14': + resolution: {integrity: sha512-ajWYhy32ksBWxwWHrjwZzyC0Ii5ZTeu5lsqA95Q/EQBB0P5qWlHWGM3AVyv82Mz/ND03ebGy123uVwgf6olnYQ==} + peerDependencies: + storybook: ^8.6.14 + vite: ^4.0.0 || ^5.0.0 || ^6.0.0 + '@storybook/components@8.4.7': resolution: {integrity: sha512-uyJIcoyeMWKAvjrG9tJBUCKxr2WZk+PomgrgrUwejkIfXMO76i6jw9BwLa0NZjYdlthDv30r9FfbYZyeNPmF0g==} peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - '@storybook/core-events@8.4.7': - resolution: {integrity: sha512-D5WhJBVfywIVBurNZ7mwSjXT18a8Ct5AfZFEukIBPLaezY21TgN/7sE2OU5dkMQsm11oAZzsdLPOzms2e9HsRg==} + '@storybook/components@8.6.14': + resolution: {integrity: sha512-HNR2mC5I4Z5ek8kTrVZlIY/B8gJGs5b3XdZPBPBopTIN6U/YHXiDyOjY3JlaS4fSG1fVhp/Qp1TpMn1w/9m1pw==} peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - '@storybook/core-webpack@8.4.7': - resolution: {integrity: sha512-Tj+CjQLpFyBJxhhMms+vbPT3+gTRAiQlrhY3L1IEVwBa3wtRMS0qjozH26d1hK4G6mUIEdwu13L54HMU/w33Sg==} + '@storybook/core-events@8.4.7': + resolution: {integrity: sha512-D5WhJBVfywIVBurNZ7mwSjXT18a8Ct5AfZFEukIBPLaezY21TgN/7sE2OU5dkMQsm11oAZzsdLPOzms2e9HsRg==} peerDependencies: - storybook: ^8.4.7 + storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - '@storybook/core@8.4.7': - resolution: {integrity: sha512-7Z8Z0A+1YnhrrSXoKKwFFI4gnsLbWzr8fnDCU6+6HlDukFYh8GHRcZ9zKfqmy6U3hw2h8H5DrHsxWfyaYUUOoA==} + '@storybook/core@8.6.14': + resolution: {integrity: sha512-1P/w4FSNRqP8j3JQBOi3yGt8PVOgSRbP66Ok520T78eJBeqx9ukCfl912PQZ7SPbW3TIunBwLXMZOjZwBB/JmA==} peerDependencies: prettier: ^2 || ^3 peerDependenciesMeta: prettier: optional: true - '@storybook/csf-plugin@8.4.7': - resolution: {integrity: sha512-Fgogplu4HImgC+AYDcdGm1rmL6OR1rVdNX1Be9C/NEXwOCpbbBwi0BxTf/2ZxHRk9fCeaPEcOdP5S8QHfltc1g==} + '@storybook/csf-plugin@8.6.14': + resolution: {integrity: sha512-dErtc9teAuN+eelN8FojzFE635xlq9cNGGGEu0WEmMUQ4iJ8pingvBO1N8X3scz4Ry7KnxX++NNf3J3gpxS8qQ==} peerDependencies: - storybook: ^8.4.7 + storybook: ^8.6.14 '@storybook/csf@0.1.13': resolution: {integrity: sha512-7xOOwCLGB3ebM87eemep89MYRFTko+D8qE7EdAAq74lgdqRR5cOUtYWJLjO2dLtP94nqoOdHJo6MdLLKzg412Q==} @@ -1796,66 +1775,54 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - '@storybook/instrumenter@8.4.7': - resolution: {integrity: sha512-k6NSD3jaRCCHAFtqXZ7tw8jAzD/yTEWXGya+REgZqq5RCkmJ+9S4Ytp/6OhQMPtPFX23gAuJJzTQVLcCr+gjRg==} + '@storybook/instrumenter@8.6.14': + resolution: {integrity: sha512-iG4MlWCcz1L7Yu8AwgsnfVAmMbvyRSk700Mfy2g4c8y5O+Cv1ejshE1LBBsCwHgkuqU0H4R0qu4g23+6UnUemQ==} peerDependencies: - storybook: ^8.4.7 + storybook: ^8.6.14 '@storybook/manager-api@8.4.7': resolution: {integrity: sha512-ELqemTviCxAsZ5tqUz39sDmQkvhVAvAgiplYy9Uf15kO0SP2+HKsCMzlrm2ue2FfkUNyqbDayCPPCB0Cdn/mpQ==} peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - '@storybook/preset-react-webpack@8.4.7': - resolution: {integrity: sha512-geTSBKyrBagVihil5MF7LkVFynbfHhCinvnbCZZqXW7M1vgcxvatunUENB+iV8eWg/0EJ+8O7scZL+BAxQ/2qg==} - engines: {node: '>=18.0.0'} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.4.7 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@storybook/preview-api@8.4.7': - resolution: {integrity: sha512-0QVQwHw+OyZGHAJEXo6Knx+6/4er7n2rTDE5RYJ9F2E2Lg42E19pfdLlq2Jhoods2Xrclo3wj6GWR//Ahi39Eg==} + '@storybook/manager-api@8.6.14': + resolution: {integrity: sha512-ez0Zihuy17udLbfHZQXkGqwtep0mSGgHcNzGN7iZrMP1m+VmNo+7aGCJJdvXi7+iU3yq8weXSQFWg5DqWgLS7g==} peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0': - resolution: {integrity: sha512-KUqXC3oa9JuQ0kZJLBhVdS4lOneKTOopnNBK4tUAgoxWQ3u/IjzdueZjFr7gyBrXMoU6duutk3RQR9u8ZpYJ4Q==} + '@storybook/preview-api@8.6.14': + resolution: {integrity: sha512-2GhcCd4dNMrnD7eooEfvbfL4I83qAqEyO0CO7JQAmIO6Rxb9BsOLLI/GD5HkvQB73ArTJ+PT50rfaO820IExOQ==} peerDependencies: - typescript: '>= 4.x' - webpack: '>= 4' + storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - '@storybook/react-dom-shim@8.4.7': - resolution: {integrity: sha512-6bkG2jvKTmWrmVzCgwpTxwIugd7Lu+2btsLAqhQSzDyIj2/uhMNp8xIMr/NBDtLgq3nomt9gefNa9xxLwk/OMg==} + '@storybook/react-dom-shim@8.6.14': + resolution: {integrity: sha512-0hixr3dOy3f3M+HBofp3jtMQMS+sqzjKNgl7Arfuj3fvjmyXOks/yGjDImySR4imPtEllvPZfhiQNlejheaInw==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.4.7 + storybook: ^8.6.14 - '@storybook/react-webpack5@8.4.7': - resolution: {integrity: sha512-T9GLqlsP4It4El7cC8rSkBPRWvORAsTDULeWlO36RST2TrYnmBOUytsi22mk7cAAAVhhD6rTrs1YdqWRMpfa1w==} + '@storybook/react-vite@8.6.14': + resolution: {integrity: sha512-FZU0xMPxa4/TO87FgcWwappOxLBHZV5HSRK5K+2bJD7rFJAoNorbHvB4Q1zvIAk7eCMjkr2GPCPHx9PRB9vJFg==} engines: {node: '>=18.0.0'} peerDependencies: + '@storybook/test': 8.6.14 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.4.7 - typescript: '>= 4.2.x' + storybook: ^8.6.14 + vite: ^4.0.0 || ^5.0.0 || ^6.0.0 peerDependenciesMeta: - typescript: + '@storybook/test': optional: true - '@storybook/react@8.4.7': - resolution: {integrity: sha512-nQ0/7i2DkaCb7dy0NaT95llRVNYWQiPIVuhNfjr1mVhEP7XD090p0g7eqUmsx8vfdHh2BzWEo6CoBFRd3+EXxw==} + '@storybook/react@8.6.14': + resolution: {integrity: sha512-BOepx5bBFwl/CPI+F+LnmMmsG1wQYmrX/UQXgUbHQUU9Tj7E2ndTnNbpIuSLc8IrM03ru+DfwSg1Co3cxWtT+g==} engines: {node: '>=18.0.0'} peerDependencies: - '@storybook/test': 8.4.7 + '@storybook/test': 8.6.14 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.4.7 + storybook: ^8.6.14 typescript: '>= 4.2.x' peerDependenciesMeta: '@storybook/test': @@ -1863,90 +1830,20 @@ packages: typescript: optional: true - '@storybook/test@8.4.7': - resolution: {integrity: sha512-AhvJsu5zl3uG40itSQVuSy5WByp3UVhS6xAnme4FWRwgSxhvZjATJ3AZkkHWOYjnnk+P2/sbz/XuPli1FVCWoQ==} + '@storybook/test@8.6.14': + resolution: {integrity: sha512-GkPNBbbZmz+XRdrhMtkxPotCLOQ1BaGNp/gFZYdGDk2KmUWBKmvc5JxxOhtoXM2703IzNFlQHSSNnhrDZYuLlw==} peerDependencies: - storybook: ^8.4.7 + storybook: ^8.6.14 '@storybook/theming@8.4.7': resolution: {integrity: sha512-99rgLEjf7iwfSEmdqlHkSG3AyLcK0sfExcr0jnc6rLiAkBhzuIsvcHjjUwkR210SOCgXqBPW0ZA6uhnuyppHLw==} peerDependencies: storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 - '@swc/core-darwin-arm64@1.10.4': - resolution: {integrity: sha512-sV/eurLhkjn/197y48bxKP19oqcLydSel42Qsy2zepBltqUx+/zZ8+/IS0Bi7kaWVFxerbW1IPB09uq8Zuvm3g==} - engines: {node: '>=10'} - cpu: [arm64] - os: [darwin] - - '@swc/core-darwin-x64@1.10.4': - resolution: {integrity: sha512-gjYNU6vrAUO4+FuovEo9ofnVosTFXkF0VDuo1MKPItz6e2pxc2ale4FGzLw0Nf7JB1sX4a8h06CN16/pLJ8Q2w==} - engines: {node: '>=10'} - cpu: [x64] - os: [darwin] - - '@swc/core-linux-arm-gnueabihf@1.10.4': - resolution: {integrity: sha512-zd7fXH5w8s+Sfvn2oO464KDWl+ZX1MJiVmE4Pdk46N3PEaNwE0koTfgx2vQRqRG4vBBobzVvzICC3618WcefOA==} - engines: {node: '>=10'} - cpu: [arm] - os: [linux] - - '@swc/core-linux-arm64-gnu@1.10.4': - resolution: {integrity: sha512-+UGfoHDxsMZgFD3tABKLeEZHqLNOkxStu+qCG7atGBhS4Slri6h6zijVvf4yI5X3kbXdvc44XV/hrP/Klnui2A==} - engines: {node: '>=10'} - cpu: [arm64] - os: [linux] - - '@swc/core-linux-arm64-musl@1.10.4': - resolution: {integrity: sha512-cDDj2/uYsOH0pgAnDkovLZvKJpFmBMyXkxEG6Q4yw99HbzO6QzZ5HDGWGWVq/6dLgYKlnnmpjZCPPQIu01mXEg==} - engines: {node: '>=10'} - cpu: [arm64] - os: [linux] - - '@swc/core-linux-x64-gnu@1.10.4': - resolution: {integrity: sha512-qJXh9D6Kf5xSdGWPINpLGixAbB5JX8JcbEJpRamhlDBoOcQC79dYfOMEIxWPhTS1DGLyFakAx2FX/b2VmQmj0g==} - engines: {node: '>=10'} - cpu: [x64] - os: [linux] - - '@swc/core-linux-x64-musl@1.10.4': - resolution: {integrity: sha512-A76lIAeyQnHCVt0RL/pG+0er8Qk9+acGJqSZOZm67Ve3B0oqMd871kPtaHBM0BW3OZAhoILgfHW3Op9Q3mx3Cw==} - engines: {node: '>=10'} - cpu: [x64] - os: [linux] - - '@swc/core-win32-arm64-msvc@1.10.4': - resolution: {integrity: sha512-e6j5kBu4fIY7fFxFxnZI0MlEovRvp50Lg59Fw+DVbtqHk3C85dckcy5xKP+UoXeuEmFceauQDczUcGs19SRGSQ==} - engines: {node: '>=10'} - cpu: [arm64] - os: [win32] - - '@swc/core-win32-ia32-msvc@1.10.4': - resolution: {integrity: sha512-RSYHfdKgNXV/amY5Tqk1EWVsyQnhlsM//jeqMLw5Fy9rfxP592W9UTumNikNRPdjI8wKKzNMXDb1U29tQjN0dg==} - engines: {node: '>=10'} - cpu: [ia32] - os: [win32] - - '@swc/core-win32-x64-msvc@1.10.4': - resolution: {integrity: sha512-1ujYpaqfqNPYdwKBlvJnOqcl+Syn3UrQ4XE0Txz6zMYgyh6cdU6a3pxqLqIUSJ12MtXRA9ZUhEz1ekU3LfLWXw==} - engines: {node: '>=10'} - cpu: [x64] - os: [win32] - - '@swc/core@1.10.4': - resolution: {integrity: sha512-ut3zfiTLORMxhr6y/GBxkHmzcGuVpwJYX4qyXWuBKkpw/0g0S5iO1/wW7RnLnZbAi8wS/n0atRZoaZlXWBkeJg==} - engines: {node: '>=10'} + '@storybook/theming@8.6.14': + resolution: {integrity: sha512-r4y+LsiB37V5hzpQo+BM10PaCsp7YlZ0YcZzQP1OCkPlYXmUAFy2VvDKaFRpD8IeNPKug2u4iFm/laDEbs03dg==} peerDependencies: - '@swc/helpers': '*' - peerDependenciesMeta: - '@swc/helpers': - optional: true - - '@swc/counter@0.1.3': - resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} - - '@swc/types@0.1.17': - resolution: {integrity: sha512-V5gRru+aD8YVyCOMAjMpWR1Ui577DD5KSJsHP8RAxopAH22jFz6GZd/qxqjO6MJHQhcsjvjOFXyDhyLQUnMveQ==} + storybook: ^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0 '@testing-library/dom@10.4.0': resolution: {integrity: sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==} @@ -2004,6 +1901,9 @@ packages: '@types/babel__traverse@7.20.6': resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} + '@types/babel__traverse@7.28.0': + resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + '@types/chai@5.2.2': resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==} @@ -2028,9 +1928,6 @@ packages: '@types/hast@3.0.4': resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} - '@types/html-minifier-terser@6.1.0': - resolution: {integrity: sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==} - '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -2040,9 +1937,6 @@ packages: '@types/node@20.19.21': resolution: {integrity: sha512-CsGG2P3I5y48RPMfprQGfy4JPRZ6csfC3ltBZSRItG3ngggmNY/qs2uZKp4p9VbrpqNNSMzUZNFZKzgOGnd/VA==} - '@types/node@22.18.10': - resolution: {integrity: sha512-anNG/V/Efn/YZY4pRzbACnKxNKoBng2VTFydVu8RRs5hQjikP8CQfaeAV59VFSCzKNp90mXiVXW2QzV56rwMrg==} - '@types/parse-json@4.0.2': resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} @@ -2068,9 +1962,6 @@ packages: '@types/resolve@1.20.6': resolution: {integrity: sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==} - '@types/semver@7.5.8': - resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} - '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} @@ -2279,11 +2170,6 @@ packages: ajv@8.17.1: resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} - ansi-html-community@0.0.8: - resolution: {integrity: sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==} - engines: {'0': node >= 0.8.0} - hasBin: true - ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} @@ -2300,9 +2186,9 @@ packages: resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} engines: {node: '>=10'} - anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} + ansi-styles@6.2.3: + resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} + engines: {node: '>=12'} argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -2364,6 +2250,10 @@ packages: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} + axe-core@4.11.0: + resolution: {integrity: sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ==} + engines: {node: '>=4'} + babel-plugin-macros@3.1.0: resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} engines: {node: '>=10', npm: '>=6'} @@ -2393,10 +2283,6 @@ packages: big.js@5.2.2: resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} - binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} @@ -2441,23 +2327,12 @@ packages: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - camel-case@4.1.2: - resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} - caniuse-api@3.0.0: resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} caniuse-lite@1.0.30001690: resolution: {integrity: sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==} - case-sensitive-paths-webpack-plugin@2.4.0: - resolution: {integrity: sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==} - engines: {node: '>=4'} - - chai@5.1.2: - resolution: {integrity: sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==} - engines: {node: '>=12'} - chai@5.3.3: resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} engines: {node: '>=18'} @@ -2474,10 +2349,6 @@ packages: resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} engines: {node: '>= 16'} - chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} - chromatic@11.22.0: resolution: {integrity: sha512-u1kAPR9lj9aFzsCp0iWPXBbsKgcxFU7iJO6mFbgNHGVg+YPBqiJMuvgB8EQHdNbHjk5amFnGnIz/Ww8fK3t9Hw==} hasBin: true @@ -2494,13 +2365,6 @@ packages: resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} engines: {node: '>=6.0'} - cjs-module-lexer@1.4.1: - resolution: {integrity: sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==} - - clean-css@5.3.3: - resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} - engines: {node: '>= 10.0'} - clsx@2.1.1: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} @@ -2515,9 +2379,6 @@ packages: colord@2.9.3: resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} - colorette@2.0.20: - resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} - combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -2533,10 +2394,6 @@ packages: resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} engines: {node: '>= 10'} - commander@8.3.0: - resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} - engines: {node: '>= 12'} - commondir@1.0.1: resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} @@ -2546,9 +2403,6 @@ packages: concat-with-sourcemaps@1.1.0: resolution: {integrity: sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==} - constants-browserify@1.0.0: - resolution: {integrity: sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==} - convert-source-map@1.9.0: resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} @@ -2559,6 +2413,9 @@ packages: resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} engines: {node: '>=18'} + copy-anything@2.0.6: + resolution: {integrity: sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==} + core-js-compat@3.39.0: resolution: {integrity: sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==} @@ -2576,18 +2433,6 @@ packages: peerDependencies: postcss: ^8.0.9 - css-loader@6.11.0: - resolution: {integrity: sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==} - engines: {node: '>= 12.13.0'} - peerDependencies: - '@rspack/core': 0.x || 1.x - webpack: ^5.0.0 - peerDependenciesMeta: - '@rspack/core': - optional: true - webpack: - optional: true - css-select@4.3.0: resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} @@ -2682,9 +2527,6 @@ packages: decimal.js@10.6.0: resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} - dedent@0.7.0: - resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==} - deep-eql@5.0.2: resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} engines: {node: '>=6'} @@ -2734,9 +2576,6 @@ packages: dom-accessibility-api@0.6.3: resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} - dom-converter@0.2.0: - resolution: {integrity: sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==} - dom-helpers@5.2.1: resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} @@ -2758,26 +2597,29 @@ packages: domutils@2.8.0: resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} - dot-case@3.0.4: - resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} - dunder-proto@1.0.1: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + electron-to-chromium@1.5.76: resolution: {integrity: sha512-CjVQyG7n7Sr+eBXE86HIulnL5N8xZY1sgmOPGuq/F0Rr0FJq63lg0kEtOIDfZBk44FnDLf6FUJ+dsJcuiUDdDQ==} email-addresses@5.0.0: resolution: {integrity: sha512-4OIPYlA6JXqtVn8zpHpGiI7vE6EQOAg16aGnDMIAlZVinnoZ8208tW1hAbjWydgN/4PLTT9q+O1K6AH/vALJGw==} + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + emojis-list@3.0.0: resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} engines: {node: '>= 4'} - endent@2.1.0: - resolution: {integrity: sha512-r8VyPX7XL8U01Xgnb1CjZ3XV+z90cXIJ9JPE/R9SEC9vpw2P6CfsRPJmp20DppC5N7ZAMCmjYkJIa744Iyg96w==} - enhanced-resolve@5.18.0: resolution: {integrity: sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ==} engines: {node: '>=10.13.0'} @@ -2793,6 +2635,10 @@ packages: resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} engines: {node: '>=0.12'} + errno@0.1.8: + resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==} + hasBin: true + error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} @@ -2812,9 +2658,6 @@ packages: resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==} engines: {node: '>= 0.4'} - es-module-lexer@1.6.0: - resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==} - es-module-lexer@1.7.0: resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} @@ -2838,11 +2681,6 @@ packages: peerDependencies: esbuild: '>=0.12 <1' - esbuild@0.24.2: - resolution: {integrity: sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==} - engines: {node: '>=18'} - hasBin: true - esbuild@0.25.11: resolution: {integrity: sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==} engines: {node: '>=18'} @@ -2982,9 +2820,6 @@ packages: resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} - fast-json-parse@1.0.3: - resolution: {integrity: sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw==} - fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} @@ -3055,10 +2890,6 @@ packages: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} - flat-cache@3.2.0: - resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} - engines: {node: ^10.12.0 || >=12.0.0} - flat-cache@4.0.1: resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} engines: {node: '>=16'} @@ -3069,31 +2900,18 @@ packages: for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - fork-ts-checker-webpack-plugin@8.0.0: - resolution: {integrity: sha512-mX3qW3idpueT2klaQXBzrIM/pHw+T0B/V9KHEvNrqijTq9NFnMZU6oreVxDYcf33P8a5cW+67PjodNHthGnNVg==} - engines: {node: '>=12.13.0', yarn: '>=1.0.0'} - peerDependencies: - typescript: '>3.6.0' - webpack: ^5.11.0 + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} form-data@4.0.4: resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==} engines: {node: '>= 6'} - fs-extra@10.1.0: - resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} - engines: {node: '>=12'} - fs-extra@11.2.0: resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} engines: {node: '>=14.14'} - fs-monkey@1.0.6: - resolution: {integrity: sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==} - - fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -3144,9 +2962,9 @@ packages: glob-to-regexp@0.4.1: resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} - glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported + glob@10.5.0: + resolution: {integrity: sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==} + hasBin: true globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} @@ -3201,10 +3019,6 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} - he@1.2.0: - resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} - hasBin: true - hoist-non-react-statics@3.3.2: resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} @@ -3212,29 +3026,6 @@ packages: resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==} engines: {node: '>=12'} - html-entities@2.5.2: - resolution: {integrity: sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==} - - html-minifier-terser@6.1.0: - resolution: {integrity: sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==} - engines: {node: '>=12'} - hasBin: true - - html-webpack-plugin@5.6.3: - resolution: {integrity: sha512-QSf1yjtSAsmf7rYBV7XX86uua4W/vkhIt0xNXKbsi2foEeW7vjJQz4bhnpL3xH+l1ryl1680uNv968Z+X6jSYg==} - engines: {node: '>=10.13.0'} - peerDependencies: - '@rspack/core': 0.x || 1.x - webpack: ^5.20.0 - peerDependenciesMeta: - '@rspack/core': - optional: true - webpack: - optional: true - - htmlparser2@6.1.0: - resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==} - http-proxy-agent@5.0.0: resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} engines: {node: '>= 6'} @@ -3260,6 +3051,11 @@ packages: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} + image-size@0.5.5: + resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==} + engines: {node: '>=0.10.0'} + hasBin: true + import-cwd@3.0.0: resolution: {integrity: sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==} engines: {node: '>=8'} @@ -3280,10 +3076,6 @@ packages: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} engines: {node: '>=8'} - inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -3310,10 +3102,6 @@ packages: resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} engines: {node: '>= 0.4'} - is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - is-boolean-object@1.2.1: resolution: {integrity: sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==} engines: {node: '>= 0.4'} @@ -3347,6 +3135,10 @@ packages: resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} engines: {node: '>= 0.4'} + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + is-generator-function@1.1.0: resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} engines: {node: '>= 0.4'} @@ -3412,6 +3204,9 @@ packages: resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} engines: {node: '>= 0.4'} + is-what@3.14.1: + resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==} + is-wsl@2.2.0: resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} engines: {node: '>=8'} @@ -3426,10 +3221,17 @@ packages: resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} engines: {node: '>= 0.4'} + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + jest-worker@27.5.1: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} + jiti@1.21.7: + resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} + hasBin: true + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -3496,6 +3298,11 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + less@4.5.1: + resolution: {integrity: sha512-UKgI3/KON4u6ngSsnDADsUERqhZknsVZbnuzlRZXLQCmfC/MDld42fTydUE9B+Mla1AL6SJ/Pp6SlEFi/AVGfw==} + engines: {node: '>=14'} + hasBin: true + levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -3558,8 +3365,8 @@ packages: loupe@3.2.1: resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} - lower-case@2.0.2: - resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -3571,9 +3378,17 @@ packages: resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true + magic-string@0.27.0: + resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==} + engines: {node: '>=12'} + magic-string@0.30.17: resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + make-dir@2.1.0: + resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==} + engines: {node: '>=6'} + make-dir@3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} @@ -3595,10 +3410,6 @@ packages: mdurl@2.0.0: resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} - memfs@3.5.3: - resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==} - engines: {node: '>= 4.0.0'} - memoizerific@1.11.3: resolution: {integrity: sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==} @@ -3621,6 +3432,11 @@ packages: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + min-indent@1.0.1: resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} engines: {node: '>=4'} @@ -3639,6 +3455,10 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -3647,30 +3467,20 @@ packages: engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - nanoid@3.3.8: - resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + needle@3.3.1: + resolution: {integrity: sha512-6k0YULvhpw+RoLNiQCRKOl09Rv1dPLr8hHnVjHqdolKwDrdNyk+Hmrthi4lIGPPz3r39dLx0hsF5s40sZ3Us4Q==} + engines: {node: '>= 4.4.x'} + hasBin: true + neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - no-case@3.0.4: - resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} - - node-abort-controller@3.1.1: - resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==} - node-releases@2.0.19: resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} - normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - normalize-url@6.1.0: resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} engines: {node: '>=10'} @@ -3709,12 +3519,6 @@ packages: resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} engines: {node: '>= 0.4'} - objectorarray@1.0.5: - resolution: {integrity: sha512-eJJDYkhJFFbBBAxeh8xW+weHlkI28n2ZdQV/J/DNfWfSKlGEf2xcfAbZTv3riEXHAhL9SVOTs2pRmXiSTf78xg==} - - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - open@8.4.2: resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} engines: {node: '>=12'} @@ -3759,12 +3563,12 @@ packages: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + pako@1.0.11: resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} - param-case@3.0.4: - resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} - parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} @@ -3773,23 +3577,17 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} + parse-node-version@1.0.1: + resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==} + engines: {node: '>= 0.10'} + parse5@7.3.0: resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} - pascal-case@3.1.2: - resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} - - path-browserify@1.0.1: - resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} - path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} - path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -3797,6 +3595,10 @@ packages: path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -3823,6 +3625,10 @@ packages: resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} engines: {node: '>=12'} + pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + pify@5.0.0: resolution: {integrity: sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==} engines: {node: '>=10'} @@ -4052,10 +3858,6 @@ packages: postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - postcss@8.4.49: - resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} - engines: {node: ^10 || ^12 || >=14} - postcss@8.5.6: resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} engines: {node: ^10 || ^12 || >=14} @@ -4073,9 +3875,6 @@ packages: engines: {node: '>=14'} hasBin: true - pretty-error@4.0.0: - resolution: {integrity: sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==} - pretty-format@27.5.1: resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -4091,6 +3890,9 @@ packages: prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + prr@1.0.1: + resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==} + psl@1.15.0: resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} @@ -4098,17 +3900,10 @@ packages: resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} engines: {node: '>=6'} - punycode@1.4.1: - resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} - punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - qs@6.13.1: - resolution: {integrity: sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==} - engines: {node: '>=0.6'} - querystringify@2.2.0: resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} @@ -4118,10 +3913,6 @@ packages: randombytes@2.1.0: resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - range-parser@1.2.1: - resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} - engines: {node: '>= 0.6'} - react-confetti@6.2.2: resolution: {integrity: sha512-K+kTyOPgX+ZujMZ+Rmb7pZdHBvg+DzinG/w4Eh52WOB8/pfO38efnnrtEZNJmjTvLxc16RBYO+tPM68Fg8viBA==} engines: {node: '>=16'} @@ -4137,6 +3928,10 @@ packages: resolution: {integrity: sha512-APPU8HB2uZnpl6Vt/+0AFoVYgSRtfiP6FLrZgPPTDmqSb2R4qZRbgd0A3VzIFxDt5e+Fozjx79WjLWnF69DK8g==} engines: {node: '>=16.14.0'} + react-docgen@8.0.2: + resolution: {integrity: sha512-+NRMYs2DyTP4/tqWz371Oo50JqmWltR1h2gcdgUMAWZJIAvrd0/SqlCfx7tpzpl/s36rzw6qH2MjoNrxtRNYhA==} + engines: {node: ^20.9.0 || >=22} + react-dom@18.3.1: resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} peerDependencies: @@ -4183,10 +3978,6 @@ packages: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} - readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - recast@0.23.9: resolution: {integrity: sha512-Hx/BGIbwj+Des3+xy5uAtAbdCyqK9y9wbBcDFDYanLS9JnMqf7OeF87HQwUimE87OEc72mr6tkKUKMBBL+hF9Q==} engines: {node: '>= 4'} @@ -4227,13 +4018,6 @@ packages: resolution: {integrity: sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==} hasBin: true - relateurl@0.2.7: - resolution: {integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==} - engines: {node: '>= 0.10'} - - renderkid@3.0.0: - resolution: {integrity: sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==} - require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} @@ -4262,11 +4046,6 @@ packages: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - deprecated: Rimraf versions prior to v4 are no longer supported - hasBin: true - rollup-plugin-dts@6.1.1: resolution: {integrity: sha512-aSHRcJ6KG2IHIioYlvAOcEq6U99sVtqDDKVhnwt70rW6tsz3tv5OSjEiWcgzfsHdLyGXZ/3b/7b/+Za3Y6r1XA==} engines: {node: '>=16'} @@ -4322,6 +4101,9 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + sax@1.4.3: + resolution: {integrity: sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==} + saxes@6.0.0: resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} engines: {node: '>=v12.22.7'} @@ -4337,6 +4119,10 @@ packages: resolution: {integrity: sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==} engines: {node: '>= 10.13.0'} + semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -4391,6 +4177,10 @@ packages: siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} @@ -4426,8 +4216,8 @@ packages: storybook-dark-mode@4.0.2: resolution: {integrity: sha512-zjcwwQ01R5t1VsakA6alc2JDIRVtavryW8J3E3eKLDIlAMcvsgtpxlelWkZs2cuNspk6Z10XzhQVrUWtYc3F0w==} - storybook@8.4.7: - resolution: {integrity: sha512-RP/nMJxiWyFc8EVMH5gp20ID032Wvk+Yr3lmKidoegto5Iy+2dVQnUoElZb2zpbVXNHWakGuAkfI0dY1Hfp/vw==} + storybook@8.6.14: + resolution: {integrity: sha512-sVKbCj/OTx67jhmauhxc2dcr1P+yOgz/x3h0krwjyMgdc5Oubvxyg4NYDZmzAw+ym36g/lzH8N0Ccp4dwtdfxw==} hasBin: true peerDependencies: prettier: ^2 || ^3 @@ -4438,6 +4228,14 @@ packages: string-hash@1.1.3: resolution: {integrity: sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==} + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + string.prototype.matchall@4.0.12: resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} engines: {node: '>= 0.4'} @@ -4491,12 +4289,6 @@ packages: style-inject@0.3.0: resolution: {integrity: sha512-IezA2qp+vcdlhJaVm5SOdPPTUu0FCEqfNSli2vRuSIBbu5Nq5UvygTk/VzeCqfLz2Atj3dVII5QBKGZRZ0edzw==} - style-loader@3.3.4: - resolution: {integrity: sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==} - engines: {node: '>= 12.13.0'} - peerDependencies: - webpack: ^5.0.0 - stylehacks@5.1.1: resolution: {integrity: sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==} engines: {node: ^10 || ^12 || >=14.0} @@ -4523,12 +4315,6 @@ packages: engines: {node: '>=10.13.0'} hasBin: true - swc-loader@0.2.6: - resolution: {integrity: sha512-9Zi9UP2YmDpgmQVbyOPJClY0dwf58JDyDMQ7uRc4krmc72twNI2fvlBWHLqVekBpPc7h5NJkGVT1zNDxFrqhvg==} - peerDependencies: - '@swc/core': ^1.2.147 - webpack: '>=2' - symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} @@ -4726,10 +4512,6 @@ packages: url-parse@1.5.10: resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} - url@0.11.4: - resolution: {integrity: sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==} - engines: {node: '>= 0.4'} - utif@3.1.0: resolution: {integrity: sha512-WEo4D/xOvFW53K5f5QTaTbbiORcm2/pCL9P6qmJnup+17eYfKaEhDeX9PeQkuyEoIxlbGklDuGl8xwuXYMrrXQ==} @@ -4739,9 +4521,6 @@ packages: util@0.12.5: resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} - utila@0.4.0: - resolution: {integrity: sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==} - uuid@9.0.1: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} hasBin: true @@ -4831,18 +4610,6 @@ packages: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} - webpack-dev-middleware@6.1.3: - resolution: {integrity: sha512-A4ChP0Qj8oGociTs6UdlRUGANIGrCDL3y+pmQMc+dSsraXHCatFpmMey4mYELA+juqwUqwQsUgJJISXl1KWmiw==} - engines: {node: '>= 14.15.0'} - peerDependencies: - webpack: ^5.0.0 - peerDependenciesMeta: - webpack: - optional: true - - webpack-hot-middleware@2.26.1: - resolution: {integrity: sha512-khZGfAeJx6I8K9zKohEWWYN6KDlVw2DHownoe+6Vtwj1LP9WFgegXnVMSkZ/dBEBtXFwrkkydsaPFlB7f8wU2A==} - webpack-sources@3.2.3: resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} engines: {node: '>=10.13.0'} @@ -4902,20 +4669,13 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} - ws@8.18.0: - resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} ws@8.18.3: resolution: {integrity: sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==} @@ -4967,8 +4727,16 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.1.1 + '@babel/code-frame@7.27.1': + dependencies: + '@babel/helper-validator-identifier': 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 + '@babel/compat-data@7.26.3': {} + '@babel/compat-data@7.28.5': {} + '@babel/core@7.26.0': dependencies: '@ampproject/remapping': 2.3.0 @@ -4982,7 +4750,27 @@ snapshots: '@babel/traverse': 7.26.4 '@babel/types': 7.26.3 convert-source-map: 2.0.0 - debug: 4.4.0 + debug: 4.4.0 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/core@7.28.5': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.5 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.5) + '@babel/helpers': 7.28.4 + '@babel/parser': 7.28.5 + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -4997,6 +4785,14 @@ snapshots: '@jridgewell/trace-mapping': 0.3.25 jsesc: 3.1.0 + '@babel/generator@7.28.5': + dependencies: + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + '@babel/helper-annotate-as-pure@7.25.9': dependencies: '@babel/types': 7.26.3 @@ -5009,6 +4805,14 @@ snapshots: lru-cache: 5.1.1 semver: 6.3.1 + '@babel/helper-compilation-targets@7.27.2': + dependencies: + '@babel/compat-data': 7.28.5 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.24.3 + lru-cache: 5.1.1 + semver: 6.3.1 + '@babel/helper-create-class-features-plugin@7.25.9(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 @@ -5040,6 +4844,8 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-globals@7.28.0': {} + '@babel/helper-member-expression-to-functions@7.25.9': dependencies: '@babel/traverse': 7.26.4 @@ -5054,6 +4860,13 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-module-imports@7.27.1': + dependencies: + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 + transitivePeerDependencies: + - supports-color + '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 @@ -5063,6 +4876,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.5)': + dependencies: + '@babel/core': 7.28.5 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.28.5 + transitivePeerDependencies: + - supports-color + '@babel/helper-optimise-call-expression@7.25.9': dependencies: '@babel/types': 7.26.3 @@ -5096,10 +4918,16 @@ snapshots: '@babel/helper-string-parser@7.25.9': {} + '@babel/helper-string-parser@7.27.1': {} + '@babel/helper-validator-identifier@7.25.9': {} + '@babel/helper-validator-identifier@7.28.5': {} + '@babel/helper-validator-option@7.25.9': {} + '@babel/helper-validator-option@7.27.1': {} + '@babel/helper-wrap-function@7.25.9': dependencies: '@babel/template': 7.25.9 @@ -5113,10 +4941,19 @@ snapshots: '@babel/template': 7.25.9 '@babel/types': 7.26.3 + '@babel/helpers@7.28.4': + dependencies: + '@babel/template': 7.27.2 + '@babel/types': 7.28.5 + '@babel/parser@7.26.3': dependencies: '@babel/types': 7.26.3 + '@babel/parser@7.28.5': + dependencies: + '@babel/types': 7.28.5 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9(@babel/core@7.26.0)': dependencies: '@babel/core': 7.26.0 @@ -5656,6 +5493,12 @@ snapshots: '@babel/parser': 7.26.3 '@babel/types': 7.26.3 + '@babel/template@7.27.2': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/parser': 7.28.5 + '@babel/types': 7.28.5 + '@babel/traverse@7.26.4': dependencies: '@babel/code-frame': 7.26.2 @@ -5668,18 +5511,35 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/traverse@7.28.5': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.5 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.28.5 + '@babel/template': 7.27.2 + '@babel/types': 7.28.5 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + '@babel/types@7.26.3': dependencies: '@babel/helper-string-parser': 7.25.9 '@babel/helper-validator-identifier': 7.25.9 - '@chromatic-com/storybook@3.2.3(react@18.3.1)(storybook@8.4.7(prettier@3.4.2))': + '@babel/types@7.28.5': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + + '@chromatic-com/storybook@3.2.3(react@18.3.1)(storybook@8.6.14(prettier@3.4.2))': dependencies: chromatic: 11.22.0 filesize: 10.1.6 jsonfile: 6.1.0 react-confetti: 6.2.2(react@18.3.1) - storybook: 8.4.7(prettier@3.4.2) + storybook: 8.6.14(prettier@3.4.2) strip-ansi: 7.1.0 transitivePeerDependencies: - '@chromatic-com/cypress' @@ -5777,162 +5637,87 @@ snapshots: '@emotion/weak-memoize@0.4.0': {} - '@esbuild/aix-ppc64@0.24.2': - optional: true - '@esbuild/aix-ppc64@0.25.11': optional: true - '@esbuild/android-arm64@0.24.2': - optional: true - '@esbuild/android-arm64@0.25.11': optional: true - '@esbuild/android-arm@0.24.2': - optional: true - '@esbuild/android-arm@0.25.11': optional: true - '@esbuild/android-x64@0.24.2': - optional: true - '@esbuild/android-x64@0.25.11': optional: true - '@esbuild/darwin-arm64@0.24.2': - optional: true - '@esbuild/darwin-arm64@0.25.11': optional: true - '@esbuild/darwin-x64@0.24.2': - optional: true - '@esbuild/darwin-x64@0.25.11': optional: true - '@esbuild/freebsd-arm64@0.24.2': - optional: true - '@esbuild/freebsd-arm64@0.25.11': optional: true - '@esbuild/freebsd-x64@0.24.2': - optional: true - '@esbuild/freebsd-x64@0.25.11': optional: true - '@esbuild/linux-arm64@0.24.2': - optional: true - '@esbuild/linux-arm64@0.25.11': optional: true - '@esbuild/linux-arm@0.24.2': - optional: true - '@esbuild/linux-arm@0.25.11': optional: true - '@esbuild/linux-ia32@0.24.2': - optional: true - '@esbuild/linux-ia32@0.25.11': optional: true - '@esbuild/linux-loong64@0.24.2': - optional: true - '@esbuild/linux-loong64@0.25.11': optional: true - '@esbuild/linux-mips64el@0.24.2': - optional: true - '@esbuild/linux-mips64el@0.25.11': optional: true - '@esbuild/linux-ppc64@0.24.2': - optional: true - '@esbuild/linux-ppc64@0.25.11': optional: true - '@esbuild/linux-riscv64@0.24.2': - optional: true - '@esbuild/linux-riscv64@0.25.11': optional: true - '@esbuild/linux-s390x@0.24.2': - optional: true - '@esbuild/linux-s390x@0.25.11': optional: true - '@esbuild/linux-x64@0.24.2': - optional: true - '@esbuild/linux-x64@0.25.11': optional: true - '@esbuild/netbsd-arm64@0.24.2': - optional: true - '@esbuild/netbsd-arm64@0.25.11': optional: true - '@esbuild/netbsd-x64@0.24.2': - optional: true - '@esbuild/netbsd-x64@0.25.11': optional: true - '@esbuild/openbsd-arm64@0.24.2': - optional: true - '@esbuild/openbsd-arm64@0.25.11': optional: true - '@esbuild/openbsd-x64@0.24.2': - optional: true - '@esbuild/openbsd-x64@0.25.11': optional: true '@esbuild/openharmony-arm64@0.25.11': optional: true - '@esbuild/sunos-x64@0.24.2': - optional: true - '@esbuild/sunos-x64@0.25.11': optional: true - '@esbuild/win32-arm64@0.24.2': - optional: true - '@esbuild/win32-arm64@0.25.11': optional: true - '@esbuild/win32-ia32@0.24.2': - optional: true - '@esbuild/win32-ia32@0.25.11': optional: true - '@esbuild/win32-x64@0.24.2': - optional: true - '@esbuild/win32-x64@0.25.11': optional: true - '@eslint-community/eslint-utils@4.4.1(eslint@9.17.0)': + '@eslint-community/eslint-utils@4.4.1(eslint@9.17.0(jiti@1.21.7))': dependencies: - eslint: 9.17.0 + eslint: 9.17.0(jiti@1.21.7) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} @@ -5992,12 +5777,40 @@ snapshots: '@humanwhocodes/retry@0.4.1': {} + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@joshwooding/vite-plugin-react-docgen-typescript@0.5.0(typescript@5.7.2)(vite@7.1.10(@types/node@20.19.21)(jiti@1.21.7)(less@4.5.1)(terser@5.37.0)(yaml@2.8.0))': + dependencies: + glob: 10.5.0 + magic-string: 0.27.0 + react-docgen-typescript: 2.2.2(typescript@5.7.2) + vite: 7.1.10(@types/node@20.19.21)(jiti@1.21.7)(less@4.5.1)(terser@5.37.0)(yaml@2.8.0) + optionalDependencies: + typescript: 5.7.2 + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.31 + '@jridgewell/gen-mapping@0.3.8': dependencies: '@jridgewell/set-array': 1.2.1 '@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/resolve-uri@3.1.2': {} '@jridgewell/set-array@1.2.1': {} @@ -6014,6 +5827,11 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jsonforms/core@3.6.0': dependencies: '@types/json-schema': 7.0.15 @@ -6172,6 +5990,9 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.18.0 + '@pkgjs/parseargs@0.11.0': + optional: true + '@pkgr/core@0.1.1': {} '@popperjs/core@2.11.8': {} @@ -6379,194 +6200,197 @@ snapshots: '@shikijs/vscode-textmate@10.0.2': {} - '@storybook/addon-actions@8.4.7(storybook@8.4.7(prettier@3.4.2))': + '@storybook/addon-a11y@8.6.14(storybook@8.6.14(prettier@3.4.2))': + dependencies: + '@storybook/addon-highlight': 8.6.14(storybook@8.6.14(prettier@3.4.2)) + '@storybook/global': 5.0.0 + '@storybook/test': 8.6.14(storybook@8.6.14(prettier@3.4.2)) + axe-core: 4.11.0 + storybook: 8.6.14(prettier@3.4.2) + + '@storybook/addon-actions@8.4.7(storybook@8.6.14(prettier@3.4.2))': + dependencies: + '@storybook/global': 5.0.0 + '@types/uuid': 9.0.8 + dequal: 2.0.3 + polished: 4.3.1 + storybook: 8.6.14(prettier@3.4.2) + uuid: 9.0.1 + + '@storybook/addon-actions@8.6.14(storybook@8.6.14(prettier@3.4.2))': dependencies: '@storybook/global': 5.0.0 '@types/uuid': 9.0.8 dequal: 2.0.3 polished: 4.3.1 - storybook: 8.4.7(prettier@3.4.2) + storybook: 8.6.14(prettier@3.4.2) uuid: 9.0.1 - '@storybook/addon-backgrounds@8.4.7(storybook@8.4.7(prettier@3.4.2))': + '@storybook/addon-backgrounds@8.6.14(storybook@8.6.14(prettier@3.4.2))': dependencies: '@storybook/global': 5.0.0 memoizerific: 1.11.3 - storybook: 8.4.7(prettier@3.4.2) + storybook: 8.6.14(prettier@3.4.2) + ts-dedent: 2.2.0 + + '@storybook/addon-controls@8.4.7(storybook@8.6.14(prettier@3.4.2))': + dependencies: + '@storybook/global': 5.0.0 + dequal: 2.0.3 + storybook: 8.6.14(prettier@3.4.2) ts-dedent: 2.2.0 - '@storybook/addon-controls@8.4.7(storybook@8.4.7(prettier@3.4.2))': + '@storybook/addon-controls@8.6.14(storybook@8.6.14(prettier@3.4.2))': dependencies: '@storybook/global': 5.0.0 dequal: 2.0.3 - storybook: 8.4.7(prettier@3.4.2) + storybook: 8.6.14(prettier@3.4.2) ts-dedent: 2.2.0 - '@storybook/addon-docs@8.4.7(@types/react@18.3.18)(storybook@8.4.7(prettier@3.4.2))': + '@storybook/addon-docs@8.6.14(@types/react@18.3.18)(storybook@8.6.14(prettier@3.4.2))': dependencies: '@mdx-js/react': 3.1.0(@types/react@18.3.18)(react@18.3.1) - '@storybook/blocks': 8.4.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.7(prettier@3.4.2)) - '@storybook/csf-plugin': 8.4.7(storybook@8.4.7(prettier@3.4.2)) - '@storybook/react-dom-shim': 8.4.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.7(prettier@3.4.2)) + '@storybook/blocks': 8.6.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.6.14(prettier@3.4.2)) + '@storybook/csf-plugin': 8.6.14(storybook@8.6.14(prettier@3.4.2)) + '@storybook/react-dom-shim': 8.6.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.6.14(prettier@3.4.2)) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - storybook: 8.4.7(prettier@3.4.2) + storybook: 8.6.14(prettier@3.4.2) ts-dedent: 2.2.0 transitivePeerDependencies: - '@types/react' - '@storybook/addon-essentials@8.4.7(@types/react@18.3.18)(storybook@8.4.7(prettier@3.4.2))': - dependencies: - '@storybook/addon-actions': 8.4.7(storybook@8.4.7(prettier@3.4.2)) - '@storybook/addon-backgrounds': 8.4.7(storybook@8.4.7(prettier@3.4.2)) - '@storybook/addon-controls': 8.4.7(storybook@8.4.7(prettier@3.4.2)) - '@storybook/addon-docs': 8.4.7(@types/react@18.3.18)(storybook@8.4.7(prettier@3.4.2)) - '@storybook/addon-highlight': 8.4.7(storybook@8.4.7(prettier@3.4.2)) - '@storybook/addon-measure': 8.4.7(storybook@8.4.7(prettier@3.4.2)) - '@storybook/addon-outline': 8.4.7(storybook@8.4.7(prettier@3.4.2)) - '@storybook/addon-toolbars': 8.4.7(storybook@8.4.7(prettier@3.4.2)) - '@storybook/addon-viewport': 8.4.7(storybook@8.4.7(prettier@3.4.2)) - storybook: 8.4.7(prettier@3.4.2) + '@storybook/addon-essentials@8.6.14(@types/react@18.3.18)(storybook@8.6.14(prettier@3.4.2))': + dependencies: + '@storybook/addon-actions': 8.6.14(storybook@8.6.14(prettier@3.4.2)) + '@storybook/addon-backgrounds': 8.6.14(storybook@8.6.14(prettier@3.4.2)) + '@storybook/addon-controls': 8.6.14(storybook@8.6.14(prettier@3.4.2)) + '@storybook/addon-docs': 8.6.14(@types/react@18.3.18)(storybook@8.6.14(prettier@3.4.2)) + '@storybook/addon-highlight': 8.6.14(storybook@8.6.14(prettier@3.4.2)) + '@storybook/addon-measure': 8.6.14(storybook@8.6.14(prettier@3.4.2)) + '@storybook/addon-outline': 8.6.14(storybook@8.6.14(prettier@3.4.2)) + '@storybook/addon-toolbars': 8.6.14(storybook@8.6.14(prettier@3.4.2)) + '@storybook/addon-viewport': 8.6.14(storybook@8.6.14(prettier@3.4.2)) + storybook: 8.6.14(prettier@3.4.2) ts-dedent: 2.2.0 transitivePeerDependencies: - '@types/react' - '@storybook/addon-highlight@8.4.7(storybook@8.4.7(prettier@3.4.2))': + '@storybook/addon-highlight@8.6.14(storybook@8.6.14(prettier@3.4.2))': dependencies: '@storybook/global': 5.0.0 - storybook: 8.4.7(prettier@3.4.2) + storybook: 8.6.14(prettier@3.4.2) - '@storybook/addon-interactions@8.4.7(storybook@8.4.7(prettier@3.4.2))': + '@storybook/addon-interactions@8.6.14(storybook@8.6.14(prettier@3.4.2))': dependencies: '@storybook/global': 5.0.0 - '@storybook/instrumenter': 8.4.7(storybook@8.4.7(prettier@3.4.2)) - '@storybook/test': 8.4.7(storybook@8.4.7(prettier@3.4.2)) + '@storybook/instrumenter': 8.6.14(storybook@8.6.14(prettier@3.4.2)) + '@storybook/test': 8.6.14(storybook@8.6.14(prettier@3.4.2)) polished: 4.3.1 - storybook: 8.4.7(prettier@3.4.2) + storybook: 8.6.14(prettier@3.4.2) ts-dedent: 2.2.0 - '@storybook/addon-links@8.4.7(react@18.3.1)(storybook@8.4.7(prettier@3.4.2))': + '@storybook/addon-links@8.6.14(react@18.3.1)(storybook@8.6.14(prettier@3.4.2))': dependencies: - '@storybook/csf': 0.1.13 '@storybook/global': 5.0.0 - storybook: 8.4.7(prettier@3.4.2) + storybook: 8.6.14(prettier@3.4.2) ts-dedent: 2.2.0 optionalDependencies: react: 18.3.1 - '@storybook/addon-measure@8.4.7(storybook@8.4.7(prettier@3.4.2))': + '@storybook/addon-measure@8.6.14(storybook@8.6.14(prettier@3.4.2))': dependencies: '@storybook/global': 5.0.0 - storybook: 8.4.7(prettier@3.4.2) + storybook: 8.6.14(prettier@3.4.2) tiny-invariant: 1.3.3 - '@storybook/addon-outline@8.4.7(storybook@8.4.7(prettier@3.4.2))': + '@storybook/addon-outline@8.6.14(storybook@8.6.14(prettier@3.4.2))': dependencies: '@storybook/global': 5.0.0 - storybook: 8.4.7(prettier@3.4.2) + storybook: 8.6.14(prettier@3.4.2) ts-dedent: 2.2.0 - '@storybook/addon-toolbars@8.4.7(storybook@8.4.7(prettier@3.4.2))': + '@storybook/addon-themes@8.6.14(storybook@8.6.14(prettier@3.4.2))': dependencies: - storybook: 8.4.7(prettier@3.4.2) + storybook: 8.6.14(prettier@3.4.2) + ts-dedent: 2.2.0 - '@storybook/addon-viewport@8.4.7(storybook@8.4.7(prettier@3.4.2))': + '@storybook/addon-toolbars@8.4.7(storybook@8.6.14(prettier@3.4.2))': dependencies: - memoizerific: 1.11.3 - storybook: 8.4.7(prettier@3.4.2) + storybook: 8.6.14(prettier@3.4.2) - '@storybook/addon-webpack5-compiler-swc@1.0.6(webpack@5.97.1(@swc/core@1.10.4)(esbuild@0.24.2))': + '@storybook/addon-toolbars@8.6.14(storybook@8.6.14(prettier@3.4.2))': dependencies: - '@swc/core': 1.10.4 - swc-loader: 0.2.6(@swc/core@1.10.4)(webpack@5.97.1(@swc/core@1.10.4)(esbuild@0.24.2)) - transitivePeerDependencies: - - '@swc/helpers' - - webpack + storybook: 8.6.14(prettier@3.4.2) + + '@storybook/addon-viewport@8.6.14(storybook@8.6.14(prettier@3.4.2))': + dependencies: + memoizerific: 1.11.3 + storybook: 8.6.14(prettier@3.4.2) - '@storybook/blocks@8.4.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.7(prettier@3.4.2))': + '@storybook/blocks@8.4.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.6.14(prettier@3.4.2))': dependencies: '@storybook/csf': 0.1.13 '@storybook/icons': 1.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - storybook: 8.4.7(prettier@3.4.2) + storybook: 8.6.14(prettier@3.4.2) ts-dedent: 2.2.0 optionalDependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@storybook/builder-webpack5@8.4.7(@swc/core@1.10.4)(esbuild@0.24.2)(storybook@8.4.7(prettier@3.4.2))(typescript@5.7.2)': + '@storybook/blocks@8.6.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.6.14(prettier@3.4.2))': dependencies: - '@storybook/core-webpack': 8.4.7(storybook@8.4.7(prettier@3.4.2)) - '@types/node': 22.18.10 - '@types/semver': 7.5.8 - browser-assert: 1.2.1 - case-sensitive-paths-webpack-plugin: 2.4.0 - cjs-module-lexer: 1.4.1 - constants-browserify: 1.0.0 - css-loader: 6.11.0(webpack@5.97.1(@swc/core@1.10.4)(esbuild@0.24.2)) - es-module-lexer: 1.6.0 - fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.7.2)(webpack@5.97.1(@swc/core@1.10.4)(esbuild@0.24.2)) - html-webpack-plugin: 5.6.3(webpack@5.97.1(@swc/core@1.10.4)(esbuild@0.24.2)) - magic-string: 0.30.17 - path-browserify: 1.0.1 - process: 0.11.10 - semver: 7.6.3 - storybook: 8.4.7(prettier@3.4.2) - style-loader: 3.3.4(webpack@5.97.1(@swc/core@1.10.4)(esbuild@0.24.2)) - terser-webpack-plugin: 5.3.11(@swc/core@1.10.4)(esbuild@0.24.2)(webpack@5.97.1(@swc/core@1.10.4)(esbuild@0.24.2)) + '@storybook/icons': 1.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + storybook: 8.6.14(prettier@3.4.2) ts-dedent: 2.2.0 - url: 0.11.4 - util: 0.12.5 - util-deprecate: 1.0.2 - webpack: 5.97.1(@swc/core@1.10.4)(esbuild@0.24.2) - webpack-dev-middleware: 6.1.3(webpack@5.97.1(@swc/core@1.10.4)(esbuild@0.24.2)) - webpack-hot-middleware: 2.26.1 - webpack-virtual-modules: 0.6.2 optionalDependencies: - typescript: 5.7.2 - transitivePeerDependencies: - - '@rspack/core' - - '@swc/core' - - esbuild - - uglify-js - - webpack-cli + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + '@storybook/builder-vite@8.6.14(storybook@8.6.14(prettier@3.4.2))(vite@7.1.10(@types/node@20.19.21)(jiti@1.21.7)(less@4.5.1)(terser@5.37.0)(yaml@2.8.0))': + dependencies: + '@storybook/csf-plugin': 8.6.14(storybook@8.6.14(prettier@3.4.2)) + browser-assert: 1.2.1 + storybook: 8.6.14(prettier@3.4.2) + ts-dedent: 2.2.0 + vite: 7.1.10(@types/node@20.19.21)(jiti@1.21.7)(less@4.5.1)(terser@5.37.0)(yaml@2.8.0) - '@storybook/components@8.4.7(storybook@8.4.7(prettier@3.4.2))': + '@storybook/components@8.4.7(storybook@8.6.14(prettier@3.4.2))': dependencies: - storybook: 8.4.7(prettier@3.4.2) + storybook: 8.6.14(prettier@3.4.2) - '@storybook/core-events@8.4.7(storybook@8.4.7(prettier@3.4.2))': + '@storybook/components@8.6.14(storybook@8.6.14(prettier@3.4.2))': dependencies: - storybook: 8.4.7(prettier@3.4.2) + storybook: 8.6.14(prettier@3.4.2) - '@storybook/core-webpack@8.4.7(storybook@8.4.7(prettier@3.4.2))': + '@storybook/core-events@8.4.7(storybook@8.6.14(prettier@3.4.2))': dependencies: - '@types/node': 22.18.10 - storybook: 8.4.7(prettier@3.4.2) - ts-dedent: 2.2.0 + storybook: 8.6.14(prettier@3.4.2) - '@storybook/core@8.4.7(prettier@3.4.2)': + '@storybook/core@8.6.14(prettier@3.4.2)(storybook@8.6.14(prettier@3.4.2))': dependencies: - '@storybook/csf': 0.1.13 + '@storybook/theming': 8.6.14(storybook@8.6.14(prettier@3.4.2)) better-opn: 3.0.2 browser-assert: 1.2.1 - esbuild: 0.24.2 - esbuild-register: 3.6.0(esbuild@0.24.2) + esbuild: 0.25.11 + esbuild-register: 3.6.0(esbuild@0.25.11) jsdoc-type-pratt-parser: 4.1.0 process: 0.11.10 recast: 0.23.9 semver: 7.6.3 util: 0.12.5 - ws: 8.18.0 + ws: 8.18.3 optionalDependencies: prettier: 3.4.2 transitivePeerDependencies: - bufferutil + - storybook - supports-color - utf-8-validate - '@storybook/csf-plugin@8.4.7(storybook@8.4.7(prettier@3.4.2))': + '@storybook/csf-plugin@8.6.14(storybook@8.6.14(prettier@3.4.2))': dependencies: - storybook: 8.4.7(prettier@3.4.2) + storybook: 8.6.14(prettier@3.4.2) unplugin: 1.16.0 '@storybook/csf@0.1.13': @@ -6580,169 +6404,85 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@storybook/instrumenter@8.4.7(storybook@8.4.7(prettier@3.4.2))': + '@storybook/instrumenter@8.6.14(storybook@8.6.14(prettier@3.4.2))': dependencies: '@storybook/global': 5.0.0 '@vitest/utils': 2.1.8 - storybook: 8.4.7(prettier@3.4.2) + storybook: 8.6.14(prettier@3.4.2) - '@storybook/manager-api@8.4.7(storybook@8.4.7(prettier@3.4.2))': + '@storybook/manager-api@8.4.7(storybook@8.6.14(prettier@3.4.2))': dependencies: - storybook: 8.4.7(prettier@3.4.2) - - '@storybook/preset-react-webpack@8.4.7(@storybook/test@8.4.7(storybook@8.4.7(prettier@3.4.2)))(@swc/core@1.10.4)(esbuild@0.24.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.7(prettier@3.4.2))(typescript@5.7.2)': - dependencies: - '@storybook/core-webpack': 8.4.7(storybook@8.4.7(prettier@3.4.2)) - '@storybook/react': 8.4.7(@storybook/test@8.4.7(storybook@8.4.7(prettier@3.4.2)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.7(prettier@3.4.2))(typescript@5.7.2) - '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.7.2)(webpack@5.97.1(@swc/core@1.10.4)(esbuild@0.24.2)) - '@types/node': 22.18.10 - '@types/semver': 7.5.8 - find-up: 5.0.0 - magic-string: 0.30.17 - react: 18.3.1 - react-docgen: 7.1.0 - react-dom: 18.3.1(react@18.3.1) - resolve: 1.22.10 - semver: 7.6.3 - storybook: 8.4.7(prettier@3.4.2) - tsconfig-paths: 4.2.0 - webpack: 5.97.1(@swc/core@1.10.4)(esbuild@0.24.2) - optionalDependencies: - typescript: 5.7.2 - transitivePeerDependencies: - - '@storybook/test' - - '@swc/core' - - esbuild - - supports-color - - uglify-js - - webpack-cli + storybook: 8.6.14(prettier@3.4.2) - '@storybook/preview-api@8.4.7(storybook@8.4.7(prettier@3.4.2))': + '@storybook/manager-api@8.6.14(storybook@8.6.14(prettier@3.4.2))': dependencies: - storybook: 8.4.7(prettier@3.4.2) + storybook: 8.6.14(prettier@3.4.2) - '@storybook/react-docgen-typescript-plugin@1.0.6--canary.9.0c3f3b7.0(typescript@5.7.2)(webpack@5.97.1(@swc/core@1.10.4)(esbuild@0.24.2))': + '@storybook/preview-api@8.6.14(storybook@8.6.14(prettier@3.4.2))': dependencies: - debug: 4.4.0 - endent: 2.1.0 - find-cache-dir: 3.3.2 - flat-cache: 3.2.0 - micromatch: 4.0.8 - react-docgen-typescript: 2.2.2(typescript@5.7.2) - tslib: 2.8.1 - typescript: 5.7.2 - webpack: 5.97.1(@swc/core@1.10.4)(esbuild@0.24.2) - transitivePeerDependencies: - - supports-color + storybook: 8.6.14(prettier@3.4.2) - '@storybook/react-dom-shim@8.4.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.7(prettier@3.4.2))': + '@storybook/react-dom-shim@8.6.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.6.14(prettier@3.4.2))': dependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - storybook: 8.4.7(prettier@3.4.2) + storybook: 8.6.14(prettier@3.4.2) - '@storybook/react-webpack5@8.4.7(@storybook/test@8.4.7(storybook@8.4.7(prettier@3.4.2)))(@swc/core@1.10.4)(esbuild@0.24.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.7(prettier@3.4.2))(typescript@5.7.2)': + '@storybook/react-vite@8.6.14(@storybook/test@8.6.14(storybook@8.6.14(prettier@3.4.2)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.30.0)(storybook@8.6.14(prettier@3.4.2))(typescript@5.7.2)(vite@7.1.10(@types/node@20.19.21)(jiti@1.21.7)(less@4.5.1)(terser@5.37.0)(yaml@2.8.0))': dependencies: - '@storybook/builder-webpack5': 8.4.7(@swc/core@1.10.4)(esbuild@0.24.2)(storybook@8.4.7(prettier@3.4.2))(typescript@5.7.2) - '@storybook/preset-react-webpack': 8.4.7(@storybook/test@8.4.7(storybook@8.4.7(prettier@3.4.2)))(@swc/core@1.10.4)(esbuild@0.24.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.7(prettier@3.4.2))(typescript@5.7.2) - '@storybook/react': 8.4.7(@storybook/test@8.4.7(storybook@8.4.7(prettier@3.4.2)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.7(prettier@3.4.2))(typescript@5.7.2) - '@types/node': 22.18.10 + '@joshwooding/vite-plugin-react-docgen-typescript': 0.5.0(typescript@5.7.2)(vite@7.1.10(@types/node@20.19.21)(jiti@1.21.7)(less@4.5.1)(terser@5.37.0)(yaml@2.8.0)) + '@rollup/pluginutils': 5.1.4(rollup@4.30.0) + '@storybook/builder-vite': 8.6.14(storybook@8.6.14(prettier@3.4.2))(vite@7.1.10(@types/node@20.19.21)(jiti@1.21.7)(less@4.5.1)(terser@5.37.0)(yaml@2.8.0)) + '@storybook/react': 8.6.14(@storybook/test@8.6.14(storybook@8.6.14(prettier@3.4.2)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.6.14(prettier@3.4.2))(typescript@5.7.2) + find-up: 5.0.0 + magic-string: 0.30.17 react: 18.3.1 + react-docgen: 7.1.0 react-dom: 18.3.1(react@18.3.1) - storybook: 8.4.7(prettier@3.4.2) + resolve: 1.22.10 + storybook: 8.6.14(prettier@3.4.2) + tsconfig-paths: 4.2.0 + vite: 7.1.10(@types/node@20.19.21)(jiti@1.21.7)(less@4.5.1)(terser@5.37.0)(yaml@2.8.0) optionalDependencies: - typescript: 5.7.2 + '@storybook/test': 8.6.14(storybook@8.6.14(prettier@3.4.2)) transitivePeerDependencies: - - '@rspack/core' - - '@storybook/test' - - '@swc/core' - - esbuild + - rollup - supports-color - - uglify-js - - webpack-cli + - typescript - '@storybook/react@8.4.7(@storybook/test@8.4.7(storybook@8.4.7(prettier@3.4.2)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.7(prettier@3.4.2))(typescript@5.7.2)': + '@storybook/react@8.6.14(@storybook/test@8.6.14(storybook@8.6.14(prettier@3.4.2)))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.6.14(prettier@3.4.2))(typescript@5.7.2)': dependencies: - '@storybook/components': 8.4.7(storybook@8.4.7(prettier@3.4.2)) + '@storybook/components': 8.6.14(storybook@8.6.14(prettier@3.4.2)) '@storybook/global': 5.0.0 - '@storybook/manager-api': 8.4.7(storybook@8.4.7(prettier@3.4.2)) - '@storybook/preview-api': 8.4.7(storybook@8.4.7(prettier@3.4.2)) - '@storybook/react-dom-shim': 8.4.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.7(prettier@3.4.2)) - '@storybook/theming': 8.4.7(storybook@8.4.7(prettier@3.4.2)) + '@storybook/manager-api': 8.6.14(storybook@8.6.14(prettier@3.4.2)) + '@storybook/preview-api': 8.6.14(storybook@8.6.14(prettier@3.4.2)) + '@storybook/react-dom-shim': 8.6.14(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.6.14(prettier@3.4.2)) + '@storybook/theming': 8.6.14(storybook@8.6.14(prettier@3.4.2)) react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - storybook: 8.4.7(prettier@3.4.2) + storybook: 8.6.14(prettier@3.4.2) optionalDependencies: - '@storybook/test': 8.4.7(storybook@8.4.7(prettier@3.4.2)) + '@storybook/test': 8.6.14(storybook@8.6.14(prettier@3.4.2)) typescript: 5.7.2 - '@storybook/test@8.4.7(storybook@8.4.7(prettier@3.4.2))': + '@storybook/test@8.6.14(storybook@8.6.14(prettier@3.4.2))': dependencies: - '@storybook/csf': 0.1.13 '@storybook/global': 5.0.0 - '@storybook/instrumenter': 8.4.7(storybook@8.4.7(prettier@3.4.2)) + '@storybook/instrumenter': 8.6.14(storybook@8.6.14(prettier@3.4.2)) '@testing-library/dom': 10.4.0 '@testing-library/jest-dom': 6.5.0 '@testing-library/user-event': 14.5.2(@testing-library/dom@10.4.0) '@vitest/expect': 2.0.5 '@vitest/spy': 2.0.5 - storybook: 8.4.7(prettier@3.4.2) - - '@storybook/theming@8.4.7(storybook@8.4.7(prettier@3.4.2))': - dependencies: - storybook: 8.4.7(prettier@3.4.2) - - '@swc/core-darwin-arm64@1.10.4': - optional: true + storybook: 8.6.14(prettier@3.4.2) - '@swc/core-darwin-x64@1.10.4': - optional: true - - '@swc/core-linux-arm-gnueabihf@1.10.4': - optional: true - - '@swc/core-linux-arm64-gnu@1.10.4': - optional: true - - '@swc/core-linux-arm64-musl@1.10.4': - optional: true - - '@swc/core-linux-x64-gnu@1.10.4': - optional: true - - '@swc/core-linux-x64-musl@1.10.4': - optional: true - - '@swc/core-win32-arm64-msvc@1.10.4': - optional: true - - '@swc/core-win32-ia32-msvc@1.10.4': - optional: true - - '@swc/core-win32-x64-msvc@1.10.4': - optional: true - - '@swc/core@1.10.4': + '@storybook/theming@8.4.7(storybook@8.6.14(prettier@3.4.2))': dependencies: - '@swc/counter': 0.1.3 - '@swc/types': 0.1.17 - optionalDependencies: - '@swc/core-darwin-arm64': 1.10.4 - '@swc/core-darwin-x64': 1.10.4 - '@swc/core-linux-arm-gnueabihf': 1.10.4 - '@swc/core-linux-arm64-gnu': 1.10.4 - '@swc/core-linux-arm64-musl': 1.10.4 - '@swc/core-linux-x64-gnu': 1.10.4 - '@swc/core-linux-x64-musl': 1.10.4 - '@swc/core-win32-arm64-msvc': 1.10.4 - '@swc/core-win32-ia32-msvc': 1.10.4 - '@swc/core-win32-x64-msvc': 1.10.4 - - '@swc/counter@0.1.3': {} + storybook: 8.6.14(prettier@3.4.2) - '@swc/types@0.1.17': + '@storybook/theming@8.6.14(storybook@8.6.14(prettier@3.4.2))': dependencies: - '@swc/counter': 0.1.3 + storybook: 8.6.14(prettier@3.4.2) '@testing-library/dom@10.4.0': dependencies: @@ -6816,6 +6556,10 @@ snapshots: dependencies: '@babel/types': 7.26.3 + '@types/babel__traverse@7.28.0': + dependencies: + '@babel/types': 7.28.5 + '@types/chai@5.2.2': dependencies: '@types/deep-eql': 4.0.2 @@ -6827,11 +6571,11 @@ snapshots: '@types/eslint-scope@3.7.7': dependencies: '@types/eslint': 9.6.1 - '@types/estree': 1.0.6 + '@types/estree': 1.0.8 '@types/eslint@9.6.1': dependencies: - '@types/estree': 1.0.6 + '@types/estree': 1.0.8 '@types/json-schema': 7.0.15 '@types/estree@1.0.6': {} @@ -6842,8 +6586,6 @@ snapshots: dependencies: '@types/unist': 3.0.3 - '@types/html-minifier-terser@6.1.0': {} - '@types/json-schema@7.0.15': {} '@types/mdx@2.0.13': {} @@ -6852,10 +6594,6 @@ snapshots: dependencies: undici-types: 6.21.0 - '@types/node@22.18.10': - dependencies: - undici-types: 6.21.0 - '@types/parse-json@4.0.2': {} '@types/prop-types@15.7.14': {} @@ -6877,8 +6615,6 @@ snapshots: '@types/resolve@1.20.6': {} - '@types/semver@7.5.8': {} - '@types/unist@3.0.3': {} '@types/utif@3.0.5': @@ -6887,15 +6623,15 @@ snapshots: '@types/uuid@9.0.8': {} - '@typescript-eslint/eslint-plugin@8.19.0(@typescript-eslint/parser@8.19.0(eslint@9.17.0)(typescript@5.7.2))(eslint@9.17.0)(typescript@5.7.2)': + '@typescript-eslint/eslint-plugin@8.19.0(@typescript-eslint/parser@8.19.0(eslint@9.17.0(jiti@1.21.7))(typescript@5.7.2))(eslint@9.17.0(jiti@1.21.7))(typescript@5.7.2)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.19.0(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/parser': 8.19.0(eslint@9.17.0(jiti@1.21.7))(typescript@5.7.2) '@typescript-eslint/scope-manager': 8.19.0 - '@typescript-eslint/type-utils': 8.19.0(eslint@9.17.0)(typescript@5.7.2) - '@typescript-eslint/utils': 8.19.0(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/type-utils': 8.19.0(eslint@9.17.0(jiti@1.21.7))(typescript@5.7.2) + '@typescript-eslint/utils': 8.19.0(eslint@9.17.0(jiti@1.21.7))(typescript@5.7.2) '@typescript-eslint/visitor-keys': 8.19.0 - eslint: 9.17.0 + eslint: 9.17.0(jiti@1.21.7) graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 @@ -6904,14 +6640,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.19.0(eslint@9.17.0)(typescript@5.7.2)': + '@typescript-eslint/parser@8.19.0(eslint@9.17.0(jiti@1.21.7))(typescript@5.7.2)': dependencies: '@typescript-eslint/scope-manager': 8.19.0 '@typescript-eslint/types': 8.19.0 '@typescript-eslint/typescript-estree': 8.19.0(typescript@5.7.2) '@typescript-eslint/visitor-keys': 8.19.0 debug: 4.4.0 - eslint: 9.17.0 + eslint: 9.17.0(jiti@1.21.7) typescript: 5.7.2 transitivePeerDependencies: - supports-color @@ -6921,12 +6657,12 @@ snapshots: '@typescript-eslint/types': 8.19.0 '@typescript-eslint/visitor-keys': 8.19.0 - '@typescript-eslint/type-utils@8.19.0(eslint@9.17.0)(typescript@5.7.2)': + '@typescript-eslint/type-utils@8.19.0(eslint@9.17.0(jiti@1.21.7))(typescript@5.7.2)': dependencies: '@typescript-eslint/typescript-estree': 8.19.0(typescript@5.7.2) - '@typescript-eslint/utils': 8.19.0(eslint@9.17.0)(typescript@5.7.2) + '@typescript-eslint/utils': 8.19.0(eslint@9.17.0(jiti@1.21.7))(typescript@5.7.2) debug: 4.4.0 - eslint: 9.17.0 + eslint: 9.17.0(jiti@1.21.7) ts-api-utils: 1.4.3(typescript@5.7.2) typescript: 5.7.2 transitivePeerDependencies: @@ -6948,13 +6684,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.19.0(eslint@9.17.0)(typescript@5.7.2)': + '@typescript-eslint/utils@8.19.0(eslint@9.17.0(jiti@1.21.7))(typescript@5.7.2)': dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.17.0) + '@eslint-community/eslint-utils': 4.4.1(eslint@9.17.0(jiti@1.21.7)) '@typescript-eslint/scope-manager': 8.19.0 '@typescript-eslint/types': 8.19.0 '@typescript-eslint/typescript-estree': 8.19.0(typescript@5.7.2) - eslint: 9.17.0 + eslint: 9.17.0(jiti@1.21.7) typescript: 5.7.2 transitivePeerDependencies: - supports-color @@ -6968,7 +6704,7 @@ snapshots: dependencies: '@vitest/spy': 2.0.5 '@vitest/utils': 2.0.5 - chai: 5.1.2 + chai: 5.3.3 tinyrainbow: 1.2.0 '@vitest/expect@3.2.4': @@ -6979,13 +6715,13 @@ snapshots: chai: 5.3.3 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.4(vite@7.1.10(@types/node@20.19.21)(terser@5.37.0)(yaml@2.8.0))': + '@vitest/mocker@3.2.4(vite@7.1.10(@types/node@20.19.21)(jiti@1.21.7)(less@4.5.1)(terser@5.37.0)(yaml@2.8.0))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.17 optionalDependencies: - vite: 7.1.10(@types/node@20.19.21)(terser@5.37.0)(yaml@2.8.0) + vite: 7.1.10(@types/node@20.19.21)(jiti@1.21.7)(less@4.5.1)(terser@5.37.0)(yaml@2.8.0) '@vitest/pretty-format@2.0.5': dependencies: @@ -7023,13 +6759,13 @@ snapshots: dependencies: '@vitest/pretty-format': 2.0.5 estree-walker: 3.0.3 - loupe: 3.1.2 + loupe: 3.2.1 tinyrainbow: 1.2.0 '@vitest/utils@2.1.8': dependencies: '@vitest/pretty-format': 2.1.8 - loupe: 3.1.2 + loupe: 3.2.1 tinyrainbow: 1.2.0 '@vitest/utils@3.2.4': @@ -7138,8 +6874,7 @@ snapshots: acorn@8.14.0: {} - acorn@8.15.0: - optional: true + acorn@8.15.0: {} agent-base@6.0.2: dependencies: @@ -7175,8 +6910,6 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 - ansi-html-community@0.0.8: {} - ansi-regex@5.0.1: {} ansi-regex@6.1.0: {} @@ -7187,10 +6920,7 @@ snapshots: ansi-styles@5.2.0: {} - anymatch@3.1.3: - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 + ansi-styles@6.2.3: {} argparse@2.0.1: {} @@ -7272,6 +7002,8 @@ snapshots: dependencies: possible-typed-array-names: 1.0.0 + axe-core@4.11.0: {} + babel-plugin-macros@3.1.0: dependencies: '@babel/runtime': 7.26.0 @@ -7310,8 +7042,6 @@ snapshots: big.js@5.2.2: {} - binary-extensions@2.3.0: {} - boolbase@1.0.0: {} brace-expansion@1.1.11: @@ -7359,11 +7089,6 @@ snapshots: callsites@3.1.0: {} - camel-case@4.1.2: - dependencies: - pascal-case: 3.1.2 - tslib: 2.8.1 - caniuse-api@3.0.0: dependencies: browserslist: 4.24.3 @@ -7373,16 +7098,6 @@ snapshots: caniuse-lite@1.0.30001690: {} - case-sensitive-paths-webpack-plugin@2.4.0: {} - - chai@5.1.2: - dependencies: - assertion-error: 2.0.1 - check-error: 2.1.1 - deep-eql: 5.0.2 - loupe: 3.1.2 - pathval: 2.0.0 - chai@5.3.3: dependencies: assertion-error: 2.0.1 @@ -7403,27 +7118,9 @@ snapshots: check-error@2.1.1: {} - chokidar@3.6.0: - dependencies: - anymatch: 3.1.3 - braces: 3.0.3 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - chromatic@11.22.0: {} - chrome-trace-event@1.0.4: {} - - cjs-module-lexer@1.4.1: {} - - clean-css@5.3.3: - dependencies: - source-map: 0.6.1 + chrome-trace-event@1.0.4: {} clsx@2.1.1: {} @@ -7435,8 +7132,6 @@ snapshots: colord@2.9.3: {} - colorette@2.0.20: {} - combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 @@ -7448,8 +7143,6 @@ snapshots: commander@7.2.0: {} - commander@8.3.0: {} - commondir@1.0.1: {} concat-map@0.0.1: {} @@ -7458,14 +7151,17 @@ snapshots: dependencies: source-map: 0.6.1 - constants-browserify@1.0.0: {} - convert-source-map@1.9.0: {} convert-source-map@2.0.0: {} cookie@1.0.2: {} + copy-anything@2.0.6: + dependencies: + is-what: 3.14.1 + optional: true + core-js-compat@3.39.0: dependencies: browserslist: 4.24.3 @@ -7484,22 +7180,9 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - css-declaration-sorter@6.4.1(postcss@8.4.49): - dependencies: - postcss: 8.4.49 - - css-loader@6.11.0(webpack@5.97.1(@swc/core@1.10.4)(esbuild@0.24.2)): + css-declaration-sorter@6.4.1(postcss@8.5.6): dependencies: - icss-utils: 5.1.0(postcss@8.4.49) - postcss: 8.4.49 - postcss-modules-extract-imports: 3.1.0(postcss@8.4.49) - postcss-modules-local-by-default: 4.2.0(postcss@8.4.49) - postcss-modules-scope: 3.2.1(postcss@8.4.49) - postcss-modules-values: 4.0.0(postcss@8.4.49) - postcss-value-parser: 4.2.0 - semver: 7.6.3 - optionalDependencies: - webpack: 5.97.1(@swc/core@1.10.4)(esbuild@0.24.2) + postcss: 8.5.6 css-select@4.3.0: dependencies: @@ -7520,48 +7203,48 @@ snapshots: cssesc@3.0.0: {} - cssnano-preset-default@5.2.14(postcss@8.4.49): - dependencies: - css-declaration-sorter: 6.4.1(postcss@8.4.49) - cssnano-utils: 3.1.0(postcss@8.4.49) - postcss: 8.4.49 - postcss-calc: 8.2.4(postcss@8.4.49) - postcss-colormin: 5.3.1(postcss@8.4.49) - postcss-convert-values: 5.1.3(postcss@8.4.49) - postcss-discard-comments: 5.1.2(postcss@8.4.49) - postcss-discard-duplicates: 5.1.0(postcss@8.4.49) - postcss-discard-empty: 5.1.1(postcss@8.4.49) - postcss-discard-overridden: 5.1.0(postcss@8.4.49) - postcss-merge-longhand: 5.1.7(postcss@8.4.49) - postcss-merge-rules: 5.1.4(postcss@8.4.49) - postcss-minify-font-values: 5.1.0(postcss@8.4.49) - postcss-minify-gradients: 5.1.1(postcss@8.4.49) - postcss-minify-params: 5.1.4(postcss@8.4.49) - postcss-minify-selectors: 5.2.1(postcss@8.4.49) - postcss-normalize-charset: 5.1.0(postcss@8.4.49) - postcss-normalize-display-values: 5.1.0(postcss@8.4.49) - postcss-normalize-positions: 5.1.1(postcss@8.4.49) - postcss-normalize-repeat-style: 5.1.1(postcss@8.4.49) - postcss-normalize-string: 5.1.0(postcss@8.4.49) - postcss-normalize-timing-functions: 5.1.0(postcss@8.4.49) - postcss-normalize-unicode: 5.1.1(postcss@8.4.49) - postcss-normalize-url: 5.1.0(postcss@8.4.49) - postcss-normalize-whitespace: 5.1.1(postcss@8.4.49) - postcss-ordered-values: 5.1.3(postcss@8.4.49) - postcss-reduce-initial: 5.1.2(postcss@8.4.49) - postcss-reduce-transforms: 5.1.0(postcss@8.4.49) - postcss-svgo: 5.1.0(postcss@8.4.49) - postcss-unique-selectors: 5.1.1(postcss@8.4.49) - - cssnano-utils@3.1.0(postcss@8.4.49): - dependencies: - postcss: 8.4.49 - - cssnano@5.1.15(postcss@8.4.49): - dependencies: - cssnano-preset-default: 5.2.14(postcss@8.4.49) + cssnano-preset-default@5.2.14(postcss@8.5.6): + dependencies: + css-declaration-sorter: 6.4.1(postcss@8.5.6) + cssnano-utils: 3.1.0(postcss@8.5.6) + postcss: 8.5.6 + postcss-calc: 8.2.4(postcss@8.5.6) + postcss-colormin: 5.3.1(postcss@8.5.6) + postcss-convert-values: 5.1.3(postcss@8.5.6) + postcss-discard-comments: 5.1.2(postcss@8.5.6) + postcss-discard-duplicates: 5.1.0(postcss@8.5.6) + postcss-discard-empty: 5.1.1(postcss@8.5.6) + postcss-discard-overridden: 5.1.0(postcss@8.5.6) + postcss-merge-longhand: 5.1.7(postcss@8.5.6) + postcss-merge-rules: 5.1.4(postcss@8.5.6) + postcss-minify-font-values: 5.1.0(postcss@8.5.6) + postcss-minify-gradients: 5.1.1(postcss@8.5.6) + postcss-minify-params: 5.1.4(postcss@8.5.6) + postcss-minify-selectors: 5.2.1(postcss@8.5.6) + postcss-normalize-charset: 5.1.0(postcss@8.5.6) + postcss-normalize-display-values: 5.1.0(postcss@8.5.6) + postcss-normalize-positions: 5.1.1(postcss@8.5.6) + postcss-normalize-repeat-style: 5.1.1(postcss@8.5.6) + postcss-normalize-string: 5.1.0(postcss@8.5.6) + postcss-normalize-timing-functions: 5.1.0(postcss@8.5.6) + postcss-normalize-unicode: 5.1.1(postcss@8.5.6) + postcss-normalize-url: 5.1.0(postcss@8.5.6) + postcss-normalize-whitespace: 5.1.1(postcss@8.5.6) + postcss-ordered-values: 5.1.3(postcss@8.5.6) + postcss-reduce-initial: 5.1.2(postcss@8.5.6) + postcss-reduce-transforms: 5.1.0(postcss@8.5.6) + postcss-svgo: 5.1.0(postcss@8.5.6) + postcss-unique-selectors: 5.1.1(postcss@8.5.6) + + cssnano-utils@3.1.0(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + cssnano@5.1.15(postcss@8.5.6): + dependencies: + cssnano-preset-default: 5.2.14(postcss@8.5.6) lilconfig: 2.1.0 - postcss: 8.4.49 + postcss: 8.5.6 yaml: 1.10.2 csso@4.2.0: @@ -7619,8 +7302,6 @@ snapshots: decimal.js@10.6.0: optional: true - dedent@0.7.0: {} - deep-eql@5.0.2: {} deep-is@0.1.4: {} @@ -7662,10 +7343,6 @@ snapshots: dom-accessibility-api@0.6.3: {} - dom-converter@0.2.0: - dependencies: - utila: 0.4.0 - dom-helpers@5.2.1: dependencies: '@babel/runtime': 7.26.0 @@ -7694,28 +7371,23 @@ snapshots: domelementtype: 2.3.0 domhandler: 4.3.1 - dot-case@3.0.4: - dependencies: - no-case: 3.0.4 - tslib: 2.8.1 - dunder-proto@1.0.1: dependencies: call-bind-apply-helpers: 1.0.1 es-errors: 1.3.0 gopd: 1.2.0 + eastasianwidth@0.2.0: {} + electron-to-chromium@1.5.76: {} email-addresses@5.0.0: {} - emojis-list@3.0.0: {} + emoji-regex@8.0.0: {} - endent@2.1.0: - dependencies: - dedent: 0.7.0 - fast-json-parse: 1.0.3 - objectorarray: 1.0.5 + emoji-regex@9.2.2: {} + + emojis-list@3.0.0: {} enhanced-resolve@5.18.0: dependencies: @@ -7729,6 +7401,11 @@ snapshots: entities@6.0.1: optional: true + errno@0.1.8: + dependencies: + prr: 1.0.1 + optional: true + error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 @@ -7810,8 +7487,6 @@ snapshots: iterator.prototype: 1.1.5 safe-array-concat: 1.1.3 - es-module-lexer@1.6.0: {} - es-module-lexer@1.7.0: {} es-object-atoms@1.0.0: @@ -7835,41 +7510,13 @@ snapshots: is-date-object: 1.1.0 is-symbol: 1.1.1 - esbuild-register@3.6.0(esbuild@0.24.2): + esbuild-register@3.6.0(esbuild@0.25.11): dependencies: - debug: 4.4.0 - esbuild: 0.24.2 + debug: 4.4.3 + esbuild: 0.25.11 transitivePeerDependencies: - supports-color - esbuild@0.24.2: - optionalDependencies: - '@esbuild/aix-ppc64': 0.24.2 - '@esbuild/android-arm': 0.24.2 - '@esbuild/android-arm64': 0.24.2 - '@esbuild/android-x64': 0.24.2 - '@esbuild/darwin-arm64': 0.24.2 - '@esbuild/darwin-x64': 0.24.2 - '@esbuild/freebsd-arm64': 0.24.2 - '@esbuild/freebsd-x64': 0.24.2 - '@esbuild/linux-arm': 0.24.2 - '@esbuild/linux-arm64': 0.24.2 - '@esbuild/linux-ia32': 0.24.2 - '@esbuild/linux-loong64': 0.24.2 - '@esbuild/linux-mips64el': 0.24.2 - '@esbuild/linux-ppc64': 0.24.2 - '@esbuild/linux-riscv64': 0.24.2 - '@esbuild/linux-s390x': 0.24.2 - '@esbuild/linux-x64': 0.24.2 - '@esbuild/netbsd-arm64': 0.24.2 - '@esbuild/netbsd-x64': 0.24.2 - '@esbuild/openbsd-arm64': 0.24.2 - '@esbuild/openbsd-x64': 0.24.2 - '@esbuild/sunos-x64': 0.24.2 - '@esbuild/win32-arm64': 0.24.2 - '@esbuild/win32-ia32': 0.24.2 - '@esbuild/win32-x64': 0.24.2 - esbuild@0.25.11: optionalDependencies: '@esbuild/aix-ppc64': 0.25.11 @@ -7914,25 +7561,25 @@ snapshots: source-map: 0.6.1 optional: true - eslint-config-prettier@9.1.0(eslint@9.17.0): + eslint-config-prettier@9.1.0(eslint@9.17.0(jiti@1.21.7)): dependencies: - eslint: 9.17.0 + eslint: 9.17.0(jiti@1.21.7) - eslint-plugin-prettier@5.2.1(@types/eslint@9.6.1)(eslint-config-prettier@9.1.0(eslint@9.17.0))(eslint@9.17.0)(prettier@3.4.2): + eslint-plugin-prettier@5.2.1(@types/eslint@9.6.1)(eslint-config-prettier@9.1.0(eslint@9.17.0(jiti@1.21.7)))(eslint@9.17.0(jiti@1.21.7))(prettier@3.4.2): dependencies: - eslint: 9.17.0 + eslint: 9.17.0(jiti@1.21.7) prettier: 3.4.2 prettier-linter-helpers: 1.0.0 synckit: 0.9.2 optionalDependencies: '@types/eslint': 9.6.1 - eslint-config-prettier: 9.1.0(eslint@9.17.0) + eslint-config-prettier: 9.1.0(eslint@9.17.0(jiti@1.21.7)) - eslint-plugin-react-hooks@5.1.0(eslint@9.17.0): + eslint-plugin-react-hooks@5.1.0(eslint@9.17.0(jiti@1.21.7)): dependencies: - eslint: 9.17.0 + eslint: 9.17.0(jiti@1.21.7) - eslint-plugin-react@7.37.3(eslint@9.17.0): + eslint-plugin-react@7.37.3(eslint@9.17.0(jiti@1.21.7)): dependencies: array-includes: 3.1.8 array.prototype.findlast: 1.2.5 @@ -7940,7 +7587,7 @@ snapshots: array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 es-iterator-helpers: 1.2.1 - eslint: 9.17.0 + eslint: 9.17.0(jiti@1.21.7) estraverse: 5.3.0 hasown: 2.0.2 jsx-ast-utils: 3.3.5 @@ -7968,9 +7615,9 @@ snapshots: eslint-visitor-keys@4.2.0: {} - eslint@9.17.0: + eslint@9.17.0(jiti@1.21.7): dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.17.0) + '@eslint-community/eslint-utils': 4.4.1(eslint@9.17.0(jiti@1.21.7)) '@eslint-community/regexpp': 4.12.1 '@eslint/config-array': 0.19.1 '@eslint/core': 0.9.1 @@ -8004,6 +7651,8 @@ snapshots: minimatch: 3.1.2 natural-compare: 1.4.0 optionator: 0.9.4 + optionalDependencies: + jiti: 1.21.7 transitivePeerDependencies: - supports-color @@ -8055,8 +7704,6 @@ snapshots: merge2: 1.4.1 micromatch: 4.0.8 - fast-json-parse@1.0.3: {} - fast-json-stable-stringify@2.1.0: {} fast-levenshtein@2.0.6: {} @@ -8079,11 +7726,11 @@ snapshots: dependencies: flat-cache: 4.0.1 - file-loader@6.2.0(webpack@5.97.1(@swc/core@1.10.4)(esbuild@0.24.2)): + file-loader@6.2.0(webpack@5.97.1(esbuild@0.25.11)): dependencies: loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.97.1(@swc/core@1.10.4)(esbuild@0.24.2) + webpack: 5.97.1(esbuild@0.25.11) filename-reserved-regex@2.0.0: {} @@ -8117,12 +7764,6 @@ snapshots: locate-path: 6.0.0 path-exists: 4.0.0 - flat-cache@3.2.0: - dependencies: - flatted: 3.3.2 - keyv: 4.5.4 - rimraf: 3.0.2 - flat-cache@4.0.1: dependencies: flatted: 3.3.2 @@ -8134,22 +7775,10 @@ snapshots: dependencies: is-callable: 1.2.7 - fork-ts-checker-webpack-plugin@8.0.0(typescript@5.7.2)(webpack@5.97.1(@swc/core@1.10.4)(esbuild@0.24.2)): + foreground-child@3.3.1: dependencies: - '@babel/code-frame': 7.26.2 - chalk: 4.1.2 - chokidar: 3.6.0 - cosmiconfig: 7.1.0 - deepmerge: 4.3.1 - fs-extra: 10.1.0 - memfs: 3.5.3 - minimatch: 3.1.2 - node-abort-controller: 3.1.1 - schema-utils: 3.3.0 - semver: 7.6.3 - tapable: 2.2.1 - typescript: 5.7.2 - webpack: 5.97.1(@swc/core@1.10.4)(esbuild@0.24.2) + cross-spawn: 7.0.6 + signal-exit: 4.1.0 form-data@4.0.4: dependencies: @@ -8160,22 +7789,12 @@ snapshots: mime-types: 2.1.35 optional: true - fs-extra@10.1.0: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 - fs-extra@11.2.0: dependencies: graceful-fs: 4.2.11 jsonfile: 6.1.0 universalify: 2.0.1 - fs-monkey@1.0.6: {} - - fs.realpath@1.0.0: {} - fsevents@2.3.3: optional: true @@ -8242,14 +7861,14 @@ snapshots: glob-to-regexp@0.4.1: {} - glob@7.2.3: + glob@10.5.0: dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 globals@11.12.0: {} @@ -8297,8 +7916,6 @@ snapshots: dependencies: function-bind: 1.1.2 - he@1.2.0: {} - hoist-non-react-statics@3.3.2: dependencies: react-is: 16.13.1 @@ -8308,35 +7925,6 @@ snapshots: whatwg-encoding: 2.0.0 optional: true - html-entities@2.5.2: {} - - html-minifier-terser@6.1.0: - dependencies: - camel-case: 4.1.2 - clean-css: 5.3.3 - commander: 8.3.0 - he: 1.2.0 - param-case: 3.0.4 - relateurl: 0.2.7 - terser: 5.37.0 - - html-webpack-plugin@5.6.3(webpack@5.97.1(@swc/core@1.10.4)(esbuild@0.24.2)): - dependencies: - '@types/html-minifier-terser': 6.1.0 - html-minifier-terser: 6.1.0 - lodash: 4.17.21 - pretty-error: 4.0.0 - tapable: 2.2.1 - optionalDependencies: - webpack: 5.97.1(@swc/core@1.10.4)(esbuild@0.24.2) - - htmlparser2@6.1.0: - dependencies: - domelementtype: 2.3.0 - domhandler: 4.3.1 - domutils: 2.8.0 - entities: 2.2.0 - http-proxy-agent@5.0.0: dependencies: '@tootallnate/once': 2.0.0 @@ -8361,12 +7949,15 @@ snapshots: icss-replace-symbols@1.1.0: {} - icss-utils@5.1.0(postcss@8.4.49): + icss-utils@5.1.0(postcss@8.5.6): dependencies: - postcss: 8.4.49 + postcss: 8.5.6 ignore@5.3.2: {} + image-size@0.5.5: + optional: true + import-cwd@3.0.0: dependencies: import-from: 3.0.0 @@ -8384,11 +7975,6 @@ snapshots: indent-string@4.0.0: {} - inflight@1.0.6: - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - inherits@2.0.4: {} internal-slot@1.1.0: @@ -8421,10 +8007,6 @@ snapshots: dependencies: has-bigints: 1.1.0 - is-binary-path@2.1.0: - dependencies: - binary-extensions: 2.3.0 - is-boolean-object@1.2.1: dependencies: call-bound: 1.0.3 @@ -8455,6 +8037,8 @@ snapshots: dependencies: call-bound: 1.0.3 + is-fullwidth-code-point@3.0.0: {} + is-generator-function@1.1.0: dependencies: call-bound: 1.0.3 @@ -8523,6 +8107,9 @@ snapshots: call-bound: 1.0.3 get-intrinsic: 1.2.7 + is-what@3.14.1: + optional: true + is-wsl@2.2.0: dependencies: is-docker: 2.2.1 @@ -8540,12 +8127,21 @@ snapshots: has-symbols: 1.1.0 set-function-name: 2.0.2 + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + jest-worker@27.5.1: dependencies: '@types/node': 20.19.21 merge-stream: 2.0.0 supports-color: 8.1.1 + jiti@1.21.7: + optional: true + js-tokens@4.0.0: {} js-tokens@9.0.1: {} @@ -8625,6 +8221,21 @@ snapshots: dependencies: json-buffer: 3.0.1 + less@4.5.1: + dependencies: + copy-anything: 2.0.6 + parse-node-version: 1.0.1 + tslib: 2.8.1 + optionalDependencies: + errno: 0.1.8 + graceful-fs: 4.2.11 + image-size: 0.5.5 + make-dir: 2.1.0 + mime: 1.6.0 + needle: 3.3.1 + source-map: 0.6.1 + optional: true + levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -8676,9 +8287,7 @@ snapshots: loupe@3.2.1: {} - lower-case@2.0.2: - dependencies: - tslib: 2.8.1 + lru-cache@10.4.3: {} lru-cache@5.1.1: dependencies: @@ -8688,10 +8297,20 @@ snapshots: lz-string@1.5.0: {} + magic-string@0.27.0: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + magic-string@0.30.17: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 + make-dir@2.1.0: + dependencies: + pify: 4.0.1 + semver: 5.7.2 + optional: true + make-dir@3.1.0: dependencies: semver: 6.3.1 @@ -8713,10 +8332,6 @@ snapshots: mdurl@2.0.0: {} - memfs@3.5.3: - dependencies: - fs-monkey: 1.0.6 - memoizerific@1.11.3: dependencies: map-or-similar: 1.5.0 @@ -8736,6 +8351,9 @@ snapshots: dependencies: mime-db: 1.52.0 + mime@1.6.0: + optional: true + min-indent@1.0.1: {} mini-svg-data-uri@1.4.4: {} @@ -8750,27 +8368,24 @@ snapshots: minimist@1.2.8: {} + minipass@7.1.2: {} + ms@2.1.3: {} nanoid@3.3.11: {} - nanoid@3.3.8: {} - natural-compare@1.4.0: {} - neo-async@2.6.2: {} - - no-case@3.0.4: + needle@3.3.1: dependencies: - lower-case: 2.0.2 - tslib: 2.8.1 + iconv-lite: 0.6.3 + sax: 1.4.3 + optional: true - node-abort-controller@3.1.1: {} + neo-async@2.6.2: {} node-releases@2.0.19: {} - normalize-path@3.0.0: {} - normalize-url@6.1.0: {} nth-check@2.1.1: @@ -8815,12 +8430,6 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.0.0 - objectorarray@1.0.5: {} - - once@1.4.0: - dependencies: - wrappy: 1.0.2 - open@8.4.2: dependencies: define-lazy-prop: 2.0.0 @@ -8871,12 +8480,9 @@ snapshots: p-try@2.2.0: {} - pako@1.0.11: {} + package-json-from-dist@1.0.1: {} - param-case@3.0.4: - dependencies: - dot-case: 3.0.4 - tslib: 2.8.1 + pako@1.0.11: {} parent-module@1.0.1: dependencies: @@ -8889,26 +8495,25 @@ snapshots: json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 + parse-node-version@1.0.1: + optional: true + parse5@7.3.0: dependencies: entities: 6.0.1 optional: true - pascal-case@3.1.2: - dependencies: - no-case: 3.0.4 - tslib: 2.8.1 - - path-browserify@1.0.1: {} - path-exists@4.0.0: {} - path-is-absolute@1.0.1: {} - path-key@3.1.1: {} path-parse@1.0.7: {} + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + path-type@4.0.0: {} pathe@2.0.3: {} @@ -8923,6 +8528,9 @@ snapshots: picomatch@4.0.3: {} + pify@4.0.1: + optional: true + pify@5.0.0: {} pkg-dir@4.2.0: @@ -8935,181 +8543,181 @@ snapshots: possible-typed-array-names@1.0.0: {} - postcss-calc@8.2.4(postcss@8.4.49): + postcss-calc@8.2.4(postcss@8.5.6): dependencies: - postcss: 8.4.49 + postcss: 8.5.6 postcss-selector-parser: 6.1.2 postcss-value-parser: 4.2.0 - postcss-colormin@5.3.1(postcss@8.4.49): + postcss-colormin@5.3.1(postcss@8.5.6): dependencies: browserslist: 4.24.3 caniuse-api: 3.0.0 colord: 2.9.3 - postcss: 8.4.49 + postcss: 8.5.6 postcss-value-parser: 4.2.0 - postcss-convert-values@5.1.3(postcss@8.4.49): + postcss-convert-values@5.1.3(postcss@8.5.6): dependencies: browserslist: 4.24.3 - postcss: 8.4.49 + postcss: 8.5.6 postcss-value-parser: 4.2.0 - postcss-discard-comments@5.1.2(postcss@8.4.49): + postcss-discard-comments@5.1.2(postcss@8.5.6): dependencies: - postcss: 8.4.49 + postcss: 8.5.6 - postcss-discard-duplicates@5.1.0(postcss@8.4.49): + postcss-discard-duplicates@5.1.0(postcss@8.5.6): dependencies: - postcss: 8.4.49 + postcss: 8.5.6 - postcss-discard-empty@5.1.1(postcss@8.4.49): + postcss-discard-empty@5.1.1(postcss@8.5.6): dependencies: - postcss: 8.4.49 + postcss: 8.5.6 - postcss-discard-overridden@5.1.0(postcss@8.4.49): + postcss-discard-overridden@5.1.0(postcss@8.5.6): dependencies: - postcss: 8.4.49 + postcss: 8.5.6 - postcss-load-config@3.1.4(postcss@8.4.49): + postcss-load-config@3.1.4(postcss@8.5.6): dependencies: lilconfig: 2.1.0 yaml: 1.10.2 optionalDependencies: - postcss: 8.4.49 + postcss: 8.5.6 - postcss-merge-longhand@5.1.7(postcss@8.4.49): + postcss-merge-longhand@5.1.7(postcss@8.5.6): dependencies: - postcss: 8.4.49 + postcss: 8.5.6 postcss-value-parser: 4.2.0 - stylehacks: 5.1.1(postcss@8.4.49) + stylehacks: 5.1.1(postcss@8.5.6) - postcss-merge-rules@5.1.4(postcss@8.4.49): + postcss-merge-rules@5.1.4(postcss@8.5.6): dependencies: browserslist: 4.24.3 caniuse-api: 3.0.0 - cssnano-utils: 3.1.0(postcss@8.4.49) - postcss: 8.4.49 + cssnano-utils: 3.1.0(postcss@8.5.6) + postcss: 8.5.6 postcss-selector-parser: 6.1.2 - postcss-minify-font-values@5.1.0(postcss@8.4.49): + postcss-minify-font-values@5.1.0(postcss@8.5.6): dependencies: - postcss: 8.4.49 + postcss: 8.5.6 postcss-value-parser: 4.2.0 - postcss-minify-gradients@5.1.1(postcss@8.4.49): + postcss-minify-gradients@5.1.1(postcss@8.5.6): dependencies: colord: 2.9.3 - cssnano-utils: 3.1.0(postcss@8.4.49) - postcss: 8.4.49 + cssnano-utils: 3.1.0(postcss@8.5.6) + postcss: 8.5.6 postcss-value-parser: 4.2.0 - postcss-minify-params@5.1.4(postcss@8.4.49): + postcss-minify-params@5.1.4(postcss@8.5.6): dependencies: browserslist: 4.24.3 - cssnano-utils: 3.1.0(postcss@8.4.49) - postcss: 8.4.49 + cssnano-utils: 3.1.0(postcss@8.5.6) + postcss: 8.5.6 postcss-value-parser: 4.2.0 - postcss-minify-selectors@5.2.1(postcss@8.4.49): + postcss-minify-selectors@5.2.1(postcss@8.5.6): dependencies: - postcss: 8.4.49 + postcss: 8.5.6 postcss-selector-parser: 6.1.2 - postcss-modules-extract-imports@3.1.0(postcss@8.4.49): + postcss-modules-extract-imports@3.1.0(postcss@8.5.6): dependencies: - postcss: 8.4.49 + postcss: 8.5.6 - postcss-modules-local-by-default@4.2.0(postcss@8.4.49): + postcss-modules-local-by-default@4.2.0(postcss@8.5.6): dependencies: - icss-utils: 5.1.0(postcss@8.4.49) - postcss: 8.4.49 + icss-utils: 5.1.0(postcss@8.5.6) + postcss: 8.5.6 postcss-selector-parser: 7.0.0 postcss-value-parser: 4.2.0 - postcss-modules-scope@3.2.1(postcss@8.4.49): + postcss-modules-scope@3.2.1(postcss@8.5.6): dependencies: - postcss: 8.4.49 + postcss: 8.5.6 postcss-selector-parser: 7.0.0 - postcss-modules-values@4.0.0(postcss@8.4.49): + postcss-modules-values@4.0.0(postcss@8.5.6): dependencies: - icss-utils: 5.1.0(postcss@8.4.49) - postcss: 8.4.49 + icss-utils: 5.1.0(postcss@8.5.6) + postcss: 8.5.6 - postcss-modules@4.3.1(postcss@8.4.49): + postcss-modules@4.3.1(postcss@8.5.6): dependencies: generic-names: 4.0.0 icss-replace-symbols: 1.1.0 lodash.camelcase: 4.3.0 - postcss: 8.4.49 - postcss-modules-extract-imports: 3.1.0(postcss@8.4.49) - postcss-modules-local-by-default: 4.2.0(postcss@8.4.49) - postcss-modules-scope: 3.2.1(postcss@8.4.49) - postcss-modules-values: 4.0.0(postcss@8.4.49) + postcss: 8.5.6 + postcss-modules-extract-imports: 3.1.0(postcss@8.5.6) + postcss-modules-local-by-default: 4.2.0(postcss@8.5.6) + postcss-modules-scope: 3.2.1(postcss@8.5.6) + postcss-modules-values: 4.0.0(postcss@8.5.6) string-hash: 1.1.3 - postcss-normalize-charset@5.1.0(postcss@8.4.49): + postcss-normalize-charset@5.1.0(postcss@8.5.6): dependencies: - postcss: 8.4.49 + postcss: 8.5.6 - postcss-normalize-display-values@5.1.0(postcss@8.4.49): + postcss-normalize-display-values@5.1.0(postcss@8.5.6): dependencies: - postcss: 8.4.49 + postcss: 8.5.6 postcss-value-parser: 4.2.0 - postcss-normalize-positions@5.1.1(postcss@8.4.49): + postcss-normalize-positions@5.1.1(postcss@8.5.6): dependencies: - postcss: 8.4.49 + postcss: 8.5.6 postcss-value-parser: 4.2.0 - postcss-normalize-repeat-style@5.1.1(postcss@8.4.49): + postcss-normalize-repeat-style@5.1.1(postcss@8.5.6): dependencies: - postcss: 8.4.49 + postcss: 8.5.6 postcss-value-parser: 4.2.0 - postcss-normalize-string@5.1.0(postcss@8.4.49): + postcss-normalize-string@5.1.0(postcss@8.5.6): dependencies: - postcss: 8.4.49 + postcss: 8.5.6 postcss-value-parser: 4.2.0 - postcss-normalize-timing-functions@5.1.0(postcss@8.4.49): + postcss-normalize-timing-functions@5.1.0(postcss@8.5.6): dependencies: - postcss: 8.4.49 + postcss: 8.5.6 postcss-value-parser: 4.2.0 - postcss-normalize-unicode@5.1.1(postcss@8.4.49): + postcss-normalize-unicode@5.1.1(postcss@8.5.6): dependencies: browserslist: 4.24.3 - postcss: 8.4.49 + postcss: 8.5.6 postcss-value-parser: 4.2.0 - postcss-normalize-url@5.1.0(postcss@8.4.49): + postcss-normalize-url@5.1.0(postcss@8.5.6): dependencies: normalize-url: 6.1.0 - postcss: 8.4.49 + postcss: 8.5.6 postcss-value-parser: 4.2.0 - postcss-normalize-whitespace@5.1.1(postcss@8.4.49): + postcss-normalize-whitespace@5.1.1(postcss@8.5.6): dependencies: - postcss: 8.4.49 + postcss: 8.5.6 postcss-value-parser: 4.2.0 - postcss-ordered-values@5.1.3(postcss@8.4.49): + postcss-ordered-values@5.1.3(postcss@8.5.6): dependencies: - cssnano-utils: 3.1.0(postcss@8.4.49) - postcss: 8.4.49 + cssnano-utils: 3.1.0(postcss@8.5.6) + postcss: 8.5.6 postcss-value-parser: 4.2.0 - postcss-reduce-initial@5.1.2(postcss@8.4.49): + postcss-reduce-initial@5.1.2(postcss@8.5.6): dependencies: browserslist: 4.24.3 caniuse-api: 3.0.0 - postcss: 8.4.49 + postcss: 8.5.6 - postcss-reduce-transforms@5.1.0(postcss@8.4.49): + postcss-reduce-transforms@5.1.0(postcss@8.5.6): dependencies: - postcss: 8.4.49 + postcss: 8.5.6 postcss-value-parser: 4.2.0 postcss-selector-parser@6.1.2: @@ -9122,25 +8730,19 @@ snapshots: cssesc: 3.0.0 util-deprecate: 1.0.2 - postcss-svgo@5.1.0(postcss@8.4.49): + postcss-svgo@5.1.0(postcss@8.5.6): dependencies: - postcss: 8.4.49 + postcss: 8.5.6 postcss-value-parser: 4.2.0 svgo: 2.8.0 - postcss-unique-selectors@5.1.1(postcss@8.4.49): + postcss-unique-selectors@5.1.1(postcss@8.5.6): dependencies: - postcss: 8.4.49 + postcss: 8.5.6 postcss-selector-parser: 6.1.2 postcss-value-parser@4.2.0: {} - postcss@8.4.49: - dependencies: - nanoid: 3.3.8 - picocolors: 1.1.1 - source-map-js: 1.2.1 - postcss@8.5.6: dependencies: nanoid: 3.3.11 @@ -9155,11 +8757,6 @@ snapshots: prettier@3.4.2: {} - pretty-error@4.0.0: - dependencies: - lodash: 4.17.21 - renderkid: 3.0.0 - pretty-format@27.5.1: dependencies: ansi-regex: 5.0.1 @@ -9176,6 +8773,9 @@ snapshots: object-assign: 4.1.1 react-is: 16.13.1 + prr@1.0.1: + optional: true + psl@1.15.0: dependencies: punycode: 2.3.1 @@ -9183,14 +8783,8 @@ snapshots: punycode.js@2.3.1: {} - punycode@1.4.1: {} - punycode@2.3.1: {} - qs@6.13.1: - dependencies: - side-channel: 1.1.0 - querystringify@2.2.0: optional: true @@ -9200,8 +8794,6 @@ snapshots: dependencies: safe-buffer: 5.2.1 - range-parser@1.2.1: {} - react-confetti@6.2.2(react@18.3.1): dependencies: react: 18.3.1 @@ -9226,6 +8818,21 @@ snapshots: transitivePeerDependencies: - supports-color + react-docgen@8.0.2: + dependencies: + '@babel/core': 7.28.5 + '@babel/traverse': 7.28.5 + '@babel/types': 7.28.5 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.28.0 + '@types/doctrine': 0.0.9 + '@types/resolve': 1.20.6 + doctrine: 3.0.0 + resolve: 1.22.10 + strip-indent: 4.0.0 + transitivePeerDependencies: + - supports-color + react-dom@18.3.1(react@18.3.1): dependencies: loose-envify: 1.4.0 @@ -9270,10 +8877,6 @@ snapshots: dependencies: loose-envify: 1.4.0 - readdirp@3.6.0: - dependencies: - picomatch: 2.3.1 - recast@0.23.9: dependencies: ast-types: 0.16.1 @@ -9334,16 +8937,6 @@ snapshots: dependencies: jsesc: 3.0.2 - relateurl@0.2.7: {} - - renderkid@3.0.0: - dependencies: - css-select: 4.3.0 - dom-converter: 0.2.0 - htmlparser2: 6.1.0 - lodash: 4.17.21 - strip-ansi: 6.0.1 - require-from-string@2.0.2: {} requires-port@1.0.0: @@ -9367,10 +8960,6 @@ snapshots: reusify@1.0.4: {} - rimraf@3.0.2: - dependencies: - glob: 7.2.3 - rollup-plugin-dts@6.1.1(rollup@4.30.0)(typescript@5.7.2): dependencies: magic-string: 0.30.17 @@ -9383,17 +8972,17 @@ snapshots: dependencies: rollup: 4.30.0 - rollup-plugin-postcss@4.0.2(postcss@8.4.49): + rollup-plugin-postcss@4.0.2(postcss@8.5.6): dependencies: chalk: 4.1.2 concat-with-sourcemaps: 1.1.0 - cssnano: 5.1.15(postcss@8.4.49) + cssnano: 5.1.15(postcss@8.5.6) import-cwd: 3.0.0 p-queue: 6.6.2 pify: 5.0.0 - postcss: 8.4.49 - postcss-load-config: 3.1.4(postcss@8.4.49) - postcss-modules: 4.3.1(postcss@8.4.49) + postcss: 8.5.6 + postcss-load-config: 3.1.4(postcss@8.5.6) + postcss-modules: 4.3.1(postcss@8.5.6) promise.series: 0.2.0 resolve: 1.22.10 rollup-pluginutils: 2.8.2 @@ -9489,6 +9078,9 @@ snapshots: safer-buffer@2.1.2: optional: true + sax@1.4.3: + optional: true + saxes@6.0.0: dependencies: xmlchars: 2.2.0 @@ -9511,6 +9103,9 @@ snapshots: ajv-formats: 2.1.1(ajv@8.17.1) ajv-keywords: 5.1.0(ajv@8.17.1) + semver@5.7.2: + optional: true + semver@6.3.1: {} semver@7.6.3: {} @@ -9579,6 +9174,8 @@ snapshots: siginfo@2.0.0: {} + signal-exit@4.1.0: {} + slash@3.0.0: {} smob@1.5.0: {} @@ -9600,14 +9197,14 @@ snapshots: std-env@3.10.0: {} - storybook-dark-mode@4.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.4.7(prettier@3.4.2)): + storybook-dark-mode@4.0.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(storybook@8.6.14(prettier@3.4.2)): dependencies: - '@storybook/components': 8.4.7(storybook@8.4.7(prettier@3.4.2)) - '@storybook/core-events': 8.4.7(storybook@8.4.7(prettier@3.4.2)) + '@storybook/components': 8.4.7(storybook@8.6.14(prettier@3.4.2)) + '@storybook/core-events': 8.4.7(storybook@8.6.14(prettier@3.4.2)) '@storybook/global': 5.0.0 '@storybook/icons': 1.3.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@storybook/manager-api': 8.4.7(storybook@8.4.7(prettier@3.4.2)) - '@storybook/theming': 8.4.7(storybook@8.4.7(prettier@3.4.2)) + '@storybook/manager-api': 8.4.7(storybook@8.6.14(prettier@3.4.2)) + '@storybook/theming': 8.4.7(storybook@8.6.14(prettier@3.4.2)) fast-deep-equal: 3.1.3 memoizerific: 1.11.3 transitivePeerDependencies: @@ -9615,9 +9212,9 @@ snapshots: - react-dom - storybook - storybook@8.4.7(prettier@3.4.2): + storybook@8.6.14(prettier@3.4.2): dependencies: - '@storybook/core': 8.4.7(prettier@3.4.2) + '@storybook/core': 8.6.14(prettier@3.4.2)(storybook@8.6.14(prettier@3.4.2)) optionalDependencies: prettier: 3.4.2 transitivePeerDependencies: @@ -9627,6 +9224,18 @@ snapshots: string-hash@1.1.3: {} + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + string.prototype.matchall@4.0.12: dependencies: call-bind: 1.0.8 @@ -9701,14 +9310,10 @@ snapshots: style-inject@0.3.0: {} - style-loader@3.3.4(webpack@5.97.1(@swc/core@1.10.4)(esbuild@0.24.2)): - dependencies: - webpack: 5.97.1(@swc/core@1.10.4)(esbuild@0.24.2) - - stylehacks@5.1.1(postcss@8.4.49): + stylehacks@5.1.1(postcss@8.5.6): dependencies: browserslist: 4.24.3 - postcss: 8.4.49 + postcss: 8.5.6 postcss-selector-parser: 6.1.2 stylis@4.2.0: {} @@ -9733,12 +9338,6 @@ snapshots: picocolors: 1.1.1 stable: 0.1.8 - swc-loader@0.2.6(@swc/core@1.10.4)(webpack@5.97.1(@swc/core@1.10.4)(esbuild@0.24.2)): - dependencies: - '@swc/core': 1.10.4 - '@swc/counter': 0.1.3 - webpack: 5.97.1(@swc/core@1.10.4)(esbuild@0.24.2) - symbol-tree@3.2.4: optional: true @@ -9749,17 +9348,16 @@ snapshots: tapable@2.2.1: {} - terser-webpack-plugin@5.3.11(@swc/core@1.10.4)(esbuild@0.24.2)(webpack@5.97.1(@swc/core@1.10.4)(esbuild@0.24.2)): + terser-webpack-plugin@5.3.11(esbuild@0.25.11)(webpack@5.97.1(esbuild@0.25.11)): dependencies: - '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 schema-utils: 4.3.0 serialize-javascript: 6.0.2 terser: 5.37.0 - webpack: 5.97.1(@swc/core@1.10.4)(esbuild@0.24.2) + webpack: 5.97.1(esbuild@0.25.11) optionalDependencies: - '@swc/core': 1.10.4 - esbuild: 0.24.2 + esbuild: 0.25.11 terser@5.37.0: dependencies: @@ -9876,12 +9474,12 @@ snapshots: typescript: 5.7.2 yaml: 2.8.0 - typescript-eslint@8.19.0(eslint@9.17.0)(typescript@5.7.2): + typescript-eslint@8.19.0(eslint@9.17.0(jiti@1.21.7))(typescript@5.7.2): dependencies: - '@typescript-eslint/eslint-plugin': 8.19.0(@typescript-eslint/parser@8.19.0(eslint@9.17.0)(typescript@5.7.2))(eslint@9.17.0)(typescript@5.7.2) - '@typescript-eslint/parser': 8.19.0(eslint@9.17.0)(typescript@5.7.2) - '@typescript-eslint/utils': 8.19.0(eslint@9.17.0)(typescript@5.7.2) - eslint: 9.17.0 + '@typescript-eslint/eslint-plugin': 8.19.0(@typescript-eslint/parser@8.19.0(eslint@9.17.0(jiti@1.21.7))(typescript@5.7.2))(eslint@9.17.0(jiti@1.21.7))(typescript@5.7.2) + '@typescript-eslint/parser': 8.19.0(eslint@9.17.0(jiti@1.21.7))(typescript@5.7.2) + '@typescript-eslint/utils': 8.19.0(eslint@9.17.0(jiti@1.21.7))(typescript@5.7.2) + eslint: 9.17.0(jiti@1.21.7) typescript: 5.7.2 transitivePeerDependencies: - supports-color @@ -9936,11 +9534,6 @@ snapshots: requires-port: 1.0.0 optional: true - url@0.11.4: - dependencies: - punycode: 1.4.1 - qs: 6.13.1 - utif@3.1.0: dependencies: pako: 1.0.11 @@ -9955,17 +9548,15 @@ snapshots: is-typed-array: 1.1.15 which-typed-array: 1.1.18 - utila@0.4.0: {} - uuid@9.0.1: {} - vite-node@3.2.4(@types/node@20.19.21)(terser@5.37.0)(yaml@2.8.0): + vite-node@3.2.4(@types/node@20.19.21)(jiti@1.21.7)(less@4.5.1)(terser@5.37.0)(yaml@2.8.0): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 7.1.10(@types/node@20.19.21)(terser@5.37.0)(yaml@2.8.0) + vite: 7.1.10(@types/node@20.19.21)(jiti@1.21.7)(less@4.5.1)(terser@5.37.0)(yaml@2.8.0) transitivePeerDependencies: - '@types/node' - jiti @@ -9980,7 +9571,7 @@ snapshots: - tsx - yaml - vite@7.1.10(@types/node@20.19.21)(terser@5.37.0)(yaml@2.8.0): + vite@7.1.10(@types/node@20.19.21)(jiti@1.21.7)(less@4.5.1)(terser@5.37.0)(yaml@2.8.0): dependencies: esbuild: 0.25.11 fdir: 6.5.0(picomatch@4.0.3) @@ -9991,14 +9582,16 @@ snapshots: optionalDependencies: '@types/node': 20.19.21 fsevents: 2.3.3 + jiti: 1.21.7 + less: 4.5.1 terser: 5.37.0 yaml: 2.8.0 - vitest@3.2.4(@types/node@20.19.21)(jsdom@20.0.3)(terser@5.37.0)(yaml@2.8.0): + vitest@3.2.4(@types/node@20.19.21)(jiti@1.21.7)(jsdom@20.0.3)(less@4.5.1)(terser@5.37.0)(yaml@2.8.0): dependencies: '@types/chai': 5.2.2 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@7.1.10(@types/node@20.19.21)(terser@5.37.0)(yaml@2.8.0)) + '@vitest/mocker': 3.2.4(vite@7.1.10(@types/node@20.19.21)(jiti@1.21.7)(less@4.5.1)(terser@5.37.0)(yaml@2.8.0)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -10016,8 +9609,8 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 7.1.10(@types/node@20.19.21)(terser@5.37.0)(yaml@2.8.0) - vite-node: 3.2.4(@types/node@20.19.21)(terser@5.37.0)(yaml@2.8.0) + vite: 7.1.10(@types/node@20.19.21)(jiti@1.21.7)(less@4.5.1)(terser@5.37.0)(yaml@2.8.0) + vite-node: 3.2.4(@types/node@20.19.21)(jiti@1.21.7)(less@4.5.1)(terser@5.37.0)(yaml@2.8.0) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 20.19.21 @@ -10049,38 +9642,22 @@ snapshots: webidl-conversions@7.0.0: optional: true - webpack-dev-middleware@6.1.3(webpack@5.97.1(@swc/core@1.10.4)(esbuild@0.24.2)): - dependencies: - colorette: 2.0.20 - memfs: 3.5.3 - mime-types: 2.1.35 - range-parser: 1.2.1 - schema-utils: 4.3.0 - optionalDependencies: - webpack: 5.97.1(@swc/core@1.10.4)(esbuild@0.24.2) - - webpack-hot-middleware@2.26.1: - dependencies: - ansi-html-community: 0.0.8 - html-entities: 2.5.2 - strip-ansi: 6.0.1 - webpack-sources@3.2.3: {} webpack-virtual-modules@0.6.2: {} - webpack@5.97.1(@swc/core@1.10.4)(esbuild@0.24.2): + webpack@5.97.1(esbuild@0.25.11): dependencies: '@types/eslint-scope': 3.7.7 - '@types/estree': 1.0.6 + '@types/estree': 1.0.8 '@webassemblyjs/ast': 1.14.1 '@webassemblyjs/wasm-edit': 1.14.1 '@webassemblyjs/wasm-parser': 1.14.1 - acorn: 8.14.0 + acorn: 8.15.0 browserslist: 4.24.3 chrome-trace-event: 1.0.4 enhanced-resolve: 5.18.0 - es-module-lexer: 1.6.0 + es-module-lexer: 1.7.0 eslint-scope: 5.1.1 events: 3.3.0 glob-to-regexp: 0.4.1 @@ -10091,7 +9668,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.11(@swc/core@1.10.4)(esbuild@0.24.2)(webpack@5.97.1(@swc/core@1.10.4)(esbuild@0.24.2)) + terser-webpack-plugin: 5.3.11(esbuild@0.25.11)(webpack@5.97.1(esbuild@0.25.11)) watchpack: 2.4.2 webpack-sources: 3.2.3 transitivePeerDependencies: @@ -10164,12 +9741,19 @@ snapshots: word-wrap@1.2.5: {} - wrappy@1.0.2: {} + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 - ws@8.18.0: {} + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.3 + string-width: 5.1.2 + strip-ansi: 7.1.0 - ws@8.18.3: - optional: true + ws@8.18.3: {} xml-name-validator@4.0.0: optional: true diff --git a/src/components/MUI/Inputs/Button.stories.tsx b/src/components/MUI/Inputs/Button.stories.tsx new file mode 100644 index 0000000..6a9420b --- /dev/null +++ b/src/components/MUI/Inputs/Button.stories.tsx @@ -0,0 +1,237 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Button } from "./Button"; + +import SaveIcon from "@mui/icons-material/Save"; +import SendIcon from "@mui/icons-material/Send"; +import DeleteIcon from "@mui/icons-material/Delete"; +import AddIcon from "@mui/icons-material/Add"; +import Stack from "@mui/material/Stack"; +import Box from "@mui/material/Box"; + +const iconMap = { + none: undefined, + save: , + send: , + delete: , + add: , +} as const; +type IconKey = keyof typeof iconMap; + +const applyIconArgs = (args: any) => { + const { startIconName, endIconName, ...rest } = args; + return { + ...rest, + startIcon: iconMap[startIconName as IconKey], + endIcon: iconMap[endIconName as IconKey], + }; +}; + +const meta: Meta = { + title: "MUI/Inputs/Button", + component: Button, + tags: ["autodocs"], + parameters: { + controls: { expanded: true }, + layout: "padded", + }, + argTypes: { + variant: { + control: { type: "select" }, + options: ["text", "contained", "outlined"], + }, + color: { + control: { type: "select" }, + options: [ + "inherit", + "primary", + "secondary", + "success", + "error", + "info", + "warning", + ], + }, + size: { + control: { type: "select" }, + options: ["small", "medium", "large"], + }, + disabled: { control: "boolean" }, + disableElevation: { control: "boolean" }, + disableFocusRipple: { control: "boolean" }, + disableRipple: { control: "boolean" }, + fullWidth: { control: "boolean" }, + startIconName: { + name: "startIcon", + control: { type: "select" }, + options: Object.keys(iconMap), + }, + endIconName: { + name: "endIcon", + control: { type: "select" }, + options: Object.keys(iconMap), + }, + + href: { control: "text" }, + target: { control: { type: "select" }, options: ["", "_self", "_blank"] }, + rel: { control: "text" }, + ariaLabel: { name: "aria-label", control: "text" }, + + component: { control: false }, + children: { name: "label", control: "text" }, + }, + args: { + children: "Button", + variant: "contained", + color: "primary", + size: "medium", + disableElevation: false, + disabled: false, + disableFocusRipple: false, + disableRipple: false, + fullWidth: false, + startIconName: "none" as IconKey, + endIconName: "none" as IconKey, + href: "", + target: "", + rel: "", + ariaLabel: "", + }, +}; + +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => ( + + ), +}; + +export const Variants: Story = { + render: (args) => ( + + + + + + ), + args: { color: "primary" }, +}; + +export const Sizes: Story = { + render: (args) => ( + + + + + + ), +}; + +export const Colors: Story = { + render: (args) => ( + + + + + + + + + ), + args: { variant: "contained" }, +}; + +export const WithIcons: Story = { + render: (args) => ( + + + + + + + + ), +}; + +export const States: Story = { + render: (args) => ( + + + + + + + + + + + + + ), +}; diff --git a/src/components/MUI/Inputs/Button.tsx b/src/components/MUI/Inputs/Button.tsx new file mode 100644 index 0000000..e280ac3 --- /dev/null +++ b/src/components/MUI/Inputs/Button.tsx @@ -0,0 +1,15 @@ +// src/components/Button/Button.tsx +import React from "react"; +import MuiButton, { ButtonProps as MuiButtonProps } from "@mui/material/Button"; + +export type ButtonProps = MuiButtonProps; + +export const Button = React.forwardRef( + ({ children, ...rest }, ref) => ( + + {children} + + ), +); + +Button; From 16048fee8952a04ce8b7270433715f1f1ab2226f Mon Sep 17 00:00:00 2001 From: VictoriaBeilstenEdmands Date: Wed, 17 Dec 2025 15:02:34 +0000 Subject: [PATCH 02/10] Add MUI stories --- .../MUI/DataDisplay/Avatar.stories.tsx | 75 +++++++ src/components/MUI/DataDisplay/Avatar.tsx | 14 ++ .../MUI/DataDisplay/Badge.stories.tsx | 77 +++++++ src/components/MUI/DataDisplay/Badge.tsx | 10 + .../MUI/DataDisplay/Chip.stories.tsx | 131 ++++++++++++ src/components/MUI/DataDisplay/Chip.tsx | 11 + .../MUI/DataDisplay/Divider.stories.tsx | 51 +++++ src/components/MUI/DataDisplay/Divider.tsx | 12 ++ .../MUI/DataDisplay/Icon.stories.tsx | 81 ++++++++ src/components/MUI/DataDisplay/Icon.tsx | 10 + .../MUI/DataDisplay/IconButton.stories.tsx | 86 ++++++++ src/components/MUI/DataDisplay/IconButton.tsx | 13 ++ .../MUI/DataDisplay/List.stories.tsx | 69 +++++++ src/components/MUI/DataDisplay/List.tsx | 11 + .../MUI/DataDisplay/MaterialIcons.stories.tsx | 74 +++++++ .../MUI/DataDisplay/MaterialIcons.tsx | 49 +++++ .../MUI/DataDisplay/Table.stories.tsx | 77 +++++++ src/components/MUI/DataDisplay/Table.tsx | 10 + .../MUI/DataDisplay/Typography.stories.tsx | 157 ++++++++++++++ src/components/MUI/DataDisplay/Typography.tsx | 12 ++ src/components/MUI/Feedback/Alert.stories.tsx | 65 ++++++ src/components/MUI/Feedback/Alert.tsx | 10 + .../MUI/Feedback/Backdrop.stories.tsx | 38 ++++ src/components/MUI/Feedback/Backdrop.tsx | 12 ++ .../MUI/Feedback/CircularProgress.stories.tsx | 46 +++++ .../MUI/Feedback/CircularProgress.tsx | 14 ++ .../MUI/Feedback/Dialog.stories.tsx | 69 +++++++ src/components/MUI/Feedback/Dialog.tsx | 10 + .../MUI/Feedback/LinearProgress.stories.tsx | 49 +++++ .../MUI/Feedback/LinearProgress.tsx | 13 ++ .../MUI/Feedback/Skeleton.stories.tsx | 23 +++ src/components/MUI/Feedback/Skeleton.tsx | 12 ++ .../MUI/Feedback/Snackbar.stories.tsx | 96 +++++++++ src/components/MUI/Feedback/Snackbar.tsx | 12 ++ .../MUI/Feedback/Tooltip.stories.tsx | 94 +++++++++ src/components/MUI/Feedback/Tooltip.tsx | 12 ++ .../MUI/Inputs/Autocomplete.stories.tsx | 189 +++++++++++++++++ src/components/MUI/Inputs/Autocomplete.tsx | 18 ++ src/components/MUI/Inputs/Button.stories.tsx | 2 +- src/components/MUI/Inputs/Button.tsx | 3 +- .../MUI/Inputs/ButtonGroup.stories.tsx | 60 ++++++ src/components/MUI/Inputs/ButtonGroup.tsx | 10 + .../MUI/Inputs/Checkbox.stories.tsx | 70 +++++++ src/components/MUI/Inputs/Checkbox.tsx | 10 + src/components/MUI/Inputs/Fab.stories.tsx | 87 ++++++++ src/components/MUI/Inputs/Fab.tsx | 10 + src/components/MUI/Inputs/Radio.stories.tsx | 70 +++++++ src/components/MUI/Inputs/Radio.tsx | 8 + .../MUI/Inputs/RadioGroup.stories.tsx | 39 ++++ src/components/MUI/Inputs/RadioGroup.tsx | 12 ++ src/components/MUI/Inputs/Rating.stories.tsx | 47 +++++ src/components/MUI/Inputs/Rating.tsx | 10 + src/components/MUI/Inputs/Select.stories.tsx | 83 ++++++++ src/components/MUI/Inputs/Select.tsx | 10 + src/components/MUI/Inputs/Slider.stories.tsx | 78 +++++++ src/components/MUI/Inputs/Slider.tsx | 10 + .../MUI/Inputs/SpeedDial.stories.tsx | 43 ++++ src/components/MUI/Inputs/SpeedDial.tsx | 12 ++ src/components/MUI/Inputs/Switch.stories.tsx | 68 ++++++ src/components/MUI/Inputs/Switch.tsx | 10 + .../MUI/Inputs/TextField.stories.tsx | 195 ++++++++++++++++++ src/components/MUI/Inputs/TextField.tsx | 12 ++ .../MUI/Inputs/ToggleButtonGroup.stories.tsx | 78 +++++++ .../MUI/Inputs/ToggleButtonGroup.tsx | 13 ++ .../MUI/Inputs/TransferList.stories.tsx | 48 +++++ src/components/MUI/Inputs/TransferList.tsx | 105 ++++++++++ src/components/MUI/Layout/Box.stories.tsx | 70 +++++++ src/components/MUI/Layout/Box.tsx | 10 + .../MUI/Layout/Container.stories.tsx | 55 +++++ src/components/MUI/Layout/Container.tsx | 12 ++ src/components/MUI/Layout/Grid2.stories.tsx | 64 ++++++ src/components/MUI/Layout/Grid2.tsx | 10 + .../MUI/Layout/ImageList.stories.tsx | 82 ++++++++ src/components/MUI/Layout/ImageList.tsx | 12 ++ src/components/MUI/Layout/Stack.stories.tsx | 77 +++++++ src/components/MUI/Layout/Stack.tsx | 10 + .../MUI/Navigation/AppBar.stories.tsx | 58 ++++++ src/components/MUI/Navigation/AppBar.tsx | 10 + .../Navigation/BottomNavigation.stories.tsx | 39 ++++ .../MUI/Navigation/BottomNavigation.tsx | 13 ++ .../MUI/Navigation/Breadcrumbs.stories.tsx | 95 +++++++++ src/components/MUI/Navigation/Breadcrumbs.tsx | 12 ++ .../MUI/Navigation/Drawer.stories.tsx | 54 +++++ src/components/MUI/Navigation/Drawer.tsx | 10 + .../MUI/Navigation/Link.stories.tsx | 40 ++++ src/components/MUI/Navigation/Link.tsx | 10 + .../MUI/Navigation/Menu.stories.tsx | 99 +++++++++ src/components/MUI/Navigation/Menu.tsx | 10 + .../MUI/Navigation/Pagination.stories.tsx | 41 ++++ src/components/MUI/Navigation/Pagination.tsx | 12 ++ .../MUI/Navigation/Stepper.stories.tsx | 104 ++++++++++ src/components/MUI/Navigation/Stepper.tsx | 12 ++ .../MUI/Navigation/Tabs.stories.tsx | 64 ++++++ src/components/MUI/Navigation/Tabs.tsx | 10 + .../MUI/Surfaces/Accordion.stories.tsx | 78 +++++++ src/components/MUI/Surfaces/Accordion.tsx | 12 ++ src/components/MUI/Surfaces/Card.stories.tsx | 66 ++++++ src/components/MUI/Surfaces/Card.tsx | 10 + src/components/MUI/Surfaces/Paper.stories.tsx | 44 ++++ src/components/MUI/Surfaces/Paper.tsx | 10 + .../MUI/Utils/ClickAwayListener.stories.tsx | 81 ++++++++ .../MUI/Utils/ClickAwayListener.tsx | 12 ++ .../MUI/Utils/CssBaseline.stories.tsx | 38 ++++ src/components/MUI/Utils/CssBaseline.tsx | 0 src/components/MUI/Utils/Modal.stories.tsx | 76 +++++++ src/components/MUI/Utils/Modal.tsx | 8 + src/components/MUI/Utils/NoSsr.stories.tsx | 53 +++++ src/components/MUI/Utils/NoSsr.tsx | 8 + src/components/MUI/Utils/Popover.stories.tsx | 58 ++++++ src/components/MUI/Utils/Popover.tsx | 12 ++ src/components/MUI/Utils/Popper.stories.tsx | 85 ++++++++ src/components/MUI/Utils/Popper.tsx | 8 + src/components/MUI/Utils/Portal.stories.tsx | 52 +++++ src/components/MUI/Utils/Portal.tsx | 8 + .../MUI/Utils/TextareaAutosize.stories.tsx | 30 +++ src/components/MUI/Utils/TextareaAutosize.tsx | 10 + .../MUI/Utils/Transitions.stories.tsx | 81 ++++++++ src/components/MUI/Utils/Transitions.tsx | 24 +++ .../MUI/Utils/UseMediaQuery.stories.tsx | 44 ++++ src/components/MUI/Utils/UseMediaQuery.tsx | 9 + 120 files changed, 5024 insertions(+), 3 deletions(-) create mode 100644 src/components/MUI/DataDisplay/Avatar.stories.tsx create mode 100644 src/components/MUI/DataDisplay/Avatar.tsx create mode 100644 src/components/MUI/DataDisplay/Badge.stories.tsx create mode 100644 src/components/MUI/DataDisplay/Badge.tsx create mode 100644 src/components/MUI/DataDisplay/Chip.stories.tsx create mode 100644 src/components/MUI/DataDisplay/Chip.tsx create mode 100644 src/components/MUI/DataDisplay/Divider.stories.tsx create mode 100644 src/components/MUI/DataDisplay/Divider.tsx create mode 100644 src/components/MUI/DataDisplay/Icon.stories.tsx create mode 100644 src/components/MUI/DataDisplay/Icon.tsx create mode 100644 src/components/MUI/DataDisplay/IconButton.stories.tsx create mode 100644 src/components/MUI/DataDisplay/IconButton.tsx create mode 100644 src/components/MUI/DataDisplay/List.stories.tsx create mode 100644 src/components/MUI/DataDisplay/List.tsx create mode 100644 src/components/MUI/DataDisplay/MaterialIcons.stories.tsx create mode 100644 src/components/MUI/DataDisplay/MaterialIcons.tsx create mode 100644 src/components/MUI/DataDisplay/Table.stories.tsx create mode 100644 src/components/MUI/DataDisplay/Table.tsx create mode 100644 src/components/MUI/DataDisplay/Typography.stories.tsx create mode 100644 src/components/MUI/DataDisplay/Typography.tsx create mode 100644 src/components/MUI/Feedback/Alert.stories.tsx create mode 100644 src/components/MUI/Feedback/Alert.tsx create mode 100644 src/components/MUI/Feedback/Backdrop.stories.tsx create mode 100644 src/components/MUI/Feedback/Backdrop.tsx create mode 100644 src/components/MUI/Feedback/CircularProgress.stories.tsx create mode 100644 src/components/MUI/Feedback/CircularProgress.tsx create mode 100644 src/components/MUI/Feedback/Dialog.stories.tsx create mode 100644 src/components/MUI/Feedback/Dialog.tsx create mode 100644 src/components/MUI/Feedback/LinearProgress.stories.tsx create mode 100644 src/components/MUI/Feedback/LinearProgress.tsx create mode 100644 src/components/MUI/Feedback/Skeleton.stories.tsx create mode 100644 src/components/MUI/Feedback/Skeleton.tsx create mode 100644 src/components/MUI/Feedback/Snackbar.stories.tsx create mode 100644 src/components/MUI/Feedback/Snackbar.tsx create mode 100644 src/components/MUI/Feedback/Tooltip.stories.tsx create mode 100644 src/components/MUI/Feedback/Tooltip.tsx create mode 100644 src/components/MUI/Inputs/Autocomplete.stories.tsx create mode 100644 src/components/MUI/Inputs/Autocomplete.tsx create mode 100644 src/components/MUI/Inputs/ButtonGroup.stories.tsx create mode 100644 src/components/MUI/Inputs/ButtonGroup.tsx create mode 100644 src/components/MUI/Inputs/Checkbox.stories.tsx create mode 100644 src/components/MUI/Inputs/Checkbox.tsx create mode 100644 src/components/MUI/Inputs/Fab.stories.tsx create mode 100644 src/components/MUI/Inputs/Fab.tsx create mode 100644 src/components/MUI/Inputs/Radio.stories.tsx create mode 100644 src/components/MUI/Inputs/Radio.tsx create mode 100644 src/components/MUI/Inputs/RadioGroup.stories.tsx create mode 100644 src/components/MUI/Inputs/RadioGroup.tsx create mode 100644 src/components/MUI/Inputs/Rating.stories.tsx create mode 100644 src/components/MUI/Inputs/Rating.tsx create mode 100644 src/components/MUI/Inputs/Select.stories.tsx create mode 100644 src/components/MUI/Inputs/Select.tsx create mode 100644 src/components/MUI/Inputs/Slider.stories.tsx create mode 100644 src/components/MUI/Inputs/Slider.tsx create mode 100644 src/components/MUI/Inputs/SpeedDial.stories.tsx create mode 100644 src/components/MUI/Inputs/SpeedDial.tsx create mode 100644 src/components/MUI/Inputs/Switch.stories.tsx create mode 100644 src/components/MUI/Inputs/Switch.tsx create mode 100644 src/components/MUI/Inputs/TextField.stories.tsx create mode 100644 src/components/MUI/Inputs/TextField.tsx create mode 100644 src/components/MUI/Inputs/ToggleButtonGroup.stories.tsx create mode 100644 src/components/MUI/Inputs/ToggleButtonGroup.tsx create mode 100644 src/components/MUI/Inputs/TransferList.stories.tsx create mode 100644 src/components/MUI/Inputs/TransferList.tsx create mode 100644 src/components/MUI/Layout/Box.stories.tsx create mode 100644 src/components/MUI/Layout/Box.tsx create mode 100644 src/components/MUI/Layout/Container.stories.tsx create mode 100644 src/components/MUI/Layout/Container.tsx create mode 100644 src/components/MUI/Layout/Grid2.stories.tsx create mode 100644 src/components/MUI/Layout/Grid2.tsx create mode 100644 src/components/MUI/Layout/ImageList.stories.tsx create mode 100644 src/components/MUI/Layout/ImageList.tsx create mode 100644 src/components/MUI/Layout/Stack.stories.tsx create mode 100644 src/components/MUI/Layout/Stack.tsx create mode 100644 src/components/MUI/Navigation/AppBar.stories.tsx create mode 100644 src/components/MUI/Navigation/AppBar.tsx create mode 100644 src/components/MUI/Navigation/BottomNavigation.stories.tsx create mode 100644 src/components/MUI/Navigation/BottomNavigation.tsx create mode 100644 src/components/MUI/Navigation/Breadcrumbs.stories.tsx create mode 100644 src/components/MUI/Navigation/Breadcrumbs.tsx create mode 100644 src/components/MUI/Navigation/Drawer.stories.tsx create mode 100644 src/components/MUI/Navigation/Drawer.tsx create mode 100644 src/components/MUI/Navigation/Link.stories.tsx create mode 100644 src/components/MUI/Navigation/Link.tsx create mode 100644 src/components/MUI/Navigation/Menu.stories.tsx create mode 100644 src/components/MUI/Navigation/Menu.tsx create mode 100644 src/components/MUI/Navigation/Pagination.stories.tsx create mode 100644 src/components/MUI/Navigation/Pagination.tsx create mode 100644 src/components/MUI/Navigation/Stepper.stories.tsx create mode 100644 src/components/MUI/Navigation/Stepper.tsx create mode 100644 src/components/MUI/Navigation/Tabs.stories.tsx create mode 100644 src/components/MUI/Navigation/Tabs.tsx create mode 100644 src/components/MUI/Surfaces/Accordion.stories.tsx create mode 100644 src/components/MUI/Surfaces/Accordion.tsx create mode 100644 src/components/MUI/Surfaces/Card.stories.tsx create mode 100644 src/components/MUI/Surfaces/Card.tsx create mode 100644 src/components/MUI/Surfaces/Paper.stories.tsx create mode 100644 src/components/MUI/Surfaces/Paper.tsx create mode 100644 src/components/MUI/Utils/ClickAwayListener.stories.tsx create mode 100644 src/components/MUI/Utils/ClickAwayListener.tsx create mode 100644 src/components/MUI/Utils/CssBaseline.stories.tsx create mode 100644 src/components/MUI/Utils/CssBaseline.tsx create mode 100644 src/components/MUI/Utils/Modal.stories.tsx create mode 100644 src/components/MUI/Utils/Modal.tsx create mode 100644 src/components/MUI/Utils/NoSsr.stories.tsx create mode 100644 src/components/MUI/Utils/NoSsr.tsx create mode 100644 src/components/MUI/Utils/Popover.stories.tsx create mode 100644 src/components/MUI/Utils/Popover.tsx create mode 100644 src/components/MUI/Utils/Popper.stories.tsx create mode 100644 src/components/MUI/Utils/Popper.tsx create mode 100644 src/components/MUI/Utils/Portal.stories.tsx create mode 100644 src/components/MUI/Utils/Portal.tsx create mode 100644 src/components/MUI/Utils/TextareaAutosize.stories.tsx create mode 100644 src/components/MUI/Utils/TextareaAutosize.tsx create mode 100644 src/components/MUI/Utils/Transitions.stories.tsx create mode 100644 src/components/MUI/Utils/Transitions.tsx create mode 100644 src/components/MUI/Utils/UseMediaQuery.stories.tsx create mode 100644 src/components/MUI/Utils/UseMediaQuery.tsx diff --git a/src/components/MUI/DataDisplay/Avatar.stories.tsx b/src/components/MUI/DataDisplay/Avatar.stories.tsx new file mode 100644 index 0000000..26c6c6a --- /dev/null +++ b/src/components/MUI/DataDisplay/Avatar.stories.tsx @@ -0,0 +1,75 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Avatar } from "./Avatar"; +import Stack from "@mui/material/Stack"; +import Diamond from "../../../public/images/diamond.jpg"; + +const meta: Meta = { + title: "MUI/Data Display/Avatar", + component: Avatar, + tags: ["autodocs"], + parameters: { + controls: { expanded: true }, + layout: "padded", + }, + argTypes: { + variant: { + control: { type: "select" }, + options: ["circular", "rounded", "square"], + }, + children: { name: "initials", control: "text" }, + alt: { control: "text" }, + src: { control: "text" }, + imgProps: { control: false }, + sx: { control: false }, + width: { control: { type: "number", min: 24, max: 160, step: 4 } }, + height: { control: { type: "number", min: 24, max: 160, step: 4 } }, + }, + args: { + variant: "circular", + children: "AB", + alt: "User avatar", + src: "", + width: 56, + height: 56, + }, +}; +export default meta; +type Story = StoryObj; + +const withSize = (args: any) => { + const { width, height, ...rest } = args; + return { ...rest, sx: { width, height } }; +}; + +export const Basic: Story = { + render: (args) => {args.children}, +}; + +export const Variants: Story = { + render: (args) => ( + + AB + CD + EF + + ), +}; + +export const WithImage: Story = { + args: { + src: Diamond, + alt: "Random", + children: "", + }, + render: (args) => , +}; + +export const Sizes: Story = { + render: (args) => ( + + SM + MD + LG + + ), +}; diff --git a/src/components/MUI/DataDisplay/Avatar.tsx b/src/components/MUI/DataDisplay/Avatar.tsx new file mode 100644 index 0000000..4916615 --- /dev/null +++ b/src/components/MUI/DataDisplay/Avatar.tsx @@ -0,0 +1,14 @@ +import * as React from "react"; +import MuiAvatar, { AvatarProps as MuiAvatarProps } from "@mui/material/Avatar"; + +export type AvatarProps = MuiAvatarProps; + +export const Avatar = React.forwardRef( + ({ children, ...rest }, ref) => ( + + {children} + + ), +); + +Avatar.displayName = "Avatar"; diff --git a/src/components/MUI/DataDisplay/Badge.stories.tsx b/src/components/MUI/DataDisplay/Badge.stories.tsx new file mode 100644 index 0000000..fc9a273 --- /dev/null +++ b/src/components/MUI/DataDisplay/Badge.stories.tsx @@ -0,0 +1,77 @@ +// src/components/Badge/Badge.stories.tsx +import type { Meta, StoryObj } from "@storybook/react"; +import { Badge } from "./Badge"; +import MailIcon from "@mui/icons-material/Mail"; +import NotificationsIcon from "@mui/icons-material/Notifications"; + +const childMap = { + mail: , + notifications: , +} as const; + +const meta: Meta = { + title: "MUI/Data Display/Badge", + component: Badge, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + color: { + control: "select", + options: [ + "default", + "primary", + "secondary", + "success", + "error", + "info", + "warning", + ], + }, + variant: { control: "select", options: ["standard", "dot"] }, + badgeContent: { control: "number" }, + max: { control: "number" }, + invisible: { control: "boolean" }, + showZero: { control: "boolean" }, + overlap: { control: "select", options: ["rectangular", "circular"] }, + anchorOrigin: { control: false }, + children: { + name: "child", + control: "select", + options: Object.keys(childMap), + mapping: childMap, + }, + }, + args: { + color: "primary", + variant: "standard", + badgeContent: 4, + max: 99, + invisible: false, + showZero: false, + overlap: "circular", + children: "mail", + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { render: (args) => }; + +export const Dot: Story = { + args: { variant: "dot", color: "secondary" }, + render: (args) => , +}; + +export const Colors: Story = { + args: { badgeContent: 7 }, + render: (args) => ( + <> + + + + + + + + ), +}; diff --git a/src/components/MUI/DataDisplay/Badge.tsx b/src/components/MUI/DataDisplay/Badge.tsx new file mode 100644 index 0000000..4ec8846 --- /dev/null +++ b/src/components/MUI/DataDisplay/Badge.tsx @@ -0,0 +1,10 @@ +// src/components/Badge/Badge.tsx +import * as React from "react"; +import MuiBadge, { BadgeProps as MuiBadgeProps } from "@mui/material/Badge"; + +export type BadgeProps = MuiBadgeProps; + +export const Badge = React.forwardRef( + (props, ref) => , +); +Badge.displayName = "Badge"; diff --git a/src/components/MUI/DataDisplay/Chip.stories.tsx b/src/components/MUI/DataDisplay/Chip.stories.tsx new file mode 100644 index 0000000..fe0c87c --- /dev/null +++ b/src/components/MUI/DataDisplay/Chip.stories.tsx @@ -0,0 +1,131 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Chip } from "./Chip"; + +import Stack from "@mui/material/Stack"; +import SaveIcon from "@mui/icons-material/Save"; +import SendIcon from "@mui/icons-material/Send"; +import DeleteIcon from "@mui/icons-material/Delete"; +import AddIcon from "@mui/icons-material/Add"; + +const iconMap = { + none: undefined, + save: , + send: , + delete: , + add: , +} as const; + +const meta: Meta = { + title: "MUI/Data Display/Chip", + component: Chip, + tags: ["autodocs"], + parameters: { + controls: { expanded: true }, + layout: "padded", + }, + argTypes: { + label: { control: "text" }, + variant: { control: { type: "select" }, options: ["filled", "outlined"] }, + color: { + control: { type: "select" }, + options: [ + "default", + "primary", + "secondary", + "success", + "error", + "info", + "warning", + ], + }, + size: { control: { type: "select" }, options: ["small", "medium"] }, + clickable: { control: "boolean" }, + disabled: { control: "boolean" }, + + // Real props with mapping + icon: { + control: { type: "select" }, + options: Object.keys(iconMap), + mapping: iconMap, + }, + deleteIcon: { + control: { type: "select" }, + options: Object.keys(iconMap), + mapping: iconMap, + }, + onDelete: { control: false }, + sx: { control: false }, + }, + args: { + label: "Chip", + variant: "filled", + color: "default", + size: "medium", + clickable: false, + disabled: false, + icon: "none", + deleteIcon: "none", + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => , +}; + +export const Variants: Story = { + render: (args) => ( + + + + + ), +}; + +export const Colors: Story = { + args: { variant: "filled" }, + render: (args) => ( + + + + + + + + + + ), +}; + +export const WithIcons: Story = { + args: { color: "primary" }, + render: (args) => ( + + + + + + + ), +}; + +export const Deletable: Story = { + render: (args) => ( + + console.log("delete clicked")} + /> + console.log("delete clicked")} + /> + + ), +}; +``; diff --git a/src/components/MUI/DataDisplay/Chip.tsx b/src/components/MUI/DataDisplay/Chip.tsx new file mode 100644 index 0000000..ffd2bbc --- /dev/null +++ b/src/components/MUI/DataDisplay/Chip.tsx @@ -0,0 +1,11 @@ +// src/components/Chip/Chip.tsx +import * as React from "react"; +import MuiChip, { ChipProps as MuiChipProps } from "@mui/material/Chip"; + +export type ChipProps = MuiChipProps; + +export const Chip = React.forwardRef( + (props, ref) => , +); + +Chip.displayName = "Chip"; diff --git a/src/components/MUI/DataDisplay/Divider.stories.tsx b/src/components/MUI/DataDisplay/Divider.stories.tsx new file mode 100644 index 0000000..f1d56b8 --- /dev/null +++ b/src/components/MUI/DataDisplay/Divider.stories.tsx @@ -0,0 +1,51 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Divider } from "./Divider"; + +const meta: Meta = { + title: "MUI/Data Display/Divider", + component: Divider, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + variant: { control: "select", options: ["fullWidth", "inset", "middle"] }, + orientation: { control: "select", options: ["horizontal", "vertical"] }, + textAlign: { control: "select", options: ["center", "left", "right"] }, + flexItem: { control: "boolean" }, + children: { name: "label", control: "text" }, + }, + args: { + variant: "fullWidth", + orientation: "horizontal", + textAlign: "center", + flexItem: false, + children: "", + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { render: (args) => }; + +export const WithLabel: Story = { + args: { children: "Section" }, + render: (args) => , +}; + +export const Vertical: Story = { + args: { orientation: "vertical", flexItem: true }, + render: (args) => ( +
+ +
+ ), +}; + +export const Variants: Story = { + render: (args) => ( +
+ + + +
+ ), +}; diff --git a/src/components/MUI/DataDisplay/Divider.tsx b/src/components/MUI/DataDisplay/Divider.tsx new file mode 100644 index 0000000..9b2a1a4 --- /dev/null +++ b/src/components/MUI/DataDisplay/Divider.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiDivider, { + DividerProps as MuiDividerProps, +} from "@mui/material/Divider"; + +export type DividerProps = MuiDividerProps; + +export const Divider = React.forwardRef( + (props, ref) => , +); + +Divider.displayName = "Divider"; diff --git a/src/components/MUI/DataDisplay/Icon.stories.tsx b/src/components/MUI/DataDisplay/Icon.stories.tsx new file mode 100644 index 0000000..54230fa --- /dev/null +++ b/src/components/MUI/DataDisplay/Icon.stories.tsx @@ -0,0 +1,81 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Icon } from "./Icon"; +import HomeIcon from "@mui/icons-material/Home"; +import FavoriteIcon from "@mui/icons-material/Favorite"; +import SearchIcon from "@mui/icons-material/Search"; +import SettingsIcon from "@mui/icons-material/Settings"; + +const iconChildrenMap = { + home: , + favorite: , + search: , + settings: , +} as const; + +const meta: Meta = { + title: "MUI/Data Display/Icon", + component: Icon, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + color: { + control: "select", + options: [ + "inherit", + "primary", + "secondary", + "action", + "disabled", + "error", + "info", + "success", + "warning", + ], + }, + fontSize: { + control: "select", + options: ["inherit", "small", "medium", "large"], + }, + children: { + name: "icon", + control: "select", + options: Object.keys(iconChildrenMap), + mapping: iconChildrenMap, + }, + baseClassName: { control: false }, + }, + args: { + color: "inherit", + fontSize: "medium", + children: "home", + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { render: (args) => }; + +export const Colors: Story = { + render: (args) => ( + <> + + + + + + + + + + ), +}; + +export const Sizes: Story = { + render: (args) => ( + <> + + + + + ), +}; diff --git a/src/components/MUI/DataDisplay/Icon.tsx b/src/components/MUI/DataDisplay/Icon.tsx new file mode 100644 index 0000000..8b76d08 --- /dev/null +++ b/src/components/MUI/DataDisplay/Icon.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiIcon, { IconProps as MuiIconProps } from "@mui/material/Icon"; + +export type IconProps = MuiIconProps; + +export const Icon = React.forwardRef( + (props, ref) => , +); + +Icon.displayName = "Icon"; diff --git a/src/components/MUI/DataDisplay/IconButton.stories.tsx b/src/components/MUI/DataDisplay/IconButton.stories.tsx new file mode 100644 index 0000000..6299136 --- /dev/null +++ b/src/components/MUI/DataDisplay/IconButton.stories.tsx @@ -0,0 +1,86 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Icon } from "./Icon"; + +const meta: Meta = { + title: "MUI/Data Display/IconButton", + component: Icon, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + // These rely on the Material Icons font if you use ligatures. + // If your project doesn't load the font, the text will render as plain text. + color: { + control: "select", + options: [ + "inherit", + "primary", + "secondary", + "action", + "disabled", + "error", + "info", + "success", + "warning", + ], + }, + fontSize: { + control: "select", + options: ["inherit", "small", "medium", "large"], + }, + baseClassName: { control: "text" }, + children: { name: "ligature/text", control: "text" }, + }, + args: { + children: "home", + color: "inherit", + fontSize: "medium", + baseClassName: "material-icons", // if you load the Material Icons font + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => , +}; + +export const Sizes: Story = { + render: (args) => ( + <> + + home + {" "} + + home + {" "} + + home + + + ), +}; + +export const Colors: Story = { + render: (args) => ( + <> + + home + {" "} + + home + {" "} + + home + {" "} + + home + {" "} + + home + {" "} + + home + + + ), +}; diff --git a/src/components/MUI/DataDisplay/IconButton.tsx b/src/components/MUI/DataDisplay/IconButton.tsx new file mode 100644 index 0000000..861458a --- /dev/null +++ b/src/components/MUI/DataDisplay/IconButton.tsx @@ -0,0 +1,13 @@ +// src/components/IconButton/IconButton.tsx +import * as React from "react"; +import MuiIconButton, { + IconButtonProps as MuiIconButtonProps, +} from "@mui/material/IconButton"; + +export type IconButtonProps = MuiIconButtonProps; + +export const IconButton = React.forwardRef( + (props, ref) => , +); + +IconButton.displayName = "IconButton"; diff --git a/src/components/MUI/DataDisplay/List.stories.tsx b/src/components/MUI/DataDisplay/List.stories.tsx new file mode 100644 index 0000000..af325ba --- /dev/null +++ b/src/components/MUI/DataDisplay/List.stories.tsx @@ -0,0 +1,69 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { List } from "./List"; + +import ListItem from "@mui/material/ListItem"; +import ListItemText from "@mui/material/ListItemText"; +import ListItemIcon from "@mui/material/ListItemIcon"; +import Divider from "@mui/material/Divider"; + +import InboxIcon from "@mui/icons-material/MoveToInbox"; +import MailIcon from "@mui/icons-material/Mail"; + +const meta: Meta = { + title: "MUI/Data Display/List", + component: List, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + dense: { control: "boolean" }, + disablePadding: { control: "boolean" }, + subheader: { control: "text" }, + }, + args: { + dense: false, + disablePadding: false, + subheader: "", + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => ( + + + + + + + + + + + + + + + + + + + ), +}; + +export const Dense: Story = { + args: { dense: true }, + render: (args) => ( + + + + + + + + + + + + ), +}; diff --git a/src/components/MUI/DataDisplay/List.tsx b/src/components/MUI/DataDisplay/List.tsx new file mode 100644 index 0000000..a036c2b --- /dev/null +++ b/src/components/MUI/DataDisplay/List.tsx @@ -0,0 +1,11 @@ +// src/components/List/List.tsx +import * as React from "react"; +import MuiList, { ListProps as MuiListProps } from "@mui/material/List"; + +export type ListProps = MuiListProps; + +export const List = React.forwardRef( + (props, ref) => , +); + +List.displayName = "List"; diff --git a/src/components/MUI/DataDisplay/MaterialIcons.stories.tsx b/src/components/MUI/DataDisplay/MaterialIcons.stories.tsx new file mode 100644 index 0000000..fbecea6 --- /dev/null +++ b/src/components/MUI/DataDisplay/MaterialIcons.stories.tsx @@ -0,0 +1,74 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { MaterialIcons } from "./MaterialIcons"; + +const meta: Meta = { + title: "MUI/Data Display/MaterialIcons", + component: MaterialIcons, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + name: { + control: "select", + options: [ + "home", + "favorite", + "search", + "settings", + "add", + "edit", + "delete", + "send", + "save", + "info", + ], + }, + color: { + control: "select", + options: [ + "inherit", + "primary", + "secondary", + "action", + "disabled", + "error", + "info", + "success", + "warning", + ], + }, + fontSize: { + control: "select", + options: ["inherit", "small", "medium", "large"], + }, + }, + args: { name: "home", color: "inherit", fontSize: "medium" }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { render: (args) => }; + +export const Colors: Story = { + render: (args) => ( +
+ + + + + + + + +
+ ), +}; + +export const Sizes: Story = { + render: (args) => ( +
+ + + +
+ ), +}; diff --git a/src/components/MUI/DataDisplay/MaterialIcons.tsx b/src/components/MUI/DataDisplay/MaterialIcons.tsx new file mode 100644 index 0000000..3582c14 --- /dev/null +++ b/src/components/MUI/DataDisplay/MaterialIcons.tsx @@ -0,0 +1,49 @@ +import * as React from "react"; +import HomeIcon from "@mui/icons-material/Home"; +import FavoriteIcon from "@mui/icons-material/Favorite"; +import SearchIcon from "@mui/icons-material/Search"; +import SettingsIcon from "@mui/icons-material/Settings"; +import AddIcon from "@mui/icons-material/Add"; +import EditIcon from "@mui/icons-material/Edit"; +import DeleteIcon from "@mui/icons-material/Delete"; +import SendIcon from "@mui/icons-material/Send"; +import SaveIcon from "@mui/icons-material/Save"; +import InfoIcon from "@mui/icons-material/Info"; + +const iconMap = { + home: , + favorite: , + search: , + settings: , + add: , + edit: , + delete: , + send: , + save: , + info: , +} as const; + +export type MaterialIconsProps = { + name: keyof typeof iconMap; + color?: + | "inherit" + | "primary" + | "secondary" + | "action" + | "disabled" + | "error" + | "info" + | "success" + | "warning"; + fontSize?: "inherit" | "small" | "medium" | "large"; +}; + +export const MaterialIcons = React.forwardRef< + SVGSVGElement, + MaterialIconsProps +>(({ name, color = "inherit", fontSize = "medium" }, ref) => { + const el = iconMap[name]; + return React.cloneElement(el, { color, fontSize, ref }); +}); + +MaterialIcons.displayName = "MaterialIcons"; diff --git a/src/components/MUI/DataDisplay/Table.stories.tsx b/src/components/MUI/DataDisplay/Table.stories.tsx new file mode 100644 index 0000000..0af1787 --- /dev/null +++ b/src/components/MUI/DataDisplay/Table.stories.tsx @@ -0,0 +1,77 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Table } from "./Table"; +import TableContainer from "@mui/material/TableContainer"; +import TableHead from "@mui/material/TableHead"; +import TableBody from "@mui/material/TableBody"; +import TableRow from "@mui/material/TableRow"; +import TableCell from "@mui/material/TableCell"; +import Paper from "@mui/material/Paper"; + +const rows = [ + { name: "Frozen yoghurt", calories: 159, fat: 6.0 }, + { name: "Ice cream sandwich", calories: 237, fat: 9.0 }, + { name: "Eclair", calories: 262, fat: 16.0 }, +]; + +const meta: Meta = { + title: "MUI/Data Display/Table", + component: Table, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + size: { control: "select", options: ["small", "medium"] }, + stickyHeader: { control: "boolean" }, + }, + args: { size: "medium", stickyHeader: false }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => ( + + + + + Dessert + Calories + Fat + + + + {rows.map((r) => ( + + {r.name} + {r.calories} + {r.fat} + + ))} + +
+
+ ), +}; + +export const Dense: Story = { + args: { size: "small" }, + render: (args) => ( + + + + + Item + Val + + + + {rows.map((r) => ( + + {r.name} + {r.calories} + + ))} + +
+
+ ), +}; diff --git a/src/components/MUI/DataDisplay/Table.tsx b/src/components/MUI/DataDisplay/Table.tsx new file mode 100644 index 0000000..a0a96c2 --- /dev/null +++ b/src/components/MUI/DataDisplay/Table.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiTable, { TableProps as MuiTableProps } from "@mui/material/Table"; + +export type TableProps = MuiTableProps; + +export const Table = React.forwardRef( + (props, ref) => , +); + +Table.displayName = "Table"; diff --git a/src/components/MUI/DataDisplay/Typography.stories.tsx b/src/components/MUI/DataDisplay/Typography.stories.tsx new file mode 100644 index 0000000..7eff38b --- /dev/null +++ b/src/components/MUI/DataDisplay/Typography.stories.tsx @@ -0,0 +1,157 @@ +// src/components/Typography/Typography.stories.tsx +import type { Meta, StoryObj } from "@storybook/react"; +import { Typography } from "./Typography"; +import Stack from "@mui/material/Stack"; + +const meta: Meta = { + title: "MUI/Data Display/Typography", + component: Typography, + tags: ["autodocs"], + parameters: { + controls: { expanded: true }, + layout: "padded", + }, + argTypes: { + variant: { + control: { type: "select" }, + options: [ + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "subtitle1", + "subtitle2", + "body1", + "body2", + "caption", + "button", + "overline", + ], + }, + color: { + control: { type: "select" }, + options: [ + "inherit", + "primary", + "secondary", + "success", + "error", + "info", + "warning", + "textPrimary", + "textSecondary", + ], + }, + align: { + control: { type: "select" }, + options: ["inherit", "left", "center", "right", "justify"], + }, + gutterBottom: { control: "boolean" }, + noWrap: { control: "boolean" }, + paragraph: { control: "boolean" }, + children: { name: "text", control: "text" }, + sx: { control: false }, + }, + args: { + variant: "body1", + color: "inherit", + align: "inherit", + gutterBottom: false, + noWrap: false, + paragraph: false, + children: "The quick brown fox jumps over the lazy dog.", + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => , +}; + +export const Variants: Story = { + render: (args) => ( + + + Heading (h4) + + + Subtitle 1 + + + Body 1 + + + Body 2 + + + Caption + + + OVERLINE + + + Button text + + + ), +}; + +export const AlignmentAndWrap: Story = { + render: (args) => ( + + + Left aligned + + + Center aligned + + + Right aligned + + + This is a very very very long line that will be truncated when noWrap is + true. + + + Paragraph renders with bottom margin to separate blocks in content + layouts. + + + ), +}; + +export const Colors: Story = { + args: { variant: "body1" }, + render: (args) => ( + + + Primary + + + Secondary + + + Success + + + Error + + + Info + + + Warning + + + textPrimary + + + textSecondary + + + ), +}; +``; diff --git a/src/components/MUI/DataDisplay/Typography.tsx b/src/components/MUI/DataDisplay/Typography.tsx new file mode 100644 index 0000000..b1d67f8 --- /dev/null +++ b/src/components/MUI/DataDisplay/Typography.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiTypography, { + TypographyProps as MuiTypographyProps, +} from "@mui/material/Typography"; + +export type TypographyProps = MuiTypographyProps; + +export const Typography = React.forwardRef( + (props, ref) => , +); + +Typography.displayName = "Typography"; diff --git a/src/components/MUI/Feedback/Alert.stories.tsx b/src/components/MUI/Feedback/Alert.stories.tsx new file mode 100644 index 0000000..1f9e2aa --- /dev/null +++ b/src/components/MUI/Feedback/Alert.stories.tsx @@ -0,0 +1,65 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Alert } from "./Alert"; +import Button from "@mui/material/Button"; + +const meta: Meta = { + title: "MUI/Feedback/Alert", + component: Alert, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + severity: { + control: "select", + options: ["success", "info", "warning", "error"], + }, + variant: { control: "select", options: ["standard", "outlined", "filled"] }, + children: { name: "message", control: "text" }, + icon: { control: false }, + action: { control: false }, + onClose: { control: false }, + }, + args: { + severity: "info", + variant: "standard", + children: "This is an info alert", + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { render: (args) => }; + +export const Variants: Story = { + render: (args) => ( + <> + + Standard + + + Outlined + + + Filled + + + ), +}; + +export const WithActionAndClose: Story = { + render: (args) => ( + <> + + UNDO + + } + onClose={() => console.log("alert close")} + > + Warning with action + + + ), +}; diff --git a/src/components/MUI/Feedback/Alert.tsx b/src/components/MUI/Feedback/Alert.tsx new file mode 100644 index 0000000..3760b7d --- /dev/null +++ b/src/components/MUI/Feedback/Alert.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiAlert, { AlertProps as MuiAlertProps } from "@mui/material/Alert"; + +export type AlertProps = MuiAlertProps; + +export const Alert = React.forwardRef( + (props, ref) => , +); + +Alert.displayName = "Alert"; diff --git a/src/components/MUI/Feedback/Backdrop.stories.tsx b/src/components/MUI/Feedback/Backdrop.stories.tsx new file mode 100644 index 0000000..409cf11 --- /dev/null +++ b/src/components/MUI/Feedback/Backdrop.stories.tsx @@ -0,0 +1,38 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import * as React from "react"; +import { Backdrop } from "./Backdrop"; +import Button from "@mui/material/Button"; +import CircularProgress from "@mui/material/CircularProgress"; + +const meta: Meta = { + title: "MUI/Feedback/Backdrop", + component: Backdrop, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + open: { control: "boolean" }, + invisible: { control: "boolean" }, + }, + args: { open: false, invisible: false }, +}; +export default meta; +type Story = StoryObj; + +export const Controlled: Story = { + render: (args) => { + const [open, setOpen] = React.useState(false); + return ( +
+ + setOpen(false)} + sx={{ color: "#fff", zIndex: (t) => t.zIndex.drawer + 1 }} + > + + +
+ ); + }, +}; diff --git a/src/components/MUI/Feedback/Backdrop.tsx b/src/components/MUI/Feedback/Backdrop.tsx new file mode 100644 index 0000000..3686d04 --- /dev/null +++ b/src/components/MUI/Feedback/Backdrop.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiBackdrop, { + BackdropProps as MuiBackdropProps, +} from "@mui/material/Backdrop"; + +export type BackdropProps = MuiBackdropProps; + +export const Backdrop = React.forwardRef( + (props, ref) => , +); + +Backdrop.displayName = "Backdrop"; diff --git a/src/components/MUI/Feedback/CircularProgress.stories.tsx b/src/components/MUI/Feedback/CircularProgress.stories.tsx new file mode 100644 index 0000000..7c7cc07 --- /dev/null +++ b/src/components/MUI/Feedback/CircularProgress.stories.tsx @@ -0,0 +1,46 @@ +// src/components/Progress/CircularProgress.stories.tsx +import type { Meta, StoryObj } from "@storybook/react"; +import { CircularProgress } from "./CircularProgress"; + +const meta: Meta = { + title: "MUI/Feedback/CircularProgress", + component: CircularProgress, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + color: { + control: "select", + options: [ + "primary", + "secondary", + "success", + "error", + "info", + "warning", + "inherit", + ], + }, + variant: { control: "select", options: ["indeterminate", "determinate"] }, + value: { control: { type: "number", min: 0, max: 100, step: 1 } }, + size: { control: { type: "number", min: 8, max: 200, step: 2 } }, + thickness: { control: { type: "number", min: 1, max: 10, step: 0.5 } }, + }, + args: { + color: "primary", + variant: "indeterminate", + value: 40, + size: 40, + thickness: 3.6, + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => , +}; + +export const Determinate: Story = { + args: { variant: "determinate", value: 70 }, + render: (args) => , +}; diff --git a/src/components/MUI/Feedback/CircularProgress.tsx b/src/components/MUI/Feedback/CircularProgress.tsx new file mode 100644 index 0000000..a522c2e --- /dev/null +++ b/src/components/MUI/Feedback/CircularProgress.tsx @@ -0,0 +1,14 @@ +// src/components/Progress/CircularProgress.tsx +import * as React from "react"; +import MuiCircularProgress, { + CircularProgressProps as MuiCircularProgressProps, +} from "@mui/material/CircularProgress"; + +export type CircularProgressProps = MuiCircularProgressProps; + +export const CircularProgress = React.forwardRef< + HTMLSpanElement, + CircularProgressProps +>((props, ref) => ); + +CircularProgress.displayName = "CircularProgress"; diff --git a/src/components/MUI/Feedback/Dialog.stories.tsx b/src/components/MUI/Feedback/Dialog.stories.tsx new file mode 100644 index 0000000..491c1a1 --- /dev/null +++ b/src/components/MUI/Feedback/Dialog.stories.tsx @@ -0,0 +1,69 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Dialog } from "./Dialog"; +import DialogTitle from "@mui/material/DialogTitle"; +import DialogContent from "@mui/material/DialogContent"; +import DialogActions from "@mui/material/DialogActions"; +import Button from "@mui/material/Button"; +import Typography from "@mui/material/Typography"; +import React from "react"; + +const meta: Meta = { + title: "MUI/Feedback/Dialog", + component: Dialog, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + fullWidth: { control: "boolean" }, + maxWidth: { + control: "select", + options: ["xs", "sm", "md", "lg", "xl", false], + }, + fullScreen: { control: "boolean" }, + scroll: { control: "select", options: ["paper", "body"] }, + }, + args: { fullWidth: true, maxWidth: "sm", fullScreen: false, scroll: "paper" }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => { + const [open, setOpen] = React.useState(false); + return ( +
+ + setOpen(false)}> + Title + + Content goes here. + + + + + + +
+ ); + }, +}; + +export const FullScreen: Story = { + args: { fullScreen: true }, + render: (args) => { + const [open, setOpen] = React.useState(false); + return ( +
+ + setOpen(false)}> + Full Screen + + Full-screen content. + + + + + +
+ ); + }, +}; diff --git a/src/components/MUI/Feedback/Dialog.tsx b/src/components/MUI/Feedback/Dialog.tsx new file mode 100644 index 0000000..88c2811 --- /dev/null +++ b/src/components/MUI/Feedback/Dialog.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiDialog, { DialogProps as MuiDialogProps } from "@mui/material/Dialog"; + +export type DialogProps = MuiDialogProps; + +export const Dialog = React.forwardRef( + (props, ref) => , +); + +Dialog.displayName = "Dialog"; diff --git a/src/components/MUI/Feedback/LinearProgress.stories.tsx b/src/components/MUI/Feedback/LinearProgress.stories.tsx new file mode 100644 index 0000000..691b52d --- /dev/null +++ b/src/components/MUI/Feedback/LinearProgress.stories.tsx @@ -0,0 +1,49 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { LinearProgress } from "./LinearProgress"; + +const meta: Meta = { + title: "MUI/Feedback/LinearProgress", + component: LinearProgress, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + color: { + control: "select", + options: [ + "primary", + "secondary", + "success", + "error", + "info", + "warning", + "inherit", + ], + }, + variant: { + control: "select", + options: ["indeterminate", "determinate", "buffer", "query"], + }, + value: { control: { type: "number", min: 0, max: 100, step: 1 } }, + valueBuffer: { control: { type: "number", min: 0, max: 100, step: 1 } }, + }, + args: { + color: "primary", + variant: "indeterminate", + value: 40, + valueBuffer: 60, + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { render: (args) => }; + +export const Determinate: Story = { + args: { variant: "determinate", value: 50 }, + render: (args) => , +}; + +export const Buffer: Story = { + args: { variant: "buffer", value: 30, valueBuffer: 60 }, + render: (args) => , +}; diff --git a/src/components/MUI/Feedback/LinearProgress.tsx b/src/components/MUI/Feedback/LinearProgress.tsx new file mode 100644 index 0000000..d21d8df --- /dev/null +++ b/src/components/MUI/Feedback/LinearProgress.tsx @@ -0,0 +1,13 @@ +import * as React from "react"; +import MuiLinearProgress, { + LinearProgressProps as MuiLinearProgressProps, +} from "@mui/material/LinearProgress"; + +export type LinearProgressProps = MuiLinearProgressProps; + +export const LinearProgress = React.forwardRef< + HTMLDivElement, + LinearProgressProps +>((props, ref) => ); + +LinearProgress.displayName = "LinearProgress"; diff --git a/src/components/MUI/Feedback/Skeleton.stories.tsx b/src/components/MUI/Feedback/Skeleton.stories.tsx new file mode 100644 index 0000000..012e7a5 --- /dev/null +++ b/src/components/MUI/Feedback/Skeleton.stories.tsx @@ -0,0 +1,23 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Skeleton } from "./Skeleton"; + +const meta: Meta = { + title: "MUI/Feedback/Skeleton", + component: Skeleton, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + variant: { + control: "select", + options: ["text", "rectangular", "circular"], + }, + animation: { control: "select", options: ["pulse", "wave", false] }, + width: { control: { type: "number", min: 16, max: 600, step: 4 } }, + height: { control: { type: "number", min: 16, max: 600, step: 4 } }, + }, + args: { variant: "text", animation: "pulse", width: 240, height: 24 }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { render: (args) => }; diff --git a/src/components/MUI/Feedback/Skeleton.tsx b/src/components/MUI/Feedback/Skeleton.tsx new file mode 100644 index 0000000..dd7b5ea --- /dev/null +++ b/src/components/MUI/Feedback/Skeleton.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiSkeleton, { + SkeletonProps as MuiSkeletonProps, +} from "@mui/material/Skeleton"; + +export type SkeletonProps = MuiSkeletonProps; + +export const Skeleton = React.forwardRef( + (props, ref) => , +); + +Skeleton.displayName = "Skeleton"; diff --git a/src/components/MUI/Feedback/Snackbar.stories.tsx b/src/components/MUI/Feedback/Snackbar.stories.tsx new file mode 100644 index 0000000..08fe5b8 --- /dev/null +++ b/src/components/MUI/Feedback/Snackbar.stories.tsx @@ -0,0 +1,96 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import Button from "@mui/material/Button"; +import React from "react"; +import { Snackbar } from "./Snackbar"; + +const anchorMap = { + "top-left": { vertical: "top", horizontal: "left" }, + "top-center": { vertical: "top", horizontal: "center" }, + "top-right": { vertical: "top", horizontal: "right" }, + "bottom-left": { vertical: "bottom", horizontal: "left" }, + "bottom-center": { vertical: "bottom", horizontal: "center" }, + "bottom-right": { vertical: "bottom", horizontal: "right" }, +} as const; + +const meta: Meta = { + title: "MUI/Feedback/Snackbar", + component: Snackbar, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + message: { control: "text" }, + autoHideDuration: { + control: { type: "number", min: 1000, max: 10000, step: 500 }, + }, + anchorOrigin: { + control: { type: "select" }, + options: Object.keys(anchorMap), + mapping: anchorMap, + }, + }, + args: { + message: "Saved", + autoHideDuration: 3000, + anchorOrigin: "bottom-left", + }, +}; +export default meta; +type Story = StoryObj; + +export const Controlled: Story = { + render: (args) => { + const [open, setOpen] = React.useState(false); + return ( +
+ + setOpen(false)} /> +
+ ); + }, +}; + +export const Positions: Story = { + render: (args) => { + const [open, setOpen] = React.useState(true); + return ( +
+ setOpen(false)} + /> + setOpen(false)} + /> + setOpen(false)} + /> + setOpen(false)} + /> + setOpen(false)} + /> + setOpen(false)} + /> +
+ ); + }, +}; diff --git a/src/components/MUI/Feedback/Snackbar.tsx b/src/components/MUI/Feedback/Snackbar.tsx new file mode 100644 index 0000000..c72a864 --- /dev/null +++ b/src/components/MUI/Feedback/Snackbar.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiSnackbar, { + SnackbarProps as MuiSnackbarProps, +} from "@mui/material/Snackbar"; + +export type SnackbarProps = MuiSnackbarProps; + +export const Snackbar = React.forwardRef( + (props, ref) => , +); + +Snackbar.displayName = "Snackbar"; diff --git a/src/components/MUI/Feedback/Tooltip.stories.tsx b/src/components/MUI/Feedback/Tooltip.stories.tsx new file mode 100644 index 0000000..283db97 --- /dev/null +++ b/src/components/MUI/Feedback/Tooltip.stories.tsx @@ -0,0 +1,94 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Tooltip } from "./Tooltip"; +import IconButton from "@mui/material/IconButton"; +import InfoIcon from "@mui/icons-material/Info"; + +const meta: Meta = { + title: "MUI/Feedback/Tooltip", + component: Tooltip, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + title: { control: "text" }, + placement: { + control: "select", + options: [ + "bottom", + "bottom-start", + "bottom-end", + "top", + "top-start", + "top-end", + "left", + "left-start", + "left-end", + "right", + "right-start", + "right-end", + ], + }, + arrow: { control: "boolean" }, + disableInteractive: { control: "boolean" }, + }, + args: { + title: "Tooltip", + placement: "top", + arrow: true, + disableInteractive: false, + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => ( + + + + + + ), +}; + +export const Placements: Story = { + render: (args) => ( +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ ), +}; diff --git a/src/components/MUI/Feedback/Tooltip.tsx b/src/components/MUI/Feedback/Tooltip.tsx new file mode 100644 index 0000000..a3a4817 --- /dev/null +++ b/src/components/MUI/Feedback/Tooltip.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiTooltip, { + TooltipProps as MuiTooltipProps, +} from "@mui/material/Tooltip"; + +export type TooltipProps = MuiTooltipProps; + +export const Tooltip = React.forwardRef((props, ref) => ( + +)); + +Tooltip.displayName = "Tooltip"; diff --git a/src/components/MUI/Inputs/Autocomplete.stories.tsx b/src/components/MUI/Inputs/Autocomplete.stories.tsx new file mode 100644 index 0000000..169ffd6 --- /dev/null +++ b/src/components/MUI/Inputs/Autocomplete.stories.tsx @@ -0,0 +1,189 @@ +import * as React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { Autocomplete } from "./Autocomplete"; +import TextField from "@mui/material/TextField"; +import Chip from "@mui/material/Chip"; + +const options = [ + "Apple", + "Apricot", + "Banana", + "Blueberry", + "Cherry", + "Date", + "Fig", + "Grape", + "Kiwi", + "Lime", + "Mango", + "Orange", + "Papaya", + "Pear", + "Plum", + "Raspberry", + "Strawberry", +]; + +type ExtraArgs = { + label: string; + placeholder?: string; + tfVariant: "outlined" | "filled" | "standard"; + tfColor: "primary" | "secondary" | "success" | "error" | "info" | "warning"; + defaultValue?: string[] | string | null; +}; +type AutoArgs = React.ComponentProps & ExtraArgs; + +const meta: Meta = { + title: "MUI/Inputs/Autocomplete", + component: Autocomplete, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + multiple: { control: "boolean" }, + freeSolo: { control: "boolean" }, + disableClearable: { control: "boolean" }, + autoHighlight: { control: "boolean" }, + autoSelect: { control: "boolean" }, + filterSelectedOptions: { control: "boolean" }, + size: { control: { type: "select" }, options: ["small", "medium"] }, + options: { control: { type: "object" } }, + tfVariant: { + name: "TextField variant", + control: { type: "select" }, + options: ["outlined", "filled", "standard"], + }, + tfColor: { + name: "TextField color", + control: { type: "select" }, + options: ["primary", "secondary", "success", "error", "info", "warning"], + }, + label: { control: "text" }, + placeholder: { control: "text" }, + renderInput: { control: false }, + renderTags: { control: false }, + value: { control: false }, + onChange: { control: false }, + defaultValue: { control: false }, + }, + args: { + options, + multiple: false, + freeSolo: false, + disableClearable: false, + autoHighlight: true, + autoSelect: false, + filterSelectedOptions: true, + size: "medium", + tfVariant: "outlined", + tfColor: "primary", + label: "Choose a fruit", + placeholder: "Type to search…", + limitTags: -1, + defaultValue: null, + }, +}; +export default meta; +type Story = StoryObj; + +const withTF = (args: AutoArgs) => ({ + ...args, + renderInput: (params: any) => ( + + ), +}); + +export const Basic: Story = { + render: (args) => , +}; + +export const FreeSolo: Story = { + args: { freeSolo: true, disableClearable: true }, + render: (args) => , +}; + +export const MultipleChips: Story = { + args: { + multiple: true, + filterSelectedOptions: true, + size: "small", + defaultValue: [], + }, + render: (args) => { + const initial = Array.isArray(args.defaultValue) + ? (args.defaultValue as string[]) + : []; + const [value, setValue] = React.useState(initial); + return ( + setValue((newValue ?? []) as string[])} + options={options} + renderTags={(selected = [], getTagProps) => + selected.map((option, index) => ( + + )) + } + /> + ); + }, +}; + +export const ToggleMultipleSafely: Story = { + args: { + multiple: false, + filterSelectedOptions: true, + size: "medium", + defaultValue: null, + }, + render: (args) => { + const [value, setValue] = React.useState( + args.defaultValue ?? null, + ); + React.useEffect(() => { + setValue((prev) => { + if (args.multiple) { + if (prev == null) return []; + return Array.isArray(prev) ? prev : prev ? [prev] : []; + } else { + if (prev == null) return null; + return Array.isArray(prev) ? (prev[0] ?? null) : prev; + } + }); + }, [args.multiple]); + return ( + { + if (args.multiple) setValue((newValue ?? []) as string[]); + else setValue((newValue as string) ?? null); + }} + options={options} + renderTags={(selected = [], getTagProps) => + selected.map((option, index) => ( + + )) + } + /> + ); + }, +}; diff --git a/src/components/MUI/Inputs/Autocomplete.tsx b/src/components/MUI/Inputs/Autocomplete.tsx new file mode 100644 index 0000000..af995a3 --- /dev/null +++ b/src/components/MUI/Inputs/Autocomplete.tsx @@ -0,0 +1,18 @@ +import * as React from "react"; +import MuiAutocomplete, { + AutocompleteProps as MuiAutocompleteProps, +} from "@mui/material/Autocomplete"; + +export type AutocompleteProps = MuiAutocompleteProps< + T, + boolean | undefined, + boolean | undefined, + boolean | undefined +>; + +export const Autocomplete = React.forwardRef< + HTMLDivElement, + AutocompleteProps +>((props, ref) => ); + +Autocomplete.displayName = "Autocomplete"; diff --git a/src/components/MUI/Inputs/Button.stories.tsx b/src/components/MUI/Inputs/Button.stories.tsx index 6a9420b..d26a966 100644 --- a/src/components/MUI/Inputs/Button.stories.tsx +++ b/src/components/MUI/Inputs/Button.stories.tsx @@ -6,7 +6,7 @@ import SendIcon from "@mui/icons-material/Send"; import DeleteIcon from "@mui/icons-material/Delete"; import AddIcon from "@mui/icons-material/Add"; import Stack from "@mui/material/Stack"; -import Box from "@mui/material/Box"; +import { Box } from "../Layout/Box"; const iconMap = { none: undefined, diff --git a/src/components/MUI/Inputs/Button.tsx b/src/components/MUI/Inputs/Button.tsx index e280ac3..7a61ef8 100644 --- a/src/components/MUI/Inputs/Button.tsx +++ b/src/components/MUI/Inputs/Button.tsx @@ -1,4 +1,3 @@ -// src/components/Button/Button.tsx import React from "react"; import MuiButton, { ButtonProps as MuiButtonProps } from "@mui/material/Button"; @@ -12,4 +11,4 @@ export const Button = React.forwardRef( ), ); -Button; +Button.displayName = "Button"; diff --git a/src/components/MUI/Inputs/ButtonGroup.stories.tsx b/src/components/MUI/Inputs/ButtonGroup.stories.tsx new file mode 100644 index 0000000..c9a2465 --- /dev/null +++ b/src/components/MUI/Inputs/ButtonGroup.stories.tsx @@ -0,0 +1,60 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { ButtonGroup } from "./ButtonGroup"; +import { Button } from "./Button"; + +const meta: Meta = { + title: "MUI/Inputs/ButtonGroup", + component: ButtonGroup, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + variant: { control: "select", options: ["text", "outlined", "contained"] }, + color: { + control: "select", + options: [ + "inherit", + "primary", + "secondary", + "success", + "error", + "info", + "warning", + ], + }, + size: { control: "select", options: ["small", "medium", "large"] }, + orientation: { control: "select", options: ["horizontal", "vertical"] }, + disabled: { control: "boolean" }, + fullWidth: { control: "boolean" }, + }, + args: { + variant: "outlined", + color: "primary", + size: "medium", + orientation: "horizontal", + disabled: false, + fullWidth: false, + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => ( + + + + + + ), +}; + +export const Vertical: Story = { + args: { orientation: "vertical" }, + render: (args) => ( + + + + + + ), +}; diff --git a/src/components/MUI/Inputs/ButtonGroup.tsx b/src/components/MUI/Inputs/ButtonGroup.tsx new file mode 100644 index 0000000..40d7ce6 --- /dev/null +++ b/src/components/MUI/Inputs/ButtonGroup.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiButtonGroup, { + ButtonGroupProps as MuiButtonGroupProps, +} from "@mui/material/ButtonGroup"; + +export type ButtonGroupProps = MuiButtonGroupProps; + +export const ButtonGroup = React.forwardRef( + (props, ref) => , +); diff --git a/src/components/MUI/Inputs/Checkbox.stories.tsx b/src/components/MUI/Inputs/Checkbox.stories.tsx new file mode 100644 index 0000000..f364c80 --- /dev/null +++ b/src/components/MUI/Inputs/Checkbox.stories.tsx @@ -0,0 +1,70 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import * as React from "react"; +import { Checkbox } from "./Checkbox"; + +type CBArgs = React.ComponentProps; + +const meta: Meta = { + title: "MUI/Inputs/Checkbox", + component: Checkbox, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + color: { + control: "select", + options: [ + "default", + "primary", + "secondary", + "success", + "error", + "info", + "warning", + ], + }, + size: { control: "select", options: ["small", "medium"] }, + disabled: { control: "boolean" }, + indeterminate: { control: "boolean" }, + + checked: { control: false }, + onChange: { control: false }, + }, + args: { + color: "primary", + size: "medium", + disabled: false, + indeterminate: false, + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => , +}; + +export const Controlled: Story = { + render: (args) => { + const [checked, setChecked] = React.useState(true); + return ( + setChecked(e.target.checked)} + /> + ); + }, +}; + +export const ColorsAndSizes: Story = { + render: (args) => ( +
+ + + + + + +
+ ), +}; diff --git a/src/components/MUI/Inputs/Checkbox.tsx b/src/components/MUI/Inputs/Checkbox.tsx new file mode 100644 index 0000000..6b7fc2d --- /dev/null +++ b/src/components/MUI/Inputs/Checkbox.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiCheckbox, { + CheckboxProps as MuiCheckboxProps, +} from "@mui/material/Checkbox"; + +export type CheckboxProps = MuiCheckboxProps; + +export const Checkbox = React.forwardRef( + (props, ref) => , +); diff --git a/src/components/MUI/Inputs/Fab.stories.tsx b/src/components/MUI/Inputs/Fab.stories.tsx new file mode 100644 index 0000000..f1a5060 --- /dev/null +++ b/src/components/MUI/Inputs/Fab.stories.tsx @@ -0,0 +1,87 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Fab } from "./Fab"; +import AddIcon from "@mui/icons-material/Add"; +import EditIcon from "@mui/icons-material/Edit"; +import NavigationIcon from "@mui/icons-material/Navigation"; + +const meta: Meta = { + title: "MUI/Inputs/Fab", + component: Fab, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + color: { + control: "select", + options: [ + "default", + "inherit", + "primary", + "secondary", + "success", + "error", + "info", + "warning", + ], + }, + size: { control: "select", options: ["small", "medium", "large"] }, + variant: { control: "select", options: ["circular", "extended"] }, + disabled: { control: "boolean" }, + }, + args: { + color: "primary", + size: "medium", + variant: "circular", + disabled: false, + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => ( + + + + ), +}; + +export const Colors: Story = { + render: (args) => ( +
+ + + + + + + + + + + + + + + + + + +
+ ), +}; + +export const Extended: Story = { + args: { variant: "extended" }, + render: (args) => ( +
+ + + Navigate + + + + Edit + +
+ ), +}; diff --git a/src/components/MUI/Inputs/Fab.tsx b/src/components/MUI/Inputs/Fab.tsx new file mode 100644 index 0000000..e463057 --- /dev/null +++ b/src/components/MUI/Inputs/Fab.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiFab, { FabProps as MuiFabProps } from "@mui/material/Fab"; + +export type FabProps = MuiFabProps; + +export const Fab = React.forwardRef( + (props, ref) => , +); + +Fab.displayName = "Fab"; diff --git a/src/components/MUI/Inputs/Radio.stories.tsx b/src/components/MUI/Inputs/Radio.stories.tsx new file mode 100644 index 0000000..e65bbc3 --- /dev/null +++ b/src/components/MUI/Inputs/Radio.stories.tsx @@ -0,0 +1,70 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import * as React from "react"; +import { Radio } from "./Radio"; +import { RadioGroup } from "./RadioGroup"; +import FormControlLabel from "@mui/material/FormControlLabel"; + +type RArgs = React.ComponentProps; + +const meta: Meta = { + title: "MUI/Inputs/Radio", + component: Radio, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + color: { + control: "select", + options: [ + "default", + "primary", + "secondary", + "success", + "error", + "info", + "warning", + ], + }, + size: { control: "select", options: ["small", "medium"] }, + disabled: { control: "boolean" }, + checked: { control: false }, + onChange: { control: false }, + }, + args: { + color: "primary", + size: "medium", + disabled: false, + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { render: (args) => }; + +export const GroupControlled: Story = { + render: (args) => { + const [value, setValue] = React.useState("a"); + return ( + setValue((e.target as HTMLInputElement).value)} + row + > + } + label="Option A" + /> + } + label="Option B" + /> + } + label="Option C" + /> + + ); + }, +}; diff --git a/src/components/MUI/Inputs/Radio.tsx b/src/components/MUI/Inputs/Radio.tsx new file mode 100644 index 0000000..ca5799c --- /dev/null +++ b/src/components/MUI/Inputs/Radio.tsx @@ -0,0 +1,8 @@ +import * as React from "react"; +import MuiRadio, { RadioProps as MuiRadioProps } from "@mui/material/Radio"; + +export type RadioProps = MuiRadioProps; + +export const Radio = React.forwardRef( + (props, ref) => , +); diff --git a/src/components/MUI/Inputs/RadioGroup.stories.tsx b/src/components/MUI/Inputs/RadioGroup.stories.tsx new file mode 100644 index 0000000..40ec1a0 --- /dev/null +++ b/src/components/MUI/Inputs/RadioGroup.stories.tsx @@ -0,0 +1,39 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { RadioGroup } from "./RadioGroup"; +import FormControlLabel from "@mui/material/FormControlLabel"; +import { Radio } from "./Radio"; + +const meta: Meta = { + title: "MUI/Inputs/RadioGroup", + component: RadioGroup, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + row: { control: "boolean" }, + name: { control: "text" }, + }, + args: { row: true, name: "choices" }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => ( + + } label="Option A" /> + } label="Option B" /> + } label="Option C" /> + + ), +}; + +export const Vertical: Story = { + args: { row: false }, + render: (args) => ( + + } label="Alpha" /> + } label="Beta" /> + } label="Gamma" /> + + ), +}; diff --git a/src/components/MUI/Inputs/RadioGroup.tsx b/src/components/MUI/Inputs/RadioGroup.tsx new file mode 100644 index 0000000..c859ec5 --- /dev/null +++ b/src/components/MUI/Inputs/RadioGroup.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiRadioGroup, { + RadioGroupProps as MuiRadioGroupProps, +} from "@mui/material/RadioGroup"; + +export type RadioGroupProps = MuiRadioGroupProps; + +export const RadioGroup = React.forwardRef( + (props, ref) => , +); + +RadioGroup.displayName = "RadioGroup"; diff --git a/src/components/MUI/Inputs/Rating.stories.tsx b/src/components/MUI/Inputs/Rating.stories.tsx new file mode 100644 index 0000000..7590f59 --- /dev/null +++ b/src/components/MUI/Inputs/Rating.stories.tsx @@ -0,0 +1,47 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import * as React from "react"; +import { Rating } from "./Rating"; + +type RatingArgs = React.ComponentProps; + +const meta: Meta = { + title: "MUI/Inputs/Rating", + component: Rating, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + value: { control: { type: "number", min: 0, max: 5, step: 0.5 } }, + precision: { control: { type: "number", min: 0.1, max: 1, step: 0.1 } }, + max: { control: { type: "number", min: 1, max: 10, step: 1 } }, + readOnly: { control: "boolean" }, + disabled: { control: "boolean" }, + size: { control: "select", options: ["small", "medium", "large"] }, + icon: { control: false }, + emptyIcon: { control: false }, + onChange: { control: false }, + }, + args: { + value: 3.5, + precision: 0.5, + max: 5, + readOnly: false, + disabled: false, + size: "medium", + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => { + const [value, setValue] = React.useState(args.value ?? 3.5); + return ( + setValue(v ?? 0)} /> + ); + }, +}; + +export const ReadOnly: Story = { + args: { readOnly: true, value: 4 }, + render: (args) => , +}; diff --git a/src/components/MUI/Inputs/Rating.tsx b/src/components/MUI/Inputs/Rating.tsx new file mode 100644 index 0000000..dc7a0b7 --- /dev/null +++ b/src/components/MUI/Inputs/Rating.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiRating, { RatingProps as MuiRatingProps } from "@mui/material/Rating"; + +export type RatingProps = MuiRatingProps; + +export const Rating = React.forwardRef( + (props, ref) => , +); + +Rating.displayName = "Rating"; diff --git a/src/components/MUI/Inputs/Select.stories.tsx b/src/components/MUI/Inputs/Select.stories.tsx new file mode 100644 index 0000000..6ce8678 --- /dev/null +++ b/src/components/MUI/Inputs/Select.stories.tsx @@ -0,0 +1,83 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Select } from "./Select"; +import FormControl from "@mui/material/FormControl"; +import MenuItem from "@mui/material/MenuItem"; +import InputLabel from "@mui/material/InputLabel"; + +const cityOptions = ["London", "Paris", "Berlin", "Rome", "Madrid"]; + +type ExtraArgs = { + label?: string; + items?: string[]; +}; +type SelectArgs = React.ComponentProps & ExtraArgs; + +const meta: Meta = { + title: "MUI/Inputs/Select", + component: Select, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + variant: { control: "select", options: ["outlined", "filled", "standard"] }, + color: { + control: "select", + options: ["primary", "secondary", "success", "error", "info", "warning"], + }, + size: { control: "select", options: ["small", "medium"] }, + multiple: { control: "boolean" }, + displayEmpty: { control: "boolean" }, + value: { control: false }, + onChange: { control: false }, + + label: { control: "text" }, + items: { control: { type: "object" } }, + }, + args: { + variant: "outlined", + color: "primary", + size: "medium", + multiple: false, + displayEmpty: false, + label: "City", + items: cityOptions, + defaultValue: cityOptions[0], + }, +}; +export default meta; +type Story = StoryObj; + +const renderSelectWithLabel = (args: SelectArgs) => ( + + {args.label && {args.label}} + + +); + +export const Basic: Story = { + render: (args: SelectArgs) => renderSelectWithLabel(args), +}; + +export const Multiple: Story = { + args: { multiple: true, defaultValue: [cityOptions[0], cityOptions[2]] }, + render: (args: SelectArgs) => renderSelectWithLabel(args), +}; + +export const FilledAndStandard: Story = { + render: (args: SelectArgs) => ( +
+ {renderSelectWithLabel({ ...args, variant: "filled" })} + {renderSelectWithLabel({ ...args, variant: "standard" })} +
+ ), +}; diff --git a/src/components/MUI/Inputs/Select.tsx b/src/components/MUI/Inputs/Select.tsx new file mode 100644 index 0000000..5c80077 --- /dev/null +++ b/src/components/MUI/Inputs/Select.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiSelect, { SelectProps as MuiSelectProps } from "@mui/material/Select"; + +export type SelectProps = MuiSelectProps; + +export const Select = React.forwardRef( + (props, ref) => , +); + +Select.displayName = "Select"; diff --git a/src/components/MUI/Inputs/Slider.stories.tsx b/src/components/MUI/Inputs/Slider.stories.tsx new file mode 100644 index 0000000..bba946a --- /dev/null +++ b/src/components/MUI/Inputs/Slider.stories.tsx @@ -0,0 +1,78 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import * as React from "react"; +import { Slider } from "./Slider"; + +type SliderArgs = React.ComponentProps; + +const meta: Meta = { + title: "MUI/Inputs/Slider", + component: Slider, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + color: { + control: "select", + options: ["primary", "secondary", "success", "error", "info", "warning"], + }, + size: { control: "select", options: ["small", "medium"] }, + orientation: { control: "select", options: ["horizontal", "vertical"] }, + min: { control: { type: "number", min: 0, max: 100, step: 1 } }, + max: { control: { type: "number", min: 0, max: 100, step: 1 } }, + step: { control: { type: "number", min: 1, max: 20, step: 1 } }, + marks: { control: "boolean" }, + valueLabelDisplay: { control: "select", options: ["off", "auto", "on"] }, + disabled: { control: "boolean" }, + value: { control: false }, + onChange: { control: false }, + }, + args: { + color: "primary", + size: "medium", + orientation: "horizontal", + min: 0, + max: 100, + step: 1, + marks: false, + valueLabelDisplay: "off", + disabled: false, + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { render: (args) => }; + +export const DiscreteWithMarks: Story = { + args: { step: 10, marks: true, valueLabelDisplay: "auto" }, + render: (args) => , +}; + +export const Range: Story = { + render: (args) => { + const [value, setValue] = React.useState([20, 80]); + return ( + setValue(v as number[])} + valueLabelDisplay="auto" + /> + ); + }, +}; + +export const Vertical: Story = { + args: { + orientation: "vertical", + min: 0, + max: 100, + step: 5, + marks: true, + valueLabelDisplay: "auto", + }, + render: (args) => ( +
+ +
+ ), +}; diff --git a/src/components/MUI/Inputs/Slider.tsx b/src/components/MUI/Inputs/Slider.tsx new file mode 100644 index 0000000..6f24ce4 --- /dev/null +++ b/src/components/MUI/Inputs/Slider.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiSlider, { SliderProps as MuiSliderProps } from "@mui/material/Slider"; + +export type SliderProps = MuiSliderProps; + +export const Slider = React.forwardRef( + (props, ref) => , +); + +Slider.displayName = "Slider"; diff --git a/src/components/MUI/Inputs/SpeedDial.stories.tsx b/src/components/MUI/Inputs/SpeedDial.stories.tsx new file mode 100644 index 0000000..0ae06b2 --- /dev/null +++ b/src/components/MUI/Inputs/SpeedDial.stories.tsx @@ -0,0 +1,43 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { SpeedDial } from "./SpeedDial"; +import SpeedDialIcon from "@mui/material/SpeedDialIcon"; +import SpeedDialAction from "@mui/material/SpeedDialAction"; +import FileCopyIcon from "@mui/icons-material/FileCopy"; +import SaveIcon from "@mui/icons-material/Save"; +import PrintIcon from "@mui/icons-material/Print"; +import ShareIcon from "@mui/icons-material/Share"; + +const meta: Meta = { + title: "MUI/Inputs/SpeedDial", + component: SpeedDial, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + ariaLabel: { control: "text" }, + direction: { control: "select", options: ["up", "down", "left", "right"] }, + FabProps: { control: false }, + open: { control: "boolean" }, + onClose: { control: false }, + onOpen: { control: false }, + }, + args: { ariaLabel: "SpeedDial", direction: "up", open: true }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => ( +
+ } + sx={{ position: "absolute", bottom: 16, right: 16 }} + > + } tooltipTitle="Copy" /> + } tooltipTitle="Save" /> + } tooltipTitle="Print" /> + } tooltipTitle="Share" /> + +
+ ), +}; diff --git a/src/components/MUI/Inputs/SpeedDial.tsx b/src/components/MUI/Inputs/SpeedDial.tsx new file mode 100644 index 0000000..abacb73 --- /dev/null +++ b/src/components/MUI/Inputs/SpeedDial.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiSpeedDial, { + SpeedDialProps as MuiSpeedDialProps, +} from "@mui/material/SpeedDial"; + +export type SpeedDialProps = MuiSpeedDialProps; + +export const SpeedDial = React.forwardRef( + (props, ref) => , +); + +SpeedDial.displayName = "SpeedDial"; diff --git a/src/components/MUI/Inputs/Switch.stories.tsx b/src/components/MUI/Inputs/Switch.stories.tsx new file mode 100644 index 0000000..0c07115 --- /dev/null +++ b/src/components/MUI/Inputs/Switch.stories.tsx @@ -0,0 +1,68 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import * as React from "react"; +import { Switch } from "./Switch"; + +type SWArgs = React.ComponentProps; + +const meta: Meta = { + title: "MUI/Inputs/Switch", + component: Switch, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + color: { + control: "select", + options: [ + "default", + "primary", + "secondary", + "success", + "error", + "info", + "warning", + ], + }, + size: { control: "select", options: ["small", "medium"] }, + disabled: { control: "boolean" }, + edge: { control: "select", options: [false, "start", "end"] }, + + checked: { control: false }, + onChange: { control: false }, + }, + args: { + color: "primary", + size: "medium", + disabled: false, + edge: false, + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { render: (args) => }; + +export const Controlled: Story = { + render: (args) => { + const [checked, setChecked] = React.useState(true); + return ( + setChecked(e.target.checked)} + /> + ); + }, +}; + +export const ColorsAndSizes: Story = { + render: (args) => ( +
+ + + + + + +
+ ), +}; diff --git a/src/components/MUI/Inputs/Switch.tsx b/src/components/MUI/Inputs/Switch.tsx new file mode 100644 index 0000000..567b57e --- /dev/null +++ b/src/components/MUI/Inputs/Switch.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiSwitch, { SwitchProps as MuiSwitchProps } from "@mui/material/Switch"; + +export type SwitchProps = MuiSwitchProps; + +export const Switch = React.forwardRef( + (props, ref) => , +); + +Switch.displayName = "Switch"; diff --git a/src/components/MUI/Inputs/TextField.stories.tsx b/src/components/MUI/Inputs/TextField.stories.tsx new file mode 100644 index 0000000..2140aeb --- /dev/null +++ b/src/components/MUI/Inputs/TextField.stories.tsx @@ -0,0 +1,195 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { TextField } from "./TextField"; + +type TFArgs = React.ComponentProps; + +const meta: Meta = { + title: "MUI/Inputs/TextField", + component: TextField, + tags: ["autodocs"], + parameters: { + controls: { expanded: true }, + layout: "padded", + }, + argTypes: { + variant: { + control: { type: "select" }, + options: ["outlined", "filled,", "standard"].map((s) => + s.replace(",", ""), + ), + }, + color: { + control: { type: "select" }, + options: ["primary", "secondary", "success", "error", "info", "warning"], + }, + size: { control: { type: "select" }, options: ["small", "medium"] }, + margin: { + control: { type: "select" }, + options: ["none", "dense", "normal"], + }, + + // Content & behavior + type: { control: "text" }, + label: { control: "text" }, + placeholder: { control: "text" }, + helperText: { control: "text" }, + error: { control: "boolean" }, + required: { control: "boolean" }, + disabled: { control: "boolean" }, + fullWidth: { control: "boolean" }, + + // Multiline + multiline: { control: "boolean" }, + rows: { control: { type: "number", min: 1, max: 12, step: 1 } }, + + // Keep value/onChange uncontrolled in Basic so demos are interactive + value: { control: false }, + onChange: { control: false }, + + // Advanced props out of Controls for clarity + InputProps: { control: false }, + InputLabelProps: { control: false }, + FormHelperTextProps: { control: false }, + sx: { control: false }, + }, + args: { + variant: "outlined", + color: "primary", + size: "medium", + margin: "none", + type: "text", + label: "Your name", + placeholder: "Type here…", + helperText: "", + error: false, + required: false, + disabled: false, + fullWidth: false, + multiline: false, + rows: 1, + }, +}; + +export default meta; +type Story = StoryObj; + +/** + * Basic interactive field driven by Controls. + */ +export const Basic: Story = { + render: (args) => , +}; + +/** + * Showcase the three variants. + */ +export const Variants: Story = { + render: (args) => ( +
+ + + +
+ ), + args: { color: "primary", helperText: "" }, +}; + +/** + * Sizes and colors examples. + */ +export const SizesAndColors: Story = { + render: (args) => ( +
+
+ + +
+
+ + +
+
+ ), + args: { variant: "outlined", helperText: "" }, +}; + +/** + * Common states: required, error, disabled, fullWidth. + */ +export const States: Story = { + render: (args) => ( +
+ + + +
+ +
+
+ ), + args: { variant: "outlined", color: "primary" }, +}; + +/** + * Multiline example. + */ +export const Multiline: Story = { + args: { + multiline: true, + rows: 4, + label: "Message", + placeholder: "Write a few lines…", + }, + render: (args) => , +}; + +/** + * Types: password, number, email, search. + */ +export const InputTypes: Story = { + render: (args) => ( +
+ + + + + +
+ ), + args: { variant: "outlined", helperText: "" }, +}; diff --git a/src/components/MUI/Inputs/TextField.tsx b/src/components/MUI/Inputs/TextField.tsx new file mode 100644 index 0000000..aa104ee --- /dev/null +++ b/src/components/MUI/Inputs/TextField.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiTextField, { + TextFieldProps as MuiTextFieldProps, +} from "@mui/material/TextField"; + +export type TextFieldProps = MuiTextFieldProps; + +export const TextField = React.forwardRef( + (props, ref) => , +); + +TextField.displayName = "TextField"; diff --git a/src/components/MUI/Inputs/ToggleButtonGroup.stories.tsx b/src/components/MUI/Inputs/ToggleButtonGroup.stories.tsx new file mode 100644 index 0000000..3b52d23 --- /dev/null +++ b/src/components/MUI/Inputs/ToggleButtonGroup.stories.tsx @@ -0,0 +1,78 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import * as React from "react"; +import { ToggleButtonGroup } from "./ToggleButtonGroup"; +import { ToggleButton } from "@mui/material"; + +type TBGArgs = React.ComponentProps; + +const meta: Meta = { + title: "MUI/Inputs/ToggleButtonGroup", + component: ToggleButtonGroup, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + color: { + control: "select", + options: [ + "standard", + "primary", + "secondary", + "success", + "error", + "info", + "warning", + ], + }, + size: { control: "select", options: ["small", "medium", "large"] }, + exclusive: { control: "boolean" }, + disabled: { control: "boolean" }, + + value: { control: false }, + onChange: { control: false }, + orientation: { control: "select", options: ["horizontal", "vertical"] }, + }, + args: { + color: "primary", + size: "medium", + exclusive: true, + disabled: false, + orientation: "horizontal", + }, +}; +export default meta; +type Story = StoryObj; + +export const ExclusiveControlled: Story = { + render: (args) => { + const [value, setValue] = React.useState("left"); + return ( + setValue(next)} + > + Left + Center + Right + + ); + }, +}; + +export const MultipleControlled: Story = { + args: { exclusive: false }, + render: (args) => { + const [value, setValue] = React.useState(["bold"]); + return ( + setValue(next)} + > + Bold + Italic + Underline + + ); + }, +}; diff --git a/src/components/MUI/Inputs/ToggleButtonGroup.tsx b/src/components/MUI/Inputs/ToggleButtonGroup.tsx new file mode 100644 index 0000000..0423f64 --- /dev/null +++ b/src/components/MUI/Inputs/ToggleButtonGroup.tsx @@ -0,0 +1,13 @@ +import * as React from "react"; +import MuiToggleButtonGroup, { + ToggleButtonGroupProps as MuiToggleButtonGroupProps, +} from "@mui/material/ToggleButtonGroup"; + +export type ToggleButtonGroupProps = MuiToggleButtonGroupProps; + +export const ToggleButtonGroup = React.forwardRef< + HTMLDivElement, + ToggleButtonGroupProps +>((props, ref) => ); + +ToggleButtonGroup.displayName = "ToggleButtonGroup"; diff --git a/src/components/MUI/Inputs/TransferList.stories.tsx b/src/components/MUI/Inputs/TransferList.stories.tsx new file mode 100644 index 0000000..11c5da9 --- /dev/null +++ b/src/components/MUI/Inputs/TransferList.stories.tsx @@ -0,0 +1,48 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { TransferList } from "./TransferList"; +// Vite raw import +import transferListSource from "./TransferList.tsx?raw"; + +const meta: Meta = { + title: "MUI/Inputs/TransferList", + component: TransferList, + tags: ["autodocs"], + parameters: { + controls: { expanded: true }, + layout: "padded", + }, + args: { + left: [ + "Apple", + "Banana", + "Cherry", + "Date", + "Fig", + "Grape", + "Kiwi", + "Lemon", + "Mango", + "Orange", + "Pear", + "Plum", + ], + right: ["Blueberry", "Raspberry", "Strawberry"], + titleLeft: "Available", + titleRight: "Chosen", + }, +}; +export default meta; + +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => , + parameters: { + docs: { + source: { + code: transferListSource, + language: "tsx", + }, + }, + }, +}; diff --git a/src/components/MUI/Inputs/TransferList.tsx b/src/components/MUI/Inputs/TransferList.tsx new file mode 100644 index 0000000..0436e79 --- /dev/null +++ b/src/components/MUI/Inputs/TransferList.tsx @@ -0,0 +1,105 @@ +import * as React from "react"; +import List from "@mui/material/List"; +import ListItem from "@mui/material/ListItem"; +import ListItemButton from "@mui/material/ListItemButton"; +import ListItemText from "@mui/material/ListItemText"; +import Checkbox from "@mui/material/Checkbox"; +import Button from "@mui/material/Button"; +import Paper from "@mui/material/Paper"; + +export type TransferListProps = { + left: string[]; + right: string[]; + onChange?: (left: string[], right: string[]) => void; + titleLeft?: string; + titleRight?: string; +}; + +export const TransferList: React.FC = ({ + left, + right, + onChange, + titleLeft = "Available", + titleRight = "Selected", +}) => { + const [leftItems, setLeftItems] = React.useState(left); + const [rightItems, setRightItems] = React.useState(right); + const [checked, setChecked] = React.useState([]); + + const leftChecked = checked.filter((v) => leftItems.includes(v)); + const rightChecked = checked.filter((v) => rightItems.includes(v)); + + const toggle = (value: string) => { + setChecked((prev) => + prev.includes(value) + ? prev.filter((v) => v !== value) + : prev.concat(value), + ); + }; + + const moveRight = () => { + const nextRight = rightItems.concat(leftChecked); + const nextLeft = leftItems.filter((v) => !leftChecked.includes(v)); + setRightItems(nextRight); + setLeftItems(nextLeft); + setChecked((prev) => prev.filter((v) => !leftChecked.includes(v))); + onChange?.(nextLeft, nextRight); + }; + + const moveLeft = () => { + const nextLeft = leftItems.concat(rightChecked); + const nextRight = rightItems.filter((v) => !rightChecked.includes(v)); + setLeftItems(nextLeft); + setRightItems(nextRight); + setChecked((prev) => prev.filter((v) => !rightChecked.includes(v))); + onChange?.(nextLeft, nextRight); + }; + + const renderList = (title: string, items: string[]) => ( + +
+ {title} +
+ + {items.map((value) => { + const checkedItem = checked.includes(value); + return ( + + toggle(value)} dense> + + + + + ); + })} + +
+ ); + + return ( +
+ {renderList(titleLeft, leftItems)} +
+ + +
+ {renderList(titleRight, rightItems)} +
+ ); +}; + +TransferList.displayName = "TransferList"; diff --git a/src/components/MUI/Layout/Box.stories.tsx b/src/components/MUI/Layout/Box.stories.tsx new file mode 100644 index 0000000..f9a72e8 --- /dev/null +++ b/src/components/MUI/Layout/Box.stories.tsx @@ -0,0 +1,70 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Box } from "./Box"; + +const meta: Meta = { + title: "MUI/Layout/Box", + component: Box, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + component: { control: "text" }, + p: { control: { type: "number", min: 0, max: 10, step: 0.5 } }, + m: { control: { type: "number", min: 0, max: 10, step: 0.5 } }, + bgcolor: { control: "text" }, + color: { control: "text" }, + borderRadius: { control: { type: "number", min: 0, max: 24, step: 1 } }, + }, + args: { + component: "div", + p: 2, + m: 0, + bgcolor: "background.paper", + color: "text.primary", + borderRadius: 1, + }, +}; +export default meta; + +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => ( + + Box content + + ), +}; + +export const Variants: Story = { + render: (args) => ( +
+ + Primary + + + Secondary + + + Success + +
+ ), +}; diff --git a/src/components/MUI/Layout/Box.tsx b/src/components/MUI/Layout/Box.tsx new file mode 100644 index 0000000..eaa781d --- /dev/null +++ b/src/components/MUI/Layout/Box.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiBox, { BoxProps as MuiBoxProps } from "@mui/material/Box"; + +export type BoxProps = MuiBoxProps; + +export const Box = React.forwardRef((props, ref) => ( + +)); + +Box.displayName = "Box"; diff --git a/src/components/MUI/Layout/Container.stories.tsx b/src/components/MUI/Layout/Container.stories.tsx new file mode 100644 index 0000000..471b62f --- /dev/null +++ b/src/components/MUI/Layout/Container.stories.tsx @@ -0,0 +1,55 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Container } from "./Container"; +import { Box } from "./Box"; + +const meta: Meta = { + title: "MUI/Layout/Container", + component: Container, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + maxWidth: { + control: "select", + options: [false, "xs", "sm", "md", "lg", "xl"], + }, + fixed: { control: "boolean" }, + disableGutters: { control: "boolean" }, + }, + args: { maxWidth: "md", fixed: false, disableGutters: false }, +}; +export default meta; + +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => ( + + + Content inside Container + + + ), +}; + +export const Sizes: Story = { + render: (args) => ( +
+ + sm + + + md + + + lg + +
+ ), +}; diff --git a/src/components/MUI/Layout/Container.tsx b/src/components/MUI/Layout/Container.tsx new file mode 100644 index 0000000..75a8c47 --- /dev/null +++ b/src/components/MUI/Layout/Container.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiContainer, { + ContainerProps as MuiContainerProps, +} from "@mui/material/Container"; + +export type ContainerProps = MuiContainerProps; + +export const Container = React.forwardRef( + (props, ref) => , +); + +Container.displayName = "Container"; diff --git a/src/components/MUI/Layout/Grid2.stories.tsx b/src/components/MUI/Layout/Grid2.stories.tsx new file mode 100644 index 0000000..dea538e --- /dev/null +++ b/src/components/MUI/Layout/Grid2.stories.tsx @@ -0,0 +1,64 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { GridV2 } from "./Grid2"; +import { Box } from "./Box"; + +const meta: Meta = { + title: "MUI/Layout/Grid v2", + component: GridV2, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + spacing: { control: { type: "number", min: 0, max: 10, step: 0.5 } }, + columns: { control: { type: "number", min: 1, max: 24, step: 1 } }, + }, + args: { spacing: 2, columns: 12 }, +}; +export default meta; + +type Story = StoryObj; + +const Item = ({ children }: { children: React.ReactNode }) => ( + + {children} + +); + +export const Basic: Story = { + render: (args) => ( + + + xs=4 + + + xs=4 + + + xs=4 + + + ), +}; + +export const Responsive: Story = { + render: (args) => ( + + + xs=12 sm=6 md=4 + + + xs=12 sm=6 md=4 + + + xs=12 sm=12 md=4 + + + ), +}; diff --git a/src/components/MUI/Layout/Grid2.tsx b/src/components/MUI/Layout/Grid2.tsx new file mode 100644 index 0000000..d434f5e --- /dev/null +++ b/src/components/MUI/Layout/Grid2.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import Grid2, { Grid2Props } from "@mui/material/Grid2"; + +export type GridV2Props = Grid2Props; + +export const GridV2 = React.forwardRef((props, ref) => ( + +)); + +GridV2.displayName = "GridV2"; diff --git a/src/components/MUI/Layout/ImageList.stories.tsx b/src/components/MUI/Layout/ImageList.stories.tsx new file mode 100644 index 0000000..b060224 --- /dev/null +++ b/src/components/MUI/Layout/ImageList.stories.tsx @@ -0,0 +1,82 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { ImageList } from "./ImageList"; + +import diamond from "../../../public/images/diamond.jpg"; +import bessy from "../../../public/images/bessy.jpg"; +import soleil from "../../../public/images/soleil.jpg"; +import shanghai from "../../../public/images/shanghai.jpg"; +import ImageListItemBar from "@mui/material/ImageListItemBar"; +import ImageListItem from "@mui/material/ImageListItem"; + +const items = [ + { + img: shanghai, + title: "Shanghai", + }, + { + img: diamond, + title: "Diamond", + }, + { + img: soleil, + title: "Soleil", + }, + { + img: bessy, + title: "Bessy", + }, +]; + +const meta: Meta = { + title: "MUI/Layout/ImageList", + component: ImageList, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + cols: { control: { type: "number", min: 1, max: 6, step: 1 } }, + rowHeight: { control: { type: "number", min: 80, max: 400, step: 10 } }, + gap: { control: { type: "number", min: 0, max: 32, step: 1 } }, + variant: { + control: "select", + options: ["masonry", "quilted", "standard", "woven"], + }, + }, + args: { cols: 3, rowHeight: 164, gap: 8, variant: "standard" }, +}; +export default meta; + +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => ( + + {items.map((it) => ( + + {it.title} + + + ))} + + ), +}; + +export const Masonry: Story = { + args: { variant: "masonry", cols: 3, gap: 8 }, + render: (args) => ( + + {items.map((it) => ( + + {it.title} + + ))} + + ), +}; diff --git a/src/components/MUI/Layout/ImageList.tsx b/src/components/MUI/Layout/ImageList.tsx new file mode 100644 index 0000000..094c5c3 --- /dev/null +++ b/src/components/MUI/Layout/ImageList.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiImageList, { + ImageListProps as MuiImageListProps, +} from "@mui/material/ImageList"; + +export type ImageListProps = MuiImageListProps; + +export const ImageList = React.forwardRef( + (props, ref) => , +); + +ImageList.displayName = "ImageList"; diff --git a/src/components/MUI/Layout/Stack.stories.tsx b/src/components/MUI/Layout/Stack.stories.tsx new file mode 100644 index 0000000..d3b7518 --- /dev/null +++ b/src/components/MUI/Layout/Stack.stories.tsx @@ -0,0 +1,77 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Stack } from "./Stack"; +import { Box } from "./Box"; + +const meta: Meta = { + title: "MUI/Layout/Stack", + component: Stack, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + direction: { + control: "select", + options: ["row", "row-reverse", "column", "column-reverse"], + }, + spacing: { control: { type: "number", min: 0, max: 10, step: 0.5 } }, + divider: { control: false }, + alignItems: { + control: "select", + options: ["stretch", "flex-start", "center", "flex-end", "baseline"], + }, + justifyContent: { + control: "select", + options: [ + "flex-start", + "center", + "flex-end", + "space-between", + "space-around", + "space-evenly", + ], + }, + }, + args: { + direction: "row", + spacing: 2, + alignItems: "center", + justifyContent: "flex-start", + }, +}; +export default meta; + +type Story = StoryObj; + +const Item = ({ children }: { children: React.ReactNode }) => ( + + {children} + +); + +export const Basic: Story = { + render: (args) => ( + + One + Two + Three + + ), +}; + +export const Vertical: Story = { + args: { direction: "column" }, + render: (args) => ( + + A + B + C + + ), +}; diff --git a/src/components/MUI/Layout/Stack.tsx b/src/components/MUI/Layout/Stack.tsx new file mode 100644 index 0000000..2006df5 --- /dev/null +++ b/src/components/MUI/Layout/Stack.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiStack, { StackProps as MuiStackProps } from "@mui/material/Stack"; + +export type StackProps = MuiStackProps; + +export const Stack = React.forwardRef( + (props, ref) => , +); + +Stack.displayName = "Stack"; diff --git a/src/components/MUI/Navigation/AppBar.stories.tsx b/src/components/MUI/Navigation/AppBar.stories.tsx new file mode 100644 index 0000000..30b90be --- /dev/null +++ b/src/components/MUI/Navigation/AppBar.stories.tsx @@ -0,0 +1,58 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { AppBar } from "./AppBar"; +import MenuIcon from "@mui/icons-material/Menu"; +import { IconButton } from "../DataDisplay/IconButton"; +import Toolbar from "@mui/material/Toolbar"; +import { Typography } from "../DataDisplay/Typography"; +import { Button } from "../Inputs/Button"; + +const meta: Meta = { + title: "MUI/Navigation/AppBar", + component: AppBar, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "fullscreen" }, + argTypes: { + color: { + control: "select", + options: [ + "default", + "primary", + "secondary", + "success", + "error", + "info", + "warning", + "transparent", + "inherit", + ], + }, + position: { + control: "select", + options: ["fixed", "absolute", "sticky", "static", "relative"], + }, + }, + args: { color: "primary", position: "static" }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => ( + + + + + + + Title + + + + + ), +}; diff --git a/src/components/MUI/Navigation/AppBar.tsx b/src/components/MUI/Navigation/AppBar.tsx new file mode 100644 index 0000000..99b3971 --- /dev/null +++ b/src/components/MUI/Navigation/AppBar.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiAppBar, { AppBarProps as MuiAppBarProps } from "@mui/material/AppBar"; + +export type AppBarProps = MuiAppBarProps; + +export const AppBar = React.forwardRef( + (props, ref) => , +); + +AppBar.displayName = "AppBar"; diff --git a/src/components/MUI/Navigation/BottomNavigation.stories.tsx b/src/components/MUI/Navigation/BottomNavigation.stories.tsx new file mode 100644 index 0000000..9b6c04f --- /dev/null +++ b/src/components/MUI/Navigation/BottomNavigation.stories.tsx @@ -0,0 +1,39 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import * as React from "react"; +import { BottomNavigation } from "./BottomNavigation"; +import RestoreIcon from "@mui/icons-material/Restore"; +import FavoriteIcon from "@mui/icons-material/Favorite"; +import LocationOnIcon from "@mui/icons-material/LocationOn"; +import BottomNavigationAction from "@mui/material/BottomNavigationAction"; + +const meta: Meta = { + title: "MUI/Navigation/BottomNavigation", + component: BottomNavigation, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + showLabels: { control: "boolean" }, + value: { control: false }, + onChange: { control: false }, + }, + args: { showLabels: true }, +}; +export default meta; +type Story = StoryObj; + +export const Controlled: Story = { + render: (args) => { + const [value, setValue] = React.useState(0); + return ( + setValue(v)} + > + } /> + } /> + } /> + + ); + }, +}; diff --git a/src/components/MUI/Navigation/BottomNavigation.tsx b/src/components/MUI/Navigation/BottomNavigation.tsx new file mode 100644 index 0000000..8030005 --- /dev/null +++ b/src/components/MUI/Navigation/BottomNavigation.tsx @@ -0,0 +1,13 @@ +import * as React from "react"; +import MuiBottomNavigation, { + BottomNavigationProps as MuiBottomNavigationProps, +} from "@mui/material/BottomNavigation"; + +export type BottomNavigationProps = MuiBottomNavigationProps; + +export const BottomNavigation = React.forwardRef< + HTMLDivElement, + BottomNavigationProps +>((props, ref) => ); + +BottomNavigation.displayName = "BottomNavigation"; diff --git a/src/components/MUI/Navigation/Breadcrumbs.stories.tsx b/src/components/MUI/Navigation/Breadcrumbs.stories.tsx new file mode 100644 index 0000000..bcd589e --- /dev/null +++ b/src/components/MUI/Navigation/Breadcrumbs.stories.tsx @@ -0,0 +1,95 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Breadcrumbs } from "./Breadcrumbs"; +import HomeIcon from "@mui/icons-material/Home"; +import WhatshotIcon from "@mui/icons-material/Whatshot"; +import GrainIcon from "@mui/icons-material/Grain"; +import { Link } from "./Link"; +import { Typography } from "../DataDisplay/Typography"; + +const meta: Meta = { + title: "MUI/Navigation/Breadcrumbs", + component: Breadcrumbs, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + separator: { control: "text" }, + maxItems: { control: { type: "number", min: 2, max: 10, step: 1 } }, + itemsBeforeCollapse: { + control: { type: "number", min: 0, max: 5, step: 1 }, + }, + itemsAfterCollapse: { + control: { type: "number", min: 0, max: 5, step: 1 }, + }, + }, + args: { + separator: "/", + maxItems: 8, + itemsBeforeCollapse: 1, + itemsAfterCollapse: 1, + }, +}; +export default meta; + +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => ( + + Home + Library + Data + + ), +}; + +export const CustomSeparator: Story = { + args: { separator: "›" }, + render: (args) => ( + + #Home + #Catalog + #Accessories + Cables + + ), +}; + +export const WithIcons: Story = { + render: (args) => ( + + + + Home + + + + Trending + + + + Details + + + ), +}; + +export const Collapsed: Story = { + args: { + maxItems: 3, + itemsBeforeCollapse: 1, + itemsAfterCollapse: 1, + separator: "/", + }, + render: (args) => ( + + #Home + #Section + #Category + #Subcategory + Item + + ), +}; diff --git a/src/components/MUI/Navigation/Breadcrumbs.tsx b/src/components/MUI/Navigation/Breadcrumbs.tsx new file mode 100644 index 0000000..10b4e5f --- /dev/null +++ b/src/components/MUI/Navigation/Breadcrumbs.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiBreadcrumbs, { + BreadcrumbsProps as MuiBreadcrumbsProps, +} from "@mui/material/Breadcrumbs"; + +export type BreadcrumbsProps = MuiBreadcrumbsProps; + +export const Breadcrumbs = React.forwardRef( + (props, ref) => , +); + +Breadcrumbs.displayName = "Breadcrumbs"; diff --git a/src/components/MUI/Navigation/Drawer.stories.tsx b/src/components/MUI/Navigation/Drawer.stories.tsx new file mode 100644 index 0000000..ab8f3c7 --- /dev/null +++ b/src/components/MUI/Navigation/Drawer.stories.tsx @@ -0,0 +1,54 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import * as React from "react"; +import { Drawer } from "./Drawer"; +import { Button } from "../Inputs/Button"; +import { List } from "../DataDisplay/List"; +import ListItem from "@mui/material/ListItem"; +import ListItemText from "@mui/material/ListItemText"; + +const meta: Meta = { + title: "MUI/Navigation/Drawer", + component: Drawer, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + anchor: { control: "select", options: ["left", "right", "top", "bottom"] }, + }, + args: { anchor: "left" }, +}; +export default meta; +type Story = StoryObj; + +export const Temporary: Story = { + render: (args) => { + const [open, setOpen] = React.useState(false); + return ( +
+ + setOpen(false)}> +
+ + + + + + + + + + + +
+
+
+ ); + }, +}; diff --git a/src/components/MUI/Navigation/Drawer.tsx b/src/components/MUI/Navigation/Drawer.tsx new file mode 100644 index 0000000..a32fc00 --- /dev/null +++ b/src/components/MUI/Navigation/Drawer.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiDrawer, { DrawerProps as MuiDrawerProps } from "@mui/material/Drawer"; + +export type DrawerProps = MuiDrawerProps; + +export const Drawer = React.forwardRef( + (props, ref) => , +); + +Drawer.displayName = "Drawer"; diff --git a/src/components/MUI/Navigation/Link.stories.tsx b/src/components/MUI/Navigation/Link.stories.tsx new file mode 100644 index 0000000..dcc0658 --- /dev/null +++ b/src/components/MUI/Navigation/Link.stories.tsx @@ -0,0 +1,40 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Link } from "./Link"; + +const meta: Meta = { + title: "MUI/Navigation/Link", + component: Link, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + underline: { control: "select", options: ["none", "hover", "always"] }, + color: { + control: "select", + options: [ + "inherit", + "primary", + "secondary", + "success", + "error", + "info", + "warning", + ], + }, + href: { control: "text" }, + target: { control: "select", options: ["", "_self", "_blank"] }, + rel: { control: "text" }, + children: { name: "text", control: "text" }, + }, + args: { + underline: "hover", + color: "primary", + href: "https://mui.com/", + target: "_blank", + rel: "noopener noreferrer", + children: "MUI docs", + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { render: (args) => }; diff --git a/src/components/MUI/Navigation/Link.tsx b/src/components/MUI/Navigation/Link.tsx new file mode 100644 index 0000000..62ac326 --- /dev/null +++ b/src/components/MUI/Navigation/Link.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiLink, { LinkProps as MuiLinkProps } from "@mui/material/Link"; + +export type LinkProps = MuiLinkProps; + +export const Link = React.forwardRef( + (props, ref) => , +); + +Link.displayName = "Link"; diff --git a/src/components/MUI/Navigation/Menu.stories.tsx b/src/components/MUI/Navigation/Menu.stories.tsx new file mode 100644 index 0000000..090d116 --- /dev/null +++ b/src/components/MUI/Navigation/Menu.stories.tsx @@ -0,0 +1,99 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Menu } from "./Menu"; +import SaveIcon from "@mui/icons-material/Save"; +import SendIcon from "@mui/icons-material/Send"; +import React from "react"; +import { Button } from "../Inputs/Button"; +import MenuItem from "@mui/material/MenuItem"; +import ListItemIcon from "@mui/material/ListItemIcon"; + +const originMap = { + tl: { vertical: "top", horizontal: "left" }, + tc: { vertical: "top", horizontal: "center" }, + tr: { vertical: "top", horizontal: "right" }, + bl: { vertical: "bottom", horizontal: "left" }, + bc: { vertical: "bottom", horizontal: "center" }, + br: { vertical: "bottom", horizontal: "right" }, +} as const; + +const meta: Meta = { + title: "MUI/Navigation/Menu", + component: Menu, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + anchorOrigin: { + control: "select", + options: Object.keys(originMap), + mapping: originMap, + }, + transformOrigin: { + control: "select", + options: Object.keys(originMap), + mapping: originMap, + }, + keepMounted: { control: "boolean" }, + variant: { control: "select", options: ["selectedMenu", "menu"] }, + }, + args: { + anchorOrigin: "bl", + transformOrigin: "tl", + keepMounted: false, + variant: "menu", + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => { + const [anchorEl, setAnchorEl] = React.useState(null); + const open = Boolean(anchorEl); + return ( +
+ + setAnchorEl(null)} + > + setAnchorEl(null)}>Profile + setAnchorEl(null)}>My account + setAnchorEl(null)}>Logout + +
+ ); + }, +}; + +export const WithIcons: Story = { + render: (args) => { + const [anchorEl, setAnchorEl] = React.useState(null); + const open = Boolean(anchorEl); + return ( +
+ + setAnchorEl(null)} + > + setAnchorEl(null)}> + + + + Save + + setAnchorEl(null)}> + + + + Send + + +
+ ); + }, +}; diff --git a/src/components/MUI/Navigation/Menu.tsx b/src/components/MUI/Navigation/Menu.tsx new file mode 100644 index 0000000..3d95d69 --- /dev/null +++ b/src/components/MUI/Navigation/Menu.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiMenu, { MenuProps as MuiMenuProps } from "@mui/material/Menu"; + +export type MenuProps = MuiMenuProps; + +export const Menu = React.forwardRef( + (props, ref) => , +); + +Menu.displayName = "Menu"; diff --git a/src/components/MUI/Navigation/Pagination.stories.tsx b/src/components/MUI/Navigation/Pagination.stories.tsx new file mode 100644 index 0000000..c49e1de --- /dev/null +++ b/src/components/MUI/Navigation/Pagination.stories.tsx @@ -0,0 +1,41 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Pagination } from "./Pagination"; +import React from "react"; + +const meta: Meta = { + title: "MUI/Navigation/Pagination", + component: Pagination, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + count: { control: { type: "number", min: 1, max: 20, step: 1 } }, + page: { control: false }, + onChange: { control: false }, + color: { control: "select", options: ["primary", "secondary", "standard"] }, + variant: { control: "select", options: ["text", "outlined"] }, + shape: { control: "select", options: ["rounded", "circular"] }, + size: { control: "select", options: ["small", "medium", "large"] }, + showFirstButton: { control: "boolean" }, + showLastButton: { control: "boolean" }, + disabled: { control: "boolean" }, + }, + args: { + count: 10, + color: "primary", + variant: "outlined", + shape: "rounded", + size: "medium", + showFirstButton: false, + showLastButton: false, + disabled: false, + }, +}; +export default meta; +type Story = StoryObj; + +export const Controlled: Story = { + render: (args) => { + const [page, setPage] = React.useState(1); + return setPage(p)} />; + }, +}; diff --git a/src/components/MUI/Navigation/Pagination.tsx b/src/components/MUI/Navigation/Pagination.tsx new file mode 100644 index 0000000..40d9dd0 --- /dev/null +++ b/src/components/MUI/Navigation/Pagination.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiPagination, { + PaginationProps as MuiPaginationProps, +} from "@mui/material/Pagination"; + +export type PaginationProps = MuiPaginationProps; + +export const Pagination = React.forwardRef( + (props, ref) => , +); + +Pagination.displayName = "Pagination"; diff --git a/src/components/MUI/Navigation/Stepper.stories.tsx b/src/components/MUI/Navigation/Stepper.stories.tsx new file mode 100644 index 0000000..e8597a7 --- /dev/null +++ b/src/components/MUI/Navigation/Stepper.stories.tsx @@ -0,0 +1,104 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Stepper } from "./Stepper"; +import React from "react"; +import StepLabel from "@mui/material/StepLabel"; +import Step from "@mui/material/Step"; +import { Button } from "../Inputs/Button"; +import StepContent from "@mui/material/StepContent"; + +const steps = [ + "Select campaign settings", + "Create an ad group", + "Create an ad", +]; + +const meta: Meta = { + title: "MUI/Navigation/Stepper", + component: Stepper, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + orientation: { control: "select", options: ["horizontal", "vertical"] }, + alternativeLabel: { control: "boolean" }, + activeStep: { + control: { type: "number", min: 0, max: steps.length - 1, step: 1 }, + }, + }, + args: { orientation: "horizontal", alternativeLabel: false, activeStep: 0 }, +}; +export default meta; +type Story = StoryObj; + +export const Controlled: Story = { + render: (args) => { + const [active, setActive] = React.useState(0); + return ( +
+ + {steps.map((label) => ( + + {label} + + ))} + +
+ + +
+
+ ); + }, +}; + +export const Vertical: Story = { + args: { orientation: "vertical" }, + render: (args) => { + const [active, setActive] = React.useState(0); + return ( +
+ + {steps.map((label, idx) => ( + + {label} + +
+ + +
+
+
+ ))} +
+
+ ); + }, +}; + +export const AlternativeLabel: Story = { + args: { alternativeLabel: true }, + render: (args) => ( + + {steps.map((label) => ( + + {label} + + ))} + + ), +}; diff --git a/src/components/MUI/Navigation/Stepper.tsx b/src/components/MUI/Navigation/Stepper.tsx new file mode 100644 index 0000000..68c7fe2 --- /dev/null +++ b/src/components/MUI/Navigation/Stepper.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiStepper, { + StepperProps as MuiStepperProps, +} from "@mui/material/Stepper"; + +export type StepperProps = MuiStepperProps; + +export const Stepper = React.forwardRef( + (props, ref) => , +); + +Stepper.displayName = "Stepper"; diff --git a/src/components/MUI/Navigation/Tabs.stories.tsx b/src/components/MUI/Navigation/Tabs.stories.tsx new file mode 100644 index 0000000..d1756a8 --- /dev/null +++ b/src/components/MUI/Navigation/Tabs.stories.tsx @@ -0,0 +1,64 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Tabs } from "./Tabs"; +import React from "react"; +import Tab from "@mui/material/Tab"; + +const meta: Meta = { + title: "MUI/Navigation/Tabs", + component: Tabs, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + orientation: { control: "select", options: ["horizontal", "vertical"] }, + variant: { + control: "select", + options: ["standard", "scrollable", "fullWidth"], + }, + textColor: { + control: "select", + options: ["inherit", "primary", "secondary"], + }, + indicatorColor: { control: "select", options: ["primary", "secondary"] }, + value: { control: false }, + onChange: { control: false }, + }, + args: { + orientation: "horizontal", + variant: "standard", + textColor: "primary", + indicatorColor: "primary", + }, +}; +export default meta; +type Story = StoryObj; + +export const Controlled: Story = { + render: (args) => { + const [value, setValue] = React.useState(0); + return ( +
+ setValue(v)}> + + + + +
+ ); + }, +}; + +export const Vertical: Story = { + args: { orientation: "vertical" }, + render: (args) => { + const [value, setValue] = React.useState(0); + return ( +
+ setValue(v)}> + + + + +
+ ); + }, +}; diff --git a/src/components/MUI/Navigation/Tabs.tsx b/src/components/MUI/Navigation/Tabs.tsx new file mode 100644 index 0000000..6573bb0 --- /dev/null +++ b/src/components/MUI/Navigation/Tabs.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiTabs, { TabsProps as MuiTabsProps } from "@mui/material/Tabs"; + +export type TabsProps = MuiTabsProps; + +export const Tabs = React.forwardRef( + (props, ref) => , +); + +Tabs.displayName = "Tabs"; diff --git a/src/components/MUI/Surfaces/Accordion.stories.tsx b/src/components/MUI/Surfaces/Accordion.stories.tsx new file mode 100644 index 0000000..27ea1f7 --- /dev/null +++ b/src/components/MUI/Surfaces/Accordion.stories.tsx @@ -0,0 +1,78 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import AccordionSummary from "@mui/material/AccordionSummary"; +import AccordionDetails from "@mui/material/AccordionDetails"; +import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; +import Typography from "@mui/material/Typography"; +import { Accordion } from "./Accordion"; + +const meta: Meta = { + title: "MUI/Surfaces/Accordion", + component: Accordion, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + disabled: { control: "boolean" }, + disableGutters: { control: "boolean" }, + square: { control: "boolean" }, + expanded: { control: false }, + defaultExpanded: { control: "boolean" }, + }, + args: { + disabled: false, + disableGutters: false, + square: false, + defaultExpanded: false, + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => ( + + }> + Summary + + + Details + + + ), +}; + +export const Multiple: Story = { + render: (args: any) => ( +
+ + }> + Item 1 + + + Content 1 + + + + }> + Item 2 + + + Content 2 + + +
+ ), +}; + +export const Disabled: Story = { + args: { disabled: true }, + render: (args) => ( + + }> + Disabled + + + Cannot expand + + + ), +}; diff --git a/src/components/MUI/Surfaces/Accordion.tsx b/src/components/MUI/Surfaces/Accordion.tsx new file mode 100644 index 0000000..56649a6 --- /dev/null +++ b/src/components/MUI/Surfaces/Accordion.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiAccordion, { + AccordionProps as MuiAccordionProps, +} from "@mui/material/Accordion"; + +export type AccordionProps = MuiAccordionProps; + +export const Accordion = React.forwardRef( + (props, ref) => , +); + +Accordion.displayName = "Accordion"; diff --git a/src/components/MUI/Surfaces/Card.stories.tsx b/src/components/MUI/Surfaces/Card.stories.tsx new file mode 100644 index 0000000..ce073c8 --- /dev/null +++ b/src/components/MUI/Surfaces/Card.stories.tsx @@ -0,0 +1,66 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Card } from "./Card"; + +import CardContent from "@mui/material/CardContent"; +import CardActions from "@mui/material/CardActions"; +import CardMedia from "@mui/material/CardMedia"; +import Button from "@mui/material/Button"; +import Typography from "@mui/material/Typography"; +import Diamond from "../../../public/images/diamond.jpg"; + +const meta: Meta = { + title: "MUI/Surfaces/Card", + component: Card, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + variant: { control: "select", options: ["elevation", "outlined"] }, + raised: { control: "boolean" }, + elevation: { control: { type: "number", min: 0, max: 24, step: 1 } }, + sx: { control: false }, + }, + args: { + variant: "elevation", + raised: false, + elevation: 1, + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => ( + + + + + Card title + + + Some descriptive text to show typical card content area sizing. + + + + + + + + ), +}; + +export const Outlined: Story = { + args: { variant: "outlined", elevation: 0 }, + render: (args) => ( + + + Outlined card + + Uses the outlined variant with zero elevation. + + + + + + + ), +}; diff --git a/src/components/MUI/Surfaces/Card.tsx b/src/components/MUI/Surfaces/Card.tsx new file mode 100644 index 0000000..ab1ee4a --- /dev/null +++ b/src/components/MUI/Surfaces/Card.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiCard, { CardProps as MuiCardProps } from "@mui/material/Card"; + +export type CardProps = MuiCardProps; + +export const Card = React.forwardRef( + (props, ref) => , +); + +Card.displayName = "Card"; diff --git a/src/components/MUI/Surfaces/Paper.stories.tsx b/src/components/MUI/Surfaces/Paper.stories.tsx new file mode 100644 index 0000000..43f4d7c --- /dev/null +++ b/src/components/MUI/Surfaces/Paper.stories.tsx @@ -0,0 +1,44 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { Paper } from "./Paper"; + +const meta: Meta = { + title: "MUI/Surfaces/Paper", + component: Paper, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + variant: { control: "select", options: ["elevation", "outlined"] }, + elevation: { control: { type: "number", min: 0, max: 24, step: 1 } }, + square: { control: "boolean" }, + }, + args: { variant: "elevation", elevation: 1, square: false }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => ( + + Paper content + + ), +}; + +export const Elevations: Story = { + render: (args) => ( +
+ + elevation 0 + + + elevation 3 + + + elevation 8 + + + elevation 16 + +
+ ), +}; diff --git a/src/components/MUI/Surfaces/Paper.tsx b/src/components/MUI/Surfaces/Paper.tsx new file mode 100644 index 0000000..ce0e7a6 --- /dev/null +++ b/src/components/MUI/Surfaces/Paper.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiPaper, { PaperProps as MuiPaperProps } from "@mui/material/Paper"; + +export type PaperProps = MuiPaperProps; + +export const Paper = React.forwardRef( + (props, ref) => , +); + +Paper.displayName = "Paper"; diff --git a/src/components/MUI/Utils/ClickAwayListener.stories.tsx b/src/components/MUI/Utils/ClickAwayListener.stories.tsx new file mode 100644 index 0000000..7c0e088 --- /dev/null +++ b/src/components/MUI/Utils/ClickAwayListener.stories.tsx @@ -0,0 +1,81 @@ +import * as React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { ClickAwayListener } from "./ClickAwayListener"; +import { Box } from "../Layout/Box"; +import { Button } from "../Inputs/Button"; + +type ExtraArgs = { + content?: string; +}; +type Args = React.ComponentProps & ExtraArgs; + +const meta: Meta = { + title: "MUI/Utils/ClickAwayListener", + component: ClickAwayListener, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + disableReactTree: { control: "boolean" }, + mouseEvent: { + control: "select", + options: [ + "onClick", + "onMouseDown", + "onMouseUp", + "onPointerDown", + "onPointerUp", + false, + ], + }, + touchEvent: { + control: "select", + options: ["onTouchEnd", "onTouchStart", false], + }, + onClickAway: { control: false }, + children: { control: false }, + content: { control: "text" }, + }, + args: { + disableReactTree: false, + mouseEvent: "onClick", + touchEvent: "onTouchEnd", + content: "Click me, I will stay visible until you click outside.", + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args: Args) => { + const [open, setOpen] = React.useState(false); + const handleClick = () => setOpen((p) => !p); + const handleClickAway = () => setOpen(false); + return ( + + + + {open && ( + + {args.content} + + )} + + + ); + }, +}; diff --git a/src/components/MUI/Utils/ClickAwayListener.tsx b/src/components/MUI/Utils/ClickAwayListener.tsx new file mode 100644 index 0000000..5640c88 --- /dev/null +++ b/src/components/MUI/Utils/ClickAwayListener.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiClickAwayListener from "@mui/material/ClickAwayListener"; + +export type ClickAwayListenerProps = React.ComponentProps< + typeof MuiClickAwayListener +>; + +export const ClickAwayListener = (props: ClickAwayListenerProps) => ( + +); + +ClickAwayListener.displayName = "ClickAwayListener"; diff --git a/src/components/MUI/Utils/CssBaseline.stories.tsx b/src/components/MUI/Utils/CssBaseline.stories.tsx new file mode 100644 index 0000000..b700ff4 --- /dev/null +++ b/src/components/MUI/Utils/CssBaseline.stories.tsx @@ -0,0 +1,38 @@ +import * as React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; + +import { CssBaseline } from "./CssBaseline"; +import { Typography } from "../DataDisplay/Typography"; +import { Box } from "../Layout/Box"; + +type Args = React.ComponentProps; + +const meta: Meta = { + title: "MUI/Utils/CssBaseline", + component: CssBaseline, + tags: ["autodocs"], + parameters: { layout: "padded" }, + argTypes: { + enableColorScheme: { control: "boolean" }, + children: { control: false }, + }, + args: { + enableColorScheme: false, + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args: Args) => ( + <> + + + CssBaseline applied + + This area reflects baseline styles. + + + + ), +}; diff --git a/src/components/MUI/Utils/CssBaseline.tsx b/src/components/MUI/Utils/CssBaseline.tsx new file mode 100644 index 0000000..e69de29 diff --git a/src/components/MUI/Utils/Modal.stories.tsx b/src/components/MUI/Utils/Modal.stories.tsx new file mode 100644 index 0000000..5ae4375 --- /dev/null +++ b/src/components/MUI/Utils/Modal.stories.tsx @@ -0,0 +1,76 @@ +import * as React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { Modal } from "./Modal"; +import { Box } from "../Layout/Box"; +import { Typography } from "../DataDisplay/Typography"; +import { Button } from "../Inputs/Button"; + +type Args = React.ComponentProps & { + title?: string; + content?: string; +}; + +const meta: Meta = { + title: "MUI/Utils/Modal", + component: Modal, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + open: { control: false }, + onClose: { control: false }, + title: { control: "text" }, + content: { control: "text" }, + keepMounted: { control: "boolean" }, + hideBackdrop: { control: "boolean" }, + closeAfterTransition: { control: "boolean" }, + }, + args: { + title: "Text in a modal", + content: "Duis mollis, est non commodo luctus, nisi erat porttitor ligula.", + keepMounted: false, + hideBackdrop: false, + closeAfterTransition: false, + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args: Args) => { + const [open, setOpen] = React.useState(false); + const style = { + position: "absolute", + top: "50%", + left: "50%", + transform: "translate(-50%, -50%)", + minWidth: 320, + bgcolor: "background.paper", + border: "1px solid", + boxShadow: 24, + p: 3, + }; + return ( + <> + + setOpen(false)} + keepMounted={args.keepMounted} + hideBackdrop={args.hideBackdrop} + closeAfterTransition={args.closeAfterTransition} + aria-labelledby="modal-title" + aria-describedby="modal-description" + > + + + {args.title} + + + {args.content} + + + + + ); + }, +}; diff --git a/src/components/MUI/Utils/Modal.tsx b/src/components/MUI/Utils/Modal.tsx new file mode 100644 index 0000000..83a7fdb --- /dev/null +++ b/src/components/MUI/Utils/Modal.tsx @@ -0,0 +1,8 @@ +import * as React from "react"; +import MuiModal from "@mui/material/Modal"; + +export type ModalProps = React.ComponentProps; + +export const Modal = React.forwardRef( + (props, ref) => , +); diff --git a/src/components/MUI/Utils/NoSsr.stories.tsx b/src/components/MUI/Utils/NoSsr.stories.tsx new file mode 100644 index 0000000..2301044 --- /dev/null +++ b/src/components/MUI/Utils/NoSsr.stories.tsx @@ -0,0 +1,53 @@ +import * as React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { NoSsr } from "./NoSsr"; +import { Box } from "../Layout/Box"; + +type Args = React.ComponentProps & { + serverContent?: string; + clientContent?: string; +}; + +const meta: Meta = { + title: "MUI/Utils/NoSsr", + component: NoSsr, + tags: ["autodocs"], + parameters: { layout: "padded" }, + argTypes: { + defer: { control: "boolean" }, + fallback: { control: "text" }, + serverContent: { control: "text" }, + clientContent: { control: "text" }, + }, + args: { + defer: false, + fallback: null, + serverContent: "Server and Client", + clientContent: "Client only", + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args: Args) => ( +
+ + {args.serverContent} + + + + {args.clientContent} + + +
+ ), +}; diff --git a/src/components/MUI/Utils/NoSsr.tsx b/src/components/MUI/Utils/NoSsr.tsx new file mode 100644 index 0000000..29f349b --- /dev/null +++ b/src/components/MUI/Utils/NoSsr.tsx @@ -0,0 +1,8 @@ +import * as React from "react"; +import MuiNoSsr from "@mui/material/NoSsr"; + +export type NoSsrProps = React.ComponentProps; + +export const NoSsr = (props: NoSsrProps) => ; + +NoSsr.displayName = "NoSsr"; diff --git a/src/components/MUI/Utils/Popover.stories.tsx b/src/components/MUI/Utils/Popover.stories.tsx new file mode 100644 index 0000000..12f0caf --- /dev/null +++ b/src/components/MUI/Utils/Popover.stories.tsx @@ -0,0 +1,58 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import React from "react"; +import { Popover } from "./Popover"; +import { Button } from "../Inputs/Button"; + +const originMap = { + tl: { vertical: "top", horizontal: "left" }, + tc: { vertical: "top", horizontal: "center" }, + tr: { vertical: "top", horizontal: "right" }, + bl: { vertical: "bottom", horizontal: "left" }, + bc: { vertical: "bottom", horizontal: "center" }, + br: { vertical: "bottom", horizontal: "right" }, +} as const; + +const meta: Meta = { + title: "MUI/Utils/Popover", + component: Popover, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + anchorOrigin: { + control: "select", + options: Object.keys(originMap), + mapping: originMap, + }, + transformOrigin: { + control: "select", + options: Object.keys(originMap), + mapping: originMap, + }, + disablePortal: { control: "boolean" }, + }, + args: { anchorOrigin: "bl", transformOrigin: "tl", disablePortal: false }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args) => { + const [anchorEl, setAnchorEl] = React.useState(null); + const open = Boolean(anchorEl); + return ( +
+ + setAnchorEl(null)} + > +
Popover content
+
+
+ ); + }, +}; diff --git a/src/components/MUI/Utils/Popover.tsx b/src/components/MUI/Utils/Popover.tsx new file mode 100644 index 0000000..35b52f7 --- /dev/null +++ b/src/components/MUI/Utils/Popover.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiPopover, { + PopoverProps as MuiPopoverProps, +} from "@mui/material/Popover"; + +export type PopoverProps = MuiPopoverProps; + +export const Popover = React.forwardRef( + (props, ref) => , +); + +Popover.displayName = "Popover"; diff --git a/src/components/MUI/Utils/Popper.stories.tsx b/src/components/MUI/Utils/Popper.stories.tsx new file mode 100644 index 0000000..9d737c9 --- /dev/null +++ b/src/components/MUI/Utils/Popper.stories.tsx @@ -0,0 +1,85 @@ +import * as React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { Popper } from "./Popper"; +import { Button } from "../Inputs/Button"; +import { Fade } from "./Transitions"; +import { Box } from "../Layout/Box"; + +type Args = React.ComponentProps & { content?: string }; + +const meta: Meta = { + title: "MUI/Utils/Popper", + component: Popper, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + placement: { + control: "select", + options: [ + "bottom", + "top", + "right", + "left", + "bottom-start", + "bottom-end", + "top-start", + "top-end", + "right-start", + "right-end", + "left-start", + "left-end", + ], + }, + disablePortal: { control: "boolean" }, + keepMounted: { control: "boolean" }, + transition: { control: "boolean" }, + modifiers: { control: false }, + container: { control: false }, + anchorEl: { control: false }, + children: { control: false }, + content: { control: "text" }, + }, + args: { + placement: "bottom", + disablePortal: false, + keepMounted: false, + transition: true, + content: "The content of the Popper.", + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args: Args) => { + const [anchorEl, setAnchorEl] = React.useState(null); + const open = Boolean(anchorEl); + const id = open ? "demo-popper" : undefined; + const handleClick = (event: React.MouseEvent) => + setAnchorEl(anchorEl ? null : event.currentTarget); + return ( + <> + + + {({ TransitionProps }) => ( + + + {args.content} + + + )} + + + ); + }, +}; diff --git a/src/components/MUI/Utils/Popper.tsx b/src/components/MUI/Utils/Popper.tsx new file mode 100644 index 0000000..f0f477a --- /dev/null +++ b/src/components/MUI/Utils/Popper.tsx @@ -0,0 +1,8 @@ +import * as React from "react"; +import MuiPopper from "@mui/material/Popper"; + +export type PopperProps = React.ComponentProps; + +export const Popper = React.forwardRef( + (props, ref) => , +); diff --git a/src/components/MUI/Utils/Portal.stories.tsx b/src/components/MUI/Utils/Portal.stories.tsx new file mode 100644 index 0000000..1d88069 --- /dev/null +++ b/src/components/MUI/Utils/Portal.stories.tsx @@ -0,0 +1,52 @@ +import * as React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { Portal } from "./Portal"; +import { Button } from "../Inputs/Button"; +import { Box } from "../Layout/Box"; + +type Args = React.ComponentProps & { text?: string }; + +const meta: Meta = { + title: "MUI/Utils/Portal", + component: Portal, + tags: ["autodocs"], + parameters: { layout: "padded" }, + argTypes: { + disablePortal: { control: "boolean" }, + container: { control: false }, + children: { control: false }, + text: { control: "text" }, + }, + args: { + disablePortal: false, + text: "But I actually render here!", + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args: Args) => { + const container = React.useRef(null); + const [show, setShow] = React.useState(false); + return ( + <> + + + It looks like I will render here. + {show ? ( + container.current!} + disablePortal={args.disablePortal} + > + {args.text} + + ) : null} + + + + ); + }, +}; diff --git a/src/components/MUI/Utils/Portal.tsx b/src/components/MUI/Utils/Portal.tsx new file mode 100644 index 0000000..1bc3ad5 --- /dev/null +++ b/src/components/MUI/Utils/Portal.tsx @@ -0,0 +1,8 @@ +import * as React from "react"; +import MuiPortal from "@mui/material/Portal"; + +export type PortalProps = React.ComponentProps; + +export const Portal = (props: PortalProps) => ; + +Portal.displayName = "Portal"; diff --git a/src/components/MUI/Utils/TextareaAutosize.stories.tsx b/src/components/MUI/Utils/TextareaAutosize.stories.tsx new file mode 100644 index 0000000..4001c01 --- /dev/null +++ b/src/components/MUI/Utils/TextareaAutosize.stories.tsx @@ -0,0 +1,30 @@ +import * as React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { TextareaAutosize } from "./TextareaAutosize"; + +type Args = React.ComponentProps; + +const meta: Meta = { + title: "MUI/Utils/TextareaAutosize", + component: TextareaAutosize, + tags: ["autodocs"], + parameters: { controls: { expanded: true }, layout: "padded" }, + argTypes: { + minRows: { control: { type: "number", min: 1 } }, + maxRows: { control: { type: "number", min: 1 } }, + placeholder: { control: "text" }, + defaultValue: { control: "text" }, + }, + args: { + minRows: 3, + maxRows: 6, + placeholder: "Type here...", + defaultValue: "", + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args: Args) => , +}; diff --git a/src/components/MUI/Utils/TextareaAutosize.tsx b/src/components/MUI/Utils/TextareaAutosize.tsx new file mode 100644 index 0000000..7faa77a --- /dev/null +++ b/src/components/MUI/Utils/TextareaAutosize.tsx @@ -0,0 +1,10 @@ +import * as React from "react"; +import MuiTextareaAutosize from "@mui/material/TextareaAutosize"; + +export type TextareaAutosizeProps = React.ComponentProps< + typeof MuiTextareaAutosize +>; + +export const TextareaAutosize = (props: TextareaAutosizeProps) => ( + +); diff --git a/src/components/MUI/Utils/Transitions.stories.tsx b/src/components/MUI/Utils/Transitions.stories.tsx new file mode 100644 index 0000000..b2a3dba --- /dev/null +++ b/src/components/MUI/Utils/Transitions.stories.tsx @@ -0,0 +1,81 @@ +import * as React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { Fade, Grow, Slide, Collapse, Zoom } from "./Transitions"; + +import FormControlLabel from "@mui/material/FormControlLabel"; +import { Box } from "../Layout/Box"; +import { Switch } from "../Inputs/Switch"; + +type ExtraArgs = { + show?: boolean; + text?: string; + direction?: "left" | "right" | "up" | "down"; +}; +type Args = ExtraArgs; + +const meta: Meta = { + title: "MUI/Utils/Transitions", + tags: ["autodocs"], + parameters: { layout: "padded" }, + argTypes: { + show: { control: "boolean" }, + text: { control: "text" }, + direction: { control: "select", options: ["left", "right", "up", "down"] }, + }, + args: { + show: true, + text: "Transition content", + direction: "up", + }, +}; +export default meta; +type Story = StoryObj; + +const Icon = (text: string) => ( + + {text} + +); + +export const All: Story = { + render: (args: Args) => { + const [checked, setChecked] = React.useState(args.show ?? true); + return ( + + setChecked(e.target.checked)} + /> + } + label="Show" + /> + + {Icon("Fade")} + {Icon("Grow")} + + {Icon("Slide")} + + {Icon("Collapse")} + {Icon("Zoom")} + + + ); + }, +}; diff --git a/src/components/MUI/Utils/Transitions.tsx b/src/components/MUI/Utils/Transitions.tsx new file mode 100644 index 0000000..1b89be2 --- /dev/null +++ b/src/components/MUI/Utils/Transitions.tsx @@ -0,0 +1,24 @@ +import * as React from "react"; +import MuiFade from "@mui/material/Fade"; +import MuiGrow from "@mui/material/Grow"; +import MuiSlide from "@mui/material/Slide"; +import MuiCollapse from "@mui/material/Collapse"; +import MuiZoom from "@mui/material/Zoom"; + +export type FadeProps = React.ComponentProps; +export type GrowProps = React.ComponentProps; +export type SlideProps = React.ComponentProps; +export type CollapseProps = React.ComponentProps; +export type ZoomProps = React.ComponentProps; + +export const Fade = (props: FadeProps) => ; +export const Grow = (props: GrowProps) => ; +export const Slide = (props: SlideProps) => ; +export const Collapse = (props: CollapseProps) => ; +export const Zoom = (props: ZoomProps) => ; + +Fade.displayName = "Fade"; +Grow.displayName = "Grow"; +Slide.displayName = "Slide"; +Collapse.displayName = "Collapse"; +Zoom.displayName = "Zoom"; diff --git a/src/components/MUI/Utils/UseMediaQuery.stories.tsx b/src/components/MUI/Utils/UseMediaQuery.stories.tsx new file mode 100644 index 0000000..d3f7777 --- /dev/null +++ b/src/components/MUI/Utils/UseMediaQuery.stories.tsx @@ -0,0 +1,44 @@ +import * as React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { UseMediaQuery } from "./UseMediaQuery"; + +import { useTheme } from "@mui/material/styles"; +import { Box } from "../Layout/Box"; + +type Args = React.ComponentProps & { + useThemeBreakpoint?: boolean; + breakpoint?: "xs" | "sm" | "md" | "lg" | "xl"; +}; + +const meta: Meta = { + title: "MUI/Utils/useMediaQuery", + component: UseMediaQuery, + tags: ["autodocs"], + parameters: { layout: "padded" }, + argTypes: { + query: { control: "text" }, + useThemeBreakpoint: { control: "boolean" }, + breakpoint: { control: "select", options: ["xs", "sm", "md", "lg", "xl"] }, + }, + args: { + query: "(min-width:600px)", + useThemeBreakpoint: false, + breakpoint: "sm", + }, +}; +export default meta; +type Story = StoryObj; + +export const Basic: Story = { + render: (args: Args) => { + const theme = useTheme(); + const query = args.useThemeBreakpoint + ? theme.breakpoints.up(args.breakpoint || "sm") + : args.query; + return ( + + + + ); + }, +}; diff --git a/src/components/MUI/Utils/UseMediaQuery.tsx b/src/components/MUI/Utils/UseMediaQuery.tsx new file mode 100644 index 0000000..c5ac931 --- /dev/null +++ b/src/components/MUI/Utils/UseMediaQuery.tsx @@ -0,0 +1,9 @@ +import * as React from "react"; +import useMediaQueryHook from "@mui/material/useMediaQuery"; + +export type UseMediaQueryProps = { query: string }; + +export const UseMediaQuery = ({ query }: UseMediaQueryProps) => { + const matches = useMediaQueryHook(query); + return {`${query} matches: ${matches}`}; +}; From dfbbdfa956d5faf232dea0781966f8418d592c77 Mon Sep 17 00:00:00 2001 From: VictoriaBeilstenEdmands Date: Fri, 19 Dec 2025 16:45:55 +0000 Subject: [PATCH 03/10] Add Inter font to Diamond theme --- .storybook/preview.tsx | 2 +- package.json | 1 + pnpm-lock.yaml | 8 ++++++++ src/themes/DiamondTheme.ts | 14 ++++++++++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 685d506..750a7eb 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -1,7 +1,7 @@ import React from "react"; import { CssBaseline } from "@mui/material"; import type { Preview } from "@storybook/react"; - +import "@fontsource-variable/inter"; import { ThemeProvider } from "../src"; import { GenericTheme, DiamondTheme } from "../src"; diff --git a/package.json b/package.json index 49e5aad..dddfdeb 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "storybook:publish": "gh-pages -b storybook/publish -d storybook-static" }, "dependencies": { + "@fontsource-variable/inter": "^5.2.8", "keycloak-js": "^26.2.1", "react-icons": "^5.3.0", "utif": "^3.1.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 41c0aef..f72c5ac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ importers: '@emotion/styled': specifier: ^11.13.0 version: 11.14.0(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1) + '@fontsource-variable/inter': + specifier: ^5.2.8 + version: 5.2.8 '@jsonforms/core': specifier: ^3.6.0 version: 3.6.0 @@ -1078,6 +1081,9 @@ packages: resolution: {integrity: sha512-zSkKow6H5Kdm0ZUQUB2kV5JIXqoG0+uH5YADhaEHswm664N9Db8dXSi0nMJpacpMf+MyyglF1vnZohpEg5yUtg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@fontsource-variable/inter@5.2.8': + resolution: {integrity: sha512-kOfP2D+ykbcX/P3IFnokOhVRNoTozo5/JxhAIVYLpea/UBmCQ/YWPBfWIDuBImXX/15KH+eKh4xpEUyS2sQQGQ==} + '@gerrit0/mini-shiki@3.7.0': resolution: {integrity: sha512-7iY9wg4FWXmeoFJpUL2u+tsmh0d0jcEJHAIzVxl3TG4KL493JNnisdLAILZ77zcD+z3J0keEXZ+lFzUgzQzPDg==} @@ -5756,6 +5762,8 @@ snapshots: dependencies: levn: 0.4.1 + '@fontsource-variable/inter@5.2.8': {} + '@gerrit0/mini-shiki@3.7.0': dependencies: '@shikijs/engine-oniguruma': 3.7.0 diff --git a/src/themes/DiamondTheme.ts b/src/themes/DiamondTheme.ts index be9ebc5..11ad5ee 100644 --- a/src/themes/DiamondTheme.ts +++ b/src/themes/DiamondTheme.ts @@ -10,6 +10,20 @@ const dlsLogoBlue = "#202740"; const dlsLogoYellow = "#facf07"; const DiamondThemeOptions = mergeThemeOptions({ + typography: { + fontFamily: [ + "Inter Variable", + "Inter", + "system-ui", + "-apple-system", + '"Segoe UI"', + "Roboto", + "Helvetica", + "Arial", + "sans-serif", + ].join(","), + }, + logos: { normal: { src: logoImageLight, From 87b9899f6f559282863c3ea03eafcab4cfd3b2c5 Mon Sep 17 00:00:00 2001 From: VictoriaBeilstenEdmands Date: Wed, 7 Jan 2026 10:52:40 +0000 Subject: [PATCH 04/10] Add MUI stories --- .../MUI/DataDisplay/Avatar.stories.tsx | 92 ++++++--- .../MUI/DataDisplay/AvatarGroup.tsx | 16 ++ .../MUI/DataDisplay/Badge.stories.tsx | 1 - src/components/MUI/DataDisplay/Badge.tsx | 2 +- .../MUI/DataDisplay/Chip.stories.tsx | 39 ++-- src/components/MUI/DataDisplay/Chip.tsx | 1 - .../MUI/DataDisplay/Icon.stories.tsx | 15 +- .../MUI/DataDisplay/IconButton.stories.tsx | 186 +++++++++++++----- src/components/MUI/DataDisplay/IconButton.tsx | 1 - .../MUI/DataDisplay/List.stories.tsx | 36 +--- src/components/MUI/DataDisplay/List.tsx | 1 - .../MUI/DataDisplay/ListItem.stories.tsx | 75 +++++++ src/components/MUI/DataDisplay/ListItem.tsx | 13 ++ .../MUI/DataDisplay/ListItemAvatar.tsx | 15 ++ .../DataDisplay/ListItemButton.stories.tsx | 38 ++++ .../MUI/DataDisplay/ListItemButton.tsx | 15 ++ .../MUI/DataDisplay/ListItemIcon.stories.tsx | 34 ++++ .../MUI/DataDisplay/ListItemIcon.tsx | 14 ++ .../MUI/DataDisplay/ListItemText.stories.tsx | 35 ++++ .../MUI/DataDisplay/ListItemText.tsx | 15 ++ .../MUI/DataDisplay/ListSubheader.stories.tsx | 44 +++++ .../MUI/DataDisplay/ListSubheader.tsx | 14 ++ .../MUI/DataDisplay/MaterialIcons.stories.tsx | 74 ------- .../MUI/DataDisplay/MaterialIcons.tsx | 49 ----- .../MUI/DataDisplay/SvgIcon.stories.tsx | 163 +++++++++++++++ src/components/MUI/DataDisplay/SvgIcon.tsx | 12 ++ .../MUI/DataDisplay/Table.stories.tsx | 101 +++++----- .../MUI/DataDisplay/TableBody.stories.tsx | 41 ++++ src/components/MUI/DataDisplay/TableBody.tsx | 15 ++ .../MUI/DataDisplay/TableCell.stories.tsx | 50 +++++ src/components/MUI/DataDisplay/TableCell.tsx | 14 ++ .../DataDisplay/TableContainer.stories.tsx | 45 +++++ .../MUI/DataDisplay/TableContainer.tsx | 15 ++ .../MUI/DataDisplay/TableFooter.stories.tsx | 49 +++++ .../MUI/DataDisplay/TableFooter.tsx | 15 ++ .../MUI/DataDisplay/TableHead.stories.tsx | 41 ++++ src/components/MUI/DataDisplay/TableHead.tsx | 15 ++ .../DataDisplay/TablePagination.stories.tsx | 72 +++++++ .../MUI/DataDisplay/TablePagination.tsx | 15 ++ .../MUI/DataDisplay/TableRow.stories.tsx | 49 +++++ src/components/MUI/DataDisplay/TableRow.tsx | 13 ++ .../DataDisplay/TableSortLabel.stories.tsx | 80 ++++++++ .../MUI/DataDisplay/TableSortLabel.tsx | 15 ++ .../MUI/DataDisplay/Typography.stories.tsx | 4 +- src/components/MUI/DataDisplay/Typography.tsx | 2 +- src/components/MUI/Feedback/Alert.stories.tsx | 2 +- .../MUI/Feedback/Backdrop.stories.tsx | 4 +- .../MUI/Feedback/CircularProgress.stories.tsx | 1 - .../MUI/Feedback/CircularProgress.tsx | 1 - .../MUI/Feedback/Dialog.stories.tsx | 6 +- .../MUI/Feedback/Snackbar.stories.tsx | 4 +- .../MUI/Feedback/Tooltip.stories.tsx | 16 +- src/components/MUI/Feedback/Tooltip.tsx | 6 +- .../MUI/Inputs/Autocomplete.stories.tsx | 4 +- src/components/MUI/Inputs/Button.stories.tsx | 18 +- src/components/MUI/Inputs/Select.stories.tsx | 4 +- .../MUI/Inputs/SpeedDial.stories.tsx | 1 + .../MUI/Inputs/TextField.stories.tsx | 26 --- .../MUI/Inputs/ToggleButtonGroup.stories.tsx | 2 +- src/components/MUI/Layout/Grid2.stories.tsx | 12 +- src/components/MUI/Layout/Grid2.tsx | 10 +- .../MUI/Navigation/Breadcrumbs.stories.tsx | 8 +- .../MUI/Navigation/Drawer.stories.tsx | 4 +- .../MUI/Navigation/Menu.stories.tsx | 6 +- .../MUI/Surfaces/Accordion.stories.tsx | 2 +- src/components/MUI/Surfaces/Card.stories.tsx | 7 +- .../MUI/Utils/CssBaseline.stories.tsx | 3 +- src/components/MUI/Utils/CssBaseline.tsx | 8 + src/components/MUI/Utils/Popover.stories.tsx | 6 +- src/components/MUI/Utils/Popper.stories.tsx | 14 +- .../MUI/Utils/UseMediaQuery.stories.tsx | 1 - src/components/MUI/Utils/UseMediaQuery.tsx | 1 - src/types/raw.d.ts | 4 + 73 files changed, 1424 insertions(+), 408 deletions(-) create mode 100644 src/components/MUI/DataDisplay/AvatarGroup.tsx create mode 100644 src/components/MUI/DataDisplay/ListItem.stories.tsx create mode 100644 src/components/MUI/DataDisplay/ListItem.tsx create mode 100644 src/components/MUI/DataDisplay/ListItemAvatar.tsx create mode 100644 src/components/MUI/DataDisplay/ListItemButton.stories.tsx create mode 100644 src/components/MUI/DataDisplay/ListItemButton.tsx create mode 100644 src/components/MUI/DataDisplay/ListItemIcon.stories.tsx create mode 100644 src/components/MUI/DataDisplay/ListItemIcon.tsx create mode 100644 src/components/MUI/DataDisplay/ListItemText.stories.tsx create mode 100644 src/components/MUI/DataDisplay/ListItemText.tsx create mode 100644 src/components/MUI/DataDisplay/ListSubheader.stories.tsx create mode 100644 src/components/MUI/DataDisplay/ListSubheader.tsx delete mode 100644 src/components/MUI/DataDisplay/MaterialIcons.stories.tsx delete mode 100644 src/components/MUI/DataDisplay/MaterialIcons.tsx create mode 100644 src/components/MUI/DataDisplay/SvgIcon.stories.tsx create mode 100644 src/components/MUI/DataDisplay/SvgIcon.tsx create mode 100644 src/components/MUI/DataDisplay/TableBody.stories.tsx create mode 100644 src/components/MUI/DataDisplay/TableBody.tsx create mode 100644 src/components/MUI/DataDisplay/TableCell.stories.tsx create mode 100644 src/components/MUI/DataDisplay/TableCell.tsx create mode 100644 src/components/MUI/DataDisplay/TableContainer.stories.tsx create mode 100644 src/components/MUI/DataDisplay/TableContainer.tsx create mode 100644 src/components/MUI/DataDisplay/TableFooter.stories.tsx create mode 100644 src/components/MUI/DataDisplay/TableFooter.tsx create mode 100644 src/components/MUI/DataDisplay/TableHead.stories.tsx create mode 100644 src/components/MUI/DataDisplay/TableHead.tsx create mode 100644 src/components/MUI/DataDisplay/TablePagination.stories.tsx create mode 100644 src/components/MUI/DataDisplay/TablePagination.tsx create mode 100644 src/components/MUI/DataDisplay/TableRow.stories.tsx create mode 100644 src/components/MUI/DataDisplay/TableRow.tsx create mode 100644 src/components/MUI/DataDisplay/TableSortLabel.stories.tsx create mode 100644 src/components/MUI/DataDisplay/TableSortLabel.tsx create mode 100644 src/types/raw.d.ts diff --git a/src/components/MUI/DataDisplay/Avatar.stories.tsx b/src/components/MUI/DataDisplay/Avatar.stories.tsx index 26c6c6a..c9cc4ed 100644 --- a/src/components/MUI/DataDisplay/Avatar.stories.tsx +++ b/src/components/MUI/DataDisplay/Avatar.stories.tsx @@ -1,7 +1,11 @@ import type { Meta, StoryObj } from "@storybook/react"; import { Avatar } from "./Avatar"; -import Stack from "@mui/material/Stack"; -import Diamond from "../../../public/images/diamond.jpg"; +import FolderIcon from "@mui/icons-material/Folder"; +import PageviewIcon from "@mui/icons-material/Pageview"; +import AssignmentIcon from "@mui/icons-material/Assignment"; + +import { Stack } from "../Layout/Stack"; +import { AvatarGroup } from "./AvatarGroup"; const meta: Meta = { title: "MUI/Data Display/Avatar", @@ -20,56 +24,92 @@ const meta: Meta = { alt: { control: "text" }, src: { control: "text" }, imgProps: { control: false }, - sx: { control: false }, - width: { control: { type: "number", min: 24, max: 160, step: 4 } }, - height: { control: { type: "number", min: 24, max: 160, step: 4 } }, + sx: { control: "object" }, }, args: { variant: "circular", children: "AB", alt: "User avatar", src: "", - width: 56, - height: 56, + sx: { width: 56, height: 56, bgcolor: "primary" }, }, }; export default meta; -type Story = StoryObj; -const withSize = (args: any) => { - const { width, height, ...rest } = args; - return { ...rest, sx: { width, height } }; -}; +type Story = StoryObj; export const Basic: Story = { - render: (args) => {args.children}, + render: (args) => {args.children}, }; export const Variants: Story = { render: (args) => ( - AB - CD - EF + + AB + + + CD + + + EF + ), }; -export const WithImage: Story = { - args: { - src: Diamond, - alt: "Random", - children: "", - }, - render: (args) => , +export const WithIcon: Story = { + render: (args) => ( + + + + + + + + + + + + ), +}; + +export const Grouped: Story = { + render: (args) => ( + + AB + CD + EF + IJ + KL + + ), }; export const Sizes: Story = { render: (args) => ( - SM - MD - LG + + SM + + + MD + + + LG + ), }; diff --git a/src/components/MUI/DataDisplay/AvatarGroup.tsx b/src/components/MUI/DataDisplay/AvatarGroup.tsx new file mode 100644 index 0000000..1e1361d --- /dev/null +++ b/src/components/MUI/DataDisplay/AvatarGroup.tsx @@ -0,0 +1,16 @@ +import * as React from "react"; +import MuiAvatarGroup, { + AvatarGroupProps as MuiAvatarGroupProps, +} from "@mui/material/AvatarGroup"; + +export type AvatarGroupProps = MuiAvatarGroupProps; + +export const AvatarGroup = React.forwardRef( + ({ children, ...rest }, ref) => ( + + {children} + + ), +); + +AvatarGroup.displayName = "AvatarGroup"; diff --git a/src/components/MUI/DataDisplay/Badge.stories.tsx b/src/components/MUI/DataDisplay/Badge.stories.tsx index fc9a273..b9812a5 100644 --- a/src/components/MUI/DataDisplay/Badge.stories.tsx +++ b/src/components/MUI/DataDisplay/Badge.stories.tsx @@ -1,4 +1,3 @@ -// src/components/Badge/Badge.stories.tsx import type { Meta, StoryObj } from "@storybook/react"; import { Badge } from "./Badge"; import MailIcon from "@mui/icons-material/Mail"; diff --git a/src/components/MUI/DataDisplay/Badge.tsx b/src/components/MUI/DataDisplay/Badge.tsx index 4ec8846..aa686af 100644 --- a/src/components/MUI/DataDisplay/Badge.tsx +++ b/src/components/MUI/DataDisplay/Badge.tsx @@ -1,4 +1,3 @@ -// src/components/Badge/Badge.tsx import * as React from "react"; import MuiBadge, { BadgeProps as MuiBadgeProps } from "@mui/material/Badge"; @@ -7,4 +6,5 @@ export type BadgeProps = MuiBadgeProps; export const Badge = React.forwardRef( (props, ref) => , ); + Badge.displayName = "Badge"; diff --git a/src/components/MUI/DataDisplay/Chip.stories.tsx b/src/components/MUI/DataDisplay/Chip.stories.tsx index fe0c87c..31060d4 100644 --- a/src/components/MUI/DataDisplay/Chip.stories.tsx +++ b/src/components/MUI/DataDisplay/Chip.stories.tsx @@ -1,11 +1,10 @@ import type { Meta, StoryObj } from "@storybook/react"; import { Chip } from "./Chip"; - -import Stack from "@mui/material/Stack"; import SaveIcon from "@mui/icons-material/Save"; import SendIcon from "@mui/icons-material/Send"; import DeleteIcon from "@mui/icons-material/Delete"; import AddIcon from "@mui/icons-material/Add"; +import { Stack } from "../Layout/Stack"; const iconMap = { none: undefined, @@ -42,7 +41,6 @@ const meta: Meta = { clickable: { control: "boolean" }, disabled: { control: "boolean" }, - // Real props with mapping icon: { control: { type: "select" }, options: Object.keys(iconMap), @@ -53,21 +51,33 @@ const meta: Meta = { options: Object.keys(iconMap), mapping: iconMap, }, - onDelete: { control: false }, - sx: { control: false }, + + onDelete: { + control: { type: "select" }, + options: ["undefined", "deletable"], + mapping: { + undefined: undefined, + deletable: () => console.log("delete clicked"), + }, + }, + + sx: { control: "object" }, }, args: { label: "Chip", variant: "filled", - color: "default", + color: "primary", size: "medium", clickable: false, disabled: false, - icon: "none", - deleteIcon: "none", + icon: undefined, + deleteIcon: undefined, + sx: { width: 80 }, + onDelete: undefined, }, }; export default meta; + type Story = StoryObj; export const Basic: Story = { @@ -102,10 +112,10 @@ export const WithIcons: Story = { args: { color: "primary" }, render: (args) => ( - - - - + + + + ), }; @@ -116,16 +126,15 @@ export const Deletable: Story = { console.log("delete clicked")} /> console.log("delete clicked")} /> ), }; -``; diff --git a/src/components/MUI/DataDisplay/Chip.tsx b/src/components/MUI/DataDisplay/Chip.tsx index ffd2bbc..c62561c 100644 --- a/src/components/MUI/DataDisplay/Chip.tsx +++ b/src/components/MUI/DataDisplay/Chip.tsx @@ -1,4 +1,3 @@ -// src/components/Chip/Chip.tsx import * as React from "react"; import MuiChip, { ChipProps as MuiChipProps } from "@mui/material/Chip"; diff --git a/src/components/MUI/DataDisplay/Icon.stories.tsx b/src/components/MUI/DataDisplay/Icon.stories.tsx index 54230fa..ca488b7 100644 --- a/src/components/MUI/DataDisplay/Icon.stories.tsx +++ b/src/components/MUI/DataDisplay/Icon.stories.tsx @@ -30,6 +30,9 @@ const meta: Meta = { "info", "success", "warning", + "red", + "blue", + "green", ], }, fontSize: { @@ -45,7 +48,7 @@ const meta: Meta = { baseClassName: { control: false }, }, args: { - color: "inherit", + color: "primary", fontSize: "medium", children: "home", }, @@ -69,13 +72,3 @@ export const Colors: Story = { ), }; - -export const Sizes: Story = { - render: (args) => ( - <> - - - - - ), -}; diff --git a/src/components/MUI/DataDisplay/IconButton.stories.tsx b/src/components/MUI/DataDisplay/IconButton.stories.tsx index 6299136..a611d3f 100644 --- a/src/components/MUI/DataDisplay/IconButton.stories.tsx +++ b/src/components/MUI/DataDisplay/IconButton.stories.tsx @@ -1,86 +1,178 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { Icon } from "./Icon"; +import { IconButton } from "./IconButton"; +import { SvgIcon } from "./SvgIcon"; +import { Stack } from "../Layout/Stack"; -const meta: Meta = { +const ArrowDownPath = ( + + + +); + +const meta: Meta = { title: "MUI/Data Display/IconButton", - component: Icon, + component: IconButton, tags: ["autodocs"], parameters: { controls: { expanded: true }, layout: "padded" }, argTypes: { - // These rely on the Material Icons font if you use ligatures. - // If your project doesn't load the font, the text will render as plain text. color: { control: "select", options: [ "inherit", "primary", "secondary", - "action", - "disabled", + "success", "error", "info", - "success", "warning", ], + description: + "Applies theme color to the IconButton (icon inherits via context).", }, - fontSize: { + size: { control: "select", - options: ["inherit", "small", "medium", "large"], + options: ["small", "medium", "large"], + description: "IconButton size. Icon inside can also set fontSize.", }, - baseClassName: { control: "text" }, - children: { name: "ligature/text", control: "text" }, + edge: { + control: "select", + options: [false, "start", "end"], + description: "Move the button to the edge of a container for alignment.", + }, + disabled: { control: "boolean" }, + "aria-label": { + control: "text", + name: "aria-label", + description: "Accessible label for screen readers.", + }, + sx: { control: "object", description: "MUI `sx` prop for ad‑hoc styling." }, + + children: { control: false }, }, args: { - children: "home", color: "inherit", - fontSize: "medium", - baseClassName: "material-icons", // if you load the Material Icons font + size: "medium", + edge: false, + disabled: false, + "aria-label": "arrow down", + sx: undefined, }, }; export default meta; + type Story = StoryObj; export const Basic: Story = { - render: (args) => , + render: (args) => {ArrowDownPath}, }; export const Sizes: Story = { render: (args) => ( - <> - - home - {" "} - - home - {" "} - - home - - + + + {ArrowDownPath} + + + {ArrowDownPath} + + + {ArrowDownPath} + + ), }; export const Colors: Story = { render: (args) => ( - <> - - home - {" "} - - home - {" "} - - home - {" "} - - home - {" "} - - home - {" "} - - home - - + + + {ArrowDownPath} + + + {ArrowDownPath} + + + {ArrowDownPath} + + + {ArrowDownPath} + + + {ArrowDownPath} + + + {ArrowDownPath} + + + {ArrowDownPath} + + + ), +}; + +export const Disabled: Story = { + args: { disabled: true }, + render: (args) => {ArrowDownPath}, +}; + +export const EdgeAlignment: Story = { + render: (args) => ( + + + {ArrowDownPath} + +
+ + {ArrowDownPath} + + + ), +}; + +export const WithCustomSvgIcon: Story = { + render: (args) => ( + + + + + + + + + + + + + +
+ + + + + +
+
+ ), +}; + +export const StyledViaSx: Story = { + args: { + sx: { "& svg": { fontSize: 40 } }, + }, + render: (args) => ( + + + {ArrowDownPath} + + + {ArrowDownPath} + + ), }; +``; diff --git a/src/components/MUI/DataDisplay/IconButton.tsx b/src/components/MUI/DataDisplay/IconButton.tsx index 861458a..52db5ef 100644 --- a/src/components/MUI/DataDisplay/IconButton.tsx +++ b/src/components/MUI/DataDisplay/IconButton.tsx @@ -1,4 +1,3 @@ -// src/components/IconButton/IconButton.tsx import * as React from "react"; import MuiIconButton, { IconButtonProps as MuiIconButtonProps, diff --git a/src/components/MUI/DataDisplay/List.stories.tsx b/src/components/MUI/DataDisplay/List.stories.tsx index af325ba..786e635 100644 --- a/src/components/MUI/DataDisplay/List.stories.tsx +++ b/src/components/MUI/DataDisplay/List.stories.tsx @@ -1,19 +1,16 @@ import type { Meta, StoryObj } from "@storybook/react"; -import { List } from "./List"; - -import ListItem from "@mui/material/ListItem"; -import ListItemText from "@mui/material/ListItemText"; -import ListItemIcon from "@mui/material/ListItemIcon"; -import Divider from "@mui/material/Divider"; - import InboxIcon from "@mui/icons-material/MoveToInbox"; import MailIcon from "@mui/icons-material/Mail"; +import { List } from "./List"; +import { ListItem } from "./ListItem"; +import { ListItemIcon } from "./ListItemIcon"; +import { ListItemText } from "./ListItemText"; +import { Divider } from "./Divider"; const meta: Meta = { - title: "MUI/Data Display/List", + title: "MUI/Data Display/List/List", component: List, - tags: ["autodocs"], - parameters: { controls: { expanded: true }, layout: "padded" }, + parameters: { layout: "padded" }, argTypes: { dense: { control: "boolean" }, disablePadding: { control: "boolean" }, @@ -28,7 +25,7 @@ const meta: Meta = { export default meta; type Story = StoryObj; -export const Basic: Story = { +export const Playground: Story = { render: (args) => ( @@ -50,20 +47,3 @@ export const Basic: Story = { ), }; - -export const Dense: Story = { - args: { dense: true }, - render: (args) => ( - - - - - - - - - - - - ), -}; diff --git a/src/components/MUI/DataDisplay/List.tsx b/src/components/MUI/DataDisplay/List.tsx index a036c2b..c80ba89 100644 --- a/src/components/MUI/DataDisplay/List.tsx +++ b/src/components/MUI/DataDisplay/List.tsx @@ -1,4 +1,3 @@ -// src/components/List/List.tsx import * as React from "react"; import MuiList, { ListProps as MuiListProps } from "@mui/material/List"; diff --git a/src/components/MUI/DataDisplay/ListItem.stories.tsx b/src/components/MUI/DataDisplay/ListItem.stories.tsx new file mode 100644 index 0000000..bd23923 --- /dev/null +++ b/src/components/MUI/DataDisplay/ListItem.stories.tsx @@ -0,0 +1,75 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { ListItem } from "./ListItem"; +import { ListItemText } from "./ListItemText"; +import { List } from "./List"; +import { ListItemIcon } from "./ListItemIcon"; +import diamond from "../../../public/images/diamond.jpg"; +import soleil from "../../../public/images/soleil.jpg"; + +import InboxIcon from "@mui/icons-material/MoveToInbox"; +import MailIcon from "@mui/icons-material/Mail"; +import { ListItemAvatar } from "./ListItemAvatar"; +import { Avatar } from "./Avatar"; + +const meta: Meta = { + title: "MUI/Data Display/List/ListItem", + component: ListItem, + parameters: { layout: "padded" }, + argTypes: { + dense: { control: "boolean" }, + disableGutters: { control: "boolean" }, + disablePadding: { control: "boolean" }, + divider: { control: "boolean" }, + }, + args: { + dense: false, + disableGutters: false, + disablePadding: false, + divider: true, + }, +}; +export default meta; +type Story = StoryObj; + +export const Playground: Story = { + render: (args) => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ), +}; diff --git a/src/components/MUI/DataDisplay/ListItem.tsx b/src/components/MUI/DataDisplay/ListItem.tsx new file mode 100644 index 0000000..f3dda62 --- /dev/null +++ b/src/components/MUI/DataDisplay/ListItem.tsx @@ -0,0 +1,13 @@ +import * as React from "react"; +import MuiListItem, { + ListItemProps as MuiListItemProps, +} from "@mui/material/ListItem"; + +export type ListItemProps = MuiListItemProps; + +export const ListItem = React.forwardRef( + function ListItem(props, ref) { + return ; + }, +); +ListItem.displayName = "ListItem"; diff --git a/src/components/MUI/DataDisplay/ListItemAvatar.tsx b/src/components/MUI/DataDisplay/ListItemAvatar.tsx new file mode 100644 index 0000000..c84c43d --- /dev/null +++ b/src/components/MUI/DataDisplay/ListItemAvatar.tsx @@ -0,0 +1,15 @@ +import * as React from "react"; +import MuiListItemAvatar, { + ListItemAvatarProps as MuiListItemAvatarProps, +} from "@mui/material/ListItemAvatar"; + +export type ListItemAvatarProps = MuiListItemAvatarProps; + +export const ListItemAvatar = React.forwardRef< + HTMLDivElement, + ListItemAvatarProps +>(function ListItemAvatar(props, ref) { + return ; +}); + +ListItemAvatar.displayName = "ListItemAvatar"; diff --git a/src/components/MUI/DataDisplay/ListItemButton.stories.tsx b/src/components/MUI/DataDisplay/ListItemButton.stories.tsx new file mode 100644 index 0000000..fcb4755 --- /dev/null +++ b/src/components/MUI/DataDisplay/ListItemButton.stories.tsx @@ -0,0 +1,38 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { ListItemButton } from "./ListItemButton"; +import { List } from "./List"; +import { ListItem } from "./ListItem"; +import { ListItemText } from "./ListItemText"; + +const meta: Meta = { + title: "MUI/Data Display/List/ListItemButton", + component: ListItemButton, + parameters: { layout: "padded" }, + argTypes: { + selected: { control: "boolean" }, + disabled: { control: "boolean" }, + }, + args: { + selected: false, + disabled: false, + }, +}; +export default meta; +type Story = StoryObj; + +export const Playground: Story = { + render: (args) => ( + + + + + + + + + + + + + ), +}; diff --git a/src/components/MUI/DataDisplay/ListItemButton.tsx b/src/components/MUI/DataDisplay/ListItemButton.tsx new file mode 100644 index 0000000..52893e9 --- /dev/null +++ b/src/components/MUI/DataDisplay/ListItemButton.tsx @@ -0,0 +1,15 @@ +import * as React from "react"; +import MuiListItemButton, { + ListItemButtonProps as MuiListItemButtonProps, +} from "@mui/material/ListItemButton"; + +export type ListItemButtonProps = MuiListItemButtonProps; + +export const ListItemButton = React.forwardRef< + HTMLDivElement, + ListItemButtonProps +>(function ListItemButton(props, ref) { + return ; +}); + +ListItemButton.displayName = "ListItemButton"; diff --git a/src/components/MUI/DataDisplay/ListItemIcon.stories.tsx b/src/components/MUI/DataDisplay/ListItemIcon.stories.tsx new file mode 100644 index 0000000..dd90220 --- /dev/null +++ b/src/components/MUI/DataDisplay/ListItemIcon.stories.tsx @@ -0,0 +1,34 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { ListItemIcon } from "./ListItemIcon"; +import { ListItem } from "./ListItem"; +import { List } from "./List"; +import { ListItemText } from "./ListItemText"; +import InboxIcon from "@mui/icons-material/MoveToInbox"; +import MailIcon from "@mui/icons-material/Mail"; + +const meta: Meta = { + title: "MUI/Data Display/List/ListItemIcon", + component: ListItemIcon, + parameters: { layout: "padded" }, +}; +export default meta; +type Story = StoryObj; + +export const Playground: Story = { + render: () => ( + + + + + + + + + + + + + + + ), +}; diff --git a/src/components/MUI/DataDisplay/ListItemIcon.tsx b/src/components/MUI/DataDisplay/ListItemIcon.tsx new file mode 100644 index 0000000..2c4f2a7 --- /dev/null +++ b/src/components/MUI/DataDisplay/ListItemIcon.tsx @@ -0,0 +1,14 @@ +import * as React from "react"; +import MuiListItemIcon, { + ListItemIconProps as MuiListItemIconProps, +} from "@mui/material/ListItemIcon"; + +export type ListItemIconProps = MuiListItemIconProps; + +export const ListItemIcon = React.forwardRef( + function ListItemIcon(props, ref) { + return ; + }, +); + +ListItemIcon.displayName = "ListItemIcon"; diff --git a/src/components/MUI/DataDisplay/ListItemText.stories.tsx b/src/components/MUI/DataDisplay/ListItemText.stories.tsx new file mode 100644 index 0000000..7f43637 --- /dev/null +++ b/src/components/MUI/DataDisplay/ListItemText.stories.tsx @@ -0,0 +1,35 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { ListItemText } from "./ListItemText"; +import { ListItem } from "./ListItem"; +import { List } from "./List"; + +const meta: Meta = { + title: "MUI/Data Display/List/ListItemText", + component: ListItemText, + parameters: { layout: "padded" }, + argTypes: { + primary: { control: "text" }, + secondary: { control: "text" }, + inset: { control: "boolean" }, + }, + args: { + primary: "Primary text", + secondary: "Secondary text", + inset: false, + }, +}; +export default meta; +type Story = StoryObj; + +export const Playground: Story = { + render: (args) => ( + + + + + + + + + ), +}; diff --git a/src/components/MUI/DataDisplay/ListItemText.tsx b/src/components/MUI/DataDisplay/ListItemText.tsx new file mode 100644 index 0000000..6157671 --- /dev/null +++ b/src/components/MUI/DataDisplay/ListItemText.tsx @@ -0,0 +1,15 @@ +import * as React from "react"; +import MuiListItemText, { + ListItemTextProps as MuiListItemTextProps, +} from "@mui/material/ListItemText"; + +export type ListItemTextProps = MuiListItemTextProps; + +export const ListItemText = React.forwardRef< + HTMLSpanElement, + ListItemTextProps +>(function ListItemText(props, ref) { + return ; +}); + +ListItemText.displayName = "ListItemText"; diff --git a/src/components/MUI/DataDisplay/ListSubheader.stories.tsx b/src/components/MUI/DataDisplay/ListSubheader.stories.tsx new file mode 100644 index 0000000..effd66f --- /dev/null +++ b/src/components/MUI/DataDisplay/ListSubheader.stories.tsx @@ -0,0 +1,44 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { ListSubheader } from "./ListSubheader"; +import { List } from "./List"; +import { ListItem } from "./ListItem"; +import { ListItemText } from "./ListItemText"; + +const meta: Meta = { + title: "MUI/Data Display/List/ListSubheader", + component: ListSubheader, + parameters: { layout: "padded" }, + argTypes: { + color: { + control: { type: "radio" }, + options: ["default", "inherit", "primary"], + }, + disableGutters: { control: "boolean" }, + disableSticky: { control: "boolean" }, + inset: { control: "boolean" }, + }, + args: { + color: "default", + disableGutters: false, + disableSticky: false, + inset: false, + }, +}; +export default meta; +type Story = StoryObj; + +export const Playground: Story = { + render: (args) => ( + Folders}> + + + + + + + + + + + ), +}; diff --git a/src/components/MUI/DataDisplay/ListSubheader.tsx b/src/components/MUI/DataDisplay/ListSubheader.tsx new file mode 100644 index 0000000..18213bc --- /dev/null +++ b/src/components/MUI/DataDisplay/ListSubheader.tsx @@ -0,0 +1,14 @@ +import * as React from "react"; +import MuiListSubheader, { + ListSubheaderProps as MuiListSubheaderProps, +} from "@mui/material/ListSubheader"; + +export type ListSubheaderProps = MuiListSubheaderProps; + +export const ListSubheader = React.forwardRef< + HTMLLIElement, + ListSubheaderProps +>(function ListSubheader(props, ref) { + return ; +}); +ListSubheader.displayName = "ListSubheader"; diff --git a/src/components/MUI/DataDisplay/MaterialIcons.stories.tsx b/src/components/MUI/DataDisplay/MaterialIcons.stories.tsx deleted file mode 100644 index fbecea6..0000000 --- a/src/components/MUI/DataDisplay/MaterialIcons.stories.tsx +++ /dev/null @@ -1,74 +0,0 @@ -import type { Meta, StoryObj } from "@storybook/react"; -import { MaterialIcons } from "./MaterialIcons"; - -const meta: Meta = { - title: "MUI/Data Display/MaterialIcons", - component: MaterialIcons, - tags: ["autodocs"], - parameters: { controls: { expanded: true }, layout: "padded" }, - argTypes: { - name: { - control: "select", - options: [ - "home", - "favorite", - "search", - "settings", - "add", - "edit", - "delete", - "send", - "save", - "info", - ], - }, - color: { - control: "select", - options: [ - "inherit", - "primary", - "secondary", - "action", - "disabled", - "error", - "info", - "success", - "warning", - ], - }, - fontSize: { - control: "select", - options: ["inherit", "small", "medium", "large"], - }, - }, - args: { name: "home", color: "inherit", fontSize: "medium" }, -}; -export default meta; -type Story = StoryObj; - -export const Basic: Story = { render: (args) => }; - -export const Colors: Story = { - render: (args) => ( -
- - - - - - - - -
- ), -}; - -export const Sizes: Story = { - render: (args) => ( -
- - - -
- ), -}; diff --git a/src/components/MUI/DataDisplay/MaterialIcons.tsx b/src/components/MUI/DataDisplay/MaterialIcons.tsx deleted file mode 100644 index 3582c14..0000000 --- a/src/components/MUI/DataDisplay/MaterialIcons.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import * as React from "react"; -import HomeIcon from "@mui/icons-material/Home"; -import FavoriteIcon from "@mui/icons-material/Favorite"; -import SearchIcon from "@mui/icons-material/Search"; -import SettingsIcon from "@mui/icons-material/Settings"; -import AddIcon from "@mui/icons-material/Add"; -import EditIcon from "@mui/icons-material/Edit"; -import DeleteIcon from "@mui/icons-material/Delete"; -import SendIcon from "@mui/icons-material/Send"; -import SaveIcon from "@mui/icons-material/Save"; -import InfoIcon from "@mui/icons-material/Info"; - -const iconMap = { - home: , - favorite: , - search: , - settings: , - add: , - edit: , - delete: , - send: , - save: , - info: , -} as const; - -export type MaterialIconsProps = { - name: keyof typeof iconMap; - color?: - | "inherit" - | "primary" - | "secondary" - | "action" - | "disabled" - | "error" - | "info" - | "success" - | "warning"; - fontSize?: "inherit" | "small" | "medium" | "large"; -}; - -export const MaterialIcons = React.forwardRef< - SVGSVGElement, - MaterialIconsProps ->(({ name, color = "inherit", fontSize = "medium" }, ref) => { - const el = iconMap[name]; - return React.cloneElement(el, { color, fontSize, ref }); -}); - -MaterialIcons.displayName = "MaterialIcons"; diff --git a/src/components/MUI/DataDisplay/SvgIcon.stories.tsx b/src/components/MUI/DataDisplay/SvgIcon.stories.tsx new file mode 100644 index 0000000..c3931df --- /dev/null +++ b/src/components/MUI/DataDisplay/SvgIcon.stories.tsx @@ -0,0 +1,163 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { SvgIcon } from "./SvgIcon"; +import { IconButton } from "./IconButton"; +import { Stack } from "../Layout/Stack"; + +const meta: Meta = { + title: "MUI/Data Display/SvgIcon", + component: SvgIcon, + tags: ["autodocs"], + parameters: { + controls: { expanded: true }, + layout: "padded", + }, + argTypes: { + color: { + control: "select", + options: [ + "inherit", + "primary", + "secondary", + "action", + "disabled", + "error", + "info", + "success", + "warning", + ], + description: "Applies theme color", + }, + fontSize: { + control: "select", + options: ["inherit", "small", "medium", "large"], + description: "Applies theme size preset", + }, + viewBox: { + control: "text", + description: "ViewBox for the SVG; default is '0 0 24 24'", + }, + inheritViewBox: { + control: "boolean", + description: + "If true, use the viewBox of the child SVG element rather than the default", + }, + titleAccess: { + control: "text", + description: + "Adds a element for accessibility (sets role='img' if provided)", + }, + sx: { + control: "object", + description: "MUI `sx` prop", + }, + }, + args: { + color: "primary", + fontSize: "medium", + viewBox: "0 0 24 24", + inheritViewBox: false, + titleAccess: "Down arrow", + sx: undefined, + }, +}; +export default meta; + +type Story = StoryObj<typeof meta>; + +const d = "M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z"; + +export const Basic: Story = { + render: (args) => <SvgIcon {...args}>{<path d={d} />}</SvgIcon>, +}; + +export const Sizes: Story = { + render: (args) => ( + <Stack direction="row" spacing={2} alignItems="center"> + <SvgIcon {...args} fontSize="small"> + {<path d={d} />} + </SvgIcon> + <SvgIcon {...args} fontSize="medium"> + {<path d={d} />} + </SvgIcon> + <SvgIcon {...args} fontSize="large"> + {<path d={d} />} + </SvgIcon> + <div style={{ fontSize: 32, display: "flex", alignItems: "center" }}> + <SvgIcon {...args} fontSize="inherit"> + {<path d={d} />} + </SvgIcon> + </div> + </Stack> + ), +}; + +export const Colors: Story = { + render: (args) => ( + <Stack direction="row" spacing={2} alignItems="center"> + <SvgIcon {...args} color="inherit"> + {<path d={d} />} + </SvgIcon> + <SvgIcon {...args} color="primary"> + {<path d={d} />} + </SvgIcon> + <SvgIcon {...args} color="secondary"> + {<path d={d} />} + </SvgIcon> + <SvgIcon {...args} color="error"> + {<path d={d} />} + </SvgIcon> + <SvgIcon {...args} color="warning"> + {<path d={d} />} + </SvgIcon> + <SvgIcon {...args} color="info"> + {<path d={d} />} + </SvgIcon> + <SvgIcon {...args} color="success"> + {<path d={d} />} + </SvgIcon> + <SvgIcon {...args} color="action"> + {<path d={d} />} + </SvgIcon> + <SvgIcon {...args} color="disabled"> + {<path d={d} />} + </SvgIcon> + </Stack> + ), +}; + +export const CustomViewBoxAndInherit: Story = { + args: { + viewBox: "0 0 48 48", + inheritViewBox: false, + titleAccess: "Custom viewBox icon", + pathD: "M24 4L12 20h8v16h8V20h8L24 4z", + }, + render: (args) => ( + <Stack direction="row" spacing={4} alignItems="center"> + <SvgIcon {...args}>{<path d={d} />}</SvgIcon> + <SvgIcon {...args} inheritViewBox> + <svg viewBox="0 0 32 32"> + <path d="M16 2l-6 10h4v8h4v-8h4L16 2z" /> + </svg> + </SvgIcon> + </Stack> + ), +}; + +export const InIconButton: Story = { + args: { color: "primary" }, + render: (args) => ( + <Stack direction="row" spacing={2}> + <IconButton color="primary" aria-label="download"> + <SvgIcon viewBox="0 0 24 24"> + <path d="M5 20h14v-2H5v2zm7-18v12l4-4 1.41 1.41L12 18l-5.41-5.59L8 10l4 4V2h2z" /> + </SvgIcon> + </IconButton> + <IconButton color="secondary" aria-label="arrow down"> + <SvgIcon> + <path d="M20 12l-1.41-1.41L13 16.17V4h-2v12.17l-5.58-5.59L4 12l8 8 8-8z" /> + </SvgIcon> + </IconButton> + </Stack> + ), +}; diff --git a/src/components/MUI/DataDisplay/SvgIcon.tsx b/src/components/MUI/DataDisplay/SvgIcon.tsx new file mode 100644 index 0000000..84dc6ec --- /dev/null +++ b/src/components/MUI/DataDisplay/SvgIcon.tsx @@ -0,0 +1,12 @@ +import * as React from "react"; +import MuiSvgIcon, { + SvgIconProps as MuiSvgIconProps, +} from "@mui/material/SvgIcon"; + +export type SvgIconProps = MuiSvgIconProps; + +export const SvgIcon = React.forwardRef<SVGSVGElement, SvgIconProps>( + (props, ref) => <MuiSvgIcon ref={ref} {...props} />, +); + +SvgIcon.displayName = "SvgIcon"; diff --git a/src/components/MUI/DataDisplay/Table.stories.tsx b/src/components/MUI/DataDisplay/Table.stories.tsx index 0af1787..50e78ac 100644 --- a/src/components/MUI/DataDisplay/Table.stories.tsx +++ b/src/components/MUI/DataDisplay/Table.stories.tsx @@ -1,73 +1,78 @@ import type { Meta, StoryObj } from "@storybook/react"; import { Table } from "./Table"; -import TableContainer from "@mui/material/TableContainer"; -import TableHead from "@mui/material/TableHead"; -import TableBody from "@mui/material/TableBody"; -import TableRow from "@mui/material/TableRow"; -import TableCell from "@mui/material/TableCell"; -import Paper from "@mui/material/Paper"; +import { TableContainer } from "./TableContainer"; +import { TableRow } from "./TableRow"; +import { TableCell } from "./TableCell"; +import { TableHead } from "./TableHead"; +import { TableBody } from "./TableBody"; +import { Paper } from "../Surfaces/Paper"; -const rows = [ - { name: "Frozen yoghurt", calories: 159, fat: 6.0 }, - { name: "Ice cream sandwich", calories: 237, fat: 9.0 }, - { name: "Eclair", calories: 262, fat: 16.0 }, +type Dessert = { + name: string; + calories: number; + fat: number; + carbs: number; + protein: number; +}; +const rows: Dessert[] = [ + { name: "Frozen yoghurt", calories: 159, fat: 6, carbs: 24, protein: 4 }, + { + name: "Ice cream sandwich", + calories: 237, + fat: 9, + carbs: 37, + protein: 4.3, + }, + { name: "Eclair", calories: 262, fat: 16, carbs: 24, protein: 6 }, ]; const meta: Meta<typeof Table> = { - title: "MUI/Data Display/Table", + title: "MUI/Data Display/Table/Table", component: Table, - tags: ["autodocs"], - parameters: { controls: { expanded: true }, layout: "padded" }, + parameters: { layout: "padded" }, argTypes: { - size: { control: "select", options: ["small", "medium"] }, + size: { control: { type: "radio" }, options: ["small", "medium"] }, + padding: { + control: { type: "radio" }, + options: ["normal", "none", "checkbox"], + }, stickyHeader: { control: "boolean" }, }, - args: { size: "medium", stickyHeader: false }, + args: { + size: "medium", + padding: "normal", + stickyHeader: false, + }, }; export default meta; type Story = StoryObj<typeof meta>; -export const Basic: Story = { +export const Playground: Story = { render: (args) => ( - <TableContainer component={Paper}> - <Table {...args} aria-label="basic table"> + <TableContainer + component={Paper} + sx={{ maxHeight: args.stickyHeader ? 320 : "auto" }} + > + <Table {...args} aria-label="desserts"> <TableHead> <TableRow> <TableCell>Dessert</TableCell> <TableCell align="right">Calories</TableCell> - <TableCell align="right">Fat</TableCell> - </TableRow> - </TableHead> - <TableBody> - {rows.map((r) => ( - <TableRow key={r.name}> - <TableCell>{r.name}</TableCell> - <TableCell align="right">{r.calories}</TableCell> - <TableCell align="right">{r.fat}</TableCell> - </TableRow> - ))} - </TableBody> - </Table> - </TableContainer> - ), -}; - -export const Dense: Story = { - args: { size: "small" }, - render: (args) => ( - <TableContainer component={Paper}> - <Table {...args}> - <TableHead> - <TableRow> - <TableCell>Item</TableCell> - <TableCell align="right">Val</TableCell> + <TableCell align="right">Fat (g)</TableCell> + <TableCell align="right">Carbs (g)</TableCell> + <TableCell align="right">Protein (g)</TableCell> </TableRow> </TableHead> <TableBody> - {rows.map((r) => ( - <TableRow key={r.name}> - <TableCell>{r.name}</TableCell> - <TableCell align="right">{r.calories}</TableCell> + {rows.map((row) => ( + <TableRow key={row.name}> + <TableCell component="th" scope="row"> + {row.name} + </TableCell> + <TableCell align="right">{row.calories}</TableCell> + <TableCell align="right">{row.fat}</TableCell> + <TableCell align="right">{row.carbs}</TableCell> + <TableCell align="right">{row.protein}</TableCell> </TableRow> ))} </TableBody> diff --git a/src/components/MUI/DataDisplay/TableBody.stories.tsx b/src/components/MUI/DataDisplay/TableBody.stories.tsx new file mode 100644 index 0000000..8e56290 --- /dev/null +++ b/src/components/MUI/DataDisplay/TableBody.stories.tsx @@ -0,0 +1,41 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { TableContainer } from "./TableContainer"; +import { Table } from "./Table"; +import { TableHead } from "./TableHead"; +import { TableCell } from "./TableCell"; +import { TableRow } from "./TableRow"; +import { TableBody } from "./TableBody"; +import { Paper } from "../Surfaces/Paper"; + +const meta: Meta<typeof TableBody> = { + title: "MUI/Data Display/Table/TableBody", + component: TableBody, + parameters: { layout: "padded" }, +}; +export default meta; +type Story = StoryObj<typeof meta>; + +export const Playground: Story = { + render: () => ( + <TableContainer component={Paper}> + <Table aria-label="body demo"> + <TableHead> + <TableRow> + <TableCell>Item</TableCell> + <TableCell align="right">Qty</TableCell> + </TableRow> + </TableHead> + <TableBody> + <TableRow> + <TableCell>Apples</TableCell> + <TableCell align="right">5</TableCell> + </TableRow> + <TableRow> + <TableCell>Oranges</TableCell> + <TableCell align="right">3</TableCell> + </TableRow> + </TableBody> + </Table> + </TableContainer> + ), +}; diff --git a/src/components/MUI/DataDisplay/TableBody.tsx b/src/components/MUI/DataDisplay/TableBody.tsx new file mode 100644 index 0000000..02fefb9 --- /dev/null +++ b/src/components/MUI/DataDisplay/TableBody.tsx @@ -0,0 +1,15 @@ +import * as React from "react"; +import MuiTableBody, { + TableBodyProps as MuiTableBodyProps, +} from "@mui/material/TableBody"; + +export type TableBodyProps = MuiTableBodyProps; + +export const TableBody = React.forwardRef< + HTMLTableSectionElement, + TableBodyProps +>(function TableBody(props, ref) { + return <MuiTableBody ref={ref} {...props} />; +}); + +TableBody.displayName = "TableBody"; diff --git a/src/components/MUI/DataDisplay/TableCell.stories.tsx b/src/components/MUI/DataDisplay/TableCell.stories.tsx new file mode 100644 index 0000000..77b3e24 --- /dev/null +++ b/src/components/MUI/DataDisplay/TableCell.stories.tsx @@ -0,0 +1,50 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { TableContainer } from "./TableContainer"; +import { Table } from "./Table"; +import { TableHead } from "./TableHead"; +import { TableCell } from "./TableCell"; +import { TableRow } from "./TableRow"; +import { TableBody } from "./TableBody"; +import { Paper } from "../Surfaces/Paper"; + +const meta: Meta<typeof TableCell> = { + title: "MUI/Data Display/Table/TableCell", + component: TableCell, + parameters: { layout: "padded" }, + argTypes: { + align: { + control: { type: "radio" }, + options: ["inherit", "left", "center", "right", "justify"], + }, + padding: { control: { type: "radio" }, options: ["normal", "none"] }, + scope: { control: "text" }, + }, + args: { + align: "left", + padding: "normal", + scope: "row", + }, +}; +export default meta; +type Story = StoryObj<typeof meta>; + +export const Playground: Story = { + render: (args) => ( + <TableContainer component={Paper}> + <Table aria-label="cell demo"> + <TableHead> + <TableRow> + <TableCell>Item</TableCell> + <TableCell align="right">Qty</TableCell> + </TableRow> + </TableHead> + <TableBody> + <TableRow> + <TableCell {...args}>Apples</TableCell> + <TableCell align="right">5</TableCell> + </TableRow> + </TableBody> + </Table> + </TableContainer> + ), +}; diff --git a/src/components/MUI/DataDisplay/TableCell.tsx b/src/components/MUI/DataDisplay/TableCell.tsx new file mode 100644 index 0000000..a412200 --- /dev/null +++ b/src/components/MUI/DataDisplay/TableCell.tsx @@ -0,0 +1,14 @@ +import * as React from "react"; +import MuiTableCell, { + TableCellProps as MuiTableCellProps, +} from "@mui/material/TableCell"; + +export type TableCellProps = MuiTableCellProps; + +export const TableCell = React.forwardRef<HTMLTableCellElement, TableCellProps>( + function TableCell(props, ref) { + return <MuiTableCell ref={ref} {...props} />; + }, +); + +TableCell.displayName = "TableCell"; diff --git a/src/components/MUI/DataDisplay/TableContainer.stories.tsx b/src/components/MUI/DataDisplay/TableContainer.stories.tsx new file mode 100644 index 0000000..8ea451a --- /dev/null +++ b/src/components/MUI/DataDisplay/TableContainer.stories.tsx @@ -0,0 +1,45 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { TableContainer } from "./TableContainer"; +import { Table } from "./Table"; +import { TableHead } from "./TableHead"; +import { TableCell } from "./TableCell"; +import { TableRow } from "./TableRow"; +import { TableBody } from "./TableBody"; +import { Paper } from "../Surfaces/Paper"; + +const meta: Meta<typeof TableContainer> = { + title: "MUI/Data Display/Table/TableContainer", + component: TableContainer, + parameters: { layout: "padded" }, + argTypes: { + component: { control: "text" }, + }, + args: { + component: "div", + }, +}; +export default meta; +type Story = StoryObj<typeof meta>; + +export const Playground: Story = { + render: (args) => ( + <TableContainer {...args} component={Paper} sx={{ maxHeight: 280 }}> + <Table stickyHeader> + <TableHead> + <TableRow> + <TableCell>Header A</TableCell> + <TableCell>Header B</TableCell> + </TableRow> + </TableHead> + <TableBody> + {Array.from({ length: 12 }).map((_, i) => ( + <TableRow key={i}> + <TableCell>Row {i + 1} A</TableCell> + <TableCell>Row {i + 1} B</TableCell> + </TableRow> + ))} + </TableBody> + </Table> + </TableContainer> + ), +}; diff --git a/src/components/MUI/DataDisplay/TableContainer.tsx b/src/components/MUI/DataDisplay/TableContainer.tsx new file mode 100644 index 0000000..a100e56 --- /dev/null +++ b/src/components/MUI/DataDisplay/TableContainer.tsx @@ -0,0 +1,15 @@ +import * as React from "react"; +import MuiTableContainer, { + TableContainerProps as MuiTableContainerProps, +} from "@mui/material/TableContainer"; + +export type TableContainerProps = MuiTableContainerProps; + +export const TableContainer = React.forwardRef< + HTMLDivElement, + TableContainerProps +>(function TableContainer(props, ref) { + return <MuiTableContainer ref={ref} {...props} />; +}); + +TableContainer.displayName = "TableContainer"; diff --git a/src/components/MUI/DataDisplay/TableFooter.stories.tsx b/src/components/MUI/DataDisplay/TableFooter.stories.tsx new file mode 100644 index 0000000..73fcec2 --- /dev/null +++ b/src/components/MUI/DataDisplay/TableFooter.stories.tsx @@ -0,0 +1,49 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { TableContainer } from "./TableContainer"; +import { Table } from "./Table"; +import { TableHead } from "./TableHead"; +import { TableCell } from "./TableCell"; +import { TableRow } from "./TableRow"; +import { TableBody } from "./TableBody"; +import { Paper } from "../Surfaces/Paper"; +import { TableFooter } from "./TableFooter"; + +const meta: Meta<typeof TableFooter> = { + title: "MUI/Data Display/Table/TableFooter", + component: TableFooter, + parameters: { layout: "padded" }, +}; +export default meta; +type Story = StoryObj<typeof meta>; + +export const Playground: Story = { + render: () => ( + <TableContainer component={Paper}> + <Table aria-label="footer demo"> + <TableHead> + <TableRow> + <TableCell>Item</TableCell> + <TableCell>Qty</TableCell> + </TableRow> + </TableHead> + <TableBody> + <TableRow> + <TableCell>Apples</TableCell> + <TableCell>5</TableCell> + </TableRow> + <TableRow> + <TableCell>Oranges</TableCell> + <TableCell>3</TableCell> + </TableRow> + </TableBody> + <TableFooter> + <TableRow> + <TableCell>Totals</TableCell> + <TableCell>8</TableCell> + </TableRow> + </TableFooter> + </Table> + </TableContainer> + ), +}; +``; diff --git a/src/components/MUI/DataDisplay/TableFooter.tsx b/src/components/MUI/DataDisplay/TableFooter.tsx new file mode 100644 index 0000000..e8db5f4 --- /dev/null +++ b/src/components/MUI/DataDisplay/TableFooter.tsx @@ -0,0 +1,15 @@ +import * as React from "react"; +import MuiTableFooter, { + TableFooterProps as MuiTableFooterProps, +} from "@mui/material/TableFooter"; + +export type TableFooterProps = MuiTableFooterProps; + +export const TableFooter = React.forwardRef< + HTMLTableSectionElement, + TableFooterProps +>(function TableFooter(props, ref) { + return <MuiTableFooter ref={ref} {...props} />; +}); + +TableFooter.displayName = "TableFooter"; diff --git a/src/components/MUI/DataDisplay/TableHead.stories.tsx b/src/components/MUI/DataDisplay/TableHead.stories.tsx new file mode 100644 index 0000000..111a76c --- /dev/null +++ b/src/components/MUI/DataDisplay/TableHead.stories.tsx @@ -0,0 +1,41 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { TableContainer } from "./TableContainer"; +import { Table } from "./Table"; +import { TableHead } from "./TableHead"; +import { TableCell } from "./TableCell"; +import { TableRow } from "./TableRow"; +import { TableBody } from "./TableBody"; +import { Paper } from "../Surfaces/Paper"; + +const meta: Meta<typeof TableHead> = { + title: "MUI/Data Display/Table/TableHead", + component: TableHead, + parameters: { layout: "padded" }, +}; +export default meta; +type Story = StoryObj<typeof meta>; + +export const Playground: Story = { + render: () => ( + <TableContainer component={Paper}> + <Table aria-label="head demo"> + <TableHead> + <TableRow> + <TableCell>Column A</TableCell> + <TableCell>Column B</TableCell> + </TableRow> + </TableHead> + <TableBody> + <TableRow> + <TableCell>A1</TableCell> + <TableCell>B1</TableCell> + </TableRow> + <TableRow> + <TableCell>A2</TableCell> + <TableCell>B2</TableCell> + </TableRow> + </TableBody> + </Table> + </TableContainer> + ), +}; diff --git a/src/components/MUI/DataDisplay/TableHead.tsx b/src/components/MUI/DataDisplay/TableHead.tsx new file mode 100644 index 0000000..765e047 --- /dev/null +++ b/src/components/MUI/DataDisplay/TableHead.tsx @@ -0,0 +1,15 @@ +import * as React from "react"; +import MuiTableHead, { + TableHeadProps as MuiTableHeadProps, +} from "@mui/material/TableHead"; + +export type TableHeadProps = MuiTableHeadProps; + +export const TableHead = React.forwardRef< + HTMLTableSectionElement, + TableHeadProps +>(function TableHead(props, ref) { + return <MuiTableHead ref={ref} {...props} />; +}); + +TableHead.displayName = "TableHead"; diff --git a/src/components/MUI/DataDisplay/TablePagination.stories.tsx b/src/components/MUI/DataDisplay/TablePagination.stories.tsx new file mode 100644 index 0000000..f80e3dc --- /dev/null +++ b/src/components/MUI/DataDisplay/TablePagination.stories.tsx @@ -0,0 +1,72 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { TableContainer } from "./TableContainer"; +import { Table } from "./Table"; +import { TableHead } from "./TableHead"; +import { TableCell } from "./TableCell"; +import { TableRow } from "./TableRow"; +import { TableBody } from "./TableBody"; +import { Paper } from "../Surfaces/Paper"; +import { TablePagination } from "./TablePagination"; +import React from "react"; +import { TableFooter } from "./TableFooter"; + +type Row = { id: number; name: string }; +const rows: Row[] = Array.from({ length: 23 }).map((_, i) => ({ + id: i + 1, + name: `Row ${i + 1}`, +})); + +const meta: Meta<typeof TablePagination> = { + title: "MUI/Data Display/Table/TablePagination", + component: TablePagination, + parameters: { layout: "padded" }, +}; +export default meta; +type Story = StoryObj<typeof meta>; + +export const Playground: Story = { + render: () => { + const [page, setPage] = React.useState(0); + const [rowsPerPage, setRowsPerPage] = React.useState(5); + const slice = rows.slice( + page * rowsPerPage, + page * rowsPerPage + rowsPerPage, + ); + + return ( + <TableContainer component={Paper}> + <Table aria-label="pagination demo"> + <TableHead> + <TableRow> + <TableCell>ID</TableCell> + <TableCell>Name</TableCell> + </TableRow> + </TableHead> + <TableBody> + {slice.map((row) => ( + <TableRow key={row.id}> + <TableCell>{row.id}</TableCell> + <TableCell>{row.name}</TableCell> + </TableRow> + ))} + </TableBody> + <TableFooter> + <TableRow> + <TablePagination + count={rows.length} + page={page} + rowsPerPage={rowsPerPage} + onPageChange={(_, newPage) => setPage(newPage)} + onRowsPerPageChange={(e) => { + setRowsPerPage(parseInt(e.target.value, 10)); + setPage(0); + }} + rowsPerPageOptions={[5, 10, 25]} + /> + </TableRow> + </TableFooter> + </Table> + </TableContainer> + ); + }, +}; diff --git a/src/components/MUI/DataDisplay/TablePagination.tsx b/src/components/MUI/DataDisplay/TablePagination.tsx new file mode 100644 index 0000000..29bbbab --- /dev/null +++ b/src/components/MUI/DataDisplay/TablePagination.tsx @@ -0,0 +1,15 @@ +import * as React from "react"; +import MuiTablePagination, { + TablePaginationProps as MuiTablePaginationProps, +} from "@mui/material/TablePagination"; + +export type TablePaginationProps = MuiTablePaginationProps; + +export const TablePagination = React.forwardRef< + HTMLDivElement, + TablePaginationProps +>(function TablePagination(props, ref) { + return <MuiTablePagination ref={ref} {...props} />; +}); + +TablePagination.displayName = "TablePagination"; diff --git a/src/components/MUI/DataDisplay/TableRow.stories.tsx b/src/components/MUI/DataDisplay/TableRow.stories.tsx new file mode 100644 index 0000000..7489a34 --- /dev/null +++ b/src/components/MUI/DataDisplay/TableRow.stories.tsx @@ -0,0 +1,49 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { TableContainer } from "./TableContainer"; +import { Table } from "./Table"; +import { TableHead } from "./TableHead"; +import { TableCell } from "./TableCell"; +import { TableRow } from "./TableRow"; +import { TableBody } from "./TableBody"; +import { Paper } from "../Surfaces/Paper"; + +const meta: Meta<typeof TableRow> = { + title: "MUI/Data Display/Table/TableRow", + component: TableRow, + parameters: { layout: "padded" }, + argTypes: { + hover: { control: "boolean" }, + selected: { control: "boolean" }, + }, + args: { + hover: true, + selected: false, + }, +}; +export default meta; +type Story = StoryObj<typeof meta>; + +export const Playground: Story = { + render: (args) => ( + <TableContainer component={Paper}> + <Table aria-label="row demo"> + <TableHead> + <TableRow> + <TableCell>Item</TableCell> + <TableCell>Qty</TableCell> + </TableRow> + </TableHead> + <TableBody> + <TableRow {...args}> + <TableCell>Apples</TableCell> + <TableCell>5</TableCell> + </TableRow> + <TableRow {...args}> + <TableCell>Oranges</TableCell> + <TableCell>3</TableCell> + </TableRow> + </TableBody> + </Table> + </TableContainer> + ), +}; diff --git a/src/components/MUI/DataDisplay/TableRow.tsx b/src/components/MUI/DataDisplay/TableRow.tsx new file mode 100644 index 0000000..a05de11 --- /dev/null +++ b/src/components/MUI/DataDisplay/TableRow.tsx @@ -0,0 +1,13 @@ +import * as React from "react"; +import MuiTableRow, { + TableRowProps as MuiTableRowProps, +} from "@mui/material/TableRow"; + +export type TableRowProps = MuiTableRowProps; + +export const TableRow = React.forwardRef<HTMLTableRowElement, TableRowProps>( + function TableRow(props, ref) { + return <MuiTableRow ref={ref} {...props} />; + }, +); +TableRow.displayName = "TableRow"; diff --git a/src/components/MUI/DataDisplay/TableSortLabel.stories.tsx b/src/components/MUI/DataDisplay/TableSortLabel.stories.tsx new file mode 100644 index 0000000..4599262 --- /dev/null +++ b/src/components/MUI/DataDisplay/TableSortLabel.stories.tsx @@ -0,0 +1,80 @@ +import React from "react"; +import type { Meta, StoryObj } from "@storybook/react"; +import { TableContainer } from "./TableContainer"; +import { Table } from "./Table"; +import { TableHead } from "./TableHead"; +import { TableCell } from "./TableCell"; +import { TableRow } from "./TableRow"; +import { TableBody } from "./TableBody"; +import { Paper } from "../Surfaces/Paper"; +import { TableSortLabel } from "./TableSortLabel"; + +type Row = { name: string; calories: number }; +const rows: Row[] = [ + { name: "Frozen yoghurt", calories: 159 }, + { name: "Ice cream sandwich", calories: 237 }, + { name: "Eclair", calories: 262 }, +]; + +const meta: Meta<typeof TableSortLabel> = { + title: "MUI/Data Display/Table/TableSortLabel", + component: TableSortLabel, + parameters: { layout: "padded" }, + argTypes: { + active: { control: "boolean" }, + direction: { control: { type: "radio" }, options: ["asc", "desc"] }, + disabled: { control: "boolean" }, + }, + args: { + active: true, + direction: "asc", + disabled: false, + }, +}; +export default meta; +type Story = StoryObj<typeof meta>; + +export const Playground: Story = { + render: (args) => { + const [orderAsc, setOrderAsc] = React.useState(args.direction === "asc"); + const [active, setActive] = React.useState(args.active); + + const sorted = [...rows].sort((a, b) => + orderAsc ? a.name.localeCompare(b.name) : b.name.localeCompare(a.name), + ); + + return ( + <TableContainer component={Paper}> + <Table aria-label="sort label demo"> + <TableHead> + <TableRow> + <TableCell sortDirection={orderAsc ? "asc" : "desc"}> + <TableSortLabel + {...args} + active={active} + direction={orderAsc ? "asc" : "desc"} + onClick={() => { + setOrderAsc(!orderAsc); + setActive(true); + }} + > + Dessert (100g serving) + </TableSortLabel> + </TableCell> + <TableCell align="right">Calories</TableCell> + </TableRow> + </TableHead> + <TableBody> + {sorted.map((row) => ( + <TableRow key={row.name}> + <TableCell>{row.name}</TableCell> + <TableCell align="right">{row.calories}</TableCell> + </TableRow> + ))} + </TableBody> + </Table> + </TableContainer> + ); + }, +}; +``; diff --git a/src/components/MUI/DataDisplay/TableSortLabel.tsx b/src/components/MUI/DataDisplay/TableSortLabel.tsx new file mode 100644 index 0000000..11ddad9 --- /dev/null +++ b/src/components/MUI/DataDisplay/TableSortLabel.tsx @@ -0,0 +1,15 @@ +import * as React from "react"; +import MuiTableSortLabel, { + TableSortLabelProps as MuiTableSortLabelProps, +} from "@mui/material/TableSortLabel"; + +export type TableSortLabelProps = MuiTableSortLabelProps; + +export const TableSortLabel = React.forwardRef< + HTMLSpanElement, + TableSortLabelProps +>(function TableSortLabel(props, ref) { + return <MuiTableSortLabel ref={ref} {...props} />; +}); + +TableSortLabel.displayName = "TableSortLabel"; diff --git a/src/components/MUI/DataDisplay/Typography.stories.tsx b/src/components/MUI/DataDisplay/Typography.stories.tsx index 7eff38b..b0e319a 100644 --- a/src/components/MUI/DataDisplay/Typography.stories.tsx +++ b/src/components/MUI/DataDisplay/Typography.stories.tsx @@ -1,7 +1,6 @@ -// src/components/Typography/Typography.stories.tsx import type { Meta, StoryObj } from "@storybook/react"; import { Typography } from "./Typography"; -import Stack from "@mui/material/Stack"; +import { Stack } from "../Layout/Stack"; const meta: Meta<typeof Typography> = { title: "MUI/Data Display/Typography", @@ -154,4 +153,3 @@ export const Colors: Story = { </Stack> ), }; -``; diff --git a/src/components/MUI/DataDisplay/Typography.tsx b/src/components/MUI/DataDisplay/Typography.tsx index b1d67f8..581ab8e 100644 --- a/src/components/MUI/DataDisplay/Typography.tsx +++ b/src/components/MUI/DataDisplay/Typography.tsx @@ -5,7 +5,7 @@ import MuiTypography, { export type TypographyProps = MuiTypographyProps; -export const Typography = React.forwardRef<unknown, TypographyProps>( +export const Typography = React.forwardRef<HTMLSpanElement, TypographyProps>( (props, ref) => <MuiTypography ref={ref} {...props} />, ); diff --git a/src/components/MUI/Feedback/Alert.stories.tsx b/src/components/MUI/Feedback/Alert.stories.tsx index 1f9e2aa..4668c09 100644 --- a/src/components/MUI/Feedback/Alert.stories.tsx +++ b/src/components/MUI/Feedback/Alert.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryObj } from "@storybook/react"; import { Alert } from "./Alert"; -import Button from "@mui/material/Button"; +import { Button } from "../Inputs/Button"; const meta: Meta<typeof Alert> = { title: "MUI/Feedback/Alert", diff --git a/src/components/MUI/Feedback/Backdrop.stories.tsx b/src/components/MUI/Feedback/Backdrop.stories.tsx index 409cf11..6e64453 100644 --- a/src/components/MUI/Feedback/Backdrop.stories.tsx +++ b/src/components/MUI/Feedback/Backdrop.stories.tsx @@ -1,8 +1,8 @@ import type { Meta, StoryObj } from "@storybook/react"; import * as React from "react"; import { Backdrop } from "./Backdrop"; -import Button from "@mui/material/Button"; -import CircularProgress from "@mui/material/CircularProgress"; +import { CircularProgress } from "./CircularProgress"; +import { Button } from "../Inputs/Button"; const meta: Meta<typeof Backdrop> = { title: "MUI/Feedback/Backdrop", diff --git a/src/components/MUI/Feedback/CircularProgress.stories.tsx b/src/components/MUI/Feedback/CircularProgress.stories.tsx index 7c7cc07..61871b1 100644 --- a/src/components/MUI/Feedback/CircularProgress.stories.tsx +++ b/src/components/MUI/Feedback/CircularProgress.stories.tsx @@ -1,4 +1,3 @@ -// src/components/Progress/CircularProgress.stories.tsx import type { Meta, StoryObj } from "@storybook/react"; import { CircularProgress } from "./CircularProgress"; diff --git a/src/components/MUI/Feedback/CircularProgress.tsx b/src/components/MUI/Feedback/CircularProgress.tsx index a522c2e..5a2aa25 100644 --- a/src/components/MUI/Feedback/CircularProgress.tsx +++ b/src/components/MUI/Feedback/CircularProgress.tsx @@ -1,4 +1,3 @@ -// src/components/Progress/CircularProgress.tsx import * as React from "react"; import MuiCircularProgress, { CircularProgressProps as MuiCircularProgressProps, diff --git a/src/components/MUI/Feedback/Dialog.stories.tsx b/src/components/MUI/Feedback/Dialog.stories.tsx index 491c1a1..ac660c8 100644 --- a/src/components/MUI/Feedback/Dialog.stories.tsx +++ b/src/components/MUI/Feedback/Dialog.stories.tsx @@ -1,11 +1,11 @@ +import React from "react"; import type { Meta, StoryObj } from "@storybook/react"; import { Dialog } from "./Dialog"; import DialogTitle from "@mui/material/DialogTitle"; import DialogContent from "@mui/material/DialogContent"; import DialogActions from "@mui/material/DialogActions"; -import Button from "@mui/material/Button"; -import Typography from "@mui/material/Typography"; -import React from "react"; +import { Typography } from "../DataDisplay/Typography"; +import { Button } from "../Inputs/Button"; const meta: Meta<typeof Dialog> = { title: "MUI/Feedback/Dialog", diff --git a/src/components/MUI/Feedback/Snackbar.stories.tsx b/src/components/MUI/Feedback/Snackbar.stories.tsx index 08fe5b8..706600c 100644 --- a/src/components/MUI/Feedback/Snackbar.stories.tsx +++ b/src/components/MUI/Feedback/Snackbar.stories.tsx @@ -1,7 +1,7 @@ import type { Meta, StoryObj } from "@storybook/react"; -import Button from "@mui/material/Button"; import React from "react"; import { Snackbar } from "./Snackbar"; +import { Button } from "../Inputs/Button"; const anchorMap = { "top-left": { vertical: "top", horizontal: "left" }, @@ -31,7 +31,7 @@ const meta: Meta<typeof Snackbar> = { args: { message: "Saved", autoHideDuration: 3000, - anchorOrigin: "bottom-left", + anchorOrigin: { vertical: "bottom", horizontal: "left" }, }, }; export default meta; diff --git a/src/components/MUI/Feedback/Tooltip.stories.tsx b/src/components/MUI/Feedback/Tooltip.stories.tsx index 283db97..4fa3ec4 100644 --- a/src/components/MUI/Feedback/Tooltip.stories.tsx +++ b/src/components/MUI/Feedback/Tooltip.stories.tsx @@ -1,7 +1,7 @@ import type { Meta, StoryObj } from "@storybook/react"; import { Tooltip } from "./Tooltip"; -import IconButton from "@mui/material/IconButton"; import InfoIcon from "@mui/icons-material/Info"; +import { IconButton } from "../DataDisplay/IconButton"; const meta: Meta<typeof Tooltip> = { title: "MUI/Feedback/Tooltip", @@ -42,7 +42,7 @@ type Story = StoryObj<typeof meta>; export const Basic: Story = { render: (args) => ( - <Tooltip {...args}> + <Tooltip {...args} title={args.title!}> <IconButton aria-label="info"> <InfoIcon /> </IconButton> @@ -59,32 +59,32 @@ export const Placements: Story = { gridTemplateColumns: "repeat(3, minmax(0, 1fr))", }} > - <Tooltip {...args} placement="top"> + <Tooltip {...args} title={args.title!} placement="top"> <IconButton> <InfoIcon /> </IconButton> </Tooltip> - <Tooltip {...args} placement="right"> + <Tooltip {...args} title={args.title!} placement="right"> <IconButton> <InfoIcon /> </IconButton> </Tooltip> - <Tooltip {...args} placement="bottom"> + <Tooltip {...args} title={args.title!} placement="bottom"> <IconButton> <InfoIcon /> </IconButton> </Tooltip> - <Tooltip {...args} placement="left"> + <Tooltip {...args} title={args.title!} placement="left"> <IconButton> <InfoIcon /> </IconButton> </Tooltip> - <Tooltip {...args} placement="top-start"> + <Tooltip {...args} title={args.title!} placement="top-start"> <IconButton> <InfoIcon /> </IconButton> </Tooltip> - <Tooltip {...args} placement="top-end"> + <Tooltip {...args} title={args.title!} placement="top-end"> <IconButton> <InfoIcon /> </IconButton> diff --git a/src/components/MUI/Feedback/Tooltip.tsx b/src/components/MUI/Feedback/Tooltip.tsx index a3a4817..536fc0c 100644 --- a/src/components/MUI/Feedback/Tooltip.tsx +++ b/src/components/MUI/Feedback/Tooltip.tsx @@ -5,8 +5,8 @@ import MuiTooltip, { export type TooltipProps = MuiTooltipProps; -export const Tooltip = React.forwardRef<unknown, TooltipProps>((props, ref) => ( - <MuiTooltip ref={ref as any} {...props} /> -)); +export const Tooltip = React.forwardRef<HTMLDivElement, TooltipProps>( + (props, ref) => <MuiTooltip ref={ref as any} {...props} />, +); Tooltip.displayName = "Tooltip"; diff --git a/src/components/MUI/Inputs/Autocomplete.stories.tsx b/src/components/MUI/Inputs/Autocomplete.stories.tsx index 169ffd6..32ebe4d 100644 --- a/src/components/MUI/Inputs/Autocomplete.stories.tsx +++ b/src/components/MUI/Inputs/Autocomplete.stories.tsx @@ -1,8 +1,8 @@ import * as React from "react"; import type { Meta, StoryObj } from "@storybook/react"; import { Autocomplete } from "./Autocomplete"; -import TextField from "@mui/material/TextField"; -import Chip from "@mui/material/Chip"; +import { Chip } from "../DataDisplay/Chip"; +import { TextField } from "./TextField"; const options = [ "Apple", diff --git a/src/components/MUI/Inputs/Button.stories.tsx b/src/components/MUI/Inputs/Button.stories.tsx index d26a966..01a2d35 100644 --- a/src/components/MUI/Inputs/Button.stories.tsx +++ b/src/components/MUI/Inputs/Button.stories.tsx @@ -1,12 +1,11 @@ import type { Meta, StoryObj } from "@storybook/react"; import { Button } from "./Button"; - import SaveIcon from "@mui/icons-material/Save"; import SendIcon from "@mui/icons-material/Send"; import DeleteIcon from "@mui/icons-material/Delete"; import AddIcon from "@mui/icons-material/Add"; -import Stack from "@mui/material/Stack"; import { Box } from "../Layout/Box"; +import { Stack } from "../Layout/Stack"; const iconMap = { none: undefined, @@ -34,6 +33,7 @@ const meta: Meta<typeof Button> = { controls: { expanded: true }, layout: "padded", }, + argTypes: { variant: { control: { type: "select" }, @@ -55,11 +55,7 @@ const meta: Meta<typeof Button> = { control: { type: "select" }, options: ["small", "medium", "large"], }, - disabled: { control: "boolean" }, - disableElevation: { control: "boolean" }, - disableFocusRipple: { control: "boolean" }, - disableRipple: { control: "boolean" }, - fullWidth: { control: "boolean" }, + startIconName: { name: "startIcon", control: { type: "select" }, @@ -78,7 +74,7 @@ const meta: Meta<typeof Button> = { component: { control: false }, children: { name: "label", control: "text" }, - }, + } as any, args: { children: "Button", variant: "contained", @@ -89,12 +85,10 @@ const meta: Meta<typeof Button> = { disableFocusRipple: false, disableRipple: false, fullWidth: false, - startIconName: "none" as IconKey, - endIconName: "none" as IconKey, + startIcon: "none" as IconKey, + endIcon: "none" as IconKey, href: "", - target: "", rel: "", - ariaLabel: "", }, }; diff --git a/src/components/MUI/Inputs/Select.stories.tsx b/src/components/MUI/Inputs/Select.stories.tsx index 6ce8678..c3ff1c8 100644 --- a/src/components/MUI/Inputs/Select.stories.tsx +++ b/src/components/MUI/Inputs/Select.stories.tsx @@ -1,8 +1,6 @@ import type { Meta, StoryObj } from "@storybook/react"; import { Select } from "./Select"; -import FormControl from "@mui/material/FormControl"; -import MenuItem from "@mui/material/MenuItem"; -import InputLabel from "@mui/material/InputLabel"; +import { FormControl, InputLabel, MenuItem } from "@mui/material"; const cityOptions = ["London", "Paris", "Berlin", "Rome", "Madrid"]; diff --git a/src/components/MUI/Inputs/SpeedDial.stories.tsx b/src/components/MUI/Inputs/SpeedDial.stories.tsx index 0ae06b2..9f02c5a 100644 --- a/src/components/MUI/Inputs/SpeedDial.stories.tsx +++ b/src/components/MUI/Inputs/SpeedDial.stories.tsx @@ -32,6 +32,7 @@ export const Basic: Story = { {...args} icon={<SpeedDialIcon />} sx={{ position: "absolute", bottom: 16, right: 16 }} + ariaLabel="" > <SpeedDialAction icon={<FileCopyIcon />} tooltipTitle="Copy" /> <SpeedDialAction icon={<SaveIcon />} tooltipTitle="Save" /> diff --git a/src/components/MUI/Inputs/TextField.stories.tsx b/src/components/MUI/Inputs/TextField.stories.tsx index 2140aeb..154c571 100644 --- a/src/components/MUI/Inputs/TextField.stories.tsx +++ b/src/components/MUI/Inputs/TextField.stories.tsx @@ -27,8 +27,6 @@ const meta: Meta<TFArgs> = { control: { type: "select" }, options: ["none", "dense", "normal"], }, - - // Content & behavior type: { control: "text" }, label: { control: "text" }, placeholder: { control: "text" }, @@ -37,16 +35,10 @@ const meta: Meta<TFArgs> = { required: { control: "boolean" }, disabled: { control: "boolean" }, fullWidth: { control: "boolean" }, - - // Multiline multiline: { control: "boolean" }, rows: { control: { type: "number", min: 1, max: 12, step: 1 } }, - - // Keep value/onChange uncontrolled in Basic so demos are interactive value: { control: false }, onChange: { control: false }, - - // Advanced props out of Controls for clarity InputProps: { control: false }, InputLabelProps: { control: false }, FormHelperTextProps: { control: false }, @@ -73,16 +65,10 @@ const meta: Meta<TFArgs> = { export default meta; type Story = StoryObj<TFArgs>; -/** - * Basic interactive field driven by Controls. - */ export const Basic: Story = { render: (args) => <TextField {...args} />, }; -/** - * Showcase the three variants. - */ export const Variants: Story = { render: (args) => ( <div style={{ display: "grid", gap: 12 }}> @@ -94,9 +80,6 @@ export const Variants: Story = { args: { color: "primary", helperText: "" }, }; -/** - * Sizes and colors examples. - */ export const SizesAndColors: Story = { render: (args) => ( <div style={{ display: "grid", gap: 12 }}> @@ -133,9 +116,6 @@ export const SizesAndColors: Story = { args: { variant: "outlined", helperText: "" }, }; -/** - * Common states: required, error, disabled, fullWidth. - */ export const States: Story = { render: (args) => ( <div style={{ display: "grid", gap: 12 }}> @@ -155,9 +135,6 @@ export const States: Story = { args: { variant: "outlined", color: "primary" }, }; -/** - * Multiline example. - */ export const Multiline: Story = { args: { multiline: true, @@ -168,9 +145,6 @@ export const Multiline: Story = { render: (args) => <TextField {...args} />, }; -/** - * Types: password, number, email, search. - */ export const InputTypes: Story = { render: (args) => ( <div style={{ display: "grid", gap: 12 }}> diff --git a/src/components/MUI/Inputs/ToggleButtonGroup.stories.tsx b/src/components/MUI/Inputs/ToggleButtonGroup.stories.tsx index 3b52d23..5b4284e 100644 --- a/src/components/MUI/Inputs/ToggleButtonGroup.stories.tsx +++ b/src/components/MUI/Inputs/ToggleButtonGroup.stories.tsx @@ -1,7 +1,7 @@ import type { Meta, StoryObj } from "@storybook/react"; import * as React from "react"; import { ToggleButtonGroup } from "./ToggleButtonGroup"; -import { ToggleButton } from "@mui/material"; +import ToggleButton from "@mui/material/ToggleButton"; type TBGArgs = React.ComponentProps<typeof ToggleButtonGroup>; diff --git a/src/components/MUI/Layout/Grid2.stories.tsx b/src/components/MUI/Layout/Grid2.stories.tsx index dea538e..2f862db 100644 --- a/src/components/MUI/Layout/Grid2.stories.tsx +++ b/src/components/MUI/Layout/Grid2.stories.tsx @@ -34,13 +34,13 @@ const Item = ({ children }: { children: React.ReactNode }) => ( export const Basic: Story = { render: (args) => ( <GridV2 container spacing={args.spacing} columns={args.columns}> - <GridV2 xs={4}> + <GridV2 size={{ xs: 4 }}> <Item>xs=4</Item> </GridV2> - <GridV2 xs={4}> + <GridV2 size={{ xs: 4 }}> <Item>xs=4</Item> </GridV2> - <GridV2 xs={4}> + <GridV2 size={{ xs: 4 }}> <Item>xs=4</Item> </GridV2> </GridV2> @@ -50,13 +50,13 @@ export const Basic: Story = { export const Responsive: Story = { render: (args) => ( <GridV2 container spacing={args.spacing} columns={12}> - <GridV2 xs={12} sm={6} md={4}> + <GridV2 size={{ xs: 12, sm: 12, md: 4 }}> <Item>xs=12 sm=6 md=4</Item> </GridV2> - <GridV2 xs={12} sm={6} md={4}> + <GridV2 size={{ xs: 12, sm: 12, md: 4 }}> <Item>xs=12 sm=6 md=4</Item> </GridV2> - <GridV2 xs={12} sm={12} md={4}> + <GridV2 size={{ xs: 12, sm: 12, md: 4 }}> <Item>xs=12 sm=12 md=4</Item> </GridV2> </GridV2> diff --git a/src/components/MUI/Layout/Grid2.tsx b/src/components/MUI/Layout/Grid2.tsx index d434f5e..e2e6197 100644 --- a/src/components/MUI/Layout/Grid2.tsx +++ b/src/components/MUI/Layout/Grid2.tsx @@ -1,10 +1,10 @@ -import * as React from "react"; -import Grid2, { Grid2Props } from "@mui/material/Grid2"; +import Grid2, { Grid2Props } from "@mui/material/Grid2/Grid2"; +import React from "react"; export type GridV2Props = Grid2Props; -export const GridV2 = React.forwardRef<any, GridV2Props>((props, ref) => ( - <Grid2 ref={ref} {...props} /> -)); +export const GridV2 = React.forwardRef<HTMLDivElement, Grid2Props>( + (props, ref) => <Grid2 ref={ref} {...props} />, +); GridV2.displayName = "GridV2"; diff --git a/src/components/MUI/Navigation/Breadcrumbs.stories.tsx b/src/components/MUI/Navigation/Breadcrumbs.stories.tsx index bcd589e..2f3e1c4 100644 --- a/src/components/MUI/Navigation/Breadcrumbs.stories.tsx +++ b/src/components/MUI/Navigation/Breadcrumbs.stories.tsx @@ -85,10 +85,10 @@ export const Collapsed: Story = { }, render: (args) => ( <Breadcrumbs {...args}> - <Link>#Home</Link> - <Link>#Section</Link> - <Link>#Category</Link> - <Link>#Subcategory</Link> + <Link>Home</Link> + <Link>Section</Link> + <Link>Category</Link> + <Link>Subcategory</Link> <Typography color="text.primary">Item</Typography> </Breadcrumbs> ), diff --git a/src/components/MUI/Navigation/Drawer.stories.tsx b/src/components/MUI/Navigation/Drawer.stories.tsx index ab8f3c7..837c216 100644 --- a/src/components/MUI/Navigation/Drawer.stories.tsx +++ b/src/components/MUI/Navigation/Drawer.stories.tsx @@ -3,8 +3,8 @@ import * as React from "react"; import { Drawer } from "./Drawer"; import { Button } from "../Inputs/Button"; import { List } from "../DataDisplay/List"; -import ListItem from "@mui/material/ListItem"; -import ListItemText from "@mui/material/ListItemText"; +import { ListItem } from "../DataDisplay/ListItem"; +import { ListItemText } from "../DataDisplay/ListItemText"; const meta: Meta<typeof Drawer> = { title: "MUI/Navigation/Drawer", diff --git a/src/components/MUI/Navigation/Menu.stories.tsx b/src/components/MUI/Navigation/Menu.stories.tsx index 090d116..5913d58 100644 --- a/src/components/MUI/Navigation/Menu.stories.tsx +++ b/src/components/MUI/Navigation/Menu.stories.tsx @@ -4,8 +4,8 @@ import SaveIcon from "@mui/icons-material/Save"; import SendIcon from "@mui/icons-material/Send"; import React from "react"; import { Button } from "../Inputs/Button"; +import { ListItemIcon } from "../DataDisplay/ListItemIcon"; import MenuItem from "@mui/material/MenuItem"; -import ListItemIcon from "@mui/material/ListItemIcon"; const originMap = { tl: { vertical: "top", horizontal: "left" }, @@ -36,8 +36,8 @@ const meta: Meta<typeof Menu> = { variant: { control: "select", options: ["selectedMenu", "menu"] }, }, args: { - anchorOrigin: "bl", - transformOrigin: "tl", + anchorOrigin: { vertical: "bottom", horizontal: "left" }, + transformOrigin: { vertical: "top", horizontal: "left" }, keepMounted: false, variant: "menu", }, diff --git a/src/components/MUI/Surfaces/Accordion.stories.tsx b/src/components/MUI/Surfaces/Accordion.stories.tsx index 27ea1f7..0543466 100644 --- a/src/components/MUI/Surfaces/Accordion.stories.tsx +++ b/src/components/MUI/Surfaces/Accordion.stories.tsx @@ -2,8 +2,8 @@ import type { Meta, StoryObj } from "@storybook/react"; import AccordionSummary from "@mui/material/AccordionSummary"; import AccordionDetails from "@mui/material/AccordionDetails"; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; -import Typography from "@mui/material/Typography"; import { Accordion } from "./Accordion"; +import { Typography } from "../DataDisplay/Typography"; const meta: Meta<typeof Accordion> = { title: "MUI/Surfaces/Accordion", diff --git a/src/components/MUI/Surfaces/Card.stories.tsx b/src/components/MUI/Surfaces/Card.stories.tsx index ce073c8..3d42bc2 100644 --- a/src/components/MUI/Surfaces/Card.stories.tsx +++ b/src/components/MUI/Surfaces/Card.stories.tsx @@ -1,12 +1,11 @@ import type { Meta, StoryObj } from "@storybook/react"; import { Card } from "./Card"; - +import Diamond from "../../../public/images/diamond.jpg"; +import { Typography } from "../DataDisplay/Typography"; +import { Button } from "../Inputs/Button"; import CardContent from "@mui/material/CardContent"; import CardActions from "@mui/material/CardActions"; import CardMedia from "@mui/material/CardMedia"; -import Button from "@mui/material/Button"; -import Typography from "@mui/material/Typography"; -import Diamond from "../../../public/images/diamond.jpg"; const meta: Meta<typeof Card> = { title: "MUI/Surfaces/Card", diff --git a/src/components/MUI/Utils/CssBaseline.stories.tsx b/src/components/MUI/Utils/CssBaseline.stories.tsx index b700ff4..e705c98 100644 --- a/src/components/MUI/Utils/CssBaseline.stories.tsx +++ b/src/components/MUI/Utils/CssBaseline.stories.tsx @@ -1,9 +1,8 @@ import * as React from "react"; import type { Meta, StoryObj } from "@storybook/react"; - -import { CssBaseline } from "./CssBaseline"; import { Typography } from "../DataDisplay/Typography"; import { Box } from "../Layout/Box"; +import { CssBaseline } from "./CssBaseline"; type Args = React.ComponentProps<typeof CssBaseline>; diff --git a/src/components/MUI/Utils/CssBaseline.tsx b/src/components/MUI/Utils/CssBaseline.tsx index e69de29..9db7067 100644 --- a/src/components/MUI/Utils/CssBaseline.tsx +++ b/src/components/MUI/Utils/CssBaseline.tsx @@ -0,0 +1,8 @@ +import * as React from "react"; +import MuiCssBaseline from "@mui/material/CssBaseline"; + +export type CssBaselineProps = React.ComponentProps<typeof MuiCssBaseline>; + +export const CssBaseline = (props: CssBaselineProps) => ( + <MuiCssBaseline {...props} /> +); diff --git a/src/components/MUI/Utils/Popover.stories.tsx b/src/components/MUI/Utils/Popover.stories.tsx index 12f0caf..49213bf 100644 --- a/src/components/MUI/Utils/Popover.stories.tsx +++ b/src/components/MUI/Utils/Popover.stories.tsx @@ -30,7 +30,11 @@ const meta: Meta<typeof Popover> = { }, disablePortal: { control: "boolean" }, }, - args: { anchorOrigin: "bl", transformOrigin: "tl", disablePortal: false }, + args: { + anchorOrigin: { vertical: "bottom", horizontal: "left" }, + transformOrigin: { vertical: "top", horizontal: "left" }, + disablePortal: false, + }, }; export default meta; type Story = StoryObj<typeof meta>; diff --git a/src/components/MUI/Utils/Popper.stories.tsx b/src/components/MUI/Utils/Popper.stories.tsx index 9d737c9..b953b05 100644 --- a/src/components/MUI/Utils/Popper.stories.tsx +++ b/src/components/MUI/Utils/Popper.stories.tsx @@ -1,11 +1,17 @@ import * as React from "react"; import type { Meta, StoryObj } from "@storybook/react"; -import { Popper } from "./Popper"; +import { Popper, PopperProps } from "./Popper"; import { Button } from "../Inputs/Button"; import { Fade } from "./Transitions"; import { Box } from "../Layout/Box"; -type Args = React.ComponentProps<typeof Popper> & { content?: string }; +type Args = { + placement?: PopperProps["placement"]; + disablePortal?: boolean; + keepMounted?: boolean; + transition?: boolean; + content?: string; +}; const meta: Meta<Args> = { title: "MUI/Utils/Popper", @@ -33,10 +39,6 @@ const meta: Meta<Args> = { disablePortal: { control: "boolean" }, keepMounted: { control: "boolean" }, transition: { control: "boolean" }, - modifiers: { control: false }, - container: { control: false }, - anchorEl: { control: false }, - children: { control: false }, content: { control: "text" }, }, args: { diff --git a/src/components/MUI/Utils/UseMediaQuery.stories.tsx b/src/components/MUI/Utils/UseMediaQuery.stories.tsx index d3f7777..54d5b88 100644 --- a/src/components/MUI/Utils/UseMediaQuery.stories.tsx +++ b/src/components/MUI/Utils/UseMediaQuery.stories.tsx @@ -1,7 +1,6 @@ import * as React from "react"; import type { Meta, StoryObj } from "@storybook/react"; import { UseMediaQuery } from "./UseMediaQuery"; - import { useTheme } from "@mui/material/styles"; import { Box } from "../Layout/Box"; diff --git a/src/components/MUI/Utils/UseMediaQuery.tsx b/src/components/MUI/Utils/UseMediaQuery.tsx index c5ac931..dbae50a 100644 --- a/src/components/MUI/Utils/UseMediaQuery.tsx +++ b/src/components/MUI/Utils/UseMediaQuery.tsx @@ -1,4 +1,3 @@ -import * as React from "react"; import useMediaQueryHook from "@mui/material/useMediaQuery"; export type UseMediaQueryProps = { query: string }; diff --git a/src/types/raw.d.ts b/src/types/raw.d.ts new file mode 100644 index 0000000..abae50b --- /dev/null +++ b/src/types/raw.d.ts @@ -0,0 +1,4 @@ +declare module "*.tsx?raw" { + const content: string; + export default content; +} From 6b92c2563bdaa8b56b6721db2174ec4d2cfa3fb6 Mon Sep 17 00:00:00 2001 From: VictoriaBeilstenEdmands <victoria.beilsten.edmands@gmail.com> Date: Tue, 27 Jan 2026 10:27:28 +0000 Subject: [PATCH 05/10] Add Diamond Theme --- .gitignore | 6 +- .storybook/preview.tsx | 72 +- .storybook/storybook.css | 59 ++ package.json | 3 + pnpm-lock.yaml | 25 + src/index.ts | 1 + .../{Introduction.mdx => Installation.mdx} | 8 +- src/storybook/about.mdx | 119 +++ src/storybook/accessibility/00-overview.mdx | 99 ++ .../accessibility/01-colour-contrast.mdx | 400 ++++++++ .../02-cognitive-and-learning.mdx | 151 +++ src/storybook/foundation/colours.mdx | 510 ++++++++++ src/storybook/foundation/typography.mdx | 77 ++ .../diamondDS/diamond-colors-primitives.css | 890 ++++++++++++++++++ .../diamondDS/diamond-mui-palette-tokens.css | 243 +++++ src/themes/DiamondDSTheme.ts | 451 +++++++++ src/themes/ThemeProvider.tsx | 39 +- src/themes/icons/CheckboxIcons.tsx | 45 + src/themes/icons/index.ts | 1 + 19 files changed, 3163 insertions(+), 36 deletions(-) create mode 100644 .storybook/storybook.css rename src/storybook/{Introduction.mdx => Installation.mdx} (98%) create mode 100644 src/storybook/about.mdx create mode 100644 src/storybook/accessibility/00-overview.mdx create mode 100644 src/storybook/accessibility/01-colour-contrast.mdx create mode 100644 src/storybook/accessibility/02-cognitive-and-learning.mdx create mode 100644 src/storybook/foundation/colours.mdx create mode 100644 src/storybook/foundation/typography.mdx create mode 100644 src/styles/diamondDS/diamond-colors-primitives.css create mode 100644 src/styles/diamondDS/diamond-mui-palette-tokens.css create mode 100644 src/themes/DiamondDSTheme.ts create mode 100644 src/themes/icons/CheckboxIcons.tsx create mode 100644 src/themes/icons/index.ts diff --git a/.gitignore b/.gitignore index 9564298..dbaee90 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,8 @@ /docs .pnpm-store/ -tsconfig.tsbuildinfo \ No newline at end of file +tsconfig.tsbuildinfo + +# System files +.DS_Store +**/.DS_Store diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 750a7eb..28bed05 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -1,15 +1,55 @@ -import React from "react"; +import React, { useLayoutEffect } from "react"; import { CssBaseline } from "@mui/material"; import type { Preview } from "@storybook/react"; import "@fontsource-variable/inter"; +import "./storybook.css"; /* Storybook CSS override */ import { ThemeProvider } from "../src"; -import { GenericTheme, DiamondTheme } from "../src"; - +import { + GenericTheme, + DiamondTheme, + DiamondDSTheme, + DiamondDSThemeDark, +} from "../src"; import { Context, ThemeSwapper, TextLight, TextDark } from "./ThemeSwapper"; const TextThemeBase = "Theme: Generic"; const TextThemeDiamond = "Theme: Diamond"; +const TextThemeDiamondDS = "Theme: DiamondDS"; + +function resolveTheme(selectedTheme: string, mode: "light" | "dark") { + switch (selectedTheme) { + case TextThemeBase: + return GenericTheme; + case TextThemeDiamondDS: + return mode === "dark" ? DiamondDSThemeDark : DiamondDSTheme; + case TextThemeDiamond: + default: + return DiamondTheme; + } +} + +function ApplyModeToPreviewDoc({ + mode, + doc, +}: { + mode: "light" | "dark"; + doc: Document; +}) { + useLayoutEffect(() => { + const root = doc.documentElement; // <html> + root.setAttribute("data-mode", mode); + + // Optional: keep class too if your CSS supports it + root.classList.toggle("dark", mode === "dark"); + root.classList.toggle("light", mode === "light"); + + root.style.colorScheme = mode; + }, [mode, doc]); + + return null; +} + export const decorators = [ (StoriesWithPadding: React.FC) => ( <div style={{ padding: "2em" }}> @@ -24,12 +64,16 @@ export const decorators = [ (StoriesWithThemeProvider: React.FC, context: Context) => { const selectedTheme = context.globals.theme || TextThemeBase; const selectedThemeMode = context.globals.themeMode || TextLight; + const mode = selectedThemeMode === TextLight ? "light" : "dark"; + // ensure we target the preview iframe document + const doc: Document = context?.canvasElement?.ownerDocument ?? document; return ( <ThemeProvider - theme={selectedTheme === TextThemeBase ? GenericTheme : DiamondTheme} - defaultMode={selectedThemeMode === TextLight ? "light" : "dark"} + theme={resolveTheme(selectedTheme, mode)} + defaultMode={mode} > + <ApplyModeToPreviewDoc mode={mode} doc={doc} /> <CssBaseline /> <StoriesWithThemeProvider /> </ThemeProvider> @@ -44,7 +88,7 @@ const preview: Preview = { toolbar: { title: "Theme", icon: "cog", - items: [TextThemeBase, TextThemeDiamond], + items: [TextThemeBase, TextThemeDiamond, TextThemeDiamondDS], dynamicTitle: true, }, }, @@ -59,8 +103,8 @@ const preview: Preview = { }, }, initialGlobals: { - theme: "Theme: Diamond", - themeMode: "Mode: Light", + theme: TextThemeDiamondDS, + themeMode: TextLight, }, parameters: { controls: { @@ -72,18 +116,6 @@ const preview: Preview = { }, backgrounds: { disable: true }, layout: "fullscreen", - options: { - storySort: { - order: [ - "Introduction", - "Components", - "Theme", - "Theme/Logos", - "Theme/Colours", - "Helpers", - ], - }, - }, }, argTypes: { linkComponent: { control: false }, diff --git a/.storybook/storybook.css b/.storybook/storybook.css new file mode 100644 index 0000000..f409b9f --- /dev/null +++ b/.storybook/storybook.css @@ -0,0 +1,59 @@ +:root { + --ds-font-body: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, + 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; + + --ds-font-heading: 'Outfit', system-ui, -apple-system, BlinkMacSystemFont, + 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; + + --ds-font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, + Consolas, 'Liberation Mono', 'Courier New', monospace; + } + + /* Docs root */ + .sbdocs, .sbdocs p, .sbdocs li,.sb-unstyled, .sb-unstyled ul, .sb-unstyled li { + font-family: var(--ds-font-body); + font-size: 16px !important; + line-height: 1.6; + } + + /* Lists */ + .sbdocs li { + font-size: 16px !important; + } + + /* Headings use Outfit or Inter */ + + .sbdocs h1 { + font-family: var(--ds-font-heading); + } + + .sbdocs h3, + .sbdocs h4, + .sbdocs h5, + .sbdocs h6 { + font-family: var(--ds-font-body); + } + + /* Code uses IBM Plex Mono */ + .sbdocs code, + .sbdocs pre, + .sbdocs kbd, + .sbdocs samp, + .token { + font-family: var(--ds-font-mono); + font-size: 1em; + f + } + + /* Neutralise Storybook Docs inline preview background wrapper */ + .sbdocs-preview div[style*="background-color"], #storybook-root div[style*="background-color"] { + background-color: transparent !important; + } + + .light .sbdocs-preview div[style*="background-color"] { + background-color: #f6f6f6 !important; + } + + .dark .sbdocs-preview div[style*="background-color"]{ + background-color: #212121 !important; + } diff --git a/package.json b/package.json index dddfdeb..901c535 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,9 @@ "@babel/preset-typescript": "^7.26.0", "@chromatic-com/storybook": "^3.2.2", "@eslint/eslintrc": "^3.2.0", + "@fontsource/ibm-plex-mono": "^5.2.7", + "@fontsource/inter": "^5.2.8", + "@fontsource/outfit": "^5.2.8", "@rollup/plugin-commonjs": "^28.0.1", "@rollup/plugin-image": "^3.0.3", "@rollup/plugin-json": "^6.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f72c5ac..f5bfffd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -63,6 +63,15 @@ importers: '@eslint/eslintrc': specifier: ^3.2.0 version: 3.2.0 + '@fontsource/ibm-plex-mono': + specifier: ^5.2.7 + version: 5.2.7 + '@fontsource/inter': + specifier: ^5.2.8 + version: 5.2.8 + '@fontsource/outfit': + specifier: ^5.2.8 + version: 5.2.8 '@rollup/plugin-commonjs': specifier: ^28.0.1 version: 28.0.2(rollup@4.30.0) @@ -1084,6 +1093,15 @@ packages: '@fontsource-variable/inter@5.2.8': resolution: {integrity: sha512-kOfP2D+ykbcX/P3IFnokOhVRNoTozo5/JxhAIVYLpea/UBmCQ/YWPBfWIDuBImXX/15KH+eKh4xpEUyS2sQQGQ==} + '@fontsource/ibm-plex-mono@5.2.7': + resolution: {integrity: sha512-MKAb8qV+CaiMQn2B0dIi1OV3565NYzp3WN5b4oT6LTkk+F0jR6j0ZN+5BKJiIhffDC3rtBULsYZE65+0018z9w==} + + '@fontsource/inter@5.2.8': + resolution: {integrity: sha512-P6r5WnJoKiNVV+zvW2xM13gNdFhAEpQ9dQJHt3naLvfg+LkF2ldgSLiF4T41lf1SQCM9QmkqPTn4TH568IRagg==} + + '@fontsource/outfit@5.2.8': + resolution: {integrity: sha512-rXC6g0MqD7cOBjht0bMqc43qM6lRqDLML9KXsmg9uykz0wLQhy8Z/ajrMG6iyoT3NJR+MYgU+OEHp7uHoTb+Yw==} + '@gerrit0/mini-shiki@3.7.0': resolution: {integrity: sha512-7iY9wg4FWXmeoFJpUL2u+tsmh0d0jcEJHAIzVxl3TG4KL493JNnisdLAILZ77zcD+z3J0keEXZ+lFzUgzQzPDg==} @@ -4636,6 +4654,7 @@ packages: whatwg-encoding@2.0.0: resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} engines: {node: '>=12'} + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation whatwg-mimetype@3.0.0: resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} @@ -5764,6 +5783,12 @@ snapshots: '@fontsource-variable/inter@5.2.8': {} + '@fontsource/ibm-plex-mono@5.2.7': {} + + '@fontsource/inter@5.2.8': {} + + '@fontsource/outfit@5.2.8': {} + '@gerrit0/mini-shiki@3.7.0': dependencies: '@shikijs/engine-oniguruma': 3.7.0 diff --git a/src/index.ts b/src/index.ts index 8277145..4c2c45a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -22,6 +22,7 @@ export * from "./components/helpers/jsonforms"; // themes export * from "./themes/BaseTheme"; export * from "./themes/DiamondTheme"; +export * from "./themes/DiamondDSTheme"; export * from "./themes/GenericTheme"; export * from "./themes/ThemeProvider"; export * from "./themes/ThemeManager"; diff --git a/src/storybook/Introduction.mdx b/src/storybook/Installation.mdx similarity index 98% rename from src/storybook/Introduction.mdx rename to src/storybook/Installation.mdx index 7113771..770c475 100644 --- a/src/storybook/Introduction.mdx +++ b/src/storybook/Installation.mdx @@ -1,7 +1,7 @@ -import packageJson from "../../package.json" +import packageJson from "../../package.json"; import { Meta } from "@storybook/blocks"; -<Meta title="Introduction" /> +<Meta title="Installation" /> <div className="sb-container"> <div className='sb-section-title'> @@ -14,6 +14,7 @@ import { Meta } from "@storybook/blocks"; Check out the list of components on the left. To use them, follow the instructions below. </div> + </div> <div className="sb-container"> @@ -111,8 +112,8 @@ import { Meta } from "@storybook/blocks"; } ``` </div> -</div> +</div> <div className="sb-container"> <div className='sb-section-title'> @@ -151,4 +152,5 @@ import { Meta } from "@storybook/blocks"; on GitHub. </div> + </div> diff --git a/src/storybook/about.mdx b/src/storybook/about.mdx new file mode 100644 index 0000000..c02e3b4 --- /dev/null +++ b/src/storybook/about.mdx @@ -0,0 +1,119 @@ +import { Meta } from "@storybook/blocks"; + +<Meta title="About" /> + +<div> + <h1>Scientific design system for Diamond</h1> + <p><strong>Version: Scientific React UI - v0.3.1-alpha.3</strong></p> + +{" "} +<p> + Diamond II brings major upgrades to our scientific capabilities, and with that + comes a growing ecosystem of tools used across beamlines, data acquisition, + analysis, and scientific support. +</p> + +{" "} +<p> + This design system gives us a shared foundation of components, patterns, and + visual rules so that every tool at Diamond feels coherent, predictable, and + efficient, in service of better science and smoother operations across the + facility. +</p> + +{" "} +<h2>Why we need a design system</h2> +<ul> + <li> + <strong>Modernise for Diamond II</strong>: redesign interfaces with clarity, + safety, and efficiency at the core. + </li> + <li> + <strong>Unify legacy systems</strong>: reduce inconsistent patterns, + behaviours, and visual languages across tools. + </li> + <li> + <strong>Reduce cognitive load</strong>: scientists and engineers move + between multiple systems; familiarity helps. + </li> + <li> + <strong>Accelerate delivery</strong>: shared components and patterns reduce + repeated work. + </li> + <li> + <strong>Future-proof</strong>: new tools start coherent and stay coherent. + </li> +</ul> + +{" "} +<h2>What the design system includes</h2> +<h3>Design assets</h3> +<ul> + <li> + <strong>Foundations</strong>: colour, typography, spacing, grid, interaction + states + </li> + <li> + <strong>Components</strong>: buttons, inputs, tables, tabs + </li> + <li> + <strong>Patterns</strong>: panels, configuration, monitoring, data browsing + </li> + <li> + <strong>Templates</strong>: pages, dashboards, details views + </li> +</ul> + +{" "} +<h3>Plus</h3> +<ul> + <li>Accessibility guidance</li> + <li>Processes and documentation</li> + <li>UX strategy and interaction principles</li> +</ul> + +{" "} +<h2>Where truth lives</h2> +<ul> + <li> + <strong>Figma</strong> is the design source of truth. + </li> + <li> + <strong>Storybook</strong> is the code source of truth. + </li> + <li> + We build on <strong>Material UI (MUI)</strong> in React, customised for + Diamond workflows. + </li> +</ul> + +{" "} +<h2>What’s different about scientific controls</h2> +<ul> + <li> + <strong>Time is scarce</strong> on beamlines; interruptions are costly. + </li> + <li> + <strong>Experiments are stateful</strong>; the UI must make state and + progress obvious. + </li> + <li> + <strong>Users may be visiting</strong> and working under pressure. + </li> + <li> + <strong>High-density data</strong> is normal: tables, logs, dashboards. + </li> + <li> + <strong>Safety-critical actions</strong> need clear signifiers, + confirmation, and recovery paths. + </li> +</ul> + + <h2>How to use this documentation</h2> + <ol> + <li>Start with Foundations to understand the rules.</li> + <li>Use Components for building blocks.</li> + <li>Use Patterns for repeatable workflows.</li> + <li>Treat docs as the shared contract: what we build, how it behaves, and why.</li> + </ol> +</div> diff --git a/src/storybook/accessibility/00-overview.mdx b/src/storybook/accessibility/00-overview.mdx new file mode 100644 index 0000000..7af1d45 --- /dev/null +++ b/src/storybook/accessibility/00-overview.mdx @@ -0,0 +1,99 @@ +import { Meta } from "@storybook/blocks"; + +<Meta title="Accessibility/Overview" /> + +<div> + <h1>Accessibility</h1> + +{" "} +<p> + Accessibility in the Diamond design system is not a checklist or a separate + mode. It’s a baseline for quality, clarity, and usability in complex + scientific tools. +</p> + +{" "} +<p> + Our goal is to make interfaces that are understandable, predictable, and + usable across a wide range of abilities, environments, and levels of fatigue. +</p> + +{" "} +<h2>Core principles</h2> +<ul> + <li> + <strong>Clarity over cleverness</strong>: interfaces should explain + themselves. + </li> + <li> + <strong>Predictable behaviour</strong>: similar things behave in similar + ways. + </li> + <li> + <strong>Multiple ways to perceive information</strong>: never rely on one + signal alone. + </li> + <li> + <strong>Low cognitive effort by default</strong>: minimise mental overhead. + </li> +</ul> + +{" "} +<h2>Do</h2> + +{" "} +<h3>Interactive elements</h3> +<ul> + <li>Ensure every interactive control has an accessible name.</li> + <li>Provide this via a visible label, `aria-label`, or `aria-labelledby`.</li> + <li>Make keyboard focus clearly visible at all times.</li> + <li> + Ensure disabled states are clearly distinguishable from enabled and default. + </li> +</ul> + +{" "} +<h3>Forms and inputs</h3> +<ul> + <li>Always associate inputs with labels (even if visually hidden).</li> + <li>Make error messages clear, specific, and actionable.</li> + <li>Associate errors programmatically with the relevant field.</li> +</ul> + +{" "} +<h3>Content and layout</h3> +<ul> + <li>Do not rely on colour alone to convey meaning.</li> + <li>Support icons with text or accessible names.</li> + <li>Use a logical, predictable reading order.</li> +</ul> + +{" "} +<h2>Don’t</h2> +<ul> + <li>Don’t use placeholder text as a replacement for labels.</li> + <li>Don’t hide important information in faint or decorative text.</li> + <li>Don’t introduce unexpected interaction patterns.</li> + <li>Don’t create dense, unbroken blocks of content.</li> +</ul> + +{" "} +<h2>Storybook guidance</h2> +<ul> + <li> + Simple component stories may be visually minimal, but they must still expose + an accessible name, or be explicitly documented as intentionally incomplete. + </li> + <li> + Accessibility warnings in Storybook are signals, not noise. Either resolve + them or document why they exist. + </li> +</ul> + + <h2>Quick sense check</h2> + <ul> + <li>Can this be used with a keyboard only?</li> + <li>Is its purpose clear without colour?</li> + <li>Would it still make sense when someone is tired or distracted?</li> + </ul> +</div> diff --git a/src/storybook/accessibility/01-colour-contrast.mdx b/src/storybook/accessibility/01-colour-contrast.mdx new file mode 100644 index 0000000..204f208 --- /dev/null +++ b/src/storybook/accessibility/01-colour-contrast.mdx @@ -0,0 +1,400 @@ +import { Meta } from "@storybook/blocks"; + +<Meta title="Accessibility/Colour contrast" /> + +<div> + <h1>Colour contrast</h1> + +<p> + Colour contrast affects readability, accuracy, and fatigue. In data-heavy + scientific tools, poor contrast slows users down and increases errors. +</p> + +<p> + We use both WCAG contrast ratios and APCA to balance compliance with + real-world readability. +</p> + +<h2>WCAG contrast</h2> + +<p> + WCAG 2.x contrast ratios provide a clear, widely accepted compliance baseline. +</p> + +<ul> + <li>Used to define minimum acceptable contrast.</li> + <li>Acts as a hard “do not go below” threshold.</li> + <li>Especially important for small text and critical UI.</li> +</ul> + +<h2>APCA contrast</h2> + +<p> + APCA (Advanced Perceptual Contrast Algorithm) models human perception more + closely. It accounts for font size, weight, and polarity (light-on-dark vs + dark-on-light). +</p> + +<ul> + <li>Used to tune readability in light and dark themes.</li> + <li>Helps avoid over-contrast that causes eye strain.</li> + <li>Works better for large text and dense information.</li> +</ul> + +<h2>How we use them together</h2> + +<p> + All text should meet WCAG minimums. APCA is then used to refine token values + for comfort and hierarchy. +</p> + + <div> + <h2>Colour-specific considerations (green, orange, and red)</h2> + + <p> + Some hues behave poorly for perceived contrast, even when WCAG 2 contrast ratios pass. + </p> + + <p> + Green, orange, and red are common examples because perceived contrast is affected by luminance, + surrounding colours, polarity (light-on-dark vs dark-on-light), and colour vision differences. + </p> + + <p> + A practical issue we see in real interfaces: WCAG 2 ratios can sometimes indicate that black + text on a saturated green, orange, or red background is “high contrast”, but in practice it + can feel low-contrast, vibrating, or tiring to read — especially for small text, thinner + fonts, or dense data. This gap between numeric ratios and human perception is one of the + problems APCA is designed to address. + </p> + + <ul> + <li> + <strong>Green</strong>: may appear muddy or unstable with dark text, and can be difficult + for users with common colour vision differences. + </li> + <li> + <strong>Orange</strong>: often looks washed out on light backgrounds or overly bright on + dark backgrounds, reducing legibility. + </li> + <li> + <strong>Red</strong>: can appear low-contrast or “vibrating” with dark text, and is + particularly problematic for error or alert states if not handled carefully. + </li> + </ul> + + <p> + When using these colours for status, emphasis, or meaning: + </p> + + <ul> + <li>Never rely on colour alone — pair with text, icons, or labels.</li> + <li>Test in both light and dark modes, at realistic sizes and weights.</li> + <li>Use APCA to assess perceived readability, not just WCAG 2 ratios.</li> + </ul> + + <p> + The examples below illustrate combinations that may pass WCAG 2 but still feel hard to read + in practice. + </p> + + <p><strong>WCAG 2 vs APCA: why “passes” can still look wrong</strong></p> + <p> + WCAG 2 contrast ratio is a useful baseline, but it can recommend text colours that feel + low-contrast in practice (especially on saturated greens/oranges/reds). APCA is designed + to better reflect perceived contrast and readability. + </p> + +{/* START EXAMPLE */} + +<style>{` /* Scoped demo styles so Storybook/theme doesn't interfere */ + .ds-a11y-demo, .ds-a11y-demo * { + box-sizing: border-box; + } + /* Reset common typography overrides that can change perceived contrast */ + .ds-a11y-demo p, + .ds-a11y-demo span, + .ds-a11y-demo strong, + .ds-a11y-demo li, + .ds-a11y-demo h3 { + margin: 0; + color: inherit; + letter-spacing: normal; + text-transform: none; + } + .ds-a11y-demo p { margin-bottom: 8px; } + .ds-a11y-demo ul { margin: 0; padding-left: 18px; } + .ds-a11y-grid { + display: grid; + gap: 16px; + max-width: 920px; + margin-top: 12px; + } + .ds-a11y-panels { + display: grid; + gap: 16px; + grid-template-columns: 1fr 1fr; + } + .ds-a11y-panel { + border-radius: 10px; + padding: 14px; + border: 1px solid rgba(0,0,0,0.12); + } + .ds-a11y-panel--light { + background: #ffffff; + color: #111111; + } + .ds-a11y-panel--dark { + background: #0b0f14; /* "inverse" surface */ + color: #f3f5f7; + border: 1px solid rgba(255,255,255,0.14); + } + .ds-a11y-row { + display: grid; + gap: 8px; + margin-top: 10px; + } + .ds-a11y-rowTitle { + font-weight: 700; + margin-bottom: 2px; + } + .ds-chipRow { + display: grid; + gap: 10px; + } + .ds-chipLabel { + font-size: 13px; + opacity: 0.9; + } + .ds-chip { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 10px 12px; + border-radius: 8px; + line-height: 1.2; + border: 1px solid rgba(0,0,0,0.12); + width: fit-content; + max-width: 100%; + } + .ds-a11y-panel--dark .ds-chip { + border: 1px solid rgba(255,255,255,0.14); + } + .ds-chipText { + font-size: 14px; + font-weight: 650; + } + /* Use CSS vars + !important so theme styles can’t override demo colours */ + .ds-chip[data-bg] { background: var(--bg) !important; } + .ds-chip[data-fg] { color: var(--fg) !important; } + .ds-note { + border-radius: 10px; + padding: 12px 14px; + border: 1px solid rgba(0,0,0,0.10); + } + .ds-a11y-panel--dark + .ds-note, + .ds-a11y-panel--dark .ds-note { + border: 1px solid rgba(255,255,255,0.14); + } + `}</style> + +<div className="ds-a11y-demo ds-a11y-grid"> + + <div className="ds-a11y-panels"> + {/* Light */} + <div className="ds-a11y-panel ds-a11y-panel--light"> + <p className="ds-a11y-rowTitle">Light surface</p> + + <div className="ds-a11y-row"> + <p><strong>Green</strong> bg `--ds-green-9` `#4CA65A`</p> + <div className="ds-chipRow"> + <div> + <p className="ds-chipLabel"><strong>WCAG 2 candidate</strong></p> + <div + className="ds-chip" + data-bg + data-fg + style={{ ['--bg']: '#4CA65A', ['--fg']: '#000000' }} + > + <span className="ds-chipText">Experiment complete · 12 files processed</span> + </div> + </div> + + <div> + <p className="ds-chipLabel"><strong>APCA candidate</strong> ✅</p> + <div + className="ds-chip" + data-bg + data-fg + style={{ ['--bg']: '#4CA65A', ['--fg']: '#FFFFFF' }} + > + <span className="ds-chipText">Experiment complete · 12 files processed</span> + </div> + </div> + </div> + </div> + + <div className="ds-a11y-row"> + <p><strong>Orange</strong> bg `--ds-orange-9` `#FF780A`</p> + <div className="ds-chipRow"> + <div> + <p className="ds-chipLabel"><strong>WCAG 2 candidate</strong></p> + <div className="ds-chip" data-bg data-fg style={{ ['--bg']: '#FF780A', ['--fg']: '#000000' }}> + <span className="ds-chipText">Beamline temperature near limit</span> + </div> + </div> + + <div> + <p className="ds-chipLabel"><strong>APCA candidate</strong> ✅</p> + <div className="ds-chip" data-bg data-fg style={{ ['--bg']: '#FF780A', ['--fg']: '#FFFFFF' }}> + <span className="ds-chipText">Beamline temperature near limit</span> + </div> + </div> + </div> + </div> + + <div className="ds-a11y-row"> + <p><strong>Red</strong> bg `--ds-red-9` `#E54D2E`</p> + <div className="ds-chipRow"> + <div> + <p className="ds-chipLabel"><strong>WCAG 2 candidate</strong></p> + <div className="ds-chip" data-bg data-fg style={{ ['--bg']: '#E54D2E', ['--fg']: '#000000' }}> + <span className="ds-chipText">Connection failed · retry required</span> + </div> + </div> + + <div> + <p className="ds-chipLabel"><strong>APCA candidate</strong> ✅</p> + <div className="ds-chip" data-bg data-fg style={{ ['--bg']: '#E54D2E', ['--fg']: '#FFFFFF' }}> + <span className="ds-chipText">Connection failed · retry required</span> + </div> + </div> + </div> + </div> + </div> + + {/* Dark / inverse */} + <div className="ds-a11y-panel ds-a11y-panel--dark"> + <p className="ds-a11y-rowTitle">Dark (inverse) surface</p> + + <div className="ds-a11y-row"> + <p><strong>Green</strong> bg `--ds-green-9` `#30A46C`</p> + <div className="ds-chipRow"> + <div> + <p className="ds-chipLabel"><strong>WCAG 2 candidate</strong></p> + <div className="ds-chip" data-bg data-fg style={{ ['--bg']: '#30A46C', ['--fg']: '#FFFFFF' }}> + <span className="ds-chipText">Experiment complete · 12 files processed</span> + </div> + </div> + + <div> + <p className="ds-chipLabel"><strong>APCA candidate</strong> ✅</p> + <div className="ds-chip" data-bg data-fg style={{ ['--bg']: '#30A46C', ['--fg']: '#000000' }}> + <span className="ds-chipText">Experiment complete · 12 files processed</span> + </div> + </div> + </div> + </div> + + <div className="ds-a11y-row"> + <p><strong>Orange</strong> bg `--ds-orange-9` `#F76B15`</p> + <div className="ds-chipRow"> + <div> + <p className="ds-chipLabel"><strong>WCAG 2 candidate</strong></p> + <div className="ds-chip" data-bg data-fg style={{ ['--bg']: '#F76B15', ['--fg']: '#000000' }}> + <span className="ds-chipText">Beamline temperature near limit</span> + </div> + </div> + + <div> + <p className="ds-chipLabel"><strong>APCA candidate</strong> ✅</p> + <div className="ds-chip" data-bg data-fg style={{ ['--bg']: '#F76B15', ['--fg']: '#FFFFFF' }}> + <span className="ds-chipText">Beamline temperature near limit</span> + </div> + </div> + </div> + </div> + + <div className="ds-a11y-row"> + <p><strong>Red</strong> bg `--ds-red-9` `#E54D2E`</p> + <div className="ds-chipRow"> + <div> + <p className="ds-chipLabel"><strong>WCAG 2 candidate</strong></p> + <div className="ds-chip" data-bg data-fg style={{ ['--bg']: '#E54D2E', ['--fg']: '#000000' }}> + <span className="ds-chipText">Connection failed · retry required</span> + </div> + </div> + + <div> + <p className="ds-chipLabel"><strong>APCA candidate</strong> ✅</p> + <div className="ds-chip" data-bg data-fg style={{ ['--bg']: '#E54D2E', ['--fg']: '#FFFFFF' }}> + <span className="ds-chipText">Connection failed · retry required</span> + </div> + </div> + </div> + </div> + </div> + </div> + </div> + + <div className="ds-note"> + <p style={{ marginBottom: 6 }}><strong>How to use this</strong></p> + <ul> + <li>Use WCAG 2 as the baseline check, especially for small text.</li> + <li>Use APCA to validate perceived readability and comfort (particularly for saturated status colours).</li> + <li>Always pair colour with icons/text — never rely on colour alone for meaning.</li> + </ul> + </div> + </div> + +{/* END EXAMPLE */} + +<h2>Practical guidance</h2> +<ul> + <li> + <strong>Body text</strong>: prioritise APCA readability while meeting WCAG. + </li> + <li> + <strong>UI chrome</strong>: prioritise WCAG clarity and consistency. + </li> + <li> + <strong>Subtle text</strong>: only for non-essential information. + </li> + <li> + <strong>Disabled states</strong>: visually distinct but still readable where + meaning matters. + </li> +</ul> + +<h2>Common pitfalls</h2> +<ul> + <li>Reducing contrast to “de-emphasise” text that still carries meaning.</li> + <li>Relying on colour alone for status or validation.</li> + <li>Forgetting that contrast behaves differently in dark mode.</li> +</ul> + +<h2>When WCAG and APCA disagree</h2> +<ul> + <li>If WCAG fails, the colour must change.</li> + <li> + If WCAG passes but APCA indicates poor readability, adjust for comfort. + </li> + <li>For critical UI, readability always wins over subtlety.</li> +</ul> + +<h2>Future: WCAG 3 and APCA</h2> + +<p> + APCA is being developed as part of WCAG 3, which is still in progress. While + WCAG 2.x remains the formal standard today, WCAG 3 reflects a shift towards + perceptual models of contrast and readability. +</p> + +<p>Our approach reflects this transition:</p> + +<ul> + <li>WCAG 2.x is treated as the compliance baseline.</li> + <li>APCA is used to improve real-world readability and comfort.</li> + <li>This positions us closer to where accessibility standards are heading.</li> +</ul> +</div> diff --git a/src/storybook/accessibility/02-cognitive-and-learning.mdx b/src/storybook/accessibility/02-cognitive-and-learning.mdx new file mode 100644 index 0000000..91ed4b9 --- /dev/null +++ b/src/storybook/accessibility/02-cognitive-and-learning.mdx @@ -0,0 +1,151 @@ +import { Meta } from "@storybook/blocks"; + +<Meta title="Accessibility/Cognitive and learning" /> + +<div> + <h1>Cognitive and learning accessibility</h1> + +<p> + Accessibility is not only about vision or motor input. People differ in how + they process information, maintain focus, remember things, and recover from + errors. +</p> + +<p> + In complex scientific tools, these differences matter. Our responsibility is + to design systems that are usable, understandable, and forgiving across a wide + range of abilities and conditions. +</p> + +<h2>Experience, usability, and accessibility by design</h2> + +<p> + Improving accessibility is not just about adding new features. It also means + continuously improving the core experience: making it more intuitive, more + inclusive, and easier to use. +</p> + +<p> + Our users include people with different processing capabilities and + disabilities. We should consider these differences when designing interfaces, + interactions, and content — not as edge cases, but as part of normal usage. +</p> + +<h2>User processing capabilities to consider</h2> +<ul> + <li>Reading, skimming, and scanning content</li> + <li>Focus and sustained attention</li> + <li>Different memory types and memorisation strategies</li> +</ul> + +<h2>Types of disabilities and conditions</h2> +<p>Users may experience one or more of the following:</p> +<ul> + <li>Cognitive disabilities</li> + <li>Learning disabilities</li> + <li>Intellectual disability</li> + <li>Vision impairment (including colour blindness)</li> + <li>Deaf or hard of hearing</li> + <li>Physical disabilities</li> + <li>Mental health conditions</li> + <li>Acquired brain injury</li> + <li>Neurodiversity</li> +</ul> + +{" "} + +<p> + With this in mind, usability and accessibility should be treated as + foundational design qualities, not optional enhancements. +</p> + +{" "} + +<h2>Design objectives</h2> + +{" "} + +<p> + The W3C guidance on cognitive and learning disabilities is useful not only for + people with disabilities, but for most users. The objectives below are adapted + from that guidance and reflect how we aim to design Diamond tools. +</p> + +{" "} + +<h3>Help users understand what things are and how to use them</h3> +<ul> + <li>Use icons, symbols, terms, and patterns that are already familiar.</li> + <li> + Avoid inventing new interaction patterns without strong justification. + </li> + <li>Make purpose and behaviour obvious at first glance.</li> +</ul> + +<h3>Help users find what they need</h3> +<ul> + <li>Use clear structure, headings, and visual boundaries.</li> + <li>Keep navigation predictable and consistent.</li> + <li>Use layout and grouping to signal relationships.</li> +</ul> + +<h3>Use clear content</h3> +<ul> + <li>Prefer simple words and short sentences.</li> + <li>Break text into small, readable blocks.</li> + <li>Use clear images and diagrams where they add meaning.</li> +</ul> + +<h3>Help users avoid mistakes</h3> +<ul> + <li>Ask only for information that is genuinely required.</li> + <li>Prevent errors where possible, rather than reacting to them.</li> + <li>When errors occur, make recovery easy and explicit.</li> +</ul> + +<h3>Help users focus</h3> +<ul> + <li>Avoid unnecessary distractions.</li> + <li> + Use headings and structure to help users re-orient if context is lost. + </li> + <li>Provide breadcrumbs or clear navigation paths where appropriate.</li> +</ul> + +<h3>Provide help and support</h3> +<ul> + <li>Make it easy to access human help or support.</li> + <li>Offer multiple ways to understand content (text, visuals, summaries).</li> + <li>Use icons and visual cues to reinforce meaning, not replace it.</li> +</ul> + +<h3>Support adaptation and personalisation</h3> +<ul> + <li>Allow users to adjust preferences when possible.</li> + <li>Design so assistive technologies and extensions can work effectively.</li> + <li>Avoid blocking browser or OS-level accessibility features.</li> +</ul> + +<h3>Test with real users</h3> +<ul> + <li>Involve people with different disabilities in research and testing.</li> + <li>Include them in usability testing and design validation.</li> + <li>Treat their feedback as expert input.</li> +</ul> + +<h2>Applying this in Storybook</h2> +<ul> + <li>Is the component understandable without prior knowledge?</li> + <li>Does it rely on memory or hidden rules?</li> + <li>Is error recovery clear and forgiving?</li> + <li>Would this still make sense at the end of a long day?</li> +</ul> + + <h2>Further reading</h2> + <ul> + <li><a href="https://www.w3.org/TR/coga-usable/" target="_blank" rel="noopener noreferrer">Making Content Usable for People with Cognitive and Learning Disabilities</a></li> + <li><a href="https://www.w3.org/WAI/fundamentals/accessibility-usability-inclusion/" target="_blank" rel="noopener noreferrer">W3C: Accessibility, Usability, and Inclusion</a></li> + <li><a href="https://www.w3.org/TR/coga-usable/" target="_blank" rel="noopener noreferrer">Making Content Usable for People with Cognitive and Learning Disabilities</a></li> + <li><a href="https://uxplanet.org/how-human-memory-works-tips-for-ux-designers-12b14071bdf9" target="_blank" rel="noopener noreferrer">How Human Memory Works: Tips for UX Designers</a></li> + </ul> +</div> diff --git a/src/storybook/foundation/colours.mdx b/src/storybook/foundation/colours.mdx new file mode 100644 index 0000000..0af345f --- /dev/null +++ b/src/storybook/foundation/colours.mdx @@ -0,0 +1,510 @@ +import { Meta } from "@storybook/blocks"; + +<Meta title="Foundation/Colour" /> + +<style>{` + .ds-note { + margin: 12px 0 20px; + padding: 12px 14px; + border: 1px solid var(--ds-gray-6); + background: var(--ds-gray-2); + border-radius: 12px; + } + .ds-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); + gap: 14px; + margin: 14px 0 24px; + } + .ds-swatch { + border: 1px solid var(--ds-gray-6); + border-radius: 14px; + background: var(--ds-gray-2); + overflow: hidden; + } + .ds-swatch__chip { + height: 56px; + background: var(--swatch); + border-bottom: 1px solid var(--ds-gray-6); + } + .ds-swatch__body { + padding: 12px 12px 10px; + } + .ds-swatch__name { + font-weight: 600; + margin: 0 0 6px; + color: var(--ds-gray-12); + } + .ds-swatch__meta { + margin: 0; + padding-left: 16px; + color: var(--ds-gray-11); + font-size: 14px; + line-height: 20px; + } + .ds-swatch__meta li { + margin: 2px 0; + } + .ds-row { + display: flex; + gap: 10px; + flex-wrap: wrap; + margin: 10px 0 0; + } + .ds-pill { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 6px 10px; + border-radius: 999px; + border: 1px solid var(--ds-gray-6); + background: var(--ds-gray-1); + color: var(--ds-gray-12); + font-size: 13px; + line-height: 18px; + } + .ds-dot { + width: 10px; + height: 10px; + border-radius: 999px; + background: var(--dot); + border: 1px solid rgba(0,0,0,0.12); + } + .ds-surface-demo { + border: 1px solid var(--ds-gray-6); + border-radius: 14px; + background: var(--ds-gray-1); + padding: 14px; + margin: 14px 0 24px; + } + .ds-surface-card { + border: 1px solid var(--ds-gray-6); + background: var(--ds-gray-2); + border-radius: 12px; + padding: 12px; + } + .ds-divider { + height: 1px; + background: var(--ds-gray-6); + margin: 12px 0; + } + .ds-text-demo p { + margin: 8px 0; + } + .ds-overlay-demo { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); + gap: 12px; + margin-top: 12px; + } + .ds-overlay-tile { + border: 1px solid var(--ds-gray-6); + border-radius: 12px; + background: var(--ds-gray-2); + overflow: hidden; + } + .ds-overlay-tile__top { + height: 56px; + background: var(--ds-gray-2); + position: relative; + } + .ds-overlay-tile__overlay { + position: absolute; + inset: 0; + background: var(--overlay); + } + .ds-overlay-tile__body { + padding: 10px 12px; + color: var(--ds-gray-12); + font-size: 13px; + } +`}</style> + +<div> + <h1>Colour</h1> + +{" "} + +<p> + Our colour system is role-based and implemented through MUI theme tokens. + Values are provided as CSS variables (primitives + semantic “on-colour” + + overlays) so light/dark mode and future refinement remain consistent. The + current primitives and semantic variables live in + `diamond-colors-primitives.css`. +</p> + +<div className="ds-note"> + <strong>How to use colour roles</strong> + <ul style={{ margin: "8px 0 0 16px" }}> + <li> + <strong>light / main</strong> — solid backgrounds and emphasis + <small>Buttons, active states, strong accents</small> + </li> + <li> + <strong>bgCanvas / bgSurface*</strong> — light backgrounds and layout + <small>Pages, panels, cards, grouped content</small> + </li> + <li> + <strong>dark / darker</strong> — text, icons, and borders on light + surfaces + <small>High-contrast foreground usage</small> + </li> + </ul> + <p style={{ marginTop: 8 }}> + If something looks like a background, use <code>bg*</code>. If it looks like + a button, use <code>main</code>. If it’s text, use <code>dark</code>. + </p> +</div> + +{" "} + +<div className="ds-note"> + <strong>What changed:</strong> the palette now exposes more layers per intent + colour: ` light → main → dark → darker`, plus `*Channel` tokens for + alpha-based overlays. Also added `brand` colour scheme. +</div> + +{" "} + +<h2>MUI palette mapping (current)</h2> +<p> + These are the current top-level palette decisions used in our MUI theme. We + also define explicit `action.*` overlays to avoid Material’s default overlay + behaviour and keep interaction states consistent with our primitives. +</p> + + <div className="ds-grid"> + {/* Primary */} + <div className="ds-swatch" style={{ ['--swatch']: 'var(--ds-indigo-9)' }}> + <div className="ds-swatch__chip" /> + <div className="ds-swatch__body"> + <p className="ds-swatch__name">Primary</p> + <ul className="ds-swatch__meta"> + <li><strong>light</strong>: `--ds-indigo-8`</li> + <li><strong>main</strong>: `--ds-indigo-9`</li> + <li><strong>dark</strong>: `--ds-indigo-10`</li> + <li><strong>darker</strong>: `--ds-indigo-11`</li> + <li><strong>contrast text</strong>: `--ds-fg-fixed-white`</li> + <li><strong>mainChannel</strong>: `--ds-indigo-9Channel`</li> + <li><strong>lightChannel</strong>: `--ds-indigo-8Channel`</li> + <li><strong>darkChannel</strong>: `--ds-indigo-10Channel`</li> + <li><strong>bgCanvas</strong>: <code>--ds-indigo-1</code></li> + <li><strong>bgSurface1</strong>: <code>--ds-indigo-2</code></li> + <li><strong>bgSurface2</strong>: <code>--ds-indigo-3</code></li> + </ul> + <div className="ds-row"> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-indigo-8)' }} /> light</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-indigo-9)' }} /> main</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-indigo-10)' }} /> dark</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-indigo-11)' }} /> darker</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-indigo-1)' }} > canvas</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-indigo-2)' }} > surface1</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-indigo-3)' }} > surface2</span> + </div> + </div> + </div> + + {/* Secondary */} + <div className="ds-swatch" style={{ ['--swatch']: 'var(--ds-navy-9)' }}> + <div className="ds-swatch__chip" /> + <div className="ds-swatch__body"> + <p className="ds-swatch__name">Secondary</p> + <ul className="ds-swatch__meta"> + <li><strong>light</strong>: `--ds-navy-8`</li> + <li><strong>main</strong>: `--ds-navy-9`</li> + <li><strong>dark</strong>: `--ds-navy-10`</li> + <li><strong>darker</strong>: `--ds-navy-11`</li> + <li><strong>contrast text</strong>: `--ds-fg-fixed-white`</li> + <li><strong>mainChannel</strong>: `--ds-navy-9Channel`</li> + <li><strong>lightChannel</strong>: `--ds-navy-8Channel`</li> + <li><strong>darkChannel</strong>: `--ds-navy-10Channel`</li> + <li><strong>bgCanvas</strong>: <code>--ds-navy-1</code></li> + <li><strong>bgSurface1</strong>: <code>--ds-navy-2</code></li> + <li><strong>bgSurface2</strong>: <code>--ds-navy-3</code></li> + </ul> + <div className="ds-row"> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-8)' }} /> light</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-9)' }} /> main</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-10)' }} /> dark</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-11)' }} /> darker</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-navy-1)' }} > canvas</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-navy-2)' }} > surface1</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-navy-3)' }} > surface2</span> + </div> + </div> + </div> + + {/* Brand */} + <div className="ds-swatch" style={{ ['--swatch']: 'var(--ds-navy-10)' }}> + <div className="ds-swatch__chip" /> + <div className="ds-swatch__body"> + <p className="ds-swatch__name">Brand</p> + <ul className="ds-swatch__meta"> + <li><strong>light</strong>: `--ds-navy-9`</li> + <li><strong>main</strong>: `--ds-navy-10`</li> + <li><strong>dark</strong>: `--ds-navy-11`</li> + <li><strong>darker</strong>: `--ds-navy-12`</li> + <li><strong>contrast text</strong>: `--ds-fg-fixed-white`</li> + <li><strong>mainChannel</strong>: `--ds-navy-10Channel`</li> + <li><strong>lightChannel</strong>: `--ds-navy-9Channel`</li> + <li><strong>darkChannel</strong>: `--ds-navy-11Channel`</li> + </ul> + <div className="ds-row"> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-9)' }} /> light</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-10)' }} /> main</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-11)' }} /> dark</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-12)' }} /> darker</span> + </div> + </div> + </div> + + {/* Success */} + <div className="ds-swatch" style={{ ['--swatch']: 'var(--ds-green-9)' }}> + <div className="ds-swatch__chip" /> + <div className="ds-swatch__body"> + <p className="ds-swatch__name">Success</p> + <ul className="ds-swatch__meta"> + <li><strong>light</strong>: `--ds-green-8`</li> + <li><strong>main</strong>: `--ds-green-9`</li> + <li><strong>dark</strong>: `--ds-green-10`</li> + <li><strong>darker</strong>: `--ds-green-11`</li> + <li><strong>contrast text</strong>: `--ds-fg-fixed-white`</li> + <li><strong>mainChannel</strong>: `--ds-green-9Channel`</li> + <li><strong>bgCanvas</strong>: <code>--ds-green-1</code></li> + <li><strong>bgSurface1</strong>: <code>--ds-green-2</code></li> + <li><strong>bgSurface2</strong>: <code>--ds-green-3</code></li> + </ul> + <div className="ds-row"> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-green-8)' }} /> light</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-green-9)' }} /> main</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-green-10)' }} /> dark</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-green-11)' }} /> darker</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-green-1)' }} > canvas</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-green-2)' }} > surface1</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-green-3)' }} > surface2</span> + </div> + </div> + </div> + + {/* Warning */} + <div className="ds-swatch" style={{ ['--swatch']: 'var(--ds-orange-9)' }}> + <div className="ds-swatch__chip" /> + <div className="ds-swatch__body"> + <p className="ds-swatch__name">Warning</p> + <ul className="ds-swatch__meta"> + <li><strong>light</strong>: `--ds-orange-8`</li> + <li><strong>main</strong>: `--ds-orange-9`</li> + <li><strong>dark</strong>: `--ds-orange-10`</li> + <li><strong>darker</strong>: `--ds-orange-11`</li> + <li><strong>contrast text</strong>: `--ds-fg-fixed-white`</li> + <li><strong>mainChannel</strong>: `--ds-orange-9Channel`</li> + <li><strong>bgCanvas</strong>: <code>--ds-orange-1</code></li> + <li><strong>bgSurface1</strong>: <code>--ds-orange-2</code></li> + <li><strong>bgSurface2</strong>: <code>--ds-orange-3</code></li> + </ul> + <div className="ds-row"> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-orange-8)' }} /> light</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-orange-9)' }} /> main</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-orange-10)' }} /> dark</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-orange-11)' }} /> darker</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-orange-1)' }} > canvas</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-orange-2)' }} > surface1</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-orange-3)' }} > surface2</span> + </div> + </div> + </div> + + {/* Error */} + <div className="ds-swatch" style={{ ['--swatch']: 'var(--ds-red-9)' }}> + <div className="ds-swatch__chip" /> + <div className="ds-swatch__body"> + <p className="ds-swatch__name">Error</p> + <ul className="ds-swatch__meta"> + <li><strong>light</strong>: `--ds-red-8`</li> + <li><strong>main</strong>: `--ds-red-9`</li> + <li><strong>dark</strong>: `--ds-red-10`</li> + <li><strong>darker</strong>: `--ds-red-11`</li> + <li><strong>contrast text</strong>: `--ds-fg-fixed-white`</li> + <li><strong>mainChannel</strong>: `--ds-red-9Channel`</li> + <li><strong>bgCanvas</strong>: <code>--ds-red-1</code></li> + <li><strong>bgSurface1</strong>: <code>--ds-red-2</code></li> + <li><strong>bgSurface2</strong>: <code>--ds-red-3</code></li> + </ul> + <div className="ds-row"> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-red-8)' }} /> light</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-red-9)' }} /> main</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-red-10)' }} /> dark</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-red-11)' }} /> darker</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-red-1)' }} > canvas</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-red-2)' }} > surface1</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-red-3)' }} > surface2</span> + </div> + </div> + </div> + +{/* Background surfaces */} + +<div className="ds-swatch" style={{ ["--swatch"]: "var(--ds-bg-paper)" }}> + <div className="ds-swatch__chip" /> + <div className="ds-swatch__body"> + <p className="ds-swatch__name">Background surfaces</p> + <ul className="ds-swatch__meta"> + <li> + <strong>default</strong>: <code>--ds-bg-canvas</code> + </li> + <li> + <strong>paper</strong>: <code>--ds-bg-paper</code> + </li> + <li> + <strong>surface1</strong>: <code>--ds-bg-surface-1</code> + </li> + <li> + <strong>surface2</strong>: <code>--ds-bg-surface-2</code> + </li> + <li> + <strong>outlinedBg</strong>: <code>--ds-bg-surface-2</code> + </li> + </ul> + <div className="ds-row"> + <span + className="ds-pill" + style={{ ["background"]: "var(--ds-bg-canvas)" }} + > + {" "} + canvas + </span> + <span + className="ds-pill" + style={{ ["background"]: "var(--ds-bg-paper)" }} + > + {" "} + paper + </span> + <span + className="ds-pill" + style={{ ["background"]: "var(--ds-bg-surface-1)" }} + > + {" "} + surface1 + </span> + <span + className="ds-pill" + style={{ ["background"]: "var(--ds-bg-surface-2)" }} + > + {" "} + surface2 + </span> + </div> + </div> +</div> + + {/* Divider */} + <div className="ds-swatch" style={{ ['--swatch']: 'var(--ds-gray-6)' }}> + <div className="ds-swatch__chip" /> + <div className="ds-swatch__body"> + <p className="ds-swatch__name">Divider</p> + <ul className="ds-swatch__meta"> + <li><strong>divider</strong>: `--ds-gray-6`</li> + </ul> + </div> + </div> + + </div> + +<h2>Surfaces, text, and dividers (quick visual check)</h2> +<div className="ds-surface-demo"> + <div className="ds-surface-card"> + <div className="ds-text-demo"> + <p style={{ color: "var(--ds-gray-12)" }}> + <strong>Text primary</strong> → `--ds-gray-12` + </p> + <p style={{ color: "var(--ds-gray-11)" }}> + Text secondary → `--ds-gray-11` + </p> + <p style={{ color: "var(--ds-gray-8)" }}>Text disabled → `--ds-gray-8`</p> + </div> + <div className="ds-divider" /> + <p style={{ margin: 0, color: "var(--ds-gray-11)" }}> + Canvas uses `--ds-gray-1` and surfaces use `--ds-gray-2`. Divider uses + `--ds-gray-6`. + </p> + </div> +</div> + +{" "} + +<h2>Interaction overlays (MUI action tokens)</h2> +<p> + We define `action.hover`, `action.selected`, `action.focus`, + `action.disabled`, and `action.disabledBackground` as explicit overlays + (`--ds-overlay-*`) so interaction states remain consistent across themes. +</p> + + <div className="ds-overlay-demo"> + <div className="ds-overlay-tile"> + <div className="ds-overlay-tile__top"> + <div className="ds-overlay-tile__overlay" style={{ ['--overlay']: 'var(--ds-overlay-hover)' }} /> + </div> + <div className="ds-overlay-tile__body"> + <ul className="ds-swatch__meta"> + <li><strong>hover</strong>: `--ds-overlay-hover`</li> + </ul> + </div> + </div> + + <div className="ds-overlay-tile"> + <div className="ds-overlay-tile__top"> + <div className="ds-overlay-tile__overlay" style={{ ['--overlay']: 'var(--ds-overlay-selected)' }} /> + </div> + <div className="ds-overlay-tile__body"> + <ul className="ds-swatch__meta"> + <li><strong>selected</strong>: `--ds-overlay-selected`</li> + </ul> + </div> + </div> + + <div className="ds-overlay-tile"> + <div className="ds-overlay-tile__top"> + <div className="ds-overlay-tile__overlay" style={{ ['--overlay']: 'var(--ds-overlay-focus)' }} /> + </div> + <div className="ds-overlay-tile__body"> + <ul className="ds-swatch__meta"> + <li><strong>focus</strong>: `--ds-overlay-focus`</li> + </ul> + </div> + </div> + + <div className="ds-overlay-tile"> + <div className="ds-overlay-tile__top"> + <div className="ds-overlay-tile__overlay" style={{ ['--overlay']: 'var(--ds-overlay-disabled)' }} /> + </div> + <div className="ds-overlay-tile__body"> + <ul className="ds-swatch__meta"> + <li><strong>disabled</strong>: `--ds-overlay-disabled`</li> + </ul> + </div> + </div> + + <div className="ds-overlay-tile"> + <div className="ds-overlay-tile__top"> + <div className="ds-overlay-tile__overlay" style={{ ['--overlay']: 'var(--ds-overlay-disabled-bg)' }} /> + </div> + <div className="ds-overlay-tile__body"> + <ul className="ds-swatch__meta"> + <li><strong>disabled background</strong>: `--ds-overlay-disabled-bg`</li> + </ul> + </div> + </div> + + </div> + +<h2>Component style example</h2> +<p> + Components can override specific behaviour where needed. For example, we set + `MuiButton` to use sentence case (no automatic uppercase). +</p> + + <div className="ds-note"> + <strong>MUI Button:</strong> `textTransform: none` + </div> +</div> diff --git a/src/storybook/foundation/typography.mdx b/src/storybook/foundation/typography.mdx new file mode 100644 index 0000000..45aa78a --- /dev/null +++ b/src/storybook/foundation/typography.mdx @@ -0,0 +1,77 @@ +import { Meta } from "@storybook/blocks"; + +<Meta title="Foundation/Typography" /> + +<div> + <h1>Typography</h1> + +<p> + Typography is a functional tool, not decoration. In scientific software, type + choices affect speed, accuracy, and confidence. +</p> + +{" "} + +<h2>Why it matters in Diamond tools</h2> +<ul> + <li> + <strong>Readability and legibility</strong>: clear at small sizes and on + imperfect displays. + </li> + <li> + <strong>Hierarchy</strong>: predictable structure for scanning data-heavy + screens. + </li> + <li> + <strong>Accessibility</strong>: legible sizing and contrast across contexts. + </li> + <li> + <strong>Reduced cognitive load</strong>: less visual noise, faster + decisions. + </li> + <li> + <strong>Works for dense data</strong>: tables, logs, dashboards, forms, + documentation. + </li> +</ul> + +{" "} + +<h2>Font roles</h2> +<ul> + <li> + <strong>Outfit</strong>: brand-forward headings and hero text. + </li> + <li> + <strong>Inter</strong>: default UI font for functional work (body, labels, + tables). + </li> + <li> + <strong>IBM Plex Mono</strong>: code, identifiers, aligned technical values. + </li> +</ul> + +<h2>Practical guidance</h2> + +<h3>Do</h3> +<ul> + <li>Keep hierarchy consistent across products and screens.</li> + <li>Prefer short, clear labels in controls and tables.</li> + <li>Make numbers and units easy to scan (alignment matters).</li> +</ul> + +{" "} + +<h3>Don’t</h3> +<ul> + <li>Don’t use brand typography for dense operational content.</li> + <li>Don’t “style your way” out of hierarchy problems.</li> + <li>Don’t hide important info in faint secondary text.</li> +</ul> + + <h2>Tokens (to be defined)</h2> + <p> + We’ll define tokens for display, body, and mono usage (e.g. `typography.display.*`, + `typography.body.*`, `typography.mono.*`) and reference them consistently. + </p> +</div> diff --git a/src/styles/diamondDS/diamond-colors-primitives.css b/src/styles/diamondDS/diamond-colors-primitives.css new file mode 100644 index 0000000..a9a898a --- /dev/null +++ b/src/styles/diamondDS/diamond-colors-primitives.css @@ -0,0 +1,890 @@ +:root { + --ds-black: #000000; + --ds-black-a1: #0000000d; + --ds-black-a2: #0000001a; + --ds-black-a3: #00000026; + --ds-black-a4: #0003; + --ds-black-a5: #0000004d; + --ds-black-a6: #0006; + --ds-black-a7: #00000080; + --ds-black-a8: #0009; + --ds-black-a9: #000000b3; + --ds-black-a10: #000c; + --ds-black-a11: #000000e6; + --ds-black-a12: #000000f2; + --ds-blackChannel: 0 0 0; + --ds-white: #ffffff; + --ds-white-a1: #ffffff0d; + --ds-white-a2: #ffffff1a; + --ds-white-a3: #ffffff26; + --ds-white-a4: #fff3; + --ds-white-a5: #ffffff4d; + --ds-white-a6: #fff6; + --ds-white-a7: #ffffff80; + --ds-white-a8: #fff9; + --ds-white-a9: #ffffffb3; + --ds-white-a10: #fffc; + --ds-white-a11: #ffffffe6; + --ds-white-a12: #fffffff2; + --ds-whiteChannel: 255 255 255; + + /* Disabled tokens (semantic) */ + --ds-fg-disabled: var(--ds-gray-8); + --ds-border-disabled: var(--ds-gray-6); + --ds-bg-disabled: var(--ds-gray-2); + } + + :root, .light, :root[data-mode="light"] { /*LIGHT MODE */ + /* Semantic on-colour tokens */ + --ds-fg-fixed-white: var(--ds-white); /* Always white */ + --ds-fg-fixed-black: var(--ds-black); /* Always black */ + --ds-fg-inverse: var(--ds-white); /* White (light) → Black (dark) */ + --ds-fg-default: var(--ds-black); /* Black (light) → White (dark) */ + + --ds-overlay-hover: rgba(0, 0, 0, 0.06); + --ds-overlay-selected: rgba(0, 0, 0, 0.10); + --ds-overlay-focus: rgba(0, 0, 0, 0.12); + --ds-overlay-disabled: rgba(0, 0, 0, 0.26); + --ds-overlay-disabled-bg: rgba(0, 0, 0, 0.06); + + --ds-bg-brand: var(--ds-navy-10); /* Diamond Brand Blue */ + + /* Canvas (app shell) */ + --ds-bg-canvas: var(--ds-olive-1); + + /* Paper (main surface) */ + --ds-bg-paper: var(--ds-white); + + /* Layering surfaces */ + --ds-bg-surface-1: var(--ds-olive-2); + --ds-bg-surface-2: var(--ds-olive-3); + + /* Borders */ + --ds-border-subtle: var(--ds-olive-6); + --ds-border-strong: var(--ds-olive-7); + + /* Radix based colours */ + --ds-gray-1:#fcfcfc; + --ds-gray-2:#f9f9f9; + --ds-gray-3:#f0f0f0; + --ds-gray-4:#e8e8e8; + --ds-gray-5:#e0e0e0; + --ds-gray-6:#d9d9d9; + --ds-gray-7:#cecece; + --ds-gray-8:#bbb; + --ds-gray-9:#8d8d8d; + --ds-gray-10:#838383; + --ds-gray-11:#646464; + --ds-gray-12:#202020; + --ds-gray-a1:#00000003; + --ds-gray-a2:#00000006; + --ds-gray-a3:#0000000f; + --ds-gray-a4:#00000017; + --ds-gray-a5:#0000001f; + --ds-gray-a6:#00000026; + --ds-gray-a7:#00000031; + --ds-gray-a8:#00000044; + --ds-gray-a9:#00000072; + --ds-gray-a10:#0000007c; + --ds-gray-a11:#0000009b; + --ds-gray-a12:#000000df; + --ds-gray-1Channel: 252 252 252; + --ds-gray-2Channel: 249 249 249; + --ds-gray-3Channel: 240 240 240; + --ds-gray-4Channel: 232 232 232; + --ds-gray-5Channel: 224 224 224; + --ds-gray-6Channel: 217 217 217; + --ds-gray-7Channel: 206 206 206; + --ds-gray-8Channel: 187 187 187; + --ds-gray-9Channel: 141 141 141; + --ds-gray-10Channel: 131 131 131; + --ds-gray-11Channel: 100 100 100; + --ds-gray-12Channel: 32 32 32; + --ds-olive-1:#fcfdfc; + --ds-olive-2:#f8faf8; + --ds-olive-3:#eff1ef; + --ds-olive-4:#e7e9e7; + --ds-olive-5:#dfe2df; + --ds-olive-6:#d7dad7; + --ds-olive-7:#cccfcc; + --ds-olive-8:#b9bcb8; + --ds-olive-9:#898e87; + --ds-olive-10:#7f847d; + --ds-olive-11:#60655f; + --ds-olive-12:#1d211c; + --ds-olive-a1:#00550003; + --ds-olive-a2:#00490007; + --ds-olive-a3:#00200010; + --ds-olive-a4:#00160018; + --ds-olive-a5:#00180020; + --ds-olive-a6:#00140028; + --ds-olive-a7:#000f0033; + --ds-olive-a8:#040f0047; + --ds-olive-a9:#050f0078; + --ds-olive-a10:#040e0082; + --ds-olive-a11:#020a00a0; + --ds-olive-a12:#010600e3; + --ds-olive-1Channel: 252 253 252; + --ds-olive-2Channel: 248 250 248; + --ds-olive-3Channel: 239 241 239; + --ds-olive-4Channel: 231 233 231; + --ds-olive-5Channel: 223 226 223; + --ds-olive-6Channel: 215 218 215; + --ds-olive-7Channel: 204 207 204; + --ds-olive-8Channel: 185 188 184; + --ds-olive-9Channel: 137 142 135; + --ds-olive-10Channel: 127 132 125; + --ds-olive-11Channel: 96 101 95; + --ds-olive-12Channel: 29 33 28; + --ds-cyan-1: #FAFEFF; + --ds-cyan-2: #F1FBFC; + --ds-cyan-3: #E3F6F8; + --ds-cyan-4: #D4EFF3; + --ds-cyan-5: #C2E6EB; + --ds-cyan-6: #ACDBE1; + --ds-cyan-7: #8CCCD3; + --ds-cyan-8: #64BAC3; + --ds-cyan-9: #3A9FAC; + --ds-cyan-10: #009CA6; /* brand */ + --ds-cyan-11: #006873; + --ds-cyan-12: #003A40; + --ds-cyan-a1: #3A9FAC05; + --ds-cyan-a2: #3A9FAC0A; + --ds-cyan-a3: #3A9FAC10; + --ds-cyan-a4: #3A9FAC17; + --ds-cyan-a5: #3A9FAC1F; + --ds-cyan-a6: #3A9FAC27; + --ds-cyan-a7: #3A9FAC33; + --ds-cyan-a8: #3A9FAC47; + --ds-cyan-a9: #3A9FAC63; + --ds-cyan-a10: #3A9FAC7D; + --ds-cyan-a11: #3A9FACA2; + --ds-cyan-a12: #3A9FACDE; + --ds-cyan-1Channel: 250 254 255; + --ds-cyan-2Channel: 241 251 252; + --ds-cyan-3Channel: 227 246 248; + --ds-cyan-4Channel: 212 239 243; + --ds-cyan-5Channel: 194 230 235; + --ds-cyan-6Channel: 172 219 225; + --ds-cyan-7Channel: 140 204 211; + --ds-cyan-8Channel: 100 186 195; + --ds-cyan-9Channel: 58 159 172; + --ds-cyan-10Channel: 0 156 166; + --ds-cyan-11Channel: 0 104 115; + --ds-cyan-12Channel: 0 58 64; + --ds-green-1: #FBFEFB; + --ds-green-2: #F3FBF4; + --ds-green-3: #E6F6E8; + --ds-green-4: #D8F0DB; + --ds-green-5: #C9E9CC; + --ds-green-6: #B4DEB8; + --ds-green-7: #95CF9B; + --ds-green-8: #70BE78; + --ds-green-9: #4CA65A; + --ds-green-10: #008C15; /* brand */ + --ds-green-11: #00620F; + --ds-green-12: #003708; + --ds-green-a1: #4CA65A05; + --ds-green-a2: #4CA65A0A; + --ds-green-a3: #4CA65A10; + --ds-green-a4: #4CA65A17; + --ds-green-a5: #4CA65A1F; + --ds-green-a6: #4CA65A27; + --ds-green-a7: #4CA65A33; + --ds-green-a8: #4CA65A47; + --ds-green-a9: #4CA65A63; + --ds-green-a10: #4CA65A7D; + --ds-green-a11: #4CA65AA2; + --ds-green-a12: #4CA65ADE; + --ds-green-1Channel: 251 254 251; + --ds-green-2Channel: 243 251 244; + --ds-green-3Channel: 230 246 232; + --ds-green-4Channel: 216 240 219; + --ds-green-5Channel: 201 233 204; + --ds-green-6Channel: 180 222 184; + --ds-green-7Channel: 149 207 155; + --ds-green-8Channel: 112 190 120; + --ds-green-9Channel: 76 166 90; + --ds-green-10Channel: 0 140 21; + --ds-green-11Channel: 0 98 15; + --ds-green-12Channel: 0 55 8; + --ds-indigo-1:#fdfdfe; + --ds-indigo-2:#f7f9ff; + --ds-indigo-3:#edf2fe; + --ds-indigo-4:#e1e9ff; + --ds-indigo-5:#d2deff; + --ds-indigo-6:#c1d0ff; + --ds-indigo-7:#abbdf9; + --ds-indigo-8:#8da4ef; + --ds-indigo-9:#3e63dd; + --ds-indigo-10:#3358d4; + --ds-indigo-11:#3a5bc7; + --ds-indigo-12:#1f2d5c; + --ds-indigo-a1:#00008002; + --ds-indigo-a2:#0040ff08; + --ds-indigo-a3:#0047f112; + --ds-indigo-a4:#0044ff1e; + --ds-indigo-a5:#0044ff2d; + --ds-indigo-a6:#003eff3e; + --ds-indigo-a7:#0037ed54; + --ds-indigo-a8:#0034dc72; + --ds-indigo-a9:#0031d2c1; + --ds-indigo-a10:#002ec9cc; + --ds-indigo-a11:#002bb7c5; + --ds-indigo-a12:#001046e0; + --ds-indigo-1Channel: 253 253 254; + --ds-indigo-2Channel: 247 249 255; + --ds-indigo-3Channel: 237 242 254; + --ds-indigo-4Channel: 225 233 255; + --ds-indigo-5Channel: 210 222 255; + --ds-indigo-6Channel: 193 208 255; + --ds-indigo-7Channel: 171 189 249; + --ds-indigo-8Channel: 141 164 239; + --ds-indigo-9Channel: 62 99 221; + --ds-indigo-10Channel: 51 88 212; + --ds-indigo-11Channel: 58 91 199; + --ds-indigo-12Channel: 31 45 92; + --ds-lime-1:#fcfdfa; + --ds-lime-2:#f8faf3; + --ds-lime-3:#eef6d6; + --ds-lime-4:#e2f0bd; + --ds-lime-5:#d3e7a6; + --ds-lime-6:#c2da91; + --ds-lime-7:#abc978; + --ds-lime-8:#8db654; + --ds-lime-9:#bdee63; + --ds-lime-10:#b0e64c; + --ds-lime-11:#5c7c2f; + --ds-lime-12:#37401c; + --ds-lime-a1:#66990005; + --ds-lime-a2:#6b95000c; + --ds-lime-a3:#96c80029; + --ds-lime-a4:#8fc60042; + --ds-lime-a5:#81bb0059; + --ds-lime-a6:#72aa006e; + --ds-lime-a7:#61990087; + --ds-lime-a8:#559200ab; + --ds-lime-a9:#93e4009c; + --ds-lime-a10:#8fdc00b3; + --ds-lime-a11:#375f00d0; + --ds-lime-a12:#1e2900e3; + --ds-lime-1Channel: 252 253 250; + --ds-lime-2Channel: 248 250 243; + --ds-lime-3Channel: 238 246 214; + --ds-lime-4Channel: 226 240 189; + --ds-lime-5Channel: 211 231 166; + --ds-lime-6Channel: 194 218 145; + --ds-lime-7Channel: 171 201 120; + --ds-lime-8Channel: 141 182 84; + --ds-lime-9Channel: 189 238 99; + --ds-lime-10Channel: 176 230 76; + --ds-lime-11Channel: 92 124 47; + --ds-lime-12Channel: 55 64 28; + --ds-violet-1: #FEFBFF; + --ds-violet-2: #FCF4FD; + --ds-violet-3: #F9E7FB; + --ds-violet-4: #F5D9F7; + --ds-violet-5: #F0C9F1; + --ds-violet-6: #E7B2E8; + --ds-violet-7: #DA98DC; + --ds-violet-8: #C978CE; + --ds-violet-9: #C91FA8; + --ds-violet-10: #B0008E; /* brand */ + --ds-violet-11: #9A007A; + --ds-violet-12: #640055; + --ds-violet-a1: #B952BF05; + --ds-violet-a2: #B952BF0A; + --ds-violet-a3: #B952BF10; + --ds-violet-a4: #B952BF17; + --ds-violet-a5: #B952BF1F; + --ds-violet-a6: #B952BF27; + --ds-violet-a7: #B952BF33; + --ds-violet-a8: #B952BF47; + --ds-violet-a9: #B952BF63; + --ds-violet-a10: #B952BF7D; + --ds-violet-a11: #B952BFA2; + --ds-violet-a12: #B952BFDE; + --ds-violet-1Channel: 254 251 255; + --ds-violet-2Channel: 252 244 253; + --ds-violet-3Channel: 249 231 251; + --ds-violet-4Channel: 245 217 247; + --ds-violet-5Channel: 240 201 241; + --ds-violet-6Channel: 231 178 232; + --ds-violet-7Channel: 218 152 220; + --ds-violet-8Channel: 201 120 206; + --ds-violet-9Channel: 201 31 168; + --ds-violet-10Channel: 176 0 142; + --ds-violet-11Channel: 154 0 122; + --ds-violet-12Channel: 100 0 85; + --ds-orange-1: #FFF9F3; + --ds-orange-2: #FFF1E3; + --ds-orange-3: #FFE4CC; + --ds-orange-4: #FFD6B3; + --ds-orange-5: #FFC796; + --ds-orange-6: #FFB777; + --ds-orange-7: #FFA457; + --ds-orange-8: #FF8B2F; + --ds-orange-9: #FF780A; + --ds-orange-10: #FF6900; /* brand */ + --ds-orange-11: #A24600; + --ds-orange-12: #552300; + --ds-orange-a1: #FF780A05; + --ds-orange-a2: #FF780A0A; + --ds-orange-a3: #FF780A10; + --ds-orange-a4: #FF780A17; + --ds-orange-a5: #FF780A1F; + --ds-orange-a6: #FF780A27; + --ds-orange-a7: #FF780A33; + --ds-orange-a8: #FF780A47; + --ds-orange-a9: #FF780A63; + --ds-orange-a10: #FF780A7D; + --ds-orange-a11: #FF780AA2; + --ds-orange-a12: #FF780ADE; + --ds-orange-1Channel: 255 249 243; + --ds-orange-2Channel: 255 241 227; + --ds-orange-3Channel: 255 228 204; + --ds-orange-4Channel: 255 214 179; + --ds-orange-5Channel: 255 199 150; + --ds-orange-6Channel: 255 183 119; + --ds-orange-7Channel: 255 164 87; + --ds-orange-8Channel: 255 139 47; + --ds-orange-9Channel: 255 120 10; + --ds-orange-10Channel: 255 105 0; + --ds-orange-11Channel: 162 70 0; + --ds-orange-12Channel: 85 35 0; + --ds-red-1: #fffcfc; + --ds-red-2: #fff8f7; + --ds-red-3: #feebe7; + --ds-red-4: #ffdcd3; + --ds-red-5: #ffcdc2; + --ds-red-6: #fdbdaf; + --ds-red-7: #f5a898; + --ds-red-9: #e54d2e; + --ds-red-10: #E10600; /* brand */ + --ds-red-11: #d13415; + --ds-red-12: #5c271f; + --ds-red-a1: #ff000003; + --ds-red-a2: #ff200008; + --ds-red-a3: #f52b0018; + --ds-red-a4: #ff35002c; + --ds-red-a5: #ff2e003d; + --ds-red-a6: #f92d0050; + --ds-red-a7: #e7280067; + --ds-red-a8: #db250084; + --ds-red-a9: #df2600d1; + --ds-red-a10: #d72400da; + --ds-red-a11: #cd2200ea; + --ds-red-a12: #460900e0; + --ds-red-1Channel: 255 252 252; + --ds-red-2Channel: 255 239 239; + --ds-red-3Channel: 255 226 225; + --ds-red-4Channel: 255 212 210; + --ds-red-5Channel: 255 195 193; + --ds-red-6Channel: 255 174 171; + --ds-red-7Channel: 255 144 141; + --ds-red-8Channel: 247 111 106; + --ds-red-9Channel: 229 75 69; + --ds-red-10Channel: 225 6 0; + --ds-red-11Channel: 150 4 0; + --ds-red-12Channel: 75 2 0; + --ds-yellow-1:#fdfdf9; + --ds-yellow-2:#fefce9; + --ds-yellow-3:#fffab8; + --ds-yellow-4:#fff394; + --ds-yellow-5:#ffe770; + --ds-yellow-6:#f3d768; + --ds-yellow-7:#e4c767; + --ds-yellow-8:#d5ae39; + --ds-yellow-9:#ffe629; + --ds-yellow-10:#FCD021; /* brand */ + --ds-yellow-11:#9e6c00; + --ds-yellow-12:#473b1f; + --ds-yellow-a1:#aaaa0006; + --ds-yellow-a2:#f4dd0016; + --ds-yellow-a3:#ffee0047; + --ds-yellow-a4:#ffe3016b; + --ds-yellow-a5:#ffd5008f; + --ds-yellow-a6:#ebbc0097; + --ds-yellow-a7:#d2a10098; + --ds-yellow-a8:#c99700c6; + --ds-yellow-a9:#ffe100d6; + --ds-yellow-a10:#FCD021; + --ds-yellow-a11:#9e6c00; + --ds-yellow-a12:#2e2000e0; + --ds-yellow-1Channel: 253 253 249; + --ds-yellow-2Channel: 254 252 233; + --ds-yellow-3Channel: 255 250 184; + --ds-yellow-4Channel: 255 243 148; + --ds-yellow-5Channel: 255 231 112; + --ds-yellow-6Channel: 243 215 104; + --ds-yellow-7Channel: 228 199 103; + --ds-yellow-8Channel: 213 174 57; + --ds-yellow-9Channel: 255 230 41; + --ds-yellow-10Channel: 255 220 0; + --ds-yellow-11Channel: 158 108 0; + --ds-yellow-12Channel: 71 59 31; + /* Diamond Brand Blue */ + --ds-navy-1: #F9FAFD; + --ds-navy-2: #EFF1F7; + --ds-navy-3: #E0E2ED; + --ds-navy-4: #D0D4E2; + --ds-navy-5: #BEC3D4; + --ds-navy-6: #A9AFC3; + --ds-navy-7: #9196AF; + --ds-navy-8: #777C98; + --ds-navy-9: #586084; + --ds-navy-10: #202945; /* brand */ + --ds-navy-11: #1D263F; + --ds-navy-12: #0C0E1C; + --ds-navy-a1: #58608405; + --ds-navy-a2: #5860840A; + --ds-navy-a3: #58608410; + --ds-navy-a4: #58608417; + --ds-navy-a5: #5860841F; + --ds-navy-a6: #58608427; + --ds-navy-a7: #58608433; + --ds-navy-a8: #58608447; + --ds-navy-a9: #58608463; + --ds-navy-a10: #5860847D; + --ds-navy-a11: #586084A2; + --ds-navy-a12: #586084DE; + --ds-navy-1Channel: 249 250 253; + --ds-navy-2Channel: 239 241 247; + --ds-navy-3Channel: 224 226 237; + --ds-navy-4Channel: 208 212 226; + --ds-navy-5Channel: 190 195 212; + --ds-navy-6Channel: 169 175 195; + --ds-navy-7Channel: 145 150 175; + --ds-navy-8Channel: 119 124 152; + --ds-navy-9Channel: 88 96 132; + --ds-navy-10Channel: 32 41 69; + --ds-navy-11Channel: 29 38 63; + --ds-navy-12Channel: 12 14 28; + } + .dark, :root[data-mode="dark"] { /* Dark Mode */ + /* Semantic on-colour tokens */ + --ds-fg-fixed-white: var(--ds-white); /* Always white */ + --ds-fg-fixed-black: var(--ds-black); /* Always black */ + --ds-fg-inverse: var(--ds-black); /* White (light) → Black (dark) */ + --ds-fg-default: var(--ds-white); /* Black (light) → White (dark) */ + + --ds-bg-brand: var(--ds-navy-7); /* Diamond Brand Blue */ + + --ds-overlay-hover: rgba(255, 255, 255, 0.06); + --ds-overlay-selected: rgba(255, 255, 255, 0.10); + --ds-overlay-focus: rgba(255, 255, 255, 0.12); + --ds-overlay-disabled: rgba(255, 255, 255, 0.30); + --ds-overlay-disabled-bg: rgba(255, 255, 255, 0.08); + + /* Canvas (app shell) */ + --ds-bg-canvas: var(--ds-olive-1); + + /* Paper (main surface) */ + --ds-bg-paper: var(--ds-olive-2); + + /* Layering surfaces */ + --ds-bg-surface-1: var(--ds-olive-3); + --ds-bg-surface-2: var(--ds-olive-4); + + /* Borders */ + --ds-border-subtle: var(--ds-olive-6); + --ds-border-strong: var(--ds-olive-7); + + /* Radix based colours */ + --ds-gray-1:#111; + --ds-gray-2:#191919; + --ds-gray-3:#222; + --ds-gray-4:#2a2a2a; + --ds-gray-5:#313131; + --ds-gray-6:#3a3a3a; + --ds-gray-7:#484848; + --ds-gray-8:#606060; + --ds-gray-9:#6e6e6e; + --ds-gray-10:#7b7b7b; + --ds-gray-11:#b4b4b4; + --ds-gray-12:#eee; + --ds-gray-a1:#0000; + --ds-gray-a2:#ffffff09; + --ds-gray-a3:#ffffff12; + --ds-gray-a4:#ffffff1b; + --ds-gray-a5:#ffffff22; + --ds-gray-a6:#ffffff2c; + --ds-gray-a7:#ffffff3b; + --ds-gray-a8:#ffffff55; + --ds-gray-a9:#ffffff64; + --ds-gray-a10:#ffffff72; + --ds-gray-a11:#ffffffaf; + --ds-gray-a12:#ffffffed; + --ds-gray-1Channel: 17 17 17; + --ds-gray-2Channel: 25 25 25; + --ds-gray-3Channel: 34 34 34; + --ds-gray-4Channel: 42 42 42; + --ds-gray-5Channel: 49 49 49; + --ds-gray-6Channel: 58 58 58; + --ds-gray-7Channel: 72 72 72; + --ds-gray-8Channel: 96 96 96; + --ds-gray-9Channel: 110 110 110; + --ds-gray-10Channel: 123 123 123; + --ds-gray-11Channel: 180 180 180; + --ds-gray-12Channel: 238 238 238; + --ds-olive-1:#111210; + --ds-olive-2:#181917; + --ds-olive-3:#212220; + --ds-olive-4:#282a27; + --ds-olive-5:#2f312e; + --ds-olive-6:#383a36; + --ds-olive-7:#454843; + --ds-olive-8:#5c625b; + --ds-olive-9:#687066; + --ds-olive-10:#767d74; + --ds-olive-11:#afb5ad; + --ds-olive-12:#eceeec; + --ds-olive-a1:#0000; + --ds-olive-a2:#f1f2f008; + --ds-olive-a3:#f4f5f312; + --ds-olive-a4:#f3fef21a; + --ds-olive-a5:#f2fbf122; + --ds-olive-a6:#f4faed2c; + --ds-olive-a7:#f2fced3b; + --ds-olive-a8:#edfdeb57; + --ds-olive-a9:#ebfde766; + --ds-olive-a10:#f0fdec74; + --ds-olive-a11:#f6fef4b0; + --ds-olive-a12:#fdfffded; + --ds-olive-1Channel: 17 18 16; + --ds-olive-2Channel: 24 25 23; + --ds-olive-3Channel: 33 34 32; + --ds-olive-4Channel: 40 42 39; + --ds-olive-5Channel: 47 49 46; + --ds-olive-6Channel: 56 58 54; + --ds-olive-7Channel: 69 72 67; + --ds-olive-8Channel: 92 98 91; + --ds-olive-9Channel: 104 112 102; + --ds-olive-10Channel: 118 125 116; + --ds-olive-11Channel: 175 181 173; + --ds-olive-12Channel: 236 238 236; + --ds-cyan-1:#0b161a; + --ds-cyan-2:#101b20; + --ds-cyan-3:#082c36; + --ds-cyan-4:#003848; + --ds-cyan-5:#004558; + --ds-cyan-6:#045468; + --ds-cyan-7:#12677e; + --ds-cyan-8:#11809c; + --ds-cyan-9:#00a2c7; + --ds-cyan-10:#23afd0; + --ds-cyan-11:#4ccce6; + --ds-cyan-12:#b6ecf7; + --ds-cyan-a1:#0091f70a; + --ds-cyan-a2:#02a7f211; + --ds-cyan-a3:#00befd28; + --ds-cyan-a4:#00baff3b; + --ds-cyan-a5:#00befd4d; + --ds-cyan-a6:#00c7fd5e; + --ds-cyan-a7:#14cdff75; + --ds-cyan-a8:#11cfff95; + --ds-cyan-a9:#00cfffc3; + --ds-cyan-a10:#28d6ffcd; + --ds-cyan-a11:#52e1fee5; + --ds-cyan-a12:#bbf3fef7; + --ds-cyan-1Channel: 11 22 26; + --ds-cyan-2Channel: 16 27 32; + --ds-cyan-3Channel: 8 44 54; + --ds-cyan-4Channel: 0 56 72; + --ds-cyan-5Channel: 0 69 88; + --ds-cyan-6Channel: 4 84 104; + --ds-cyan-7Channel: 18 103 126; + --ds-cyan-8Channel: 17 128 156; + --ds-cyan-9Channel: 0 162 199; + --ds-cyan-10Channel: 35 175 208; + --ds-cyan-11Channel: 76 204 230; + --ds-cyan-12Channel: 182 236 247; + --ds-green-1:#0e1512; + --ds-green-2:#121b17; + --ds-green-3:#132d21; + --ds-green-4:#113b29; + --ds-green-5:#174933; + --ds-green-6:#20573e; + --ds-green-7:#28684a; + --ds-green-8:#2f7c57; + --ds-green-9:#30a46c; + --ds-green-10:#33b074; + --ds-green-11:#3dd68c; + --ds-green-12:#b1f1cb; + --ds-green-a1:#00de4505; + --ds-green-a2:#29f99d0b; + --ds-green-a3:#22ff991e; + --ds-green-a4:#11ff992d; + --ds-green-a5:#2bffa23c; + --ds-green-a6:#44ffaa4b; + --ds-green-a7:#50fdac5e; + --ds-green-a8:#54ffad73; + --ds-green-a9:#44ffa49e; + --ds-green-a10:#43fea4ab; + --ds-green-a11:#46fea5d4; + --ds-green-a12:#bbffd7f0; + --ds-green-1Channel: 14 21 18; + --ds-green-2Channel: 18 27 23; + --ds-green-3Channel: 19 45 33; + --ds-green-4Channel: 17 59 41; + --ds-green-5Channel: 23 73 51; + --ds-green-6Channel: 32 87 62; + --ds-green-7Channel: 40 104 74; + --ds-green-8Channel: 47 124 87; + --ds-green-9Channel: 48 164 108; + --ds-green-10Channel: 51 176 116; + --ds-green-11Channel: 61 214 140; + --ds-green-12Channel: 177 241 203; + --ds-indigo-1:#11131f; + --ds-indigo-2:#141726; + --ds-indigo-3:#182449; + --ds-indigo-4:#1d2e62; + --ds-indigo-5:#253974; + --ds-indigo-6:#304384; + --ds-indigo-7:#3a4f97; + --ds-indigo-8:#435db1; + --ds-indigo-9:#3e63dd; + --ds-indigo-10:#5472e4; + --ds-indigo-11:#9eb1ff; + --ds-indigo-12:#d6e1ff; + --ds-indigo-a1:#1133ff0f; + --ds-indigo-a2:#3354fa17; + --ds-indigo-a3:#2f62ff3c; + --ds-indigo-a4:#3566ff57; + --ds-indigo-a5:#4171fd6b; + --ds-indigo-a6:#5178fd7c; + --ds-indigo-a7:#5a7fff90; + --ds-indigo-a8:#5b81feac; + --ds-indigo-a9:#4671ffdb; + --ds-indigo-a10:#5c7efee3; + --ds-indigo-a11:#9eb1ff; + --ds-indigo-a12:#d6e1ff; + --ds-indigo-1Channel: 17 19 31; + --ds-indigo-2Channel: 20 23 38; + --ds-indigo-3Channel: 24 36 73; + --ds-indigo-4Channel: 29 46 98; + --ds-indigo-5Channel: 37 57 116; + --ds-indigo-6Channel: 48 67 132; + --ds-indigo-7Channel: 58 79 151; + --ds-indigo-8Channel: 67 93 177; + --ds-indigo-9Channel: 62 99 221; + --ds-indigo-10Channel: 84 114 228; + --ds-indigo-11Channel: 158 177 255; + --ds-indigo-12Channel: 214 225 255; + --ds-lime-1:#11130c; + --ds-lime-2:#151a10; + --ds-lime-3:#1f2917; + --ds-lime-4:#29371d; + --ds-lime-5:#334423; + --ds-lime-6:#3d522a; + --ds-lime-7:#496231; + --ds-lime-8:#577538; + --ds-lime-9:#bdee63; + --ds-lime-10:#d4ff70; + --ds-lime-11:#bde56c; + --ds-lime-12:#e3f7ba; + --ds-lime-a1:#11bb0003; + --ds-lime-a2:#78f7000a; + --ds-lime-a3:#9bfd4c1a; + --ds-lime-a4:#a7fe5c29; + --ds-lime-a5:#affe6537; + --ds-lime-a6:#b2fe6d46; + --ds-lime-a7:#b6ff6f57; + --ds-lime-a8:#b6fd6d6c; + --ds-lime-a9:#caff69ed; + --ds-lime-a10:#d4ff70; + --ds-lime-a11:#d1fe77e4; + --ds-lime-a12:#e9febff7; + --ds-lime-1Channel: 17 19 12; + --ds-lime-2Channel: 21 26 16; + --ds-lime-3Channel: 31 41 23; + --ds-lime-4Channel: 41 55 29; + --ds-lime-5Channel: 51 68 35; + --ds-lime-6Channel: 61 82 42; + --ds-lime-7Channel: 73 98 49; + --ds-lime-8Channel: 87 117 56; + --ds-lime-9Channel: 189 238 99; + --ds-lime-10Channel: 212 255 112; + --ds-lime-11Channel: 189 229 108; + --ds-lime-12Channel: 227 247 186; + --ds-orange-1:#17120e; + --ds-orange-2:#1e160f; + --ds-orange-3:#331e0b; + --ds-orange-4:#462100; + --ds-orange-5:#562800; + --ds-orange-6:#66350c; + --ds-orange-7:#7e451d; + --ds-orange-8:#a35829; + --ds-orange-9:#f76b15; + --ds-orange-10:#ff801f; + --ds-orange-11:#ffa057; + --ds-orange-12:#ffe0c2; + --ds-orange-a1:#ec360007; + --ds-orange-a2:#fe6d000e; + --ds-orange-a3:#fb6a0025; + --ds-orange-a4:#ff590039; + --ds-orange-a5:#ff61004a; + --ds-orange-a6:#fd75045c; + --ds-orange-a7:#ff832c75; + --ds-orange-a8:#fe84389d; + --ds-orange-a9:#fe6d15f7; + --ds-orange-a10:#ff801f; + --ds-orange-a11:#ffa057; + --ds-orange-a12:#ffe0c2; + --ds-orange-1Channel: 23 18 14; + --ds-orange-2Channel: 30 22 15; + --ds-orange-3Channel: 51 30 11; + --ds-orange-4Channel: 70 33 0; + --ds-orange-5Channel: 86 40 0; + --ds-orange-6Channel: 102 53 12; + --ds-orange-7Channel: 126 69 29; + --ds-orange-8Channel: 163 88 41; + --ds-orange-9Channel: 247 107 21; + --ds-orange-10Channel: 255 128 31; + --ds-orange-11Channel: 255 160 87; + --ds-orange-12Channel: 255 224 194; + --ds-violet-1:#181118; + --ds-violet-2:#201320; + --ds-violet-3:#351a35; + --ds-violet-4:#451d47; + --ds-violet-5:#512454; + --ds-violet-6:#5e3061; + --ds-violet-7:#734079; + --ds-violet-8:#92549c; + --ds-violet-9:#ab4aba; + --ds-violet-10:#b658c4; + --ds-violet-11:#e796f3; + --ds-violet-12:#f4d4f4; + --ds-violet-a1:#f112f108; + --ds-violet-a2:#f22ff211; + --ds-violet-a3:#fd4cfd27; + --ds-violet-a4:#f646ff3a; + --ds-violet-a5:#f455ff48; + --ds-violet-a6:#f66dff56; + --ds-violet-a7:#f07cfd70; + --ds-violet-a8:#ee84ff95; + --ds-violet-a9:#e961feb6; + --ds-violet-a10:#ed70ffc0; + --ds-violet-a11:#f19cfef3; + --ds-violet-a12:#feddfef4; + --ds-violet-1Channel: 24 17 24; + --ds-violet-2Channel: 32 19 32; + --ds-violet-3Channel: 53 26 53; + --ds-violet-4Channel: 69 29 71; + --ds-violet-5Channel: 81 36 84; + --ds-violet-6Channel: 94 48 97; + --ds-violet-7Channel: 115 64 121; + --ds-violet-8Channel: 146 84 156; + --ds-violet-9Channel: 171 74 186; + --ds-violet-10Channel: 182 88 196; + --ds-violet-11Channel: 231 150 243; + --ds-violet-12Channel: 244 212 244; + --ds-red-1: #181111; + --ds-red-2: #1f1513; + --ds-red-3: #391714; + --ds-red-4: #4e1511; + --ds-red-5: #5e1c16; + --ds-red-6: #6e2920; + --ds-red-7: #853a2d; + --ds-red-8: #ac4d39; + --ds-red-10: #ec6142; + --ds-red-11: #ff977d; + --ds-red-12: #fbd3cb; + --ds-red-a1: #f1121208; + --ds-red-a2: #ff55330f; + --ds-red-a3: #ff35232b; + --ds-red-a4: #fd201142; + --ds-red-a5: #fe332153; + --ds-red-a6: #ff4f3864; + --ds-red-a7: #fd644a7d; + --ds-red-a8: #fe6d4ea7; + --ds-red-a9: #fe5431e4; + --ds-red-a10: #ff6847eb; + --ds-red-a11: #ff977d; + --ds-red-a12: #ffd6cefb; + --ds-red-1Channel: 25 17 17; + --ds-red-2Channel: 32 19 20; + --ds-red-3Channel: 59 18 25; + --ds-red-4Channel: 80 15 28; + --ds-red-5Channel: 97 22 35; + --ds-red-6Channel: 114 35 45; + --ds-red-7Channel: 140 51 58; + --ds-red-8Channel: 181 69 72; + --ds-red-9Channel: 229 72 77; + --ds-red-10Channel: 236 93 94; + --ds-red-11Channel: 255 149 146; + --ds-red-12Channel: 255 209 217; + --ds-yellow-1:#14120b; + --ds-yellow-2:#1b180f; + --ds-yellow-3:#2d2305; + --ds-yellow-4:#362b00; + --ds-yellow-5:#433500; + --ds-yellow-6:#524202; + --ds-yellow-7:#665417; + --ds-yellow-8:#836a21; + --ds-yellow-9:#ffe629; + --ds-yellow-10:#ffff57; + --ds-yellow-11:#f5e147; + --ds-yellow-12:#f6eeb4; + --ds-yellow-a1:#d1510004; + --ds-yellow-a2:#f9b4000b; + --ds-yellow-a3:#ffaa001e; + --ds-yellow-a4:#fdb70028; + --ds-yellow-a5:#febb0036; + --ds-yellow-a6:#fec40046; + --ds-yellow-a7:#fdcb225c; + --ds-yellow-a8:#fdca327b; + --ds-yellow-a9:#ffe629; + --ds-yellow-a10:#ffff57; + --ds-yellow-a11:#fee949f5; + --ds-yellow-a12:#fef6baf6; + --ds-yellow-1Channel: 20 18 11; + --ds-yellow-2Channel: 27 24 15; + --ds-yellow-3Channel: 45 35 5; + --ds-yellow-4Channel: 54 43 0; + --ds-yellow-5Channel: 67 53 0; + --ds-yellow-6Channel: 82 66 2; + --ds-yellow-7Channel: 102 84 23; + --ds-yellow-8Channel: 131 106 33; + --ds-yellow-9Channel: 255 230 41; + --ds-yellow-10Channel: 255 255 87; + --ds-yellow-11Channel: 245 225 71; + --ds-yellow-12Channel: 246 238 180; + /* Diamond Brand Blue */ + --ds-navy-1: #070910; + --ds-navy-2: #0B0E17; + --ds-navy-3: #101521; + --ds-navy-4: #141A2B; + --ds-navy-5: #192034; + --ds-navy-6: #1D263F; + --ds-navy-7: #202945; /* brand sits here in dark ramp */ + --ds-navy-8: #273352; + --ds-navy-9: #5F678D; + --ds-navy-10: #7983AF; + --ds-navy-11: #9ca9ce; + --ds-navy-12: #d5ddf0; + --ds-navy-a1: #32406405; + --ds-navy-a2: #3240640A; + --ds-navy-a3: #32406410; + --ds-navy-a4: #32406417; + --ds-navy-a5: #3240641F; + --ds-navy-a6: #32406427; + --ds-navy-a7: #32406433; + --ds-navy-a8: #32406447; + --ds-navy-a9: #32406463; + --ds-navy-a10: #3240647D; + --ds-navy-a11: #324064A2; + --ds-navy-a12: #324064DE; + --ds-navy-1Channel: 7 9 16; /* #070910 */ + --ds-navy-2Channel: 11 14 23; /* #0b0e17 */ + --ds-navy-3Channel: 16 21 33; /* #101521 */ + --ds-navy-4Channel: 20 26 43; /* #141a2b */ + --ds-navy-5Channel: 25 32 52; /* #192034 */ + --ds-navy-6Channel: 29 38 63; /* #1d263f */ + --ds-navy-7Channel: 32 41 69; /* #202945 (brand) */ + --ds-navy-8Channel: 39 51 82; /* #273352 */ + --ds-navy-9Channel: 95 103 141; /* #324064 */ + --ds-navy-10Channel: 121 131 175; + --ds-navy-11Channel: 156 169 206; /* #9ca9ce */ + --ds-navy-12Channel: 213 221 240; /* #d5ddf0 */ + } \ No newline at end of file diff --git a/src/styles/diamondDS/diamond-mui-palette-tokens.css b/src/styles/diamondDS/diamond-mui-palette-tokens.css new file mode 100644 index 0000000..f17fdc2 --- /dev/null +++ b/src/styles/diamondDS/diamond-mui-palette-tokens.css @@ -0,0 +1,243 @@ +/* ============================================================ + NEW DIAMOND THEME (Diamond + Radix) - NOT USED CURRENTLY + ============================================================ */ + :root { + + /* COMMON */ + --mui-palette-common-black: var(--ds-black); + --mui-palette-common-white: var(--ds-white); + + --mui-palette-common-blackChannel: var(--ds-blackChannel); + --mui-palette-common-whiteChannel: var(--ds-Channel); + + --mui-palette-common-background: var(--ds-olive-1); + --mui-palette-common-onBackground: var(--ds-navy-11); + + --mui-palette-common-backgroundChannel: var(--ds-olive-1Channel); + --mui-palette-common-onBackgroundChannel: var(--ds-navy-11Channel); + + /* PRIMARY = Indigo */ + --mui-palette-primary-lighter: var(--ds-indigo-3); + --mui-palette-primary-light: var(--ds-indigo-6); + --mui-palette-primary-main: var(--ds-indigo-9); + --mui-palette-primary-dark: var(--ds-indigo-10); + --mui-palette-primary-darker: var(--ds-indigo-12); + --mui-palette-primary-contrastText: var(--ds-mui-palette-common-white); + + --mui-palette-primary-lighterChannel: var(--ds-indigo-3Channel); + --mui-palette-primary-lightChannel: var(--ds-indigo-6Channel); + --mui-palette-primary-mainChannel: var(--ds-indigo-9Channel); + --mui-palette-primary-darkChannel: var(--ds-indigo-10Channel); + --mui-palette-primary-darkerChannel: var(--ds-indigo-12Channel); + --mui-palette-primary-contrastTextChannel: var(--ds-mui-palette-common-whiteChannel); + + /* SECONDARY = Gray */ + --mui-palette-secondary-lighter: var(--ds-navy-3); + --mui-palette-secondary-light: var(--ds-navy-6); + --mui-palette-secondary-main: var(--ds-navy-9); + --mui-palette-secondary-dark: var(--ds-navy-11); + --mui-palette-secondary-darker: var(--ds-navy-12); + --mui-palette-secondary-contrastText: var(--ds-mui-palette-common-white); + + --mui-palette-secondary-lighterChannel: var(--ds-navy-3Channel); + --mui-palette-secondary-lightChannel: var(--ds-navy-6Channel); + --mui-palette-secondary-mainChannel: var(--ds-navy-9Channel); + --mui-palette-secondary-darkChannel: var(--ds-navy-11Channel); + --mui-palette-secondary-darkerChannel: var(--ds-navy-12Channel); + --mui-palette-secondary-contrastTextChannel: var(--ds-mui-palette-common-whiteChannel); + + /* ERROR = Red */ + --mui-palette-error-lighter: var(--ds-red-3); + --mui-palette-error-light: var(--ds-red-6); + --mui-palette-error-main: var(--ds-red-9); + --mui-palette-error-dark: var(--ds-red-11); + --mui-palette-error-darker: var(--ds-red-12); + --mui-palette-error-contrastText: var(--ds-mui-palette-common-white); + + --mui-palette-error-lighterChannel: var(--ds-red-3Channel); + --mui-palette-error-lightChannel: var(--ds-red-6Channel); + --mui-palette-error-mainChannel: var(--ds-red-9Channel); + --mui-palette-error-darkChannel: var(--ds-red-11Channel); + --mui-palette-error-darkerChannel: var(--ds-red-12Channel); + --mui-palette-error-contrastTextChannel: var(--ds-mui-palette-common-whiteChannel); + + /* WARNING = Yellow */ + --mui-palette-warning-lighter: var(--ds-yellow-2); + --mui-palette-warning-light: var(--ds-yellow-6); + --mui-palette-warning-main: var(--ds-yellow-9); + --mui-palette-warning-dark: var(--ds-yellow-11); + --mui-palette-warning-darker: var(--ds-yellow-12); + --mui-palette-warning-contrastText: var(--ds-mui-palette-common-black); + + --mui-palette-warning-lighterChannel: var(--ds-yellow-2Channel); + --mui-palette-warning-lightChannel: var(--ds-yellow-6Channel); + --mui-palette-warning-mainChannel: var(--ds-yellow-9Channel); + --mui-palette-warning-darkChannel: var(--ds-yellow-11Channel); + --mui-palette-warning-darkerChannel: var(--ds-yellow-12Channel); + --mui-palette-warning-contrastTextChannel: var(--ds-mui-palette-common-blackChannel); + + /* INFO = Cyan */ + --mui-palette-info-lighter: var(--ds-cyan-2); + --mui-palette-info-light: var(--ds-cyan-6); + --mui-palette-info-main: var(--ds-cyan-9); + --mui-palette-info-dark: var(--ds-cyan-11); + --mui-palette-info-darker: var(--ds-cyan-12); + --mui-palette-info-contrastText: var(--ds-mui-palette-common-black); + + --mui-palette-info-lighterChannel: var(--ds-cyan-2Channel); + --mui-palette-info-lightChannel: var(--ds-cyan-6Channel); + --mui-palette-info-mainChannel: var(--ds-cyan-9Channel); + --mui-palette-info-darkChannel: var(--ds-cyan-11Channel); + --mui-palette-info-darkerChannel: var(--ds-cyan-12Channel); + --mui-palette-info-contrastTextChannel: var(--ds-mui-palette-common-blackChannel); + + /* SUCCESS = Green */ + --mui-palette-success-lighter: var(--ds-green-2); + --mui-palette-success-light: var(--ds-green-6); + --mui-palette-success-main: var(--ds-green-9); + --mui-palette-success-dark: var(--ds-green-11); + --mui-palette-success-darker: var(--ds-green-12); + --mui-palette-success-contrastText: var(--ds-mui-palette-common-black); + + --mui-palette-success-lighterChannel: var(--ds-green-2Channel); + --mui-palette-success-lightChannel: var(--ds-green-6Channel); + --mui-palette-success-mainChannel: var(--ds-green-9Channel); + --mui-palette-success-darkChannel: var(--ds-green-11Channel); + --mui-palette-success-darkerChannel: var(--ds-green-12Channel); + --mui-palette-success-contrastTextChannel: var(--ds-mui-palette-common-blackChannel); + + /* TEXT */ + --mui-palette-text-primary: var(--ds-navy-10); + --mui-palette-text-secondary: var(--ds-olive-9); + --mui-palette-text-disabled: var(--ds-olive-7); + + --mui-palette-text-primaryChannel: var(--ds-navy-11Channel); + --mui-palette-text-secondaryChannel: var(--ds-olive-9Channel); + + /* ACTIONS */ + --mui-palette-action-disabled: var(--ds-olive-6); + --mui-palette-action-active: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.54); + --mui-palette-action-hover: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.04); + --mui-palette-action-selected: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.08); + --mui-palette-action-disabledBackground: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.12); + --mui-palette-action-focus: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.12); + + --mui-palette-action-activeChannel: var(--ds-mui-palette-text-primaryChannel); + --mui-palette-action-selectedChannel: var(--ds-mui-palette-text-primaryChannel); + + /* BACKGROUNDS */ + --mui-palette-divider: var(--ds-olive-3); + --mui-palette-dividerChannel: var(--ds-olive-3Channel); + + --mui-palette-background-paper: var(--ds-mui-palette-common-white); + --mui-palette-background-default: var(--ds-olive-2); + + --mui-palette-background-defaultChannel: var(--ds-olive-2Channel); + --mui-palette-background-paperChannel: var(--ds-mui-palette-common-whiteChannel); + + /* ALERTS */ + --mui-palette-Alert-errorColor: var(--ds-mui-palette-error-dark); + --mui-palette-Alert-infoColor: var(--ds-mui-palette-info-dark); + --mui-palette-Alert-successColor: var(--ds-mui-palette-success-dark); + --mui-palette-Alert-warningColor: var(--ds-mui-palette-warning-dark); + + --mui-palette-Alert-errorFilledBg: var(--ds-mui-palette-error-main); + --mui-palette-Alert-infoFilledBg: var(--ds-mui-palette-info-main); + --mui-palette-Alert-successFilledBg: var(--ds-mui-palette-success-main); + --mui-palette-Alert-warningFilledBg: var(--ds-mui-palette-warning-main); + + --mui-palette-Alert-errorFilledColor: var(--ds-mui-palette-common-white); + --mui-palette-Alert-infoFilledColor: rgba(var(--ds-mui-palette-common-blackChannel) / 0.87); + --mui-palette-Alert-successFilledColor: rgba(var(--ds-mui-palette-common-blackChannel) / 0.87); + --mui-palette-Alert-warningFilledColor: rgba(var(--ds-mui-palette-common-blackChannel) / 0.87); + + --mui-palette-Alert-errorStandardBg: var(--ds-mui-palette-error-lighter); + --mui-palette-Alert-infoStandardBg: var(--ds-mui-palette-info-lighter); + --mui-palette-Alert-successStandardBg: var(--ds-mui-palette-success-lighter); + --mui-palette-Alert-warningStandardBg: var(--ds-mui-palette-warning-lighter); + + --mui-palette-Alert-errorIconColor: var(--ds-mui-palette-error-main); + --mui-palette-Alert-infoIconColor: var(--ds-mui-palette-info-main); + --mui-palette-Alert-successIconColor: var(--ds-mui-palette-success-main); + --mui-palette-Alert-warningIconColor: var(--ds-mui-palette-warning-main); + + /* COMPONENTS */ + --mui-palette-AppBar-defaultBg: var(--ds-navy-10); + + --mui-palette-Avatar-defaultBg: var(--ds-olive-5); + + --mui-palette-Button-inheritContainedBg: var(--ds-olive-4); + --mui-palette-Button-inheritContainedHoverBg: var(--ds-olive-2); + + --mui-palette-Chip-defaultBorder: var(--ds-olive-5); + --mui-palette-Chip-defaultAvatarColor: var(--ds-olive-11); + --mui-palette-Chip-defaultIconColor: var(--ds-olive-11); + + --mui-palette-FilledInput-bg: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.06); + --mui-palette-FilledInput-hoverBg: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.09); + --mui-palette-FilledInput-disabledBg: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.12); + + --mui-palette-LinearProgress-primaryBg: var(--ds-mui-palette-primary-lighter); + --mui-palette-LinearProgress-secondaryBg: var(--ds-mui-palette-secondary-lighter); + --mui-palette-LinearProgress-errorBg: var(--ds-mui-palette-error-lighter); + --mui-palette-LinearProgress-infoBg: var(--ds-mui-palette-info-lighter); + --mui-palette-LinearProgress-successBg: var(--ds-mui-palette-success-lighter); + --mui-palette-LinearProgress-warningBg: var(--ds-mui-palette-warning-lighter); + + --mui-palette-Skeleton-bg: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.11); + + --mui-palette-Slider-primaryTrack: var(--ds-mui-palette-primary-lighter); + --mui-palette-Slider-secondaryTrack: var(--ds-mui-palette-secondary-lighter); + --mui-palette-Slider-errorTrack: var(--ds-mui-palette-error-lighter); + --mui-palette-Slider-infoTrack: var(--ds-mui-palette-info-lighter); + --mui-palette-Slider-successTrack: var(--ds-mui-palette-success-lighter); + --mui-palette-Slider-warningTrack: var(--ds-mui-palette-warning-lighter); + + --mui-palette-SnackbarContent-bg: var(--ds-navy-11); + --mui-palette-SnackbarContent-color: var(--ds-mui-palette-common-white); + + --mui-palette-SpeedDialAction-fabHoverBg: var(--ds-olive-4); + + --mui-palette-StepConnector-border: var(--ds-olive-5); + --mui-palette-StepContent-border: var(--ds-olive-5); + + --mui-palette-Switch-defaultColor: var(--ds-mui-palette-common-white); + --mui-palette-Switch-defaultDisabledColor: var(--ds-olive-2); + --mui-palette-Switch-primaryDisabledColor: var(--ds-mui-palette-primary-lighter); + --mui-palette-Switch-secondaryDisabledColor: var(--ds-mui-palette-secondary-lighter); + --mui-palette-Switch-errorDisabledColor: var(--ds-mui-palette-error-lighter); + --mui-palette-Switch-infoDisabledColor: var(--ds-mui-palette-info-lighter); + --mui-palette-Switch-successDisabledColor: var(--ds-mui-palette-success-lighter); + --mui-palette-Switch-warningDisabledColor: var(--ds-mui-palette-warning-lighter); + + --mui-palette-TableCell-border: var(--ds-olive-1); + + --mui-palette-Tooltip-bg: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.92); + + /* SHADOWS */ + --customShadows-button: 0 2px #0000000b; + --customShadows-text: 0 -1px 0 rgba(var(--ds-mui-palette-common-blackChannel) / 0.12); + --customShadows-z1: 0px 1px 4px rgba(var(--ds-mui-palette-common-blackChannel) / 0.08); + + --customShadows-primary: 0 0 0 2px rgba(var(--ds-mui-palette-primary-mainChannel) / 0.2); + --customShadows-secondary: 0 0 0 2px rgba(var(--ds-mui-palette-secondary-mainChannel) / 0.2); + --customShadows-error: 0 0 0 2px rgba(var(--ds-mui-palette-error-mainChannel) / 0.2); + --customShadows-warning: 0 0 0 2px rgba(var(--ds-mui-palette-warning-mainChannel) / 0.2); + --customShadows-info: 0 0 0 2px rgba(var(--ds-mui-palette-info-mainChannel) / 0.2); + --customShadows-success: 0 0 0 2px rgba(var(--ds-mui-palette-success-mainChannel) / 0.2); + --customShadows-grey: 0 0 0 2px rgba(var(--ds-mui-palette-secondary-mainChannel) / 0.2); + + --customShadows-primaryButton: 0 14px 12px rgba(var(--ds-mui-palette-primary-mainChannel) / 0.2); + --customShadows-secondaryButton: 0 14px 12px rgba(var(--ds-mui-palette-secondary-mainChannel) / 0.2); + --customShadows-errorButton: 0 14px 12px rgba(var(--ds-mui-palette-error-mainChannel) / 0.2); + --customShadows-warningButton: 0 14px 12px rgba(var(--ds-mui-palette-warning-mainChannel) / 0.2); + --customShadows-infoButton: 0 14px 12px rgba(var(--ds-mui-palette-info-mainChannel) / 0.2); + --customShadows-successButton: 0 14px 12px rgba(var(--ds-mui-palette-success-mainChannel) / 0.2); + --customShadows-greyButton: 0 14px 12px rgba(var(--ds-mui-palette-secondary-mainChannel) / 0.2); + + /* OPACITY */ + --opacity-inputPlaceholder: 0.42; + --opacity-inputUnderline: 0.42; + --opacity-switchTrackDisabled: 0.12; + --opacity-switchTrack: 0.38; + } \ No newline at end of file diff --git a/src/themes/DiamondDSTheme.ts b/src/themes/DiamondDSTheme.ts new file mode 100644 index 0000000..24e3a87 --- /dev/null +++ b/src/themes/DiamondDSTheme.ts @@ -0,0 +1,451 @@ +import "../styles/diamondDS/diamond-colors-primitives.css"; + +import type {} from "@mui/material/themeCssVarsAugmentation"; +import { createTheme, Theme } from "@mui/material/styles"; + +import { mergeThemeOptions } from "./ThemeManager"; + +import logoImageLight from "../public/diamond/logo-light.svg"; +import logoImageDark from "../public/diamond/logo-dark.svg"; +import logoShort from "../public/diamond/logo-short.svg"; + +import React from "react"; +import { + DsCheckboxBlankIcon, + DsCheckboxCheckedIcon, + DsCheckboxIndeterminateIcon, +} from "./icons"; + +declare module "@mui/material/styles" { + interface TypeBackground { + surface1?: string; + surface2?: string; + } + interface PaletteColor { + bgCanvas?: string; + bgSurface1?: string; + bgSurface2?: string; + } + interface SimplePaletteColorOptions { + bgCanvas?: string; + bgSurface1?: string; + bgSurface2?: string; + } +} + +export type DSMode = "light" | "dark"; + +export const createMuiTheme = (mode: DSMode): Theme => { + const DiamondDSThemeOptions = mergeThemeOptions({ + typography: { + fontFamily: [ + "Inter Variable", + "Inter", + "system-ui", + "-apple-system", + '"Segoe UI"', + "Roboto", + "Helvetica", + "Arial", + "sans-serif", + ].join(","), + }, + + logos: { + normal: { + src: + mode === "dark" ? (logoImageDark ?? logoImageLight) : logoImageLight, + srcDark: logoImageDark ?? logoImageLight, + alt: "Diamond Light Source Logo", + width: "100", + }, + short: { + src: logoShort, + alt: "Diamond Light Source Logo", + width: "35", + }, + }, + + palette: { + mode, + + // Prevent "Material dark overlays" by defining action tokens from primitives + action: { + hover: "var(--ds-overlay-hover)", + selected: "var(--ds-overlay-selected)", + focus: "var(--ds-overlay-focus)", + disabled: "var(--ds-overlay-disabled)", + disabledBackground: "var(--ds-overlay-disabled-bg)", + + hoverOpacity: 0.08, + selectedOpacity: 0.12, + disabledOpacity: 0.38, + focusOpacity: 0.12, + }, + + text: { + primary: "var(--ds-gray-12)", + secondary: "var(--ds-gray-11)", + disabled: "var(--ds-gray-8)", + }, + + background: { + default: "var(--ds-bg-canvas)", // page / app shell + paper: "var(--ds-bg-paper)", // cards, dialogs + outlinedBg: "var(--ds-bg-surface-2)", // inputs, outlined containers + surface1: "var(--ds-bg-surface-1)", + surface2: "var(--ds-bg-surface-2)", + }, + + divider: "var(--ds-border-subtle)", + dividerInverse: "var(--ds-white-a4)", + + primary: { + main: "var(--ds-indigo-9)", + light: "var(--ds-indigo-8)", + dark: "var(--ds-indigo-10)", + darker: "var(--ds-indigo-11)", + contrastText: "var(--ds-fg-fixed-white)", + + mainChannel: "var(--ds-indigo-9Channel)", + lightChannel: "var(--ds-indigo-8Channel)", + darkChannel: "var(--ds-indigo-10Channel)", + + bgCanvas: "var(--ds-indigo-1)", + bgSurface1: "var(--ds-indigo-2)", + bgSurface2: "var(--ds-indigo-3)", + }, + + secondary: { + main: "var(--ds-navy-9)", + light: "var(--ds-navy-8)", + dark: "var(--ds-navy-10)", + darker: "var(--ds-navy-11)", + contrastText: "var(--ds-fg-fixed-white)", + + mainChannel: "var(--ds-navy-9Channel)", + lightChannel: "var(--ds-navy-8Channel)", + darkChannel: "var(--ds-navy-10Channel)", + + bgCanvas: "var(--ds-navy-1)", + bgSurface1: "var(--ds-navy-2)", + bgSurface2: "var(--ds-navy-3)", + }, + + brand: { + main: "var(--ds-navy-10)", + light: "var(--ds-navy-9)", + dark: "var(--ds-navy-11)", + darker: "var(--ds-navy-12)", + contrastText: "var(--ds-fg-fixed-white)", + + mainChannel: "var(--ds-navy-10Channel)", + lightChannel: "var(--ds-navy-9Channel)", + darkChannel: "var(--ds-navy-11Channel)", + }, + + error: { + main: "var(--ds-red-10)", + light: "var(--ds-red-9)", + dark: "var(--ds-red-11)", + darker: "var(--ds-red-11)", + contrastText: "var(--ds-fg-fixed-white)", + + mainChannel: "var(--ds-red-9Channel)", + lightChannel: "var(--ds-red-8Channel)", + darkChannel: "var(--ds-red-10Channel)", + + bgCanvas: "var(--ds-red-1)", + bgSurface1: "var(--ds-red-2)", + bgSurface2: "var(--ds-red-3)", + }, + + warning: { + main: "var(--ds-orange-10)", + light: "var(--ds-orange-9)", + dark: "var(--ds-orange-11)", + darker: "var(--ds-orange-11)", + contrastText: "var(--ds-fg-fixed-white)", + + mainChannel: "var(--ds-orange-9Channel)", + lightChannel: "var(--ds-orange-8Channel)", + darkChannel: "var(--ds-orange-10Channel)", + + bgCanvas: "var(--ds-orange-1)", + bgSurface1: "var(--ds-orange-2)", + bgSurface2: "var(--ds-orange-3)", + }, + + success: { + main: "var(--ds-green-10)", + light: "var(--ds-green-9)", + dark: "var(--ds-green-11)", + darker: "var(--ds-green-11)", + contrastText: "var(--ds-fg-fixed-white)", + + mainChannel: "var(--ds-green-9Channel)", + lightChannel: "var(--ds-green-8Channel)", + darkChannel: "var(--ds-green-10Channel)", + + bgCanvas: "var(--ds-green-1)", + bgSurface1: "var(--ds-green-2)", + bgSurface2: "var(--ds-green-3)", + }, + + info: { + main: "var(--ds-indigo-9)", + light: "var(--ds-indigo-8)", + dark: "var(--ds-indigo-10)", + darker: "var(--ds-indigo-11)", + contrastText: "var(--ds-fg-fixed-white)", + + mainChannel: "var(--ds-indigo-9Channel)", + lightChannel: "var(--ds-indigo-8Channel)", + darkChannel: "var(--ds-indigo-10Channel)", + + bgCanvas: "var(--ds-indigo-1)", + bgSurface1: "var(--ds-indigo-2)", + bgSurface2: "var(--ds-indigo-3)", + }, + + grey: { + 50: "var(--ds-olive-1)", + 100: "var(--ds-olive-2)", + 200: "var(--ds-olive-3)", + 300: "var(--ds-olive-4)", + 400: "var(--ds-olive-5)", + 500: "var(--ds-olive-6)", + 600: "var(--ds-olive-7)", + 700: "var(--ds-olive-8)", + 800: "var(--ds-olive-9)", + 900: "var(--ds-olive-10)", + }, + }, + + components: { + MuiButton: { + styleOverrides: { + root: ({ ownerState, theme }) => { + const base = { textTransform: "none" as const }; + + const variant = ownerState.variant ?? "text"; + + const rawColour = ownerState.color ?? "primary"; + if (rawColour === "inherit") return base; + + const colour = rawColour as + | "primary" + | "secondary" + | "error" + | "warning" + | "info" + | "success"; + + const varsPalette = (theme as any).vars?.palette?.[colour]; + const fallbackPalette = (theme.palette as any)[colour]; + + const darker = + varsPalette?.darker ?? + fallbackPalette?.darker ?? + varsPalette?.dark ?? + fallbackPalette?.dark; + + const mainChannel = + varsPalette?.mainChannel ?? fallbackPalette?.mainChannel; + + if (variant === "outlined") { + return { + ...base, + ...(darker && { + "--variant-outlinedColor": darker, + color: darker, + }), + ...(mainChannel && { + "--variant-outlinedBorder": `rgba(${mainChannel} / 0.7)`, + borderColor: `rgba(${mainChannel} / 0.7)`, + }), + }; + } + + if (variant === "text") { + return { + ...base, + ...(darker && { "--variant-textColor": darker, color: darker }), + }; + } + + return base; + }, + }, + }, + + MuiChip: { + styleOverrides: { + root: ({ ownerState }) => { + const base = { + "& .MuiChip-icon, & .MuiChip-deleteIcon": { + color: "currentColor", + }, + } as const; + + const isDefault = (ownerState.color ?? "default") === "default"; + const isOutlined = ownerState.variant === "outlined"; + const isInteractive = ownerState.clickable || ownerState.onDelete; + + if (isDefault) { + return { + ...base, + color: "var(--ds-olive-12)", + borderColor: "var(--ds-border-strong)", + backgroundColor: isOutlined + ? "transparent" + : "var(--ds-olive-4)", + + ...(isInteractive && { + "&:hover": { + backgroundColor: isOutlined + ? "var(--ds-overlay-hover)" + : "var(--ds-olive-5)", + }, + }), + }; + } + + return base; + }, + + outlinedPrimary: ({ theme }) => ({ + color: theme.palette.primary.darker ?? theme.palette.primary.dark, + borderColor: `rgba(${theme.palette.primary.darkChannel ?? theme.palette.primary.mainChannel} / 0.7)`, + }), + outlinedSecondary: ({ theme }) => ({ + color: theme.palette.secondary.dark, + borderColor: `rgba(${theme.palette.secondary.darkChannel ?? theme.palette.secondary.mainChannel} / 0.7)`, + }), + outlinedError: ({ theme }) => ({ + color: theme.palette.error.darker ?? theme.palette.error.dark, + borderColor: `rgba(${theme.palette.error.darkChannel ?? theme.palette.error.mainChannel} / 0.7)`, + }), + outlinedWarning: ({ theme }) => ({ + color: theme.palette.warning.darker ?? theme.palette.warning.dark, + borderColor: `rgba(${theme.palette.warning.darkChannel ?? theme.palette.warning.mainChannel} / 0.7)`, + }), + outlinedInfo: ({ theme }) => ({ + color: theme.palette.info.darker ?? theme.palette.info.dark, + borderColor: `rgba(${theme.palette.info.darkChannel ?? theme.palette.info.mainChannel} / 0.7)`, + }), + outlinedSuccess: ({ theme }) => ({ + color: theme.palette.success.darker ?? theme.palette.success.dark, + borderColor: `rgba(${theme.palette.success.darkChannel ?? theme.palette.success.mainChannel} / 0.7)`, + }), + }, + }, + + MuiCheckbox: { + defaultProps: { + icon: React.createElement(DsCheckboxBlankIcon), + checkedIcon: React.createElement(DsCheckboxCheckedIcon), + indeterminateIcon: React.createElement(DsCheckboxIndeterminateIcon), + }, + styleOverrides: { + root: ({ ownerState, theme }) => { + const base = { + "&:hover, &.Mui-focusVisible": { backgroundColor: "transparent" }, + } as const; + + // ✅ Disabled wins over everything + if (ownerState.disabled) { + return { + ...base, + + // Force disabled look regardless of colour/default/anything + color: "var(--ds-fg-disabled)", + + // Ensure our DS icons render as outlined when disabled + "--ds-checkbox-box-fill": "none", + "--ds-checkbox-box-stroke": "var(--ds-fg-disabled)", + "--ds-checkbox-box-strokeWidth": "2", + + // Disabled glyph colour (tick/bar) + "--ds-checkbox-glyph": "var(--ds-fg-disabled)", + } as any; + } + + const raw = (ownerState.color ?? "default") as + | "default" + | "primary" + | "secondary" + | "error" + | "warning" + | "info" + | "success"; + + const isDefault = raw === "default"; + const colour = raw as Exclude<typeof raw, "default">; + + const varsPalette = !isDefault + ? (theme as any).vars?.palette?.[colour] + : null; + const fallbackPalette = !isDefault + ? (theme.palette as any)[colour] + : null; + + const selectedMain = isDefault + ? "var(--ds-olive-9)" // if someone sets color="default", selected remains neutral + : (varsPalette?.main ?? fallbackPalette?.main); + + const selectedMainChannel = isDefault + ? null + : (varsPalette?.mainChannel ?? fallbackPalette?.mainChannel); + + // Unchecked (enabled) should always look "default" + const uncheckedOutline = "var(--ds-olive-9)"; // or var(--ds-gray-9) + + return { + ...base, + + // ✅ Unchecked: neutral outline, regardless of intent colour + "&:not(.Mui-checked):not(.MuiCheckbox-indeterminate)": { + color: uncheckedOutline, + + // If DS icon variables are ever used pre-fill, keep it outlined + "--ds-checkbox-box-fill": "none", + "--ds-checkbox-box-stroke": uncheckedOutline, + "--ds-checkbox-box-strokeWidth": "2", + }, + + // ✅ Checked: solid fill in intent colour + white tick + "&.Mui-checked": { + color: selectedMain, + "--ds-checkbox-box-fill": "currentColor", + "--ds-checkbox-box-stroke": "none", + "--ds-checkbox-box-strokeWidth": "0", + "--ds-checkbox-glyph": "var(--ds-white)", + }, + + // ✅ Indeterminate: “outlined button feel” in intent colour + "&.MuiCheckbox-indeterminate": { + color: selectedMain, + "--ds-checkbox-box-fill": "none", + "--ds-checkbox-box-stroke": "currentColor", + "--ds-checkbox-box-strokeWidth": "2", + "--ds-checkbox-glyph": "currentColor", + }, + + // Optional: hover tint for selected states only + ...(selectedMainChannel && { + "&.Mui-checked:hover, &.MuiCheckbox-indeterminate:hover": { + backgroundColor: `rgba(${selectedMainChannel} / ${theme.palette.action.hoverOpacity})`, + }, + }), + }; + }, + }, + }, + }, + }); + + return createTheme(DiamondDSThemeOptions); +}; +export const DiamondDSTheme = createMuiTheme("light"); +export const DiamondDSThemeDark = createMuiTheme("dark"); diff --git a/src/themes/ThemeProvider.tsx b/src/themes/ThemeProvider.tsx index d4328d3..fdcf100 100644 --- a/src/themes/ThemeProvider.tsx +++ b/src/themes/ThemeProvider.tsx @@ -1,26 +1,41 @@ -import { ThemeProvider as Mui_ThemeProvider } from "@mui/material/styles"; +import React, { useLayoutEffect, useMemo } from "react"; import { CssBaseline } from "@mui/material"; -import { GenericTheme } from "./GenericTheme"; -import { ThemeProviderProps as Mui_ThemeProviderProps } from "@mui/material/styles/ThemeProvider"; +import { ThemeProvider as MuiThemeProvider } from "@mui/material/styles"; +import { ThemeProviderProps as MuiThemeProviderProps } from "@mui/material/styles/ThemeProvider"; +import { createMuiTheme } from "./DiamondDSTheme"; +import type { DSMode } from "./DiamondDSTheme"; -interface ThemeProviderProps extends Partial<Mui_ThemeProviderProps> { +interface ThemeProviderProps extends Partial<MuiThemeProviderProps> { baseline?: boolean; + mode: DSMode; // controlled (source of truth) } -const ThemeProvider = function ({ +export function ThemeProvider({ children, - theme = GenericTheme, baseline = true, defaultMode = "system", + mode, ...props }: ThemeProviderProps) { + useLayoutEffect(() => { + const root = document.documentElement; + + // single source of truth for variables + root.setAttribute("data-mode", mode); + + // optional: keep classes for convenience, but NOT for variables + root.classList.toggle("dark", mode === "dark"); + root.classList.toggle("light", mode === "light"); + + // help UA styles / scrollbars + root.style.colorScheme = mode; + }, [mode]); + + const theme = useMemo(() => createMuiTheme(mode), [mode]); return ( - <Mui_ThemeProvider theme={theme} defaultMode={defaultMode} {...props}> + <MuiThemeProvider theme={theme} defaultMode={defaultMode} {...props}> {baseline && <CssBaseline />} {children} - </Mui_ThemeProvider> + </MuiThemeProvider> ); -}; - -export { ThemeProvider }; -export type { ThemeProviderProps }; +} diff --git a/src/themes/icons/CheckboxIcons.tsx b/src/themes/icons/CheckboxIcons.tsx new file mode 100644 index 0000000..2eb3412 --- /dev/null +++ b/src/themes/icons/CheckboxIcons.tsx @@ -0,0 +1,45 @@ +import * as React from "react"; +import SvgIcon, { SvgIconProps } from "@mui/material/SvgIcon"; + +const BoxPath = (props: React.SVGProps<SVGPathElement>) => ( + <path + d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2z" + fill="var(--ds-checkbox-box-fill, none)" + stroke="var(--ds-checkbox-box-stroke, currentColor)" + strokeWidth="var(--ds-checkbox-box-strokeWidth, 2)" + strokeLinejoin="round" + {...props} + /> +); + +/** Unchecked (outline only) */ +export function DsCheckboxBlankIcon(props: SvgIconProps) { + return ( + <SvgIcon {...props} viewBox="0 0 24 24"> + <BoxPath /> + </SvgIcon> + ); +} + +/** Checked (fill + tick) */ +export function DsCheckboxCheckedIcon(props: SvgIconProps) { + return ( + <SvgIcon {...props} viewBox="0 0 24 24"> + <BoxPath /> + <path + d="M10 14.17l-3.59-3.58L5 12l5 5 9-9-1.41-1.41z" + fill="var(--ds-checkbox-glyph, var(--ds-white))" + /> + </SvgIcon> + ); +} + +/** Indeterminate (outlined feel by default via vars, bar uses glyph var) */ +export function DsCheckboxIndeterminateIcon(props: SvgIconProps) { + return ( + <SvgIcon {...props} viewBox="0 0 24 24"> + <BoxPath /> + <path d="M7 11h10v2H7z" fill="var(--ds-checkbox-glyph, currentColor)" /> + </SvgIcon> + ); +} diff --git a/src/themes/icons/index.ts b/src/themes/icons/index.ts new file mode 100644 index 0000000..ab573c6 --- /dev/null +++ b/src/themes/icons/index.ts @@ -0,0 +1 @@ +export * from "./CheckboxIcons"; From ff3c783d845653b8b8b457e96d3cc51769c51d84 Mon Sep 17 00:00:00 2001 From: Zohar Manor-Abel <zohar.manor-abel@diamond.ac.uk> Date: Tue, 27 Jan 2026 10:27:28 +0000 Subject: [PATCH 06/10] Add Diamond Theme and merge filed (with Victoria) --- .gitignore | 6 +- .storybook/preview.tsx | 72 +- .storybook/storybook.css | 59 ++ package.json | 3 + pnpm-lock.yaml | 25 + src/index.ts | 1 + .../{Introduction.mdx => Installation.mdx} | 8 +- src/storybook/about.mdx | 119 +++ src/storybook/accessibility/00-overview.mdx | 99 ++ .../accessibility/01-colour-contrast.mdx | 400 ++++++++ .../02-cognitive-and-learning.mdx | 151 +++ src/storybook/foundation/colours.mdx | 510 ++++++++++ src/storybook/foundation/typography.mdx | 77 ++ .../diamondDS/diamond-colors-primitives.css | 890 ++++++++++++++++++ .../diamondDS/diamond-mui-palette-tokens.css | 243 +++++ src/themes/DiamondDSTheme.ts | 451 +++++++++ src/themes/ThemeProvider.tsx | 39 +- src/themes/icons/CheckboxIcons.tsx | 45 + src/themes/icons/index.ts | 1 + 19 files changed, 3163 insertions(+), 36 deletions(-) create mode 100644 .storybook/storybook.css rename src/storybook/{Introduction.mdx => Installation.mdx} (98%) create mode 100644 src/storybook/about.mdx create mode 100644 src/storybook/accessibility/00-overview.mdx create mode 100644 src/storybook/accessibility/01-colour-contrast.mdx create mode 100644 src/storybook/accessibility/02-cognitive-and-learning.mdx create mode 100644 src/storybook/foundation/colours.mdx create mode 100644 src/storybook/foundation/typography.mdx create mode 100644 src/styles/diamondDS/diamond-colors-primitives.css create mode 100644 src/styles/diamondDS/diamond-mui-palette-tokens.css create mode 100644 src/themes/DiamondDSTheme.ts create mode 100644 src/themes/icons/CheckboxIcons.tsx create mode 100644 src/themes/icons/index.ts diff --git a/.gitignore b/.gitignore index 9564298..dbaee90 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,8 @@ /docs .pnpm-store/ -tsconfig.tsbuildinfo \ No newline at end of file +tsconfig.tsbuildinfo + +# System files +.DS_Store +**/.DS_Store diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 750a7eb..28bed05 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -1,15 +1,55 @@ -import React from "react"; +import React, { useLayoutEffect } from "react"; import { CssBaseline } from "@mui/material"; import type { Preview } from "@storybook/react"; import "@fontsource-variable/inter"; +import "./storybook.css"; /* Storybook CSS override */ import { ThemeProvider } from "../src"; -import { GenericTheme, DiamondTheme } from "../src"; - +import { + GenericTheme, + DiamondTheme, + DiamondDSTheme, + DiamondDSThemeDark, +} from "../src"; import { Context, ThemeSwapper, TextLight, TextDark } from "./ThemeSwapper"; const TextThemeBase = "Theme: Generic"; const TextThemeDiamond = "Theme: Diamond"; +const TextThemeDiamondDS = "Theme: DiamondDS"; + +function resolveTheme(selectedTheme: string, mode: "light" | "dark") { + switch (selectedTheme) { + case TextThemeBase: + return GenericTheme; + case TextThemeDiamondDS: + return mode === "dark" ? DiamondDSThemeDark : DiamondDSTheme; + case TextThemeDiamond: + default: + return DiamondTheme; + } +} + +function ApplyModeToPreviewDoc({ + mode, + doc, +}: { + mode: "light" | "dark"; + doc: Document; +}) { + useLayoutEffect(() => { + const root = doc.documentElement; // <html> + root.setAttribute("data-mode", mode); + + // Optional: keep class too if your CSS supports it + root.classList.toggle("dark", mode === "dark"); + root.classList.toggle("light", mode === "light"); + + root.style.colorScheme = mode; + }, [mode, doc]); + + return null; +} + export const decorators = [ (StoriesWithPadding: React.FC) => ( <div style={{ padding: "2em" }}> @@ -24,12 +64,16 @@ export const decorators = [ (StoriesWithThemeProvider: React.FC, context: Context) => { const selectedTheme = context.globals.theme || TextThemeBase; const selectedThemeMode = context.globals.themeMode || TextLight; + const mode = selectedThemeMode === TextLight ? "light" : "dark"; + // ensure we target the preview iframe document + const doc: Document = context?.canvasElement?.ownerDocument ?? document; return ( <ThemeProvider - theme={selectedTheme === TextThemeBase ? GenericTheme : DiamondTheme} - defaultMode={selectedThemeMode === TextLight ? "light" : "dark"} + theme={resolveTheme(selectedTheme, mode)} + defaultMode={mode} > + <ApplyModeToPreviewDoc mode={mode} doc={doc} /> <CssBaseline /> <StoriesWithThemeProvider /> </ThemeProvider> @@ -44,7 +88,7 @@ const preview: Preview = { toolbar: { title: "Theme", icon: "cog", - items: [TextThemeBase, TextThemeDiamond], + items: [TextThemeBase, TextThemeDiamond, TextThemeDiamondDS], dynamicTitle: true, }, }, @@ -59,8 +103,8 @@ const preview: Preview = { }, }, initialGlobals: { - theme: "Theme: Diamond", - themeMode: "Mode: Light", + theme: TextThemeDiamondDS, + themeMode: TextLight, }, parameters: { controls: { @@ -72,18 +116,6 @@ const preview: Preview = { }, backgrounds: { disable: true }, layout: "fullscreen", - options: { - storySort: { - order: [ - "Introduction", - "Components", - "Theme", - "Theme/Logos", - "Theme/Colours", - "Helpers", - ], - }, - }, }, argTypes: { linkComponent: { control: false }, diff --git a/.storybook/storybook.css b/.storybook/storybook.css new file mode 100644 index 0000000..f409b9f --- /dev/null +++ b/.storybook/storybook.css @@ -0,0 +1,59 @@ +:root { + --ds-font-body: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, + 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; + + --ds-font-heading: 'Outfit', system-ui, -apple-system, BlinkMacSystemFont, + 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; + + --ds-font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, + Consolas, 'Liberation Mono', 'Courier New', monospace; + } + + /* Docs root */ + .sbdocs, .sbdocs p, .sbdocs li,.sb-unstyled, .sb-unstyled ul, .sb-unstyled li { + font-family: var(--ds-font-body); + font-size: 16px !important; + line-height: 1.6; + } + + /* Lists */ + .sbdocs li { + font-size: 16px !important; + } + + /* Headings use Outfit or Inter */ + + .sbdocs h1 { + font-family: var(--ds-font-heading); + } + + .sbdocs h3, + .sbdocs h4, + .sbdocs h5, + .sbdocs h6 { + font-family: var(--ds-font-body); + } + + /* Code uses IBM Plex Mono */ + .sbdocs code, + .sbdocs pre, + .sbdocs kbd, + .sbdocs samp, + .token { + font-family: var(--ds-font-mono); + font-size: 1em; + f + } + + /* Neutralise Storybook Docs inline preview background wrapper */ + .sbdocs-preview div[style*="background-color"], #storybook-root div[style*="background-color"] { + background-color: transparent !important; + } + + .light .sbdocs-preview div[style*="background-color"] { + background-color: #f6f6f6 !important; + } + + .dark .sbdocs-preview div[style*="background-color"]{ + background-color: #212121 !important; + } diff --git a/package.json b/package.json index dddfdeb..901c535 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,9 @@ "@babel/preset-typescript": "^7.26.0", "@chromatic-com/storybook": "^3.2.2", "@eslint/eslintrc": "^3.2.0", + "@fontsource/ibm-plex-mono": "^5.2.7", + "@fontsource/inter": "^5.2.8", + "@fontsource/outfit": "^5.2.8", "@rollup/plugin-commonjs": "^28.0.1", "@rollup/plugin-image": "^3.0.3", "@rollup/plugin-json": "^6.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f72c5ac..f5bfffd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -63,6 +63,15 @@ importers: '@eslint/eslintrc': specifier: ^3.2.0 version: 3.2.0 + '@fontsource/ibm-plex-mono': + specifier: ^5.2.7 + version: 5.2.7 + '@fontsource/inter': + specifier: ^5.2.8 + version: 5.2.8 + '@fontsource/outfit': + specifier: ^5.2.8 + version: 5.2.8 '@rollup/plugin-commonjs': specifier: ^28.0.1 version: 28.0.2(rollup@4.30.0) @@ -1084,6 +1093,15 @@ packages: '@fontsource-variable/inter@5.2.8': resolution: {integrity: sha512-kOfP2D+ykbcX/P3IFnokOhVRNoTozo5/JxhAIVYLpea/UBmCQ/YWPBfWIDuBImXX/15KH+eKh4xpEUyS2sQQGQ==} + '@fontsource/ibm-plex-mono@5.2.7': + resolution: {integrity: sha512-MKAb8qV+CaiMQn2B0dIi1OV3565NYzp3WN5b4oT6LTkk+F0jR6j0ZN+5BKJiIhffDC3rtBULsYZE65+0018z9w==} + + '@fontsource/inter@5.2.8': + resolution: {integrity: sha512-P6r5WnJoKiNVV+zvW2xM13gNdFhAEpQ9dQJHt3naLvfg+LkF2ldgSLiF4T41lf1SQCM9QmkqPTn4TH568IRagg==} + + '@fontsource/outfit@5.2.8': + resolution: {integrity: sha512-rXC6g0MqD7cOBjht0bMqc43qM6lRqDLML9KXsmg9uykz0wLQhy8Z/ajrMG6iyoT3NJR+MYgU+OEHp7uHoTb+Yw==} + '@gerrit0/mini-shiki@3.7.0': resolution: {integrity: sha512-7iY9wg4FWXmeoFJpUL2u+tsmh0d0jcEJHAIzVxl3TG4KL493JNnisdLAILZ77zcD+z3J0keEXZ+lFzUgzQzPDg==} @@ -4636,6 +4654,7 @@ packages: whatwg-encoding@2.0.0: resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} engines: {node: '>=12'} + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation whatwg-mimetype@3.0.0: resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} @@ -5764,6 +5783,12 @@ snapshots: '@fontsource-variable/inter@5.2.8': {} + '@fontsource/ibm-plex-mono@5.2.7': {} + + '@fontsource/inter@5.2.8': {} + + '@fontsource/outfit@5.2.8': {} + '@gerrit0/mini-shiki@3.7.0': dependencies: '@shikijs/engine-oniguruma': 3.7.0 diff --git a/src/index.ts b/src/index.ts index 8277145..4c2c45a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -22,6 +22,7 @@ export * from "./components/helpers/jsonforms"; // themes export * from "./themes/BaseTheme"; export * from "./themes/DiamondTheme"; +export * from "./themes/DiamondDSTheme"; export * from "./themes/GenericTheme"; export * from "./themes/ThemeProvider"; export * from "./themes/ThemeManager"; diff --git a/src/storybook/Introduction.mdx b/src/storybook/Installation.mdx similarity index 98% rename from src/storybook/Introduction.mdx rename to src/storybook/Installation.mdx index 7113771..770c475 100644 --- a/src/storybook/Introduction.mdx +++ b/src/storybook/Installation.mdx @@ -1,7 +1,7 @@ -import packageJson from "../../package.json" +import packageJson from "../../package.json"; import { Meta } from "@storybook/blocks"; -<Meta title="Introduction" /> +<Meta title="Installation" /> <div className="sb-container"> <div className='sb-section-title'> @@ -14,6 +14,7 @@ import { Meta } from "@storybook/blocks"; Check out the list of components on the left. To use them, follow the instructions below. </div> + </div> <div className="sb-container"> @@ -111,8 +112,8 @@ import { Meta } from "@storybook/blocks"; } ``` </div> -</div> +</div> <div className="sb-container"> <div className='sb-section-title'> @@ -151,4 +152,5 @@ import { Meta } from "@storybook/blocks"; on GitHub. </div> + </div> diff --git a/src/storybook/about.mdx b/src/storybook/about.mdx new file mode 100644 index 0000000..c02e3b4 --- /dev/null +++ b/src/storybook/about.mdx @@ -0,0 +1,119 @@ +import { Meta } from "@storybook/blocks"; + +<Meta title="About" /> + +<div> + <h1>Scientific design system for Diamond</h1> + <p><strong>Version: Scientific React UI - v0.3.1-alpha.3</strong></p> + +{" "} +<p> + Diamond II brings major upgrades to our scientific capabilities, and with that + comes a growing ecosystem of tools used across beamlines, data acquisition, + analysis, and scientific support. +</p> + +{" "} +<p> + This design system gives us a shared foundation of components, patterns, and + visual rules so that every tool at Diamond feels coherent, predictable, and + efficient, in service of better science and smoother operations across the + facility. +</p> + +{" "} +<h2>Why we need a design system</h2> +<ul> + <li> + <strong>Modernise for Diamond II</strong>: redesign interfaces with clarity, + safety, and efficiency at the core. + </li> + <li> + <strong>Unify legacy systems</strong>: reduce inconsistent patterns, + behaviours, and visual languages across tools. + </li> + <li> + <strong>Reduce cognitive load</strong>: scientists and engineers move + between multiple systems; familiarity helps. + </li> + <li> + <strong>Accelerate delivery</strong>: shared components and patterns reduce + repeated work. + </li> + <li> + <strong>Future-proof</strong>: new tools start coherent and stay coherent. + </li> +</ul> + +{" "} +<h2>What the design system includes</h2> +<h3>Design assets</h3> +<ul> + <li> + <strong>Foundations</strong>: colour, typography, spacing, grid, interaction + states + </li> + <li> + <strong>Components</strong>: buttons, inputs, tables, tabs + </li> + <li> + <strong>Patterns</strong>: panels, configuration, monitoring, data browsing + </li> + <li> + <strong>Templates</strong>: pages, dashboards, details views + </li> +</ul> + +{" "} +<h3>Plus</h3> +<ul> + <li>Accessibility guidance</li> + <li>Processes and documentation</li> + <li>UX strategy and interaction principles</li> +</ul> + +{" "} +<h2>Where truth lives</h2> +<ul> + <li> + <strong>Figma</strong> is the design source of truth. + </li> + <li> + <strong>Storybook</strong> is the code source of truth. + </li> + <li> + We build on <strong>Material UI (MUI)</strong> in React, customised for + Diamond workflows. + </li> +</ul> + +{" "} +<h2>What’s different about scientific controls</h2> +<ul> + <li> + <strong>Time is scarce</strong> on beamlines; interruptions are costly. + </li> + <li> + <strong>Experiments are stateful</strong>; the UI must make state and + progress obvious. + </li> + <li> + <strong>Users may be visiting</strong> and working under pressure. + </li> + <li> + <strong>High-density data</strong> is normal: tables, logs, dashboards. + </li> + <li> + <strong>Safety-critical actions</strong> need clear signifiers, + confirmation, and recovery paths. + </li> +</ul> + + <h2>How to use this documentation</h2> + <ol> + <li>Start with Foundations to understand the rules.</li> + <li>Use Components for building blocks.</li> + <li>Use Patterns for repeatable workflows.</li> + <li>Treat docs as the shared contract: what we build, how it behaves, and why.</li> + </ol> +</div> diff --git a/src/storybook/accessibility/00-overview.mdx b/src/storybook/accessibility/00-overview.mdx new file mode 100644 index 0000000..7af1d45 --- /dev/null +++ b/src/storybook/accessibility/00-overview.mdx @@ -0,0 +1,99 @@ +import { Meta } from "@storybook/blocks"; + +<Meta title="Accessibility/Overview" /> + +<div> + <h1>Accessibility</h1> + +{" "} +<p> + Accessibility in the Diamond design system is not a checklist or a separate + mode. It’s a baseline for quality, clarity, and usability in complex + scientific tools. +</p> + +{" "} +<p> + Our goal is to make interfaces that are understandable, predictable, and + usable across a wide range of abilities, environments, and levels of fatigue. +</p> + +{" "} +<h2>Core principles</h2> +<ul> + <li> + <strong>Clarity over cleverness</strong>: interfaces should explain + themselves. + </li> + <li> + <strong>Predictable behaviour</strong>: similar things behave in similar + ways. + </li> + <li> + <strong>Multiple ways to perceive information</strong>: never rely on one + signal alone. + </li> + <li> + <strong>Low cognitive effort by default</strong>: minimise mental overhead. + </li> +</ul> + +{" "} +<h2>Do</h2> + +{" "} +<h3>Interactive elements</h3> +<ul> + <li>Ensure every interactive control has an accessible name.</li> + <li>Provide this via a visible label, `aria-label`, or `aria-labelledby`.</li> + <li>Make keyboard focus clearly visible at all times.</li> + <li> + Ensure disabled states are clearly distinguishable from enabled and default. + </li> +</ul> + +{" "} +<h3>Forms and inputs</h3> +<ul> + <li>Always associate inputs with labels (even if visually hidden).</li> + <li>Make error messages clear, specific, and actionable.</li> + <li>Associate errors programmatically with the relevant field.</li> +</ul> + +{" "} +<h3>Content and layout</h3> +<ul> + <li>Do not rely on colour alone to convey meaning.</li> + <li>Support icons with text or accessible names.</li> + <li>Use a logical, predictable reading order.</li> +</ul> + +{" "} +<h2>Don’t</h2> +<ul> + <li>Don’t use placeholder text as a replacement for labels.</li> + <li>Don’t hide important information in faint or decorative text.</li> + <li>Don’t introduce unexpected interaction patterns.</li> + <li>Don’t create dense, unbroken blocks of content.</li> +</ul> + +{" "} +<h2>Storybook guidance</h2> +<ul> + <li> + Simple component stories may be visually minimal, but they must still expose + an accessible name, or be explicitly documented as intentionally incomplete. + </li> + <li> + Accessibility warnings in Storybook are signals, not noise. Either resolve + them or document why they exist. + </li> +</ul> + + <h2>Quick sense check</h2> + <ul> + <li>Can this be used with a keyboard only?</li> + <li>Is its purpose clear without colour?</li> + <li>Would it still make sense when someone is tired or distracted?</li> + </ul> +</div> diff --git a/src/storybook/accessibility/01-colour-contrast.mdx b/src/storybook/accessibility/01-colour-contrast.mdx new file mode 100644 index 0000000..204f208 --- /dev/null +++ b/src/storybook/accessibility/01-colour-contrast.mdx @@ -0,0 +1,400 @@ +import { Meta } from "@storybook/blocks"; + +<Meta title="Accessibility/Colour contrast" /> + +<div> + <h1>Colour contrast</h1> + +<p> + Colour contrast affects readability, accuracy, and fatigue. In data-heavy + scientific tools, poor contrast slows users down and increases errors. +</p> + +<p> + We use both WCAG contrast ratios and APCA to balance compliance with + real-world readability. +</p> + +<h2>WCAG contrast</h2> + +<p> + WCAG 2.x contrast ratios provide a clear, widely accepted compliance baseline. +</p> + +<ul> + <li>Used to define minimum acceptable contrast.</li> + <li>Acts as a hard “do not go below” threshold.</li> + <li>Especially important for small text and critical UI.</li> +</ul> + +<h2>APCA contrast</h2> + +<p> + APCA (Advanced Perceptual Contrast Algorithm) models human perception more + closely. It accounts for font size, weight, and polarity (light-on-dark vs + dark-on-light). +</p> + +<ul> + <li>Used to tune readability in light and dark themes.</li> + <li>Helps avoid over-contrast that causes eye strain.</li> + <li>Works better for large text and dense information.</li> +</ul> + +<h2>How we use them together</h2> + +<p> + All text should meet WCAG minimums. APCA is then used to refine token values + for comfort and hierarchy. +</p> + + <div> + <h2>Colour-specific considerations (green, orange, and red)</h2> + + <p> + Some hues behave poorly for perceived contrast, even when WCAG 2 contrast ratios pass. + </p> + + <p> + Green, orange, and red are common examples because perceived contrast is affected by luminance, + surrounding colours, polarity (light-on-dark vs dark-on-light), and colour vision differences. + </p> + + <p> + A practical issue we see in real interfaces: WCAG 2 ratios can sometimes indicate that black + text on a saturated green, orange, or red background is “high contrast”, but in practice it + can feel low-contrast, vibrating, or tiring to read — especially for small text, thinner + fonts, or dense data. This gap between numeric ratios and human perception is one of the + problems APCA is designed to address. + </p> + + <ul> + <li> + <strong>Green</strong>: may appear muddy or unstable with dark text, and can be difficult + for users with common colour vision differences. + </li> + <li> + <strong>Orange</strong>: often looks washed out on light backgrounds or overly bright on + dark backgrounds, reducing legibility. + </li> + <li> + <strong>Red</strong>: can appear low-contrast or “vibrating” with dark text, and is + particularly problematic for error or alert states if not handled carefully. + </li> + </ul> + + <p> + When using these colours for status, emphasis, or meaning: + </p> + + <ul> + <li>Never rely on colour alone — pair with text, icons, or labels.</li> + <li>Test in both light and dark modes, at realistic sizes and weights.</li> + <li>Use APCA to assess perceived readability, not just WCAG 2 ratios.</li> + </ul> + + <p> + The examples below illustrate combinations that may pass WCAG 2 but still feel hard to read + in practice. + </p> + + <p><strong>WCAG 2 vs APCA: why “passes” can still look wrong</strong></p> + <p> + WCAG 2 contrast ratio is a useful baseline, but it can recommend text colours that feel + low-contrast in practice (especially on saturated greens/oranges/reds). APCA is designed + to better reflect perceived contrast and readability. + </p> + +{/* START EXAMPLE */} + +<style>{` /* Scoped demo styles so Storybook/theme doesn't interfere */ + .ds-a11y-demo, .ds-a11y-demo * { + box-sizing: border-box; + } + /* Reset common typography overrides that can change perceived contrast */ + .ds-a11y-demo p, + .ds-a11y-demo span, + .ds-a11y-demo strong, + .ds-a11y-demo li, + .ds-a11y-demo h3 { + margin: 0; + color: inherit; + letter-spacing: normal; + text-transform: none; + } + .ds-a11y-demo p { margin-bottom: 8px; } + .ds-a11y-demo ul { margin: 0; padding-left: 18px; } + .ds-a11y-grid { + display: grid; + gap: 16px; + max-width: 920px; + margin-top: 12px; + } + .ds-a11y-panels { + display: grid; + gap: 16px; + grid-template-columns: 1fr 1fr; + } + .ds-a11y-panel { + border-radius: 10px; + padding: 14px; + border: 1px solid rgba(0,0,0,0.12); + } + .ds-a11y-panel--light { + background: #ffffff; + color: #111111; + } + .ds-a11y-panel--dark { + background: #0b0f14; /* "inverse" surface */ + color: #f3f5f7; + border: 1px solid rgba(255,255,255,0.14); + } + .ds-a11y-row { + display: grid; + gap: 8px; + margin-top: 10px; + } + .ds-a11y-rowTitle { + font-weight: 700; + margin-bottom: 2px; + } + .ds-chipRow { + display: grid; + gap: 10px; + } + .ds-chipLabel { + font-size: 13px; + opacity: 0.9; + } + .ds-chip { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 10px 12px; + border-radius: 8px; + line-height: 1.2; + border: 1px solid rgba(0,0,0,0.12); + width: fit-content; + max-width: 100%; + } + .ds-a11y-panel--dark .ds-chip { + border: 1px solid rgba(255,255,255,0.14); + } + .ds-chipText { + font-size: 14px; + font-weight: 650; + } + /* Use CSS vars + !important so theme styles can’t override demo colours */ + .ds-chip[data-bg] { background: var(--bg) !important; } + .ds-chip[data-fg] { color: var(--fg) !important; } + .ds-note { + border-radius: 10px; + padding: 12px 14px; + border: 1px solid rgba(0,0,0,0.10); + } + .ds-a11y-panel--dark + .ds-note, + .ds-a11y-panel--dark .ds-note { + border: 1px solid rgba(255,255,255,0.14); + } + `}</style> + +<div className="ds-a11y-demo ds-a11y-grid"> + + <div className="ds-a11y-panels"> + {/* Light */} + <div className="ds-a11y-panel ds-a11y-panel--light"> + <p className="ds-a11y-rowTitle">Light surface</p> + + <div className="ds-a11y-row"> + <p><strong>Green</strong> bg `--ds-green-9` `#4CA65A`</p> + <div className="ds-chipRow"> + <div> + <p className="ds-chipLabel"><strong>WCAG 2 candidate</strong></p> + <div + className="ds-chip" + data-bg + data-fg + style={{ ['--bg']: '#4CA65A', ['--fg']: '#000000' }} + > + <span className="ds-chipText">Experiment complete · 12 files processed</span> + </div> + </div> + + <div> + <p className="ds-chipLabel"><strong>APCA candidate</strong> ✅</p> + <div + className="ds-chip" + data-bg + data-fg + style={{ ['--bg']: '#4CA65A', ['--fg']: '#FFFFFF' }} + > + <span className="ds-chipText">Experiment complete · 12 files processed</span> + </div> + </div> + </div> + </div> + + <div className="ds-a11y-row"> + <p><strong>Orange</strong> bg `--ds-orange-9` `#FF780A`</p> + <div className="ds-chipRow"> + <div> + <p className="ds-chipLabel"><strong>WCAG 2 candidate</strong></p> + <div className="ds-chip" data-bg data-fg style={{ ['--bg']: '#FF780A', ['--fg']: '#000000' }}> + <span className="ds-chipText">Beamline temperature near limit</span> + </div> + </div> + + <div> + <p className="ds-chipLabel"><strong>APCA candidate</strong> ✅</p> + <div className="ds-chip" data-bg data-fg style={{ ['--bg']: '#FF780A', ['--fg']: '#FFFFFF' }}> + <span className="ds-chipText">Beamline temperature near limit</span> + </div> + </div> + </div> + </div> + + <div className="ds-a11y-row"> + <p><strong>Red</strong> bg `--ds-red-9` `#E54D2E`</p> + <div className="ds-chipRow"> + <div> + <p className="ds-chipLabel"><strong>WCAG 2 candidate</strong></p> + <div className="ds-chip" data-bg data-fg style={{ ['--bg']: '#E54D2E', ['--fg']: '#000000' }}> + <span className="ds-chipText">Connection failed · retry required</span> + </div> + </div> + + <div> + <p className="ds-chipLabel"><strong>APCA candidate</strong> ✅</p> + <div className="ds-chip" data-bg data-fg style={{ ['--bg']: '#E54D2E', ['--fg']: '#FFFFFF' }}> + <span className="ds-chipText">Connection failed · retry required</span> + </div> + </div> + </div> + </div> + </div> + + {/* Dark / inverse */} + <div className="ds-a11y-panel ds-a11y-panel--dark"> + <p className="ds-a11y-rowTitle">Dark (inverse) surface</p> + + <div className="ds-a11y-row"> + <p><strong>Green</strong> bg `--ds-green-9` `#30A46C`</p> + <div className="ds-chipRow"> + <div> + <p className="ds-chipLabel"><strong>WCAG 2 candidate</strong></p> + <div className="ds-chip" data-bg data-fg style={{ ['--bg']: '#30A46C', ['--fg']: '#FFFFFF' }}> + <span className="ds-chipText">Experiment complete · 12 files processed</span> + </div> + </div> + + <div> + <p className="ds-chipLabel"><strong>APCA candidate</strong> ✅</p> + <div className="ds-chip" data-bg data-fg style={{ ['--bg']: '#30A46C', ['--fg']: '#000000' }}> + <span className="ds-chipText">Experiment complete · 12 files processed</span> + </div> + </div> + </div> + </div> + + <div className="ds-a11y-row"> + <p><strong>Orange</strong> bg `--ds-orange-9` `#F76B15`</p> + <div className="ds-chipRow"> + <div> + <p className="ds-chipLabel"><strong>WCAG 2 candidate</strong></p> + <div className="ds-chip" data-bg data-fg style={{ ['--bg']: '#F76B15', ['--fg']: '#000000' }}> + <span className="ds-chipText">Beamline temperature near limit</span> + </div> + </div> + + <div> + <p className="ds-chipLabel"><strong>APCA candidate</strong> ✅</p> + <div className="ds-chip" data-bg data-fg style={{ ['--bg']: '#F76B15', ['--fg']: '#FFFFFF' }}> + <span className="ds-chipText">Beamline temperature near limit</span> + </div> + </div> + </div> + </div> + + <div className="ds-a11y-row"> + <p><strong>Red</strong> bg `--ds-red-9` `#E54D2E`</p> + <div className="ds-chipRow"> + <div> + <p className="ds-chipLabel"><strong>WCAG 2 candidate</strong></p> + <div className="ds-chip" data-bg data-fg style={{ ['--bg']: '#E54D2E', ['--fg']: '#000000' }}> + <span className="ds-chipText">Connection failed · retry required</span> + </div> + </div> + + <div> + <p className="ds-chipLabel"><strong>APCA candidate</strong> ✅</p> + <div className="ds-chip" data-bg data-fg style={{ ['--bg']: '#E54D2E', ['--fg']: '#FFFFFF' }}> + <span className="ds-chipText">Connection failed · retry required</span> + </div> + </div> + </div> + </div> + </div> + </div> + </div> + + <div className="ds-note"> + <p style={{ marginBottom: 6 }}><strong>How to use this</strong></p> + <ul> + <li>Use WCAG 2 as the baseline check, especially for small text.</li> + <li>Use APCA to validate perceived readability and comfort (particularly for saturated status colours).</li> + <li>Always pair colour with icons/text — never rely on colour alone for meaning.</li> + </ul> + </div> + </div> + +{/* END EXAMPLE */} + +<h2>Practical guidance</h2> +<ul> + <li> + <strong>Body text</strong>: prioritise APCA readability while meeting WCAG. + </li> + <li> + <strong>UI chrome</strong>: prioritise WCAG clarity and consistency. + </li> + <li> + <strong>Subtle text</strong>: only for non-essential information. + </li> + <li> + <strong>Disabled states</strong>: visually distinct but still readable where + meaning matters. + </li> +</ul> + +<h2>Common pitfalls</h2> +<ul> + <li>Reducing contrast to “de-emphasise” text that still carries meaning.</li> + <li>Relying on colour alone for status or validation.</li> + <li>Forgetting that contrast behaves differently in dark mode.</li> +</ul> + +<h2>When WCAG and APCA disagree</h2> +<ul> + <li>If WCAG fails, the colour must change.</li> + <li> + If WCAG passes but APCA indicates poor readability, adjust for comfort. + </li> + <li>For critical UI, readability always wins over subtlety.</li> +</ul> + +<h2>Future: WCAG 3 and APCA</h2> + +<p> + APCA is being developed as part of WCAG 3, which is still in progress. While + WCAG 2.x remains the formal standard today, WCAG 3 reflects a shift towards + perceptual models of contrast and readability. +</p> + +<p>Our approach reflects this transition:</p> + +<ul> + <li>WCAG 2.x is treated as the compliance baseline.</li> + <li>APCA is used to improve real-world readability and comfort.</li> + <li>This positions us closer to where accessibility standards are heading.</li> +</ul> +</div> diff --git a/src/storybook/accessibility/02-cognitive-and-learning.mdx b/src/storybook/accessibility/02-cognitive-and-learning.mdx new file mode 100644 index 0000000..91ed4b9 --- /dev/null +++ b/src/storybook/accessibility/02-cognitive-and-learning.mdx @@ -0,0 +1,151 @@ +import { Meta } from "@storybook/blocks"; + +<Meta title="Accessibility/Cognitive and learning" /> + +<div> + <h1>Cognitive and learning accessibility</h1> + +<p> + Accessibility is not only about vision or motor input. People differ in how + they process information, maintain focus, remember things, and recover from + errors. +</p> + +<p> + In complex scientific tools, these differences matter. Our responsibility is + to design systems that are usable, understandable, and forgiving across a wide + range of abilities and conditions. +</p> + +<h2>Experience, usability, and accessibility by design</h2> + +<p> + Improving accessibility is not just about adding new features. It also means + continuously improving the core experience: making it more intuitive, more + inclusive, and easier to use. +</p> + +<p> + Our users include people with different processing capabilities and + disabilities. We should consider these differences when designing interfaces, + interactions, and content — not as edge cases, but as part of normal usage. +</p> + +<h2>User processing capabilities to consider</h2> +<ul> + <li>Reading, skimming, and scanning content</li> + <li>Focus and sustained attention</li> + <li>Different memory types and memorisation strategies</li> +</ul> + +<h2>Types of disabilities and conditions</h2> +<p>Users may experience one or more of the following:</p> +<ul> + <li>Cognitive disabilities</li> + <li>Learning disabilities</li> + <li>Intellectual disability</li> + <li>Vision impairment (including colour blindness)</li> + <li>Deaf or hard of hearing</li> + <li>Physical disabilities</li> + <li>Mental health conditions</li> + <li>Acquired brain injury</li> + <li>Neurodiversity</li> +</ul> + +{" "} + +<p> + With this in mind, usability and accessibility should be treated as + foundational design qualities, not optional enhancements. +</p> + +{" "} + +<h2>Design objectives</h2> + +{" "} + +<p> + The W3C guidance on cognitive and learning disabilities is useful not only for + people with disabilities, but for most users. The objectives below are adapted + from that guidance and reflect how we aim to design Diamond tools. +</p> + +{" "} + +<h3>Help users understand what things are and how to use them</h3> +<ul> + <li>Use icons, symbols, terms, and patterns that are already familiar.</li> + <li> + Avoid inventing new interaction patterns without strong justification. + </li> + <li>Make purpose and behaviour obvious at first glance.</li> +</ul> + +<h3>Help users find what they need</h3> +<ul> + <li>Use clear structure, headings, and visual boundaries.</li> + <li>Keep navigation predictable and consistent.</li> + <li>Use layout and grouping to signal relationships.</li> +</ul> + +<h3>Use clear content</h3> +<ul> + <li>Prefer simple words and short sentences.</li> + <li>Break text into small, readable blocks.</li> + <li>Use clear images and diagrams where they add meaning.</li> +</ul> + +<h3>Help users avoid mistakes</h3> +<ul> + <li>Ask only for information that is genuinely required.</li> + <li>Prevent errors where possible, rather than reacting to them.</li> + <li>When errors occur, make recovery easy and explicit.</li> +</ul> + +<h3>Help users focus</h3> +<ul> + <li>Avoid unnecessary distractions.</li> + <li> + Use headings and structure to help users re-orient if context is lost. + </li> + <li>Provide breadcrumbs or clear navigation paths where appropriate.</li> +</ul> + +<h3>Provide help and support</h3> +<ul> + <li>Make it easy to access human help or support.</li> + <li>Offer multiple ways to understand content (text, visuals, summaries).</li> + <li>Use icons and visual cues to reinforce meaning, not replace it.</li> +</ul> + +<h3>Support adaptation and personalisation</h3> +<ul> + <li>Allow users to adjust preferences when possible.</li> + <li>Design so assistive technologies and extensions can work effectively.</li> + <li>Avoid blocking browser or OS-level accessibility features.</li> +</ul> + +<h3>Test with real users</h3> +<ul> + <li>Involve people with different disabilities in research and testing.</li> + <li>Include them in usability testing and design validation.</li> + <li>Treat their feedback as expert input.</li> +</ul> + +<h2>Applying this in Storybook</h2> +<ul> + <li>Is the component understandable without prior knowledge?</li> + <li>Does it rely on memory or hidden rules?</li> + <li>Is error recovery clear and forgiving?</li> + <li>Would this still make sense at the end of a long day?</li> +</ul> + + <h2>Further reading</h2> + <ul> + <li><a href="https://www.w3.org/TR/coga-usable/" target="_blank" rel="noopener noreferrer">Making Content Usable for People with Cognitive and Learning Disabilities</a></li> + <li><a href="https://www.w3.org/WAI/fundamentals/accessibility-usability-inclusion/" target="_blank" rel="noopener noreferrer">W3C: Accessibility, Usability, and Inclusion</a></li> + <li><a href="https://www.w3.org/TR/coga-usable/" target="_blank" rel="noopener noreferrer">Making Content Usable for People with Cognitive and Learning Disabilities</a></li> + <li><a href="https://uxplanet.org/how-human-memory-works-tips-for-ux-designers-12b14071bdf9" target="_blank" rel="noopener noreferrer">How Human Memory Works: Tips for UX Designers</a></li> + </ul> +</div> diff --git a/src/storybook/foundation/colours.mdx b/src/storybook/foundation/colours.mdx new file mode 100644 index 0000000..0af345f --- /dev/null +++ b/src/storybook/foundation/colours.mdx @@ -0,0 +1,510 @@ +import { Meta } from "@storybook/blocks"; + +<Meta title="Foundation/Colour" /> + +<style>{` + .ds-note { + margin: 12px 0 20px; + padding: 12px 14px; + border: 1px solid var(--ds-gray-6); + background: var(--ds-gray-2); + border-radius: 12px; + } + .ds-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); + gap: 14px; + margin: 14px 0 24px; + } + .ds-swatch { + border: 1px solid var(--ds-gray-6); + border-radius: 14px; + background: var(--ds-gray-2); + overflow: hidden; + } + .ds-swatch__chip { + height: 56px; + background: var(--swatch); + border-bottom: 1px solid var(--ds-gray-6); + } + .ds-swatch__body { + padding: 12px 12px 10px; + } + .ds-swatch__name { + font-weight: 600; + margin: 0 0 6px; + color: var(--ds-gray-12); + } + .ds-swatch__meta { + margin: 0; + padding-left: 16px; + color: var(--ds-gray-11); + font-size: 14px; + line-height: 20px; + } + .ds-swatch__meta li { + margin: 2px 0; + } + .ds-row { + display: flex; + gap: 10px; + flex-wrap: wrap; + margin: 10px 0 0; + } + .ds-pill { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 6px 10px; + border-radius: 999px; + border: 1px solid var(--ds-gray-6); + background: var(--ds-gray-1); + color: var(--ds-gray-12); + font-size: 13px; + line-height: 18px; + } + .ds-dot { + width: 10px; + height: 10px; + border-radius: 999px; + background: var(--dot); + border: 1px solid rgba(0,0,0,0.12); + } + .ds-surface-demo { + border: 1px solid var(--ds-gray-6); + border-radius: 14px; + background: var(--ds-gray-1); + padding: 14px; + margin: 14px 0 24px; + } + .ds-surface-card { + border: 1px solid var(--ds-gray-6); + background: var(--ds-gray-2); + border-radius: 12px; + padding: 12px; + } + .ds-divider { + height: 1px; + background: var(--ds-gray-6); + margin: 12px 0; + } + .ds-text-demo p { + margin: 8px 0; + } + .ds-overlay-demo { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); + gap: 12px; + margin-top: 12px; + } + .ds-overlay-tile { + border: 1px solid var(--ds-gray-6); + border-radius: 12px; + background: var(--ds-gray-2); + overflow: hidden; + } + .ds-overlay-tile__top { + height: 56px; + background: var(--ds-gray-2); + position: relative; + } + .ds-overlay-tile__overlay { + position: absolute; + inset: 0; + background: var(--overlay); + } + .ds-overlay-tile__body { + padding: 10px 12px; + color: var(--ds-gray-12); + font-size: 13px; + } +`}</style> + +<div> + <h1>Colour</h1> + +{" "} + +<p> + Our colour system is role-based and implemented through MUI theme tokens. + Values are provided as CSS variables (primitives + semantic “on-colour” + + overlays) so light/dark mode and future refinement remain consistent. The + current primitives and semantic variables live in + `diamond-colors-primitives.css`. +</p> + +<div className="ds-note"> + <strong>How to use colour roles</strong> + <ul style={{ margin: "8px 0 0 16px" }}> + <li> + <strong>light / main</strong> — solid backgrounds and emphasis + <small>Buttons, active states, strong accents</small> + </li> + <li> + <strong>bgCanvas / bgSurface*</strong> — light backgrounds and layout + <small>Pages, panels, cards, grouped content</small> + </li> + <li> + <strong>dark / darker</strong> — text, icons, and borders on light + surfaces + <small>High-contrast foreground usage</small> + </li> + </ul> + <p style={{ marginTop: 8 }}> + If something looks like a background, use <code>bg*</code>. If it looks like + a button, use <code>main</code>. If it’s text, use <code>dark</code>. + </p> +</div> + +{" "} + +<div className="ds-note"> + <strong>What changed:</strong> the palette now exposes more layers per intent + colour: ` light → main → dark → darker`, plus `*Channel` tokens for + alpha-based overlays. Also added `brand` colour scheme. +</div> + +{" "} + +<h2>MUI palette mapping (current)</h2> +<p> + These are the current top-level palette decisions used in our MUI theme. We + also define explicit `action.*` overlays to avoid Material’s default overlay + behaviour and keep interaction states consistent with our primitives. +</p> + + <div className="ds-grid"> + {/* Primary */} + <div className="ds-swatch" style={{ ['--swatch']: 'var(--ds-indigo-9)' }}> + <div className="ds-swatch__chip" /> + <div className="ds-swatch__body"> + <p className="ds-swatch__name">Primary</p> + <ul className="ds-swatch__meta"> + <li><strong>light</strong>: `--ds-indigo-8`</li> + <li><strong>main</strong>: `--ds-indigo-9`</li> + <li><strong>dark</strong>: `--ds-indigo-10`</li> + <li><strong>darker</strong>: `--ds-indigo-11`</li> + <li><strong>contrast text</strong>: `--ds-fg-fixed-white`</li> + <li><strong>mainChannel</strong>: `--ds-indigo-9Channel`</li> + <li><strong>lightChannel</strong>: `--ds-indigo-8Channel`</li> + <li><strong>darkChannel</strong>: `--ds-indigo-10Channel`</li> + <li><strong>bgCanvas</strong>: <code>--ds-indigo-1</code></li> + <li><strong>bgSurface1</strong>: <code>--ds-indigo-2</code></li> + <li><strong>bgSurface2</strong>: <code>--ds-indigo-3</code></li> + </ul> + <div className="ds-row"> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-indigo-8)' }} /> light</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-indigo-9)' }} /> main</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-indigo-10)' }} /> dark</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-indigo-11)' }} /> darker</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-indigo-1)' }} > canvas</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-indigo-2)' }} > surface1</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-indigo-3)' }} > surface2</span> + </div> + </div> + </div> + + {/* Secondary */} + <div className="ds-swatch" style={{ ['--swatch']: 'var(--ds-navy-9)' }}> + <div className="ds-swatch__chip" /> + <div className="ds-swatch__body"> + <p className="ds-swatch__name">Secondary</p> + <ul className="ds-swatch__meta"> + <li><strong>light</strong>: `--ds-navy-8`</li> + <li><strong>main</strong>: `--ds-navy-9`</li> + <li><strong>dark</strong>: `--ds-navy-10`</li> + <li><strong>darker</strong>: `--ds-navy-11`</li> + <li><strong>contrast text</strong>: `--ds-fg-fixed-white`</li> + <li><strong>mainChannel</strong>: `--ds-navy-9Channel`</li> + <li><strong>lightChannel</strong>: `--ds-navy-8Channel`</li> + <li><strong>darkChannel</strong>: `--ds-navy-10Channel`</li> + <li><strong>bgCanvas</strong>: <code>--ds-navy-1</code></li> + <li><strong>bgSurface1</strong>: <code>--ds-navy-2</code></li> + <li><strong>bgSurface2</strong>: <code>--ds-navy-3</code></li> + </ul> + <div className="ds-row"> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-8)' }} /> light</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-9)' }} /> main</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-10)' }} /> dark</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-11)' }} /> darker</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-navy-1)' }} > canvas</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-navy-2)' }} > surface1</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-navy-3)' }} > surface2</span> + </div> + </div> + </div> + + {/* Brand */} + <div className="ds-swatch" style={{ ['--swatch']: 'var(--ds-navy-10)' }}> + <div className="ds-swatch__chip" /> + <div className="ds-swatch__body"> + <p className="ds-swatch__name">Brand</p> + <ul className="ds-swatch__meta"> + <li><strong>light</strong>: `--ds-navy-9`</li> + <li><strong>main</strong>: `--ds-navy-10`</li> + <li><strong>dark</strong>: `--ds-navy-11`</li> + <li><strong>darker</strong>: `--ds-navy-12`</li> + <li><strong>contrast text</strong>: `--ds-fg-fixed-white`</li> + <li><strong>mainChannel</strong>: `--ds-navy-10Channel`</li> + <li><strong>lightChannel</strong>: `--ds-navy-9Channel`</li> + <li><strong>darkChannel</strong>: `--ds-navy-11Channel`</li> + </ul> + <div className="ds-row"> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-9)' }} /> light</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-10)' }} /> main</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-11)' }} /> dark</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-12)' }} /> darker</span> + </div> + </div> + </div> + + {/* Success */} + <div className="ds-swatch" style={{ ['--swatch']: 'var(--ds-green-9)' }}> + <div className="ds-swatch__chip" /> + <div className="ds-swatch__body"> + <p className="ds-swatch__name">Success</p> + <ul className="ds-swatch__meta"> + <li><strong>light</strong>: `--ds-green-8`</li> + <li><strong>main</strong>: `--ds-green-9`</li> + <li><strong>dark</strong>: `--ds-green-10`</li> + <li><strong>darker</strong>: `--ds-green-11`</li> + <li><strong>contrast text</strong>: `--ds-fg-fixed-white`</li> + <li><strong>mainChannel</strong>: `--ds-green-9Channel`</li> + <li><strong>bgCanvas</strong>: <code>--ds-green-1</code></li> + <li><strong>bgSurface1</strong>: <code>--ds-green-2</code></li> + <li><strong>bgSurface2</strong>: <code>--ds-green-3</code></li> + </ul> + <div className="ds-row"> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-green-8)' }} /> light</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-green-9)' }} /> main</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-green-10)' }} /> dark</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-green-11)' }} /> darker</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-green-1)' }} > canvas</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-green-2)' }} > surface1</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-green-3)' }} > surface2</span> + </div> + </div> + </div> + + {/* Warning */} + <div className="ds-swatch" style={{ ['--swatch']: 'var(--ds-orange-9)' }}> + <div className="ds-swatch__chip" /> + <div className="ds-swatch__body"> + <p className="ds-swatch__name">Warning</p> + <ul className="ds-swatch__meta"> + <li><strong>light</strong>: `--ds-orange-8`</li> + <li><strong>main</strong>: `--ds-orange-9`</li> + <li><strong>dark</strong>: `--ds-orange-10`</li> + <li><strong>darker</strong>: `--ds-orange-11`</li> + <li><strong>contrast text</strong>: `--ds-fg-fixed-white`</li> + <li><strong>mainChannel</strong>: `--ds-orange-9Channel`</li> + <li><strong>bgCanvas</strong>: <code>--ds-orange-1</code></li> + <li><strong>bgSurface1</strong>: <code>--ds-orange-2</code></li> + <li><strong>bgSurface2</strong>: <code>--ds-orange-3</code></li> + </ul> + <div className="ds-row"> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-orange-8)' }} /> light</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-orange-9)' }} /> main</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-orange-10)' }} /> dark</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-orange-11)' }} /> darker</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-orange-1)' }} > canvas</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-orange-2)' }} > surface1</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-orange-3)' }} > surface2</span> + </div> + </div> + </div> + + {/* Error */} + <div className="ds-swatch" style={{ ['--swatch']: 'var(--ds-red-9)' }}> + <div className="ds-swatch__chip" /> + <div className="ds-swatch__body"> + <p className="ds-swatch__name">Error</p> + <ul className="ds-swatch__meta"> + <li><strong>light</strong>: `--ds-red-8`</li> + <li><strong>main</strong>: `--ds-red-9`</li> + <li><strong>dark</strong>: `--ds-red-10`</li> + <li><strong>darker</strong>: `--ds-red-11`</li> + <li><strong>contrast text</strong>: `--ds-fg-fixed-white`</li> + <li><strong>mainChannel</strong>: `--ds-red-9Channel`</li> + <li><strong>bgCanvas</strong>: <code>--ds-red-1</code></li> + <li><strong>bgSurface1</strong>: <code>--ds-red-2</code></li> + <li><strong>bgSurface2</strong>: <code>--ds-red-3</code></li> + </ul> + <div className="ds-row"> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-red-8)' }} /> light</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-red-9)' }} /> main</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-red-10)' }} /> dark</span> + <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-red-11)' }} /> darker</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-red-1)' }} > canvas</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-red-2)' }} > surface1</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-red-3)' }} > surface2</span> + </div> + </div> + </div> + +{/* Background surfaces */} + +<div className="ds-swatch" style={{ ["--swatch"]: "var(--ds-bg-paper)" }}> + <div className="ds-swatch__chip" /> + <div className="ds-swatch__body"> + <p className="ds-swatch__name">Background surfaces</p> + <ul className="ds-swatch__meta"> + <li> + <strong>default</strong>: <code>--ds-bg-canvas</code> + </li> + <li> + <strong>paper</strong>: <code>--ds-bg-paper</code> + </li> + <li> + <strong>surface1</strong>: <code>--ds-bg-surface-1</code> + </li> + <li> + <strong>surface2</strong>: <code>--ds-bg-surface-2</code> + </li> + <li> + <strong>outlinedBg</strong>: <code>--ds-bg-surface-2</code> + </li> + </ul> + <div className="ds-row"> + <span + className="ds-pill" + style={{ ["background"]: "var(--ds-bg-canvas)" }} + > + {" "} + canvas + </span> + <span + className="ds-pill" + style={{ ["background"]: "var(--ds-bg-paper)" }} + > + {" "} + paper + </span> + <span + className="ds-pill" + style={{ ["background"]: "var(--ds-bg-surface-1)" }} + > + {" "} + surface1 + </span> + <span + className="ds-pill" + style={{ ["background"]: "var(--ds-bg-surface-2)" }} + > + {" "} + surface2 + </span> + </div> + </div> +</div> + + {/* Divider */} + <div className="ds-swatch" style={{ ['--swatch']: 'var(--ds-gray-6)' }}> + <div className="ds-swatch__chip" /> + <div className="ds-swatch__body"> + <p className="ds-swatch__name">Divider</p> + <ul className="ds-swatch__meta"> + <li><strong>divider</strong>: `--ds-gray-6`</li> + </ul> + </div> + </div> + + </div> + +<h2>Surfaces, text, and dividers (quick visual check)</h2> +<div className="ds-surface-demo"> + <div className="ds-surface-card"> + <div className="ds-text-demo"> + <p style={{ color: "var(--ds-gray-12)" }}> + <strong>Text primary</strong> → `--ds-gray-12` + </p> + <p style={{ color: "var(--ds-gray-11)" }}> + Text secondary → `--ds-gray-11` + </p> + <p style={{ color: "var(--ds-gray-8)" }}>Text disabled → `--ds-gray-8`</p> + </div> + <div className="ds-divider" /> + <p style={{ margin: 0, color: "var(--ds-gray-11)" }}> + Canvas uses `--ds-gray-1` and surfaces use `--ds-gray-2`. Divider uses + `--ds-gray-6`. + </p> + </div> +</div> + +{" "} + +<h2>Interaction overlays (MUI action tokens)</h2> +<p> + We define `action.hover`, `action.selected`, `action.focus`, + `action.disabled`, and `action.disabledBackground` as explicit overlays + (`--ds-overlay-*`) so interaction states remain consistent across themes. +</p> + + <div className="ds-overlay-demo"> + <div className="ds-overlay-tile"> + <div className="ds-overlay-tile__top"> + <div className="ds-overlay-tile__overlay" style={{ ['--overlay']: 'var(--ds-overlay-hover)' }} /> + </div> + <div className="ds-overlay-tile__body"> + <ul className="ds-swatch__meta"> + <li><strong>hover</strong>: `--ds-overlay-hover`</li> + </ul> + </div> + </div> + + <div className="ds-overlay-tile"> + <div className="ds-overlay-tile__top"> + <div className="ds-overlay-tile__overlay" style={{ ['--overlay']: 'var(--ds-overlay-selected)' }} /> + </div> + <div className="ds-overlay-tile__body"> + <ul className="ds-swatch__meta"> + <li><strong>selected</strong>: `--ds-overlay-selected`</li> + </ul> + </div> + </div> + + <div className="ds-overlay-tile"> + <div className="ds-overlay-tile__top"> + <div className="ds-overlay-tile__overlay" style={{ ['--overlay']: 'var(--ds-overlay-focus)' }} /> + </div> + <div className="ds-overlay-tile__body"> + <ul className="ds-swatch__meta"> + <li><strong>focus</strong>: `--ds-overlay-focus`</li> + </ul> + </div> + </div> + + <div className="ds-overlay-tile"> + <div className="ds-overlay-tile__top"> + <div className="ds-overlay-tile__overlay" style={{ ['--overlay']: 'var(--ds-overlay-disabled)' }} /> + </div> + <div className="ds-overlay-tile__body"> + <ul className="ds-swatch__meta"> + <li><strong>disabled</strong>: `--ds-overlay-disabled`</li> + </ul> + </div> + </div> + + <div className="ds-overlay-tile"> + <div className="ds-overlay-tile__top"> + <div className="ds-overlay-tile__overlay" style={{ ['--overlay']: 'var(--ds-overlay-disabled-bg)' }} /> + </div> + <div className="ds-overlay-tile__body"> + <ul className="ds-swatch__meta"> + <li><strong>disabled background</strong>: `--ds-overlay-disabled-bg`</li> + </ul> + </div> + </div> + + </div> + +<h2>Component style example</h2> +<p> + Components can override specific behaviour where needed. For example, we set + `MuiButton` to use sentence case (no automatic uppercase). +</p> + + <div className="ds-note"> + <strong>MUI Button:</strong> `textTransform: none` + </div> +</div> diff --git a/src/storybook/foundation/typography.mdx b/src/storybook/foundation/typography.mdx new file mode 100644 index 0000000..45aa78a --- /dev/null +++ b/src/storybook/foundation/typography.mdx @@ -0,0 +1,77 @@ +import { Meta } from "@storybook/blocks"; + +<Meta title="Foundation/Typography" /> + +<div> + <h1>Typography</h1> + +<p> + Typography is a functional tool, not decoration. In scientific software, type + choices affect speed, accuracy, and confidence. +</p> + +{" "} + +<h2>Why it matters in Diamond tools</h2> +<ul> + <li> + <strong>Readability and legibility</strong>: clear at small sizes and on + imperfect displays. + </li> + <li> + <strong>Hierarchy</strong>: predictable structure for scanning data-heavy + screens. + </li> + <li> + <strong>Accessibility</strong>: legible sizing and contrast across contexts. + </li> + <li> + <strong>Reduced cognitive load</strong>: less visual noise, faster + decisions. + </li> + <li> + <strong>Works for dense data</strong>: tables, logs, dashboards, forms, + documentation. + </li> +</ul> + +{" "} + +<h2>Font roles</h2> +<ul> + <li> + <strong>Outfit</strong>: brand-forward headings and hero text. + </li> + <li> + <strong>Inter</strong>: default UI font for functional work (body, labels, + tables). + </li> + <li> + <strong>IBM Plex Mono</strong>: code, identifiers, aligned technical values. + </li> +</ul> + +<h2>Practical guidance</h2> + +<h3>Do</h3> +<ul> + <li>Keep hierarchy consistent across products and screens.</li> + <li>Prefer short, clear labels in controls and tables.</li> + <li>Make numbers and units easy to scan (alignment matters).</li> +</ul> + +{" "} + +<h3>Don’t</h3> +<ul> + <li>Don’t use brand typography for dense operational content.</li> + <li>Don’t “style your way” out of hierarchy problems.</li> + <li>Don’t hide important info in faint secondary text.</li> +</ul> + + <h2>Tokens (to be defined)</h2> + <p> + We’ll define tokens for display, body, and mono usage (e.g. `typography.display.*`, + `typography.body.*`, `typography.mono.*`) and reference them consistently. + </p> +</div> diff --git a/src/styles/diamondDS/diamond-colors-primitives.css b/src/styles/diamondDS/diamond-colors-primitives.css new file mode 100644 index 0000000..a9a898a --- /dev/null +++ b/src/styles/diamondDS/diamond-colors-primitives.css @@ -0,0 +1,890 @@ +:root { + --ds-black: #000000; + --ds-black-a1: #0000000d; + --ds-black-a2: #0000001a; + --ds-black-a3: #00000026; + --ds-black-a4: #0003; + --ds-black-a5: #0000004d; + --ds-black-a6: #0006; + --ds-black-a7: #00000080; + --ds-black-a8: #0009; + --ds-black-a9: #000000b3; + --ds-black-a10: #000c; + --ds-black-a11: #000000e6; + --ds-black-a12: #000000f2; + --ds-blackChannel: 0 0 0; + --ds-white: #ffffff; + --ds-white-a1: #ffffff0d; + --ds-white-a2: #ffffff1a; + --ds-white-a3: #ffffff26; + --ds-white-a4: #fff3; + --ds-white-a5: #ffffff4d; + --ds-white-a6: #fff6; + --ds-white-a7: #ffffff80; + --ds-white-a8: #fff9; + --ds-white-a9: #ffffffb3; + --ds-white-a10: #fffc; + --ds-white-a11: #ffffffe6; + --ds-white-a12: #fffffff2; + --ds-whiteChannel: 255 255 255; + + /* Disabled tokens (semantic) */ + --ds-fg-disabled: var(--ds-gray-8); + --ds-border-disabled: var(--ds-gray-6); + --ds-bg-disabled: var(--ds-gray-2); + } + + :root, .light, :root[data-mode="light"] { /*LIGHT MODE */ + /* Semantic on-colour tokens */ + --ds-fg-fixed-white: var(--ds-white); /* Always white */ + --ds-fg-fixed-black: var(--ds-black); /* Always black */ + --ds-fg-inverse: var(--ds-white); /* White (light) → Black (dark) */ + --ds-fg-default: var(--ds-black); /* Black (light) → White (dark) */ + + --ds-overlay-hover: rgba(0, 0, 0, 0.06); + --ds-overlay-selected: rgba(0, 0, 0, 0.10); + --ds-overlay-focus: rgba(0, 0, 0, 0.12); + --ds-overlay-disabled: rgba(0, 0, 0, 0.26); + --ds-overlay-disabled-bg: rgba(0, 0, 0, 0.06); + + --ds-bg-brand: var(--ds-navy-10); /* Diamond Brand Blue */ + + /* Canvas (app shell) */ + --ds-bg-canvas: var(--ds-olive-1); + + /* Paper (main surface) */ + --ds-bg-paper: var(--ds-white); + + /* Layering surfaces */ + --ds-bg-surface-1: var(--ds-olive-2); + --ds-bg-surface-2: var(--ds-olive-3); + + /* Borders */ + --ds-border-subtle: var(--ds-olive-6); + --ds-border-strong: var(--ds-olive-7); + + /* Radix based colours */ + --ds-gray-1:#fcfcfc; + --ds-gray-2:#f9f9f9; + --ds-gray-3:#f0f0f0; + --ds-gray-4:#e8e8e8; + --ds-gray-5:#e0e0e0; + --ds-gray-6:#d9d9d9; + --ds-gray-7:#cecece; + --ds-gray-8:#bbb; + --ds-gray-9:#8d8d8d; + --ds-gray-10:#838383; + --ds-gray-11:#646464; + --ds-gray-12:#202020; + --ds-gray-a1:#00000003; + --ds-gray-a2:#00000006; + --ds-gray-a3:#0000000f; + --ds-gray-a4:#00000017; + --ds-gray-a5:#0000001f; + --ds-gray-a6:#00000026; + --ds-gray-a7:#00000031; + --ds-gray-a8:#00000044; + --ds-gray-a9:#00000072; + --ds-gray-a10:#0000007c; + --ds-gray-a11:#0000009b; + --ds-gray-a12:#000000df; + --ds-gray-1Channel: 252 252 252; + --ds-gray-2Channel: 249 249 249; + --ds-gray-3Channel: 240 240 240; + --ds-gray-4Channel: 232 232 232; + --ds-gray-5Channel: 224 224 224; + --ds-gray-6Channel: 217 217 217; + --ds-gray-7Channel: 206 206 206; + --ds-gray-8Channel: 187 187 187; + --ds-gray-9Channel: 141 141 141; + --ds-gray-10Channel: 131 131 131; + --ds-gray-11Channel: 100 100 100; + --ds-gray-12Channel: 32 32 32; + --ds-olive-1:#fcfdfc; + --ds-olive-2:#f8faf8; + --ds-olive-3:#eff1ef; + --ds-olive-4:#e7e9e7; + --ds-olive-5:#dfe2df; + --ds-olive-6:#d7dad7; + --ds-olive-7:#cccfcc; + --ds-olive-8:#b9bcb8; + --ds-olive-9:#898e87; + --ds-olive-10:#7f847d; + --ds-olive-11:#60655f; + --ds-olive-12:#1d211c; + --ds-olive-a1:#00550003; + --ds-olive-a2:#00490007; + --ds-olive-a3:#00200010; + --ds-olive-a4:#00160018; + --ds-olive-a5:#00180020; + --ds-olive-a6:#00140028; + --ds-olive-a7:#000f0033; + --ds-olive-a8:#040f0047; + --ds-olive-a9:#050f0078; + --ds-olive-a10:#040e0082; + --ds-olive-a11:#020a00a0; + --ds-olive-a12:#010600e3; + --ds-olive-1Channel: 252 253 252; + --ds-olive-2Channel: 248 250 248; + --ds-olive-3Channel: 239 241 239; + --ds-olive-4Channel: 231 233 231; + --ds-olive-5Channel: 223 226 223; + --ds-olive-6Channel: 215 218 215; + --ds-olive-7Channel: 204 207 204; + --ds-olive-8Channel: 185 188 184; + --ds-olive-9Channel: 137 142 135; + --ds-olive-10Channel: 127 132 125; + --ds-olive-11Channel: 96 101 95; + --ds-olive-12Channel: 29 33 28; + --ds-cyan-1: #FAFEFF; + --ds-cyan-2: #F1FBFC; + --ds-cyan-3: #E3F6F8; + --ds-cyan-4: #D4EFF3; + --ds-cyan-5: #C2E6EB; + --ds-cyan-6: #ACDBE1; + --ds-cyan-7: #8CCCD3; + --ds-cyan-8: #64BAC3; + --ds-cyan-9: #3A9FAC; + --ds-cyan-10: #009CA6; /* brand */ + --ds-cyan-11: #006873; + --ds-cyan-12: #003A40; + --ds-cyan-a1: #3A9FAC05; + --ds-cyan-a2: #3A9FAC0A; + --ds-cyan-a3: #3A9FAC10; + --ds-cyan-a4: #3A9FAC17; + --ds-cyan-a5: #3A9FAC1F; + --ds-cyan-a6: #3A9FAC27; + --ds-cyan-a7: #3A9FAC33; + --ds-cyan-a8: #3A9FAC47; + --ds-cyan-a9: #3A9FAC63; + --ds-cyan-a10: #3A9FAC7D; + --ds-cyan-a11: #3A9FACA2; + --ds-cyan-a12: #3A9FACDE; + --ds-cyan-1Channel: 250 254 255; + --ds-cyan-2Channel: 241 251 252; + --ds-cyan-3Channel: 227 246 248; + --ds-cyan-4Channel: 212 239 243; + --ds-cyan-5Channel: 194 230 235; + --ds-cyan-6Channel: 172 219 225; + --ds-cyan-7Channel: 140 204 211; + --ds-cyan-8Channel: 100 186 195; + --ds-cyan-9Channel: 58 159 172; + --ds-cyan-10Channel: 0 156 166; + --ds-cyan-11Channel: 0 104 115; + --ds-cyan-12Channel: 0 58 64; + --ds-green-1: #FBFEFB; + --ds-green-2: #F3FBF4; + --ds-green-3: #E6F6E8; + --ds-green-4: #D8F0DB; + --ds-green-5: #C9E9CC; + --ds-green-6: #B4DEB8; + --ds-green-7: #95CF9B; + --ds-green-8: #70BE78; + --ds-green-9: #4CA65A; + --ds-green-10: #008C15; /* brand */ + --ds-green-11: #00620F; + --ds-green-12: #003708; + --ds-green-a1: #4CA65A05; + --ds-green-a2: #4CA65A0A; + --ds-green-a3: #4CA65A10; + --ds-green-a4: #4CA65A17; + --ds-green-a5: #4CA65A1F; + --ds-green-a6: #4CA65A27; + --ds-green-a7: #4CA65A33; + --ds-green-a8: #4CA65A47; + --ds-green-a9: #4CA65A63; + --ds-green-a10: #4CA65A7D; + --ds-green-a11: #4CA65AA2; + --ds-green-a12: #4CA65ADE; + --ds-green-1Channel: 251 254 251; + --ds-green-2Channel: 243 251 244; + --ds-green-3Channel: 230 246 232; + --ds-green-4Channel: 216 240 219; + --ds-green-5Channel: 201 233 204; + --ds-green-6Channel: 180 222 184; + --ds-green-7Channel: 149 207 155; + --ds-green-8Channel: 112 190 120; + --ds-green-9Channel: 76 166 90; + --ds-green-10Channel: 0 140 21; + --ds-green-11Channel: 0 98 15; + --ds-green-12Channel: 0 55 8; + --ds-indigo-1:#fdfdfe; + --ds-indigo-2:#f7f9ff; + --ds-indigo-3:#edf2fe; + --ds-indigo-4:#e1e9ff; + --ds-indigo-5:#d2deff; + --ds-indigo-6:#c1d0ff; + --ds-indigo-7:#abbdf9; + --ds-indigo-8:#8da4ef; + --ds-indigo-9:#3e63dd; + --ds-indigo-10:#3358d4; + --ds-indigo-11:#3a5bc7; + --ds-indigo-12:#1f2d5c; + --ds-indigo-a1:#00008002; + --ds-indigo-a2:#0040ff08; + --ds-indigo-a3:#0047f112; + --ds-indigo-a4:#0044ff1e; + --ds-indigo-a5:#0044ff2d; + --ds-indigo-a6:#003eff3e; + --ds-indigo-a7:#0037ed54; + --ds-indigo-a8:#0034dc72; + --ds-indigo-a9:#0031d2c1; + --ds-indigo-a10:#002ec9cc; + --ds-indigo-a11:#002bb7c5; + --ds-indigo-a12:#001046e0; + --ds-indigo-1Channel: 253 253 254; + --ds-indigo-2Channel: 247 249 255; + --ds-indigo-3Channel: 237 242 254; + --ds-indigo-4Channel: 225 233 255; + --ds-indigo-5Channel: 210 222 255; + --ds-indigo-6Channel: 193 208 255; + --ds-indigo-7Channel: 171 189 249; + --ds-indigo-8Channel: 141 164 239; + --ds-indigo-9Channel: 62 99 221; + --ds-indigo-10Channel: 51 88 212; + --ds-indigo-11Channel: 58 91 199; + --ds-indigo-12Channel: 31 45 92; + --ds-lime-1:#fcfdfa; + --ds-lime-2:#f8faf3; + --ds-lime-3:#eef6d6; + --ds-lime-4:#e2f0bd; + --ds-lime-5:#d3e7a6; + --ds-lime-6:#c2da91; + --ds-lime-7:#abc978; + --ds-lime-8:#8db654; + --ds-lime-9:#bdee63; + --ds-lime-10:#b0e64c; + --ds-lime-11:#5c7c2f; + --ds-lime-12:#37401c; + --ds-lime-a1:#66990005; + --ds-lime-a2:#6b95000c; + --ds-lime-a3:#96c80029; + --ds-lime-a4:#8fc60042; + --ds-lime-a5:#81bb0059; + --ds-lime-a6:#72aa006e; + --ds-lime-a7:#61990087; + --ds-lime-a8:#559200ab; + --ds-lime-a9:#93e4009c; + --ds-lime-a10:#8fdc00b3; + --ds-lime-a11:#375f00d0; + --ds-lime-a12:#1e2900e3; + --ds-lime-1Channel: 252 253 250; + --ds-lime-2Channel: 248 250 243; + --ds-lime-3Channel: 238 246 214; + --ds-lime-4Channel: 226 240 189; + --ds-lime-5Channel: 211 231 166; + --ds-lime-6Channel: 194 218 145; + --ds-lime-7Channel: 171 201 120; + --ds-lime-8Channel: 141 182 84; + --ds-lime-9Channel: 189 238 99; + --ds-lime-10Channel: 176 230 76; + --ds-lime-11Channel: 92 124 47; + --ds-lime-12Channel: 55 64 28; + --ds-violet-1: #FEFBFF; + --ds-violet-2: #FCF4FD; + --ds-violet-3: #F9E7FB; + --ds-violet-4: #F5D9F7; + --ds-violet-5: #F0C9F1; + --ds-violet-6: #E7B2E8; + --ds-violet-7: #DA98DC; + --ds-violet-8: #C978CE; + --ds-violet-9: #C91FA8; + --ds-violet-10: #B0008E; /* brand */ + --ds-violet-11: #9A007A; + --ds-violet-12: #640055; + --ds-violet-a1: #B952BF05; + --ds-violet-a2: #B952BF0A; + --ds-violet-a3: #B952BF10; + --ds-violet-a4: #B952BF17; + --ds-violet-a5: #B952BF1F; + --ds-violet-a6: #B952BF27; + --ds-violet-a7: #B952BF33; + --ds-violet-a8: #B952BF47; + --ds-violet-a9: #B952BF63; + --ds-violet-a10: #B952BF7D; + --ds-violet-a11: #B952BFA2; + --ds-violet-a12: #B952BFDE; + --ds-violet-1Channel: 254 251 255; + --ds-violet-2Channel: 252 244 253; + --ds-violet-3Channel: 249 231 251; + --ds-violet-4Channel: 245 217 247; + --ds-violet-5Channel: 240 201 241; + --ds-violet-6Channel: 231 178 232; + --ds-violet-7Channel: 218 152 220; + --ds-violet-8Channel: 201 120 206; + --ds-violet-9Channel: 201 31 168; + --ds-violet-10Channel: 176 0 142; + --ds-violet-11Channel: 154 0 122; + --ds-violet-12Channel: 100 0 85; + --ds-orange-1: #FFF9F3; + --ds-orange-2: #FFF1E3; + --ds-orange-3: #FFE4CC; + --ds-orange-4: #FFD6B3; + --ds-orange-5: #FFC796; + --ds-orange-6: #FFB777; + --ds-orange-7: #FFA457; + --ds-orange-8: #FF8B2F; + --ds-orange-9: #FF780A; + --ds-orange-10: #FF6900; /* brand */ + --ds-orange-11: #A24600; + --ds-orange-12: #552300; + --ds-orange-a1: #FF780A05; + --ds-orange-a2: #FF780A0A; + --ds-orange-a3: #FF780A10; + --ds-orange-a4: #FF780A17; + --ds-orange-a5: #FF780A1F; + --ds-orange-a6: #FF780A27; + --ds-orange-a7: #FF780A33; + --ds-orange-a8: #FF780A47; + --ds-orange-a9: #FF780A63; + --ds-orange-a10: #FF780A7D; + --ds-orange-a11: #FF780AA2; + --ds-orange-a12: #FF780ADE; + --ds-orange-1Channel: 255 249 243; + --ds-orange-2Channel: 255 241 227; + --ds-orange-3Channel: 255 228 204; + --ds-orange-4Channel: 255 214 179; + --ds-orange-5Channel: 255 199 150; + --ds-orange-6Channel: 255 183 119; + --ds-orange-7Channel: 255 164 87; + --ds-orange-8Channel: 255 139 47; + --ds-orange-9Channel: 255 120 10; + --ds-orange-10Channel: 255 105 0; + --ds-orange-11Channel: 162 70 0; + --ds-orange-12Channel: 85 35 0; + --ds-red-1: #fffcfc; + --ds-red-2: #fff8f7; + --ds-red-3: #feebe7; + --ds-red-4: #ffdcd3; + --ds-red-5: #ffcdc2; + --ds-red-6: #fdbdaf; + --ds-red-7: #f5a898; + --ds-red-9: #e54d2e; + --ds-red-10: #E10600; /* brand */ + --ds-red-11: #d13415; + --ds-red-12: #5c271f; + --ds-red-a1: #ff000003; + --ds-red-a2: #ff200008; + --ds-red-a3: #f52b0018; + --ds-red-a4: #ff35002c; + --ds-red-a5: #ff2e003d; + --ds-red-a6: #f92d0050; + --ds-red-a7: #e7280067; + --ds-red-a8: #db250084; + --ds-red-a9: #df2600d1; + --ds-red-a10: #d72400da; + --ds-red-a11: #cd2200ea; + --ds-red-a12: #460900e0; + --ds-red-1Channel: 255 252 252; + --ds-red-2Channel: 255 239 239; + --ds-red-3Channel: 255 226 225; + --ds-red-4Channel: 255 212 210; + --ds-red-5Channel: 255 195 193; + --ds-red-6Channel: 255 174 171; + --ds-red-7Channel: 255 144 141; + --ds-red-8Channel: 247 111 106; + --ds-red-9Channel: 229 75 69; + --ds-red-10Channel: 225 6 0; + --ds-red-11Channel: 150 4 0; + --ds-red-12Channel: 75 2 0; + --ds-yellow-1:#fdfdf9; + --ds-yellow-2:#fefce9; + --ds-yellow-3:#fffab8; + --ds-yellow-4:#fff394; + --ds-yellow-5:#ffe770; + --ds-yellow-6:#f3d768; + --ds-yellow-7:#e4c767; + --ds-yellow-8:#d5ae39; + --ds-yellow-9:#ffe629; + --ds-yellow-10:#FCD021; /* brand */ + --ds-yellow-11:#9e6c00; + --ds-yellow-12:#473b1f; + --ds-yellow-a1:#aaaa0006; + --ds-yellow-a2:#f4dd0016; + --ds-yellow-a3:#ffee0047; + --ds-yellow-a4:#ffe3016b; + --ds-yellow-a5:#ffd5008f; + --ds-yellow-a6:#ebbc0097; + --ds-yellow-a7:#d2a10098; + --ds-yellow-a8:#c99700c6; + --ds-yellow-a9:#ffe100d6; + --ds-yellow-a10:#FCD021; + --ds-yellow-a11:#9e6c00; + --ds-yellow-a12:#2e2000e0; + --ds-yellow-1Channel: 253 253 249; + --ds-yellow-2Channel: 254 252 233; + --ds-yellow-3Channel: 255 250 184; + --ds-yellow-4Channel: 255 243 148; + --ds-yellow-5Channel: 255 231 112; + --ds-yellow-6Channel: 243 215 104; + --ds-yellow-7Channel: 228 199 103; + --ds-yellow-8Channel: 213 174 57; + --ds-yellow-9Channel: 255 230 41; + --ds-yellow-10Channel: 255 220 0; + --ds-yellow-11Channel: 158 108 0; + --ds-yellow-12Channel: 71 59 31; + /* Diamond Brand Blue */ + --ds-navy-1: #F9FAFD; + --ds-navy-2: #EFF1F7; + --ds-navy-3: #E0E2ED; + --ds-navy-4: #D0D4E2; + --ds-navy-5: #BEC3D4; + --ds-navy-6: #A9AFC3; + --ds-navy-7: #9196AF; + --ds-navy-8: #777C98; + --ds-navy-9: #586084; + --ds-navy-10: #202945; /* brand */ + --ds-navy-11: #1D263F; + --ds-navy-12: #0C0E1C; + --ds-navy-a1: #58608405; + --ds-navy-a2: #5860840A; + --ds-navy-a3: #58608410; + --ds-navy-a4: #58608417; + --ds-navy-a5: #5860841F; + --ds-navy-a6: #58608427; + --ds-navy-a7: #58608433; + --ds-navy-a8: #58608447; + --ds-navy-a9: #58608463; + --ds-navy-a10: #5860847D; + --ds-navy-a11: #586084A2; + --ds-navy-a12: #586084DE; + --ds-navy-1Channel: 249 250 253; + --ds-navy-2Channel: 239 241 247; + --ds-navy-3Channel: 224 226 237; + --ds-navy-4Channel: 208 212 226; + --ds-navy-5Channel: 190 195 212; + --ds-navy-6Channel: 169 175 195; + --ds-navy-7Channel: 145 150 175; + --ds-navy-8Channel: 119 124 152; + --ds-navy-9Channel: 88 96 132; + --ds-navy-10Channel: 32 41 69; + --ds-navy-11Channel: 29 38 63; + --ds-navy-12Channel: 12 14 28; + } + .dark, :root[data-mode="dark"] { /* Dark Mode */ + /* Semantic on-colour tokens */ + --ds-fg-fixed-white: var(--ds-white); /* Always white */ + --ds-fg-fixed-black: var(--ds-black); /* Always black */ + --ds-fg-inverse: var(--ds-black); /* White (light) → Black (dark) */ + --ds-fg-default: var(--ds-white); /* Black (light) → White (dark) */ + + --ds-bg-brand: var(--ds-navy-7); /* Diamond Brand Blue */ + + --ds-overlay-hover: rgba(255, 255, 255, 0.06); + --ds-overlay-selected: rgba(255, 255, 255, 0.10); + --ds-overlay-focus: rgba(255, 255, 255, 0.12); + --ds-overlay-disabled: rgba(255, 255, 255, 0.30); + --ds-overlay-disabled-bg: rgba(255, 255, 255, 0.08); + + /* Canvas (app shell) */ + --ds-bg-canvas: var(--ds-olive-1); + + /* Paper (main surface) */ + --ds-bg-paper: var(--ds-olive-2); + + /* Layering surfaces */ + --ds-bg-surface-1: var(--ds-olive-3); + --ds-bg-surface-2: var(--ds-olive-4); + + /* Borders */ + --ds-border-subtle: var(--ds-olive-6); + --ds-border-strong: var(--ds-olive-7); + + /* Radix based colours */ + --ds-gray-1:#111; + --ds-gray-2:#191919; + --ds-gray-3:#222; + --ds-gray-4:#2a2a2a; + --ds-gray-5:#313131; + --ds-gray-6:#3a3a3a; + --ds-gray-7:#484848; + --ds-gray-8:#606060; + --ds-gray-9:#6e6e6e; + --ds-gray-10:#7b7b7b; + --ds-gray-11:#b4b4b4; + --ds-gray-12:#eee; + --ds-gray-a1:#0000; + --ds-gray-a2:#ffffff09; + --ds-gray-a3:#ffffff12; + --ds-gray-a4:#ffffff1b; + --ds-gray-a5:#ffffff22; + --ds-gray-a6:#ffffff2c; + --ds-gray-a7:#ffffff3b; + --ds-gray-a8:#ffffff55; + --ds-gray-a9:#ffffff64; + --ds-gray-a10:#ffffff72; + --ds-gray-a11:#ffffffaf; + --ds-gray-a12:#ffffffed; + --ds-gray-1Channel: 17 17 17; + --ds-gray-2Channel: 25 25 25; + --ds-gray-3Channel: 34 34 34; + --ds-gray-4Channel: 42 42 42; + --ds-gray-5Channel: 49 49 49; + --ds-gray-6Channel: 58 58 58; + --ds-gray-7Channel: 72 72 72; + --ds-gray-8Channel: 96 96 96; + --ds-gray-9Channel: 110 110 110; + --ds-gray-10Channel: 123 123 123; + --ds-gray-11Channel: 180 180 180; + --ds-gray-12Channel: 238 238 238; + --ds-olive-1:#111210; + --ds-olive-2:#181917; + --ds-olive-3:#212220; + --ds-olive-4:#282a27; + --ds-olive-5:#2f312e; + --ds-olive-6:#383a36; + --ds-olive-7:#454843; + --ds-olive-8:#5c625b; + --ds-olive-9:#687066; + --ds-olive-10:#767d74; + --ds-olive-11:#afb5ad; + --ds-olive-12:#eceeec; + --ds-olive-a1:#0000; + --ds-olive-a2:#f1f2f008; + --ds-olive-a3:#f4f5f312; + --ds-olive-a4:#f3fef21a; + --ds-olive-a5:#f2fbf122; + --ds-olive-a6:#f4faed2c; + --ds-olive-a7:#f2fced3b; + --ds-olive-a8:#edfdeb57; + --ds-olive-a9:#ebfde766; + --ds-olive-a10:#f0fdec74; + --ds-olive-a11:#f6fef4b0; + --ds-olive-a12:#fdfffded; + --ds-olive-1Channel: 17 18 16; + --ds-olive-2Channel: 24 25 23; + --ds-olive-3Channel: 33 34 32; + --ds-olive-4Channel: 40 42 39; + --ds-olive-5Channel: 47 49 46; + --ds-olive-6Channel: 56 58 54; + --ds-olive-7Channel: 69 72 67; + --ds-olive-8Channel: 92 98 91; + --ds-olive-9Channel: 104 112 102; + --ds-olive-10Channel: 118 125 116; + --ds-olive-11Channel: 175 181 173; + --ds-olive-12Channel: 236 238 236; + --ds-cyan-1:#0b161a; + --ds-cyan-2:#101b20; + --ds-cyan-3:#082c36; + --ds-cyan-4:#003848; + --ds-cyan-5:#004558; + --ds-cyan-6:#045468; + --ds-cyan-7:#12677e; + --ds-cyan-8:#11809c; + --ds-cyan-9:#00a2c7; + --ds-cyan-10:#23afd0; + --ds-cyan-11:#4ccce6; + --ds-cyan-12:#b6ecf7; + --ds-cyan-a1:#0091f70a; + --ds-cyan-a2:#02a7f211; + --ds-cyan-a3:#00befd28; + --ds-cyan-a4:#00baff3b; + --ds-cyan-a5:#00befd4d; + --ds-cyan-a6:#00c7fd5e; + --ds-cyan-a7:#14cdff75; + --ds-cyan-a8:#11cfff95; + --ds-cyan-a9:#00cfffc3; + --ds-cyan-a10:#28d6ffcd; + --ds-cyan-a11:#52e1fee5; + --ds-cyan-a12:#bbf3fef7; + --ds-cyan-1Channel: 11 22 26; + --ds-cyan-2Channel: 16 27 32; + --ds-cyan-3Channel: 8 44 54; + --ds-cyan-4Channel: 0 56 72; + --ds-cyan-5Channel: 0 69 88; + --ds-cyan-6Channel: 4 84 104; + --ds-cyan-7Channel: 18 103 126; + --ds-cyan-8Channel: 17 128 156; + --ds-cyan-9Channel: 0 162 199; + --ds-cyan-10Channel: 35 175 208; + --ds-cyan-11Channel: 76 204 230; + --ds-cyan-12Channel: 182 236 247; + --ds-green-1:#0e1512; + --ds-green-2:#121b17; + --ds-green-3:#132d21; + --ds-green-4:#113b29; + --ds-green-5:#174933; + --ds-green-6:#20573e; + --ds-green-7:#28684a; + --ds-green-8:#2f7c57; + --ds-green-9:#30a46c; + --ds-green-10:#33b074; + --ds-green-11:#3dd68c; + --ds-green-12:#b1f1cb; + --ds-green-a1:#00de4505; + --ds-green-a2:#29f99d0b; + --ds-green-a3:#22ff991e; + --ds-green-a4:#11ff992d; + --ds-green-a5:#2bffa23c; + --ds-green-a6:#44ffaa4b; + --ds-green-a7:#50fdac5e; + --ds-green-a8:#54ffad73; + --ds-green-a9:#44ffa49e; + --ds-green-a10:#43fea4ab; + --ds-green-a11:#46fea5d4; + --ds-green-a12:#bbffd7f0; + --ds-green-1Channel: 14 21 18; + --ds-green-2Channel: 18 27 23; + --ds-green-3Channel: 19 45 33; + --ds-green-4Channel: 17 59 41; + --ds-green-5Channel: 23 73 51; + --ds-green-6Channel: 32 87 62; + --ds-green-7Channel: 40 104 74; + --ds-green-8Channel: 47 124 87; + --ds-green-9Channel: 48 164 108; + --ds-green-10Channel: 51 176 116; + --ds-green-11Channel: 61 214 140; + --ds-green-12Channel: 177 241 203; + --ds-indigo-1:#11131f; + --ds-indigo-2:#141726; + --ds-indigo-3:#182449; + --ds-indigo-4:#1d2e62; + --ds-indigo-5:#253974; + --ds-indigo-6:#304384; + --ds-indigo-7:#3a4f97; + --ds-indigo-8:#435db1; + --ds-indigo-9:#3e63dd; + --ds-indigo-10:#5472e4; + --ds-indigo-11:#9eb1ff; + --ds-indigo-12:#d6e1ff; + --ds-indigo-a1:#1133ff0f; + --ds-indigo-a2:#3354fa17; + --ds-indigo-a3:#2f62ff3c; + --ds-indigo-a4:#3566ff57; + --ds-indigo-a5:#4171fd6b; + --ds-indigo-a6:#5178fd7c; + --ds-indigo-a7:#5a7fff90; + --ds-indigo-a8:#5b81feac; + --ds-indigo-a9:#4671ffdb; + --ds-indigo-a10:#5c7efee3; + --ds-indigo-a11:#9eb1ff; + --ds-indigo-a12:#d6e1ff; + --ds-indigo-1Channel: 17 19 31; + --ds-indigo-2Channel: 20 23 38; + --ds-indigo-3Channel: 24 36 73; + --ds-indigo-4Channel: 29 46 98; + --ds-indigo-5Channel: 37 57 116; + --ds-indigo-6Channel: 48 67 132; + --ds-indigo-7Channel: 58 79 151; + --ds-indigo-8Channel: 67 93 177; + --ds-indigo-9Channel: 62 99 221; + --ds-indigo-10Channel: 84 114 228; + --ds-indigo-11Channel: 158 177 255; + --ds-indigo-12Channel: 214 225 255; + --ds-lime-1:#11130c; + --ds-lime-2:#151a10; + --ds-lime-3:#1f2917; + --ds-lime-4:#29371d; + --ds-lime-5:#334423; + --ds-lime-6:#3d522a; + --ds-lime-7:#496231; + --ds-lime-8:#577538; + --ds-lime-9:#bdee63; + --ds-lime-10:#d4ff70; + --ds-lime-11:#bde56c; + --ds-lime-12:#e3f7ba; + --ds-lime-a1:#11bb0003; + --ds-lime-a2:#78f7000a; + --ds-lime-a3:#9bfd4c1a; + --ds-lime-a4:#a7fe5c29; + --ds-lime-a5:#affe6537; + --ds-lime-a6:#b2fe6d46; + --ds-lime-a7:#b6ff6f57; + --ds-lime-a8:#b6fd6d6c; + --ds-lime-a9:#caff69ed; + --ds-lime-a10:#d4ff70; + --ds-lime-a11:#d1fe77e4; + --ds-lime-a12:#e9febff7; + --ds-lime-1Channel: 17 19 12; + --ds-lime-2Channel: 21 26 16; + --ds-lime-3Channel: 31 41 23; + --ds-lime-4Channel: 41 55 29; + --ds-lime-5Channel: 51 68 35; + --ds-lime-6Channel: 61 82 42; + --ds-lime-7Channel: 73 98 49; + --ds-lime-8Channel: 87 117 56; + --ds-lime-9Channel: 189 238 99; + --ds-lime-10Channel: 212 255 112; + --ds-lime-11Channel: 189 229 108; + --ds-lime-12Channel: 227 247 186; + --ds-orange-1:#17120e; + --ds-orange-2:#1e160f; + --ds-orange-3:#331e0b; + --ds-orange-4:#462100; + --ds-orange-5:#562800; + --ds-orange-6:#66350c; + --ds-orange-7:#7e451d; + --ds-orange-8:#a35829; + --ds-orange-9:#f76b15; + --ds-orange-10:#ff801f; + --ds-orange-11:#ffa057; + --ds-orange-12:#ffe0c2; + --ds-orange-a1:#ec360007; + --ds-orange-a2:#fe6d000e; + --ds-orange-a3:#fb6a0025; + --ds-orange-a4:#ff590039; + --ds-orange-a5:#ff61004a; + --ds-orange-a6:#fd75045c; + --ds-orange-a7:#ff832c75; + --ds-orange-a8:#fe84389d; + --ds-orange-a9:#fe6d15f7; + --ds-orange-a10:#ff801f; + --ds-orange-a11:#ffa057; + --ds-orange-a12:#ffe0c2; + --ds-orange-1Channel: 23 18 14; + --ds-orange-2Channel: 30 22 15; + --ds-orange-3Channel: 51 30 11; + --ds-orange-4Channel: 70 33 0; + --ds-orange-5Channel: 86 40 0; + --ds-orange-6Channel: 102 53 12; + --ds-orange-7Channel: 126 69 29; + --ds-orange-8Channel: 163 88 41; + --ds-orange-9Channel: 247 107 21; + --ds-orange-10Channel: 255 128 31; + --ds-orange-11Channel: 255 160 87; + --ds-orange-12Channel: 255 224 194; + --ds-violet-1:#181118; + --ds-violet-2:#201320; + --ds-violet-3:#351a35; + --ds-violet-4:#451d47; + --ds-violet-5:#512454; + --ds-violet-6:#5e3061; + --ds-violet-7:#734079; + --ds-violet-8:#92549c; + --ds-violet-9:#ab4aba; + --ds-violet-10:#b658c4; + --ds-violet-11:#e796f3; + --ds-violet-12:#f4d4f4; + --ds-violet-a1:#f112f108; + --ds-violet-a2:#f22ff211; + --ds-violet-a3:#fd4cfd27; + --ds-violet-a4:#f646ff3a; + --ds-violet-a5:#f455ff48; + --ds-violet-a6:#f66dff56; + --ds-violet-a7:#f07cfd70; + --ds-violet-a8:#ee84ff95; + --ds-violet-a9:#e961feb6; + --ds-violet-a10:#ed70ffc0; + --ds-violet-a11:#f19cfef3; + --ds-violet-a12:#feddfef4; + --ds-violet-1Channel: 24 17 24; + --ds-violet-2Channel: 32 19 32; + --ds-violet-3Channel: 53 26 53; + --ds-violet-4Channel: 69 29 71; + --ds-violet-5Channel: 81 36 84; + --ds-violet-6Channel: 94 48 97; + --ds-violet-7Channel: 115 64 121; + --ds-violet-8Channel: 146 84 156; + --ds-violet-9Channel: 171 74 186; + --ds-violet-10Channel: 182 88 196; + --ds-violet-11Channel: 231 150 243; + --ds-violet-12Channel: 244 212 244; + --ds-red-1: #181111; + --ds-red-2: #1f1513; + --ds-red-3: #391714; + --ds-red-4: #4e1511; + --ds-red-5: #5e1c16; + --ds-red-6: #6e2920; + --ds-red-7: #853a2d; + --ds-red-8: #ac4d39; + --ds-red-10: #ec6142; + --ds-red-11: #ff977d; + --ds-red-12: #fbd3cb; + --ds-red-a1: #f1121208; + --ds-red-a2: #ff55330f; + --ds-red-a3: #ff35232b; + --ds-red-a4: #fd201142; + --ds-red-a5: #fe332153; + --ds-red-a6: #ff4f3864; + --ds-red-a7: #fd644a7d; + --ds-red-a8: #fe6d4ea7; + --ds-red-a9: #fe5431e4; + --ds-red-a10: #ff6847eb; + --ds-red-a11: #ff977d; + --ds-red-a12: #ffd6cefb; + --ds-red-1Channel: 25 17 17; + --ds-red-2Channel: 32 19 20; + --ds-red-3Channel: 59 18 25; + --ds-red-4Channel: 80 15 28; + --ds-red-5Channel: 97 22 35; + --ds-red-6Channel: 114 35 45; + --ds-red-7Channel: 140 51 58; + --ds-red-8Channel: 181 69 72; + --ds-red-9Channel: 229 72 77; + --ds-red-10Channel: 236 93 94; + --ds-red-11Channel: 255 149 146; + --ds-red-12Channel: 255 209 217; + --ds-yellow-1:#14120b; + --ds-yellow-2:#1b180f; + --ds-yellow-3:#2d2305; + --ds-yellow-4:#362b00; + --ds-yellow-5:#433500; + --ds-yellow-6:#524202; + --ds-yellow-7:#665417; + --ds-yellow-8:#836a21; + --ds-yellow-9:#ffe629; + --ds-yellow-10:#ffff57; + --ds-yellow-11:#f5e147; + --ds-yellow-12:#f6eeb4; + --ds-yellow-a1:#d1510004; + --ds-yellow-a2:#f9b4000b; + --ds-yellow-a3:#ffaa001e; + --ds-yellow-a4:#fdb70028; + --ds-yellow-a5:#febb0036; + --ds-yellow-a6:#fec40046; + --ds-yellow-a7:#fdcb225c; + --ds-yellow-a8:#fdca327b; + --ds-yellow-a9:#ffe629; + --ds-yellow-a10:#ffff57; + --ds-yellow-a11:#fee949f5; + --ds-yellow-a12:#fef6baf6; + --ds-yellow-1Channel: 20 18 11; + --ds-yellow-2Channel: 27 24 15; + --ds-yellow-3Channel: 45 35 5; + --ds-yellow-4Channel: 54 43 0; + --ds-yellow-5Channel: 67 53 0; + --ds-yellow-6Channel: 82 66 2; + --ds-yellow-7Channel: 102 84 23; + --ds-yellow-8Channel: 131 106 33; + --ds-yellow-9Channel: 255 230 41; + --ds-yellow-10Channel: 255 255 87; + --ds-yellow-11Channel: 245 225 71; + --ds-yellow-12Channel: 246 238 180; + /* Diamond Brand Blue */ + --ds-navy-1: #070910; + --ds-navy-2: #0B0E17; + --ds-navy-3: #101521; + --ds-navy-4: #141A2B; + --ds-navy-5: #192034; + --ds-navy-6: #1D263F; + --ds-navy-7: #202945; /* brand sits here in dark ramp */ + --ds-navy-8: #273352; + --ds-navy-9: #5F678D; + --ds-navy-10: #7983AF; + --ds-navy-11: #9ca9ce; + --ds-navy-12: #d5ddf0; + --ds-navy-a1: #32406405; + --ds-navy-a2: #3240640A; + --ds-navy-a3: #32406410; + --ds-navy-a4: #32406417; + --ds-navy-a5: #3240641F; + --ds-navy-a6: #32406427; + --ds-navy-a7: #32406433; + --ds-navy-a8: #32406447; + --ds-navy-a9: #32406463; + --ds-navy-a10: #3240647D; + --ds-navy-a11: #324064A2; + --ds-navy-a12: #324064DE; + --ds-navy-1Channel: 7 9 16; /* #070910 */ + --ds-navy-2Channel: 11 14 23; /* #0b0e17 */ + --ds-navy-3Channel: 16 21 33; /* #101521 */ + --ds-navy-4Channel: 20 26 43; /* #141a2b */ + --ds-navy-5Channel: 25 32 52; /* #192034 */ + --ds-navy-6Channel: 29 38 63; /* #1d263f */ + --ds-navy-7Channel: 32 41 69; /* #202945 (brand) */ + --ds-navy-8Channel: 39 51 82; /* #273352 */ + --ds-navy-9Channel: 95 103 141; /* #324064 */ + --ds-navy-10Channel: 121 131 175; + --ds-navy-11Channel: 156 169 206; /* #9ca9ce */ + --ds-navy-12Channel: 213 221 240; /* #d5ddf0 */ + } \ No newline at end of file diff --git a/src/styles/diamondDS/diamond-mui-palette-tokens.css b/src/styles/diamondDS/diamond-mui-palette-tokens.css new file mode 100644 index 0000000..f17fdc2 --- /dev/null +++ b/src/styles/diamondDS/diamond-mui-palette-tokens.css @@ -0,0 +1,243 @@ +/* ============================================================ + NEW DIAMOND THEME (Diamond + Radix) - NOT USED CURRENTLY + ============================================================ */ + :root { + + /* COMMON */ + --mui-palette-common-black: var(--ds-black); + --mui-palette-common-white: var(--ds-white); + + --mui-palette-common-blackChannel: var(--ds-blackChannel); + --mui-palette-common-whiteChannel: var(--ds-Channel); + + --mui-palette-common-background: var(--ds-olive-1); + --mui-palette-common-onBackground: var(--ds-navy-11); + + --mui-palette-common-backgroundChannel: var(--ds-olive-1Channel); + --mui-palette-common-onBackgroundChannel: var(--ds-navy-11Channel); + + /* PRIMARY = Indigo */ + --mui-palette-primary-lighter: var(--ds-indigo-3); + --mui-palette-primary-light: var(--ds-indigo-6); + --mui-palette-primary-main: var(--ds-indigo-9); + --mui-palette-primary-dark: var(--ds-indigo-10); + --mui-palette-primary-darker: var(--ds-indigo-12); + --mui-palette-primary-contrastText: var(--ds-mui-palette-common-white); + + --mui-palette-primary-lighterChannel: var(--ds-indigo-3Channel); + --mui-palette-primary-lightChannel: var(--ds-indigo-6Channel); + --mui-palette-primary-mainChannel: var(--ds-indigo-9Channel); + --mui-palette-primary-darkChannel: var(--ds-indigo-10Channel); + --mui-palette-primary-darkerChannel: var(--ds-indigo-12Channel); + --mui-palette-primary-contrastTextChannel: var(--ds-mui-palette-common-whiteChannel); + + /* SECONDARY = Gray */ + --mui-palette-secondary-lighter: var(--ds-navy-3); + --mui-palette-secondary-light: var(--ds-navy-6); + --mui-palette-secondary-main: var(--ds-navy-9); + --mui-palette-secondary-dark: var(--ds-navy-11); + --mui-palette-secondary-darker: var(--ds-navy-12); + --mui-palette-secondary-contrastText: var(--ds-mui-palette-common-white); + + --mui-palette-secondary-lighterChannel: var(--ds-navy-3Channel); + --mui-palette-secondary-lightChannel: var(--ds-navy-6Channel); + --mui-palette-secondary-mainChannel: var(--ds-navy-9Channel); + --mui-palette-secondary-darkChannel: var(--ds-navy-11Channel); + --mui-palette-secondary-darkerChannel: var(--ds-navy-12Channel); + --mui-palette-secondary-contrastTextChannel: var(--ds-mui-palette-common-whiteChannel); + + /* ERROR = Red */ + --mui-palette-error-lighter: var(--ds-red-3); + --mui-palette-error-light: var(--ds-red-6); + --mui-palette-error-main: var(--ds-red-9); + --mui-palette-error-dark: var(--ds-red-11); + --mui-palette-error-darker: var(--ds-red-12); + --mui-palette-error-contrastText: var(--ds-mui-palette-common-white); + + --mui-palette-error-lighterChannel: var(--ds-red-3Channel); + --mui-palette-error-lightChannel: var(--ds-red-6Channel); + --mui-palette-error-mainChannel: var(--ds-red-9Channel); + --mui-palette-error-darkChannel: var(--ds-red-11Channel); + --mui-palette-error-darkerChannel: var(--ds-red-12Channel); + --mui-palette-error-contrastTextChannel: var(--ds-mui-palette-common-whiteChannel); + + /* WARNING = Yellow */ + --mui-palette-warning-lighter: var(--ds-yellow-2); + --mui-palette-warning-light: var(--ds-yellow-6); + --mui-palette-warning-main: var(--ds-yellow-9); + --mui-palette-warning-dark: var(--ds-yellow-11); + --mui-palette-warning-darker: var(--ds-yellow-12); + --mui-palette-warning-contrastText: var(--ds-mui-palette-common-black); + + --mui-palette-warning-lighterChannel: var(--ds-yellow-2Channel); + --mui-palette-warning-lightChannel: var(--ds-yellow-6Channel); + --mui-palette-warning-mainChannel: var(--ds-yellow-9Channel); + --mui-palette-warning-darkChannel: var(--ds-yellow-11Channel); + --mui-palette-warning-darkerChannel: var(--ds-yellow-12Channel); + --mui-palette-warning-contrastTextChannel: var(--ds-mui-palette-common-blackChannel); + + /* INFO = Cyan */ + --mui-palette-info-lighter: var(--ds-cyan-2); + --mui-palette-info-light: var(--ds-cyan-6); + --mui-palette-info-main: var(--ds-cyan-9); + --mui-palette-info-dark: var(--ds-cyan-11); + --mui-palette-info-darker: var(--ds-cyan-12); + --mui-palette-info-contrastText: var(--ds-mui-palette-common-black); + + --mui-palette-info-lighterChannel: var(--ds-cyan-2Channel); + --mui-palette-info-lightChannel: var(--ds-cyan-6Channel); + --mui-palette-info-mainChannel: var(--ds-cyan-9Channel); + --mui-palette-info-darkChannel: var(--ds-cyan-11Channel); + --mui-palette-info-darkerChannel: var(--ds-cyan-12Channel); + --mui-palette-info-contrastTextChannel: var(--ds-mui-palette-common-blackChannel); + + /* SUCCESS = Green */ + --mui-palette-success-lighter: var(--ds-green-2); + --mui-palette-success-light: var(--ds-green-6); + --mui-palette-success-main: var(--ds-green-9); + --mui-palette-success-dark: var(--ds-green-11); + --mui-palette-success-darker: var(--ds-green-12); + --mui-palette-success-contrastText: var(--ds-mui-palette-common-black); + + --mui-palette-success-lighterChannel: var(--ds-green-2Channel); + --mui-palette-success-lightChannel: var(--ds-green-6Channel); + --mui-palette-success-mainChannel: var(--ds-green-9Channel); + --mui-palette-success-darkChannel: var(--ds-green-11Channel); + --mui-palette-success-darkerChannel: var(--ds-green-12Channel); + --mui-palette-success-contrastTextChannel: var(--ds-mui-palette-common-blackChannel); + + /* TEXT */ + --mui-palette-text-primary: var(--ds-navy-10); + --mui-palette-text-secondary: var(--ds-olive-9); + --mui-palette-text-disabled: var(--ds-olive-7); + + --mui-palette-text-primaryChannel: var(--ds-navy-11Channel); + --mui-palette-text-secondaryChannel: var(--ds-olive-9Channel); + + /* ACTIONS */ + --mui-palette-action-disabled: var(--ds-olive-6); + --mui-palette-action-active: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.54); + --mui-palette-action-hover: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.04); + --mui-palette-action-selected: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.08); + --mui-palette-action-disabledBackground: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.12); + --mui-palette-action-focus: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.12); + + --mui-palette-action-activeChannel: var(--ds-mui-palette-text-primaryChannel); + --mui-palette-action-selectedChannel: var(--ds-mui-palette-text-primaryChannel); + + /* BACKGROUNDS */ + --mui-palette-divider: var(--ds-olive-3); + --mui-palette-dividerChannel: var(--ds-olive-3Channel); + + --mui-palette-background-paper: var(--ds-mui-palette-common-white); + --mui-palette-background-default: var(--ds-olive-2); + + --mui-palette-background-defaultChannel: var(--ds-olive-2Channel); + --mui-palette-background-paperChannel: var(--ds-mui-palette-common-whiteChannel); + + /* ALERTS */ + --mui-palette-Alert-errorColor: var(--ds-mui-palette-error-dark); + --mui-palette-Alert-infoColor: var(--ds-mui-palette-info-dark); + --mui-palette-Alert-successColor: var(--ds-mui-palette-success-dark); + --mui-palette-Alert-warningColor: var(--ds-mui-palette-warning-dark); + + --mui-palette-Alert-errorFilledBg: var(--ds-mui-palette-error-main); + --mui-palette-Alert-infoFilledBg: var(--ds-mui-palette-info-main); + --mui-palette-Alert-successFilledBg: var(--ds-mui-palette-success-main); + --mui-palette-Alert-warningFilledBg: var(--ds-mui-palette-warning-main); + + --mui-palette-Alert-errorFilledColor: var(--ds-mui-palette-common-white); + --mui-palette-Alert-infoFilledColor: rgba(var(--ds-mui-palette-common-blackChannel) / 0.87); + --mui-palette-Alert-successFilledColor: rgba(var(--ds-mui-palette-common-blackChannel) / 0.87); + --mui-palette-Alert-warningFilledColor: rgba(var(--ds-mui-palette-common-blackChannel) / 0.87); + + --mui-palette-Alert-errorStandardBg: var(--ds-mui-palette-error-lighter); + --mui-palette-Alert-infoStandardBg: var(--ds-mui-palette-info-lighter); + --mui-palette-Alert-successStandardBg: var(--ds-mui-palette-success-lighter); + --mui-palette-Alert-warningStandardBg: var(--ds-mui-palette-warning-lighter); + + --mui-palette-Alert-errorIconColor: var(--ds-mui-palette-error-main); + --mui-palette-Alert-infoIconColor: var(--ds-mui-palette-info-main); + --mui-palette-Alert-successIconColor: var(--ds-mui-palette-success-main); + --mui-palette-Alert-warningIconColor: var(--ds-mui-palette-warning-main); + + /* COMPONENTS */ + --mui-palette-AppBar-defaultBg: var(--ds-navy-10); + + --mui-palette-Avatar-defaultBg: var(--ds-olive-5); + + --mui-palette-Button-inheritContainedBg: var(--ds-olive-4); + --mui-palette-Button-inheritContainedHoverBg: var(--ds-olive-2); + + --mui-palette-Chip-defaultBorder: var(--ds-olive-5); + --mui-palette-Chip-defaultAvatarColor: var(--ds-olive-11); + --mui-palette-Chip-defaultIconColor: var(--ds-olive-11); + + --mui-palette-FilledInput-bg: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.06); + --mui-palette-FilledInput-hoverBg: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.09); + --mui-palette-FilledInput-disabledBg: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.12); + + --mui-palette-LinearProgress-primaryBg: var(--ds-mui-palette-primary-lighter); + --mui-palette-LinearProgress-secondaryBg: var(--ds-mui-palette-secondary-lighter); + --mui-palette-LinearProgress-errorBg: var(--ds-mui-palette-error-lighter); + --mui-palette-LinearProgress-infoBg: var(--ds-mui-palette-info-lighter); + --mui-palette-LinearProgress-successBg: var(--ds-mui-palette-success-lighter); + --mui-palette-LinearProgress-warningBg: var(--ds-mui-palette-warning-lighter); + + --mui-palette-Skeleton-bg: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.11); + + --mui-palette-Slider-primaryTrack: var(--ds-mui-palette-primary-lighter); + --mui-palette-Slider-secondaryTrack: var(--ds-mui-palette-secondary-lighter); + --mui-palette-Slider-errorTrack: var(--ds-mui-palette-error-lighter); + --mui-palette-Slider-infoTrack: var(--ds-mui-palette-info-lighter); + --mui-palette-Slider-successTrack: var(--ds-mui-palette-success-lighter); + --mui-palette-Slider-warningTrack: var(--ds-mui-palette-warning-lighter); + + --mui-palette-SnackbarContent-bg: var(--ds-navy-11); + --mui-palette-SnackbarContent-color: var(--ds-mui-palette-common-white); + + --mui-palette-SpeedDialAction-fabHoverBg: var(--ds-olive-4); + + --mui-palette-StepConnector-border: var(--ds-olive-5); + --mui-palette-StepContent-border: var(--ds-olive-5); + + --mui-palette-Switch-defaultColor: var(--ds-mui-palette-common-white); + --mui-palette-Switch-defaultDisabledColor: var(--ds-olive-2); + --mui-palette-Switch-primaryDisabledColor: var(--ds-mui-palette-primary-lighter); + --mui-palette-Switch-secondaryDisabledColor: var(--ds-mui-palette-secondary-lighter); + --mui-palette-Switch-errorDisabledColor: var(--ds-mui-palette-error-lighter); + --mui-palette-Switch-infoDisabledColor: var(--ds-mui-palette-info-lighter); + --mui-palette-Switch-successDisabledColor: var(--ds-mui-palette-success-lighter); + --mui-palette-Switch-warningDisabledColor: var(--ds-mui-palette-warning-lighter); + + --mui-palette-TableCell-border: var(--ds-olive-1); + + --mui-palette-Tooltip-bg: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.92); + + /* SHADOWS */ + --customShadows-button: 0 2px #0000000b; + --customShadows-text: 0 -1px 0 rgba(var(--ds-mui-palette-common-blackChannel) / 0.12); + --customShadows-z1: 0px 1px 4px rgba(var(--ds-mui-palette-common-blackChannel) / 0.08); + + --customShadows-primary: 0 0 0 2px rgba(var(--ds-mui-palette-primary-mainChannel) / 0.2); + --customShadows-secondary: 0 0 0 2px rgba(var(--ds-mui-palette-secondary-mainChannel) / 0.2); + --customShadows-error: 0 0 0 2px rgba(var(--ds-mui-palette-error-mainChannel) / 0.2); + --customShadows-warning: 0 0 0 2px rgba(var(--ds-mui-palette-warning-mainChannel) / 0.2); + --customShadows-info: 0 0 0 2px rgba(var(--ds-mui-palette-info-mainChannel) / 0.2); + --customShadows-success: 0 0 0 2px rgba(var(--ds-mui-palette-success-mainChannel) / 0.2); + --customShadows-grey: 0 0 0 2px rgba(var(--ds-mui-palette-secondary-mainChannel) / 0.2); + + --customShadows-primaryButton: 0 14px 12px rgba(var(--ds-mui-palette-primary-mainChannel) / 0.2); + --customShadows-secondaryButton: 0 14px 12px rgba(var(--ds-mui-palette-secondary-mainChannel) / 0.2); + --customShadows-errorButton: 0 14px 12px rgba(var(--ds-mui-palette-error-mainChannel) / 0.2); + --customShadows-warningButton: 0 14px 12px rgba(var(--ds-mui-palette-warning-mainChannel) / 0.2); + --customShadows-infoButton: 0 14px 12px rgba(var(--ds-mui-palette-info-mainChannel) / 0.2); + --customShadows-successButton: 0 14px 12px rgba(var(--ds-mui-palette-success-mainChannel) / 0.2); + --customShadows-greyButton: 0 14px 12px rgba(var(--ds-mui-palette-secondary-mainChannel) / 0.2); + + /* OPACITY */ + --opacity-inputPlaceholder: 0.42; + --opacity-inputUnderline: 0.42; + --opacity-switchTrackDisabled: 0.12; + --opacity-switchTrack: 0.38; + } \ No newline at end of file diff --git a/src/themes/DiamondDSTheme.ts b/src/themes/DiamondDSTheme.ts new file mode 100644 index 0000000..24e3a87 --- /dev/null +++ b/src/themes/DiamondDSTheme.ts @@ -0,0 +1,451 @@ +import "../styles/diamondDS/diamond-colors-primitives.css"; + +import type {} from "@mui/material/themeCssVarsAugmentation"; +import { createTheme, Theme } from "@mui/material/styles"; + +import { mergeThemeOptions } from "./ThemeManager"; + +import logoImageLight from "../public/diamond/logo-light.svg"; +import logoImageDark from "../public/diamond/logo-dark.svg"; +import logoShort from "../public/diamond/logo-short.svg"; + +import React from "react"; +import { + DsCheckboxBlankIcon, + DsCheckboxCheckedIcon, + DsCheckboxIndeterminateIcon, +} from "./icons"; + +declare module "@mui/material/styles" { + interface TypeBackground { + surface1?: string; + surface2?: string; + } + interface PaletteColor { + bgCanvas?: string; + bgSurface1?: string; + bgSurface2?: string; + } + interface SimplePaletteColorOptions { + bgCanvas?: string; + bgSurface1?: string; + bgSurface2?: string; + } +} + +export type DSMode = "light" | "dark"; + +export const createMuiTheme = (mode: DSMode): Theme => { + const DiamondDSThemeOptions = mergeThemeOptions({ + typography: { + fontFamily: [ + "Inter Variable", + "Inter", + "system-ui", + "-apple-system", + '"Segoe UI"', + "Roboto", + "Helvetica", + "Arial", + "sans-serif", + ].join(","), + }, + + logos: { + normal: { + src: + mode === "dark" ? (logoImageDark ?? logoImageLight) : logoImageLight, + srcDark: logoImageDark ?? logoImageLight, + alt: "Diamond Light Source Logo", + width: "100", + }, + short: { + src: logoShort, + alt: "Diamond Light Source Logo", + width: "35", + }, + }, + + palette: { + mode, + + // Prevent "Material dark overlays" by defining action tokens from primitives + action: { + hover: "var(--ds-overlay-hover)", + selected: "var(--ds-overlay-selected)", + focus: "var(--ds-overlay-focus)", + disabled: "var(--ds-overlay-disabled)", + disabledBackground: "var(--ds-overlay-disabled-bg)", + + hoverOpacity: 0.08, + selectedOpacity: 0.12, + disabledOpacity: 0.38, + focusOpacity: 0.12, + }, + + text: { + primary: "var(--ds-gray-12)", + secondary: "var(--ds-gray-11)", + disabled: "var(--ds-gray-8)", + }, + + background: { + default: "var(--ds-bg-canvas)", // page / app shell + paper: "var(--ds-bg-paper)", // cards, dialogs + outlinedBg: "var(--ds-bg-surface-2)", // inputs, outlined containers + surface1: "var(--ds-bg-surface-1)", + surface2: "var(--ds-bg-surface-2)", + }, + + divider: "var(--ds-border-subtle)", + dividerInverse: "var(--ds-white-a4)", + + primary: { + main: "var(--ds-indigo-9)", + light: "var(--ds-indigo-8)", + dark: "var(--ds-indigo-10)", + darker: "var(--ds-indigo-11)", + contrastText: "var(--ds-fg-fixed-white)", + + mainChannel: "var(--ds-indigo-9Channel)", + lightChannel: "var(--ds-indigo-8Channel)", + darkChannel: "var(--ds-indigo-10Channel)", + + bgCanvas: "var(--ds-indigo-1)", + bgSurface1: "var(--ds-indigo-2)", + bgSurface2: "var(--ds-indigo-3)", + }, + + secondary: { + main: "var(--ds-navy-9)", + light: "var(--ds-navy-8)", + dark: "var(--ds-navy-10)", + darker: "var(--ds-navy-11)", + contrastText: "var(--ds-fg-fixed-white)", + + mainChannel: "var(--ds-navy-9Channel)", + lightChannel: "var(--ds-navy-8Channel)", + darkChannel: "var(--ds-navy-10Channel)", + + bgCanvas: "var(--ds-navy-1)", + bgSurface1: "var(--ds-navy-2)", + bgSurface2: "var(--ds-navy-3)", + }, + + brand: { + main: "var(--ds-navy-10)", + light: "var(--ds-navy-9)", + dark: "var(--ds-navy-11)", + darker: "var(--ds-navy-12)", + contrastText: "var(--ds-fg-fixed-white)", + + mainChannel: "var(--ds-navy-10Channel)", + lightChannel: "var(--ds-navy-9Channel)", + darkChannel: "var(--ds-navy-11Channel)", + }, + + error: { + main: "var(--ds-red-10)", + light: "var(--ds-red-9)", + dark: "var(--ds-red-11)", + darker: "var(--ds-red-11)", + contrastText: "var(--ds-fg-fixed-white)", + + mainChannel: "var(--ds-red-9Channel)", + lightChannel: "var(--ds-red-8Channel)", + darkChannel: "var(--ds-red-10Channel)", + + bgCanvas: "var(--ds-red-1)", + bgSurface1: "var(--ds-red-2)", + bgSurface2: "var(--ds-red-3)", + }, + + warning: { + main: "var(--ds-orange-10)", + light: "var(--ds-orange-9)", + dark: "var(--ds-orange-11)", + darker: "var(--ds-orange-11)", + contrastText: "var(--ds-fg-fixed-white)", + + mainChannel: "var(--ds-orange-9Channel)", + lightChannel: "var(--ds-orange-8Channel)", + darkChannel: "var(--ds-orange-10Channel)", + + bgCanvas: "var(--ds-orange-1)", + bgSurface1: "var(--ds-orange-2)", + bgSurface2: "var(--ds-orange-3)", + }, + + success: { + main: "var(--ds-green-10)", + light: "var(--ds-green-9)", + dark: "var(--ds-green-11)", + darker: "var(--ds-green-11)", + contrastText: "var(--ds-fg-fixed-white)", + + mainChannel: "var(--ds-green-9Channel)", + lightChannel: "var(--ds-green-8Channel)", + darkChannel: "var(--ds-green-10Channel)", + + bgCanvas: "var(--ds-green-1)", + bgSurface1: "var(--ds-green-2)", + bgSurface2: "var(--ds-green-3)", + }, + + info: { + main: "var(--ds-indigo-9)", + light: "var(--ds-indigo-8)", + dark: "var(--ds-indigo-10)", + darker: "var(--ds-indigo-11)", + contrastText: "var(--ds-fg-fixed-white)", + + mainChannel: "var(--ds-indigo-9Channel)", + lightChannel: "var(--ds-indigo-8Channel)", + darkChannel: "var(--ds-indigo-10Channel)", + + bgCanvas: "var(--ds-indigo-1)", + bgSurface1: "var(--ds-indigo-2)", + bgSurface2: "var(--ds-indigo-3)", + }, + + grey: { + 50: "var(--ds-olive-1)", + 100: "var(--ds-olive-2)", + 200: "var(--ds-olive-3)", + 300: "var(--ds-olive-4)", + 400: "var(--ds-olive-5)", + 500: "var(--ds-olive-6)", + 600: "var(--ds-olive-7)", + 700: "var(--ds-olive-8)", + 800: "var(--ds-olive-9)", + 900: "var(--ds-olive-10)", + }, + }, + + components: { + MuiButton: { + styleOverrides: { + root: ({ ownerState, theme }) => { + const base = { textTransform: "none" as const }; + + const variant = ownerState.variant ?? "text"; + + const rawColour = ownerState.color ?? "primary"; + if (rawColour === "inherit") return base; + + const colour = rawColour as + | "primary" + | "secondary" + | "error" + | "warning" + | "info" + | "success"; + + const varsPalette = (theme as any).vars?.palette?.[colour]; + const fallbackPalette = (theme.palette as any)[colour]; + + const darker = + varsPalette?.darker ?? + fallbackPalette?.darker ?? + varsPalette?.dark ?? + fallbackPalette?.dark; + + const mainChannel = + varsPalette?.mainChannel ?? fallbackPalette?.mainChannel; + + if (variant === "outlined") { + return { + ...base, + ...(darker && { + "--variant-outlinedColor": darker, + color: darker, + }), + ...(mainChannel && { + "--variant-outlinedBorder": `rgba(${mainChannel} / 0.7)`, + borderColor: `rgba(${mainChannel} / 0.7)`, + }), + }; + } + + if (variant === "text") { + return { + ...base, + ...(darker && { "--variant-textColor": darker, color: darker }), + }; + } + + return base; + }, + }, + }, + + MuiChip: { + styleOverrides: { + root: ({ ownerState }) => { + const base = { + "& .MuiChip-icon, & .MuiChip-deleteIcon": { + color: "currentColor", + }, + } as const; + + const isDefault = (ownerState.color ?? "default") === "default"; + const isOutlined = ownerState.variant === "outlined"; + const isInteractive = ownerState.clickable || ownerState.onDelete; + + if (isDefault) { + return { + ...base, + color: "var(--ds-olive-12)", + borderColor: "var(--ds-border-strong)", + backgroundColor: isOutlined + ? "transparent" + : "var(--ds-olive-4)", + + ...(isInteractive && { + "&:hover": { + backgroundColor: isOutlined + ? "var(--ds-overlay-hover)" + : "var(--ds-olive-5)", + }, + }), + }; + } + + return base; + }, + + outlinedPrimary: ({ theme }) => ({ + color: theme.palette.primary.darker ?? theme.palette.primary.dark, + borderColor: `rgba(${theme.palette.primary.darkChannel ?? theme.palette.primary.mainChannel} / 0.7)`, + }), + outlinedSecondary: ({ theme }) => ({ + color: theme.palette.secondary.dark, + borderColor: `rgba(${theme.palette.secondary.darkChannel ?? theme.palette.secondary.mainChannel} / 0.7)`, + }), + outlinedError: ({ theme }) => ({ + color: theme.palette.error.darker ?? theme.palette.error.dark, + borderColor: `rgba(${theme.palette.error.darkChannel ?? theme.palette.error.mainChannel} / 0.7)`, + }), + outlinedWarning: ({ theme }) => ({ + color: theme.palette.warning.darker ?? theme.palette.warning.dark, + borderColor: `rgba(${theme.palette.warning.darkChannel ?? theme.palette.warning.mainChannel} / 0.7)`, + }), + outlinedInfo: ({ theme }) => ({ + color: theme.palette.info.darker ?? theme.palette.info.dark, + borderColor: `rgba(${theme.palette.info.darkChannel ?? theme.palette.info.mainChannel} / 0.7)`, + }), + outlinedSuccess: ({ theme }) => ({ + color: theme.palette.success.darker ?? theme.palette.success.dark, + borderColor: `rgba(${theme.palette.success.darkChannel ?? theme.palette.success.mainChannel} / 0.7)`, + }), + }, + }, + + MuiCheckbox: { + defaultProps: { + icon: React.createElement(DsCheckboxBlankIcon), + checkedIcon: React.createElement(DsCheckboxCheckedIcon), + indeterminateIcon: React.createElement(DsCheckboxIndeterminateIcon), + }, + styleOverrides: { + root: ({ ownerState, theme }) => { + const base = { + "&:hover, &.Mui-focusVisible": { backgroundColor: "transparent" }, + } as const; + + // ✅ Disabled wins over everything + if (ownerState.disabled) { + return { + ...base, + + // Force disabled look regardless of colour/default/anything + color: "var(--ds-fg-disabled)", + + // Ensure our DS icons render as outlined when disabled + "--ds-checkbox-box-fill": "none", + "--ds-checkbox-box-stroke": "var(--ds-fg-disabled)", + "--ds-checkbox-box-strokeWidth": "2", + + // Disabled glyph colour (tick/bar) + "--ds-checkbox-glyph": "var(--ds-fg-disabled)", + } as any; + } + + const raw = (ownerState.color ?? "default") as + | "default" + | "primary" + | "secondary" + | "error" + | "warning" + | "info" + | "success"; + + const isDefault = raw === "default"; + const colour = raw as Exclude<typeof raw, "default">; + + const varsPalette = !isDefault + ? (theme as any).vars?.palette?.[colour] + : null; + const fallbackPalette = !isDefault + ? (theme.palette as any)[colour] + : null; + + const selectedMain = isDefault + ? "var(--ds-olive-9)" // if someone sets color="default", selected remains neutral + : (varsPalette?.main ?? fallbackPalette?.main); + + const selectedMainChannel = isDefault + ? null + : (varsPalette?.mainChannel ?? fallbackPalette?.mainChannel); + + // Unchecked (enabled) should always look "default" + const uncheckedOutline = "var(--ds-olive-9)"; // or var(--ds-gray-9) + + return { + ...base, + + // ✅ Unchecked: neutral outline, regardless of intent colour + "&:not(.Mui-checked):not(.MuiCheckbox-indeterminate)": { + color: uncheckedOutline, + + // If DS icon variables are ever used pre-fill, keep it outlined + "--ds-checkbox-box-fill": "none", + "--ds-checkbox-box-stroke": uncheckedOutline, + "--ds-checkbox-box-strokeWidth": "2", + }, + + // ✅ Checked: solid fill in intent colour + white tick + "&.Mui-checked": { + color: selectedMain, + "--ds-checkbox-box-fill": "currentColor", + "--ds-checkbox-box-stroke": "none", + "--ds-checkbox-box-strokeWidth": "0", + "--ds-checkbox-glyph": "var(--ds-white)", + }, + + // ✅ Indeterminate: “outlined button feel” in intent colour + "&.MuiCheckbox-indeterminate": { + color: selectedMain, + "--ds-checkbox-box-fill": "none", + "--ds-checkbox-box-stroke": "currentColor", + "--ds-checkbox-box-strokeWidth": "2", + "--ds-checkbox-glyph": "currentColor", + }, + + // Optional: hover tint for selected states only + ...(selectedMainChannel && { + "&.Mui-checked:hover, &.MuiCheckbox-indeterminate:hover": { + backgroundColor: `rgba(${selectedMainChannel} / ${theme.palette.action.hoverOpacity})`, + }, + }), + }; + }, + }, + }, + }, + }); + + return createTheme(DiamondDSThemeOptions); +}; +export const DiamondDSTheme = createMuiTheme("light"); +export const DiamondDSThemeDark = createMuiTheme("dark"); diff --git a/src/themes/ThemeProvider.tsx b/src/themes/ThemeProvider.tsx index d4328d3..fdcf100 100644 --- a/src/themes/ThemeProvider.tsx +++ b/src/themes/ThemeProvider.tsx @@ -1,26 +1,41 @@ -import { ThemeProvider as Mui_ThemeProvider } from "@mui/material/styles"; +import React, { useLayoutEffect, useMemo } from "react"; import { CssBaseline } from "@mui/material"; -import { GenericTheme } from "./GenericTheme"; -import { ThemeProviderProps as Mui_ThemeProviderProps } from "@mui/material/styles/ThemeProvider"; +import { ThemeProvider as MuiThemeProvider } from "@mui/material/styles"; +import { ThemeProviderProps as MuiThemeProviderProps } from "@mui/material/styles/ThemeProvider"; +import { createMuiTheme } from "./DiamondDSTheme"; +import type { DSMode } from "./DiamondDSTheme"; -interface ThemeProviderProps extends Partial<Mui_ThemeProviderProps> { +interface ThemeProviderProps extends Partial<MuiThemeProviderProps> { baseline?: boolean; + mode: DSMode; // controlled (source of truth) } -const ThemeProvider = function ({ +export function ThemeProvider({ children, - theme = GenericTheme, baseline = true, defaultMode = "system", + mode, ...props }: ThemeProviderProps) { + useLayoutEffect(() => { + const root = document.documentElement; + + // single source of truth for variables + root.setAttribute("data-mode", mode); + + // optional: keep classes for convenience, but NOT for variables + root.classList.toggle("dark", mode === "dark"); + root.classList.toggle("light", mode === "light"); + + // help UA styles / scrollbars + root.style.colorScheme = mode; + }, [mode]); + + const theme = useMemo(() => createMuiTheme(mode), [mode]); return ( - <Mui_ThemeProvider theme={theme} defaultMode={defaultMode} {...props}> + <MuiThemeProvider theme={theme} defaultMode={defaultMode} {...props}> {baseline && <CssBaseline />} {children} - </Mui_ThemeProvider> + </MuiThemeProvider> ); -}; - -export { ThemeProvider }; -export type { ThemeProviderProps }; +} diff --git a/src/themes/icons/CheckboxIcons.tsx b/src/themes/icons/CheckboxIcons.tsx new file mode 100644 index 0000000..2eb3412 --- /dev/null +++ b/src/themes/icons/CheckboxIcons.tsx @@ -0,0 +1,45 @@ +import * as React from "react"; +import SvgIcon, { SvgIconProps } from "@mui/material/SvgIcon"; + +const BoxPath = (props: React.SVGProps<SVGPathElement>) => ( + <path + d="M19 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.11 0 2-.9 2-2V5c0-1.1-.89-2-2-2z" + fill="var(--ds-checkbox-box-fill, none)" + stroke="var(--ds-checkbox-box-stroke, currentColor)" + strokeWidth="var(--ds-checkbox-box-strokeWidth, 2)" + strokeLinejoin="round" + {...props} + /> +); + +/** Unchecked (outline only) */ +export function DsCheckboxBlankIcon(props: SvgIconProps) { + return ( + <SvgIcon {...props} viewBox="0 0 24 24"> + <BoxPath /> + </SvgIcon> + ); +} + +/** Checked (fill + tick) */ +export function DsCheckboxCheckedIcon(props: SvgIconProps) { + return ( + <SvgIcon {...props} viewBox="0 0 24 24"> + <BoxPath /> + <path + d="M10 14.17l-3.59-3.58L5 12l5 5 9-9-1.41-1.41z" + fill="var(--ds-checkbox-glyph, var(--ds-white))" + /> + </SvgIcon> + ); +} + +/** Indeterminate (outlined feel by default via vars, bar uses glyph var) */ +export function DsCheckboxIndeterminateIcon(props: SvgIconProps) { + return ( + <SvgIcon {...props} viewBox="0 0 24 24"> + <BoxPath /> + <path d="M7 11h10v2H7z" fill="var(--ds-checkbox-glyph, currentColor)" /> + </SvgIcon> + ); +} diff --git a/src/themes/icons/index.ts b/src/themes/icons/index.ts new file mode 100644 index 0000000..ab573c6 --- /dev/null +++ b/src/themes/icons/index.ts @@ -0,0 +1 @@ +export * from "./CheckboxIcons"; From 8d4c32e19621249f9702a278044b60bdb7f20b60 Mon Sep 17 00:00:00 2001 From: Zohar Manor-Abel <zohar.manor-abel@diamond.ac.uk> Date: Tue, 27 Jan 2026 11:14:16 +0000 Subject: [PATCH 07/10] Fix multiple issues Fixed build errors updated brand bg color and some colour schemes fixed colour scheme Updated input colours fix duplicate issue and update colours mdx with recent changes fix build error Update border colours fixing build errors Fix hover colours for border errors brought back dark theme as it was deleted by mistake + changes to colour documentation Changes to lighter colour --- src/storybook/foundation/colours.mdx | 200 ++++--- .../diamondDS/diamond-colors-primitives.css | 21 +- src/themes/DiamondDSTheme.ts | 490 +++++++++++++++--- src/themes/ThemeProvider.tsx | 12 +- 4 files changed, 510 insertions(+), 213 deletions(-) diff --git a/src/storybook/foundation/colours.mdx b/src/storybook/foundation/colours.mdx index 0af345f..3b0ce84 100644 --- a/src/storybook/foundation/colours.mdx +++ b/src/storybook/foundation/colours.mdx @@ -6,8 +6,8 @@ import { Meta } from "@storybook/blocks"; .ds-note { margin: 12px 0 20px; padding: 12px 14px; - border: 1px solid var(--ds-gray-6); - background: var(--ds-gray-2); + border: 1px solid var(--ds-olive-6); + background: var(--ds-olive-2); border-radius: 12px; } .ds-grid { @@ -17,15 +17,15 @@ import { Meta } from "@storybook/blocks"; margin: 14px 0 24px; } .ds-swatch { - border: 1px solid var(--ds-gray-6); + border: 1px solid var(--ds-olive-6); border-radius: 14px; - background: var(--ds-gray-2); + background: var(--ds-olive-1); overflow: hidden; } .ds-swatch__chip { height: 56px; background: var(--swatch); - border-bottom: 1px solid var(--ds-gray-6); + border-bottom: 1px solid var(--ds-olive-6); } .ds-swatch__body { padding: 12px 12px 10px; @@ -33,17 +33,18 @@ import { Meta } from "@storybook/blocks"; .ds-swatch__name { font-weight: 600; margin: 0 0 6px; - color: var(--ds-gray-12); + color: var(--ds-olive-12); } .ds-swatch__meta { margin: 0; padding-left: 16px; - color: var(--ds-gray-11); + color: var(--ds-olive-11); font-size: 14px; line-height: 20px; } .ds-swatch__meta li { margin: 2px 0; + list-style-type: none; } .ds-row { display: flex; @@ -57,35 +58,43 @@ import { Meta } from "@storybook/blocks"; gap: 8px; padding: 6px 10px; border-radius: 999px; - border: 1px solid var(--ds-gray-6); - background: var(--ds-gray-1); - color: var(--ds-gray-12); + border: 1px solid var(--ds-olive-6); + background: var(--ds-olive-1); + color: var(--ds-olive-12); font-size: 13px; line-height: 18px; } + .text-inverse { + color: var(--ds-olive-1); + } .ds-dot { - width: 10px; - height: 10px; + width: 12px; + height: 12px; border-radius: 999px; background: var(--dot); border: 1px solid rgba(0,0,0,0.12); + display: inline-block; + } + li .ds-dot { + margin-left: -16px; + margin-right: 8px; } .ds-surface-demo { - border: 1px solid var(--ds-gray-6); + border: 1px solid var(--ds-olive-6); border-radius: 14px; - background: var(--ds-gray-1); + background: var(--ds-olive-1); padding: 14px; margin: 14px 0 24px; } .ds-surface-card { - border: 1px solid var(--ds-gray-6); - background: var(--ds-gray-2); + border: 1px solid var(--ds-olive-6); + background: var(--ds-olive-2); border-radius: 12px; padding: 12px; } .ds-divider { height: 1px; - background: var(--ds-gray-6); + background: var(--ds-olive-6); margin: 12px 0; } .ds-text-demo p { @@ -98,14 +107,14 @@ import { Meta } from "@storybook/blocks"; margin-top: 12px; } .ds-overlay-tile { - border: 1px solid var(--ds-gray-6); + border: 1px solid var(--ds-olive-6); border-radius: 12px; - background: var(--ds-gray-2); + background: var(--ds-olive-2); overflow: hidden; } .ds-overlay-tile__top { height: 56px; - background: var(--ds-gray-2); + background: var(--ds-olive-2); position: relative; } .ds-overlay-tile__overlay { @@ -115,7 +124,7 @@ import { Meta } from "@storybook/blocks"; } .ds-overlay-tile__body { padding: 10px 12px; - color: var(--ds-gray-12); + color: var(--ds-olive-12); font-size: 13px; } `}</style> @@ -160,8 +169,8 @@ import { Meta } from "@storybook/blocks"; <div className="ds-note"> <strong>What changed:</strong> the palette now exposes more layers per intent - colour: ` light → main → dark → darker`, plus `*Channel` tokens for - alpha-based overlays. Also added `brand` colour scheme. + colour: ` lighter → light → main → dark → darker`, plus `*Channel` tokens for + alpha-based overlays. Also added `brand` colour scheme, fixed background colours </div> {" "} @@ -180,10 +189,12 @@ import { Meta } from "@storybook/blocks"; <div className="ds-swatch__body"> <p className="ds-swatch__name">Primary</p> <ul className="ds-swatch__meta"> - <li><strong>light</strong>: `--ds-indigo-8`</li> - <li><strong>main</strong>: `--ds-indigo-9`</li> - <li><strong>dark</strong>: `--ds-indigo-10`</li> - <li><strong>darker</strong>: `--ds-indigo-11`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-indigo-7)' }} /> <strong>lighter</strong>: `--ds-indigo-7`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-indigo-8)' }} /> <strong>light</strong>: `--ds-indigo-8`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-indigo-9)' }} /> <strong>main</strong>: `--ds-indigo-9`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-indigo-10)' }} /> <strong>dark</strong>: `--ds-indigo-10`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-indigo-11)' }} /> <strong>darker</strong>: `--ds-indigo-11`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-indigo-12)' }} /> <strong>darkest</strong>: `--ds-indigo-12`</li> <li><strong>contrast text</strong>: `--ds-fg-fixed-white`</li> <li><strong>mainChannel</strong>: `--ds-indigo-9Channel`</li> <li><strong>lightChannel</strong>: `--ds-indigo-8Channel`</li> @@ -193,10 +204,8 @@ import { Meta } from "@storybook/blocks"; <li><strong>bgSurface2</strong>: <code>--ds-indigo-3</code></li> </ul> <div className="ds-row"> - <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-indigo-8)' }} /> light</span> - <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-indigo-9)' }} /> main</span> - <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-indigo-10)' }} /> dark</span> - <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-indigo-11)' }} /> darker</span> + <span className="ds-pill text-inverse" style={{ ['background']: 'var(--ds-indigo-9)' }} > main</span> + <span className="ds-pill text-inverse" style={{ ['background']: 'var(--ds-indigo-10)' }} > dark</span> <span className="ds-pill" style={{ ['background']: 'var(--ds-indigo-1)' }} > canvas</span> <span className="ds-pill" style={{ ['background']: 'var(--ds-indigo-2)' }} > surface1</span> <span className="ds-pill" style={{ ['background']: 'var(--ds-indigo-3)' }} > surface2</span> @@ -210,10 +219,12 @@ import { Meta } from "@storybook/blocks"; <div className="ds-swatch__body"> <p className="ds-swatch__name">Secondary</p> <ul className="ds-swatch__meta"> - <li><strong>light</strong>: `--ds-navy-8`</li> - <li><strong>main</strong>: `--ds-navy-9`</li> - <li><strong>dark</strong>: `--ds-navy-10`</li> - <li><strong>darker</strong>: `--ds-navy-11`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-7)' }} /> <strong>lighter</strong>: `--ds-navy-7`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-8)' }} /> <strong>light</strong>: `--ds-navy-8`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-9)' }} /> <strong>main</strong>: `--ds-navy-9`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-10)' }} /> <strong>dark</strong>: `--ds-navy-10`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-11)' }} /> <strong>darker</strong>: `--ds-navy-11`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-12)' }} /> <strong>darkest</strong>: `--ds-navy-12`</li> <li><strong>contrast text</strong>: `--ds-fg-fixed-white`</li> <li><strong>mainChannel</strong>: `--ds-navy-9Channel`</li> <li><strong>lightChannel</strong>: `--ds-navy-8Channel`</li> @@ -223,10 +234,8 @@ import { Meta } from "@storybook/blocks"; <li><strong>bgSurface2</strong>: <code>--ds-navy-3</code></li> </ul> <div className="ds-row"> - <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-8)' }} /> light</span> - <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-9)' }} /> main</span> - <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-10)' }} /> dark</span> - <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-11)' }} /> darker</span> + <span className="ds-pill text-inverse" style={{ ['background']: 'var(--ds-navy-9)' }} > main</span> + <span className="ds-pill text-inverse" style={{ ['background']: 'var(--ds-navy-10)' }} > dark</span> <span className="ds-pill" style={{ ['background']: 'var(--ds-navy-1)' }} > canvas</span> <span className="ds-pill" style={{ ['background']: 'var(--ds-navy-2)' }} > surface1</span> <span className="ds-pill" style={{ ['background']: 'var(--ds-navy-3)' }} > surface2</span> @@ -240,20 +249,11 @@ import { Meta } from "@storybook/blocks"; <div className="ds-swatch__body"> <p className="ds-swatch__name">Brand</p> <ul className="ds-swatch__meta"> - <li><strong>light</strong>: `--ds-navy-9`</li> - <li><strong>main</strong>: `--ds-navy-10`</li> - <li><strong>dark</strong>: `--ds-navy-11`</li> - <li><strong>darker</strong>: `--ds-navy-12`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-10)' }} /> <strong>main</strong>: `--ds-navy-10`</li> <li><strong>contrast text</strong>: `--ds-fg-fixed-white`</li> - <li><strong>mainChannel</strong>: `--ds-navy-10Channel`</li> - <li><strong>lightChannel</strong>: `--ds-navy-9Channel`</li> - <li><strong>darkChannel</strong>: `--ds-navy-11Channel`</li> </ul> <div className="ds-row"> - <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-9)' }} /> light</span> - <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-10)' }} /> main</span> - <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-11)' }} /> dark</span> - <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-navy-12)' }} /> darker</span> + <span className="ds-pill text-inverse" style={{ ['background']: 'var(--ds-navy-10)' }} > main</span> </div> </div> </div> @@ -264,10 +264,12 @@ import { Meta } from "@storybook/blocks"; <div className="ds-swatch__body"> <p className="ds-swatch__name">Success</p> <ul className="ds-swatch__meta"> - <li><strong>light</strong>: `--ds-green-8`</li> - <li><strong>main</strong>: `--ds-green-9`</li> - <li><strong>dark</strong>: `--ds-green-10`</li> - <li><strong>darker</strong>: `--ds-green-11`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-green-7)' }} /> <strong>lighter</strong>: `--ds-green-7`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-green-8)' }} /> <strong>light</strong>: `--ds-green-8`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-green-9)' }} /> <strong>main</strong>: `--ds-green-9`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-green-10)' }} /> <strong>dark</strong>: `--ds-green-10`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-green-11)' }} /> <strong>darker</strong>: `--ds-green-11`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-green-12)' }} /> <strong>darkest</strong>: `--ds-green-12`</li> <li><strong>contrast text</strong>: `--ds-fg-fixed-white`</li> <li><strong>mainChannel</strong>: `--ds-green-9Channel`</li> <li><strong>bgCanvas</strong>: <code>--ds-green-1</code></li> @@ -275,10 +277,8 @@ import { Meta } from "@storybook/blocks"; <li><strong>bgSurface2</strong>: <code>--ds-green-3</code></li> </ul> <div className="ds-row"> - <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-green-8)' }} /> light</span> - <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-green-9)' }} /> main</span> - <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-green-10)' }} /> dark</span> - <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-green-11)' }} /> darker</span> + <span className="ds-pill text-inverse" style={{ ['background']: 'var(--ds-green-9)' }} > main</span> + <span className="ds-pill text-inverse" style={{ ['background']: 'var(--ds-green-10)' }} > dark</span> <span className="ds-pill" style={{ ['background']: 'var(--ds-green-1)' }} > canvas</span> <span className="ds-pill" style={{ ['background']: 'var(--ds-green-2)' }} > surface1</span> <span className="ds-pill" style={{ ['background']: 'var(--ds-green-3)' }} > surface2</span> @@ -292,10 +292,12 @@ import { Meta } from "@storybook/blocks"; <div className="ds-swatch__body"> <p className="ds-swatch__name">Warning</p> <ul className="ds-swatch__meta"> - <li><strong>light</strong>: `--ds-orange-8`</li> - <li><strong>main</strong>: `--ds-orange-9`</li> - <li><strong>dark</strong>: `--ds-orange-10`</li> - <li><strong>darker</strong>: `--ds-orange-11`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-orange-7)' }} /> <strong>lighter</strong>: `--ds-orange-7`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-orange-8)' }} /> <strong>light</strong>: `--ds-orange-8`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-orange-9)' }} /> <strong>main</strong>: `--ds-orange-9`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-orange-10)' }} /> <strong>dark</strong>: `--ds-orange-10`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-orange-11)' }} /> <strong>darker</strong>: `--ds-orange-11`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-orange-12)' }} /> <strong>darkest</strong>: `--ds-orange-12`</li> <li><strong>contrast text</strong>: `--ds-fg-fixed-white`</li> <li><strong>mainChannel</strong>: `--ds-orange-9Channel`</li> <li><strong>bgCanvas</strong>: <code>--ds-orange-1</code></li> @@ -303,10 +305,8 @@ import { Meta } from "@storybook/blocks"; <li><strong>bgSurface2</strong>: <code>--ds-orange-3</code></li> </ul> <div className="ds-row"> - <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-orange-8)' }} /> light</span> - <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-orange-9)' }} /> main</span> - <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-orange-10)' }} /> dark</span> - <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-orange-11)' }} /> darker</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-orange-9)' }} > main</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-orange-10)' }} > dark</span> <span className="ds-pill" style={{ ['background']: 'var(--ds-orange-1)' }} > canvas</span> <span className="ds-pill" style={{ ['background']: 'var(--ds-orange-2)' }} > surface1</span> <span className="ds-pill" style={{ ['background']: 'var(--ds-orange-3)' }} > surface2</span> @@ -320,10 +320,12 @@ import { Meta } from "@storybook/blocks"; <div className="ds-swatch__body"> <p className="ds-swatch__name">Error</p> <ul className="ds-swatch__meta"> - <li><strong>light</strong>: `--ds-red-8`</li> - <li><strong>main</strong>: `--ds-red-9`</li> - <li><strong>dark</strong>: `--ds-red-10`</li> - <li><strong>darker</strong>: `--ds-red-11`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-red-7)' }} /> <strong>lighter</strong>: `--ds-red-7`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-red-8)' }} /> <strong>light</strong>: `--ds-red-8`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-red-9)' }} /> <strong>main</strong>: `--ds-red-9`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-red-10)' }} /> <strong>dark</strong>: `--ds-red-10`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-red-11)' }} /> <strong>darker</strong>: `--ds-red-11`</li> + <li><span className="ds-dot" style={{ ['--dot']: 'var(--ds-red-12)' }} /> <strong>darkest</strong>: `--ds-red-12`</li> <li><strong>contrast text</strong>: `--ds-fg-fixed-white`</li> <li><strong>mainChannel</strong>: `--ds-red-9Channel`</li> <li><strong>bgCanvas</strong>: <code>--ds-red-1</code></li> @@ -331,10 +333,8 @@ import { Meta } from "@storybook/blocks"; <li><strong>bgSurface2</strong>: <code>--ds-red-3</code></li> </ul> <div className="ds-row"> - <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-red-8)' }} /> light</span> - <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-red-9)' }} /> main</span> - <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-red-10)' }} /> dark</span> - <span className="ds-pill"><span className="ds-dot" style={{ ['--dot']: 'var(--ds-red-11)' }} /> darker</span> + <span className="ds-pill text-inverse" style={{ ['background']: 'var(--ds-red-9)' }} > main</span> + <span className="ds-pill text-inverse" style={{ ['background']: 'var(--ds-red-10)' }} > dark</span> <span className="ds-pill" style={{ ['background']: 'var(--ds-red-1)' }} > canvas</span> <span className="ds-pill" style={{ ['background']: 'var(--ds-red-2)' }} > surface1</span> <span className="ds-pill" style={{ ['background']: 'var(--ds-red-3)' }} > surface2</span> @@ -366,45 +366,21 @@ import { Meta } from "@storybook/blocks"; </li> </ul> <div className="ds-row"> - <span - className="ds-pill" - style={{ ["background"]: "var(--ds-bg-canvas)" }} - > - {" "} - canvas - </span> - <span - className="ds-pill" - style={{ ["background"]: "var(--ds-bg-paper)" }} - > - {" "} - paper - </span> - <span - className="ds-pill" - style={{ ["background"]: "var(--ds-bg-surface-1)" }} - > - {" "} - surface1 - </span> - <span - className="ds-pill" - style={{ ["background"]: "var(--ds-bg-surface-2)" }} - > - {" "} - surface2 - </span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-bg-canvas)' }} > canvas</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-bg-paper)' }} > paper</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-bg-surface-1)' }} > surface1</span> + <span className="ds-pill" style={{ ['background']: 'var(--ds-bg-surface-2)' }} > surface2</span> </div> </div> </div> {/* Divider */} - <div className="ds-swatch" style={{ ['--swatch']: 'var(--ds-gray-6)' }}> + <div className="ds-swatch" style={{ ['--swatch']: 'var(--ds-olive-6)' }}> <div className="ds-swatch__chip" /> <div className="ds-swatch__body"> <p className="ds-swatch__name">Divider</p> <ul className="ds-swatch__meta"> - <li><strong>divider</strong>: `--ds-gray-6`</li> + <li><strong>divider</strong>: `--ds-olive-6`</li> </ul> </div> </div> @@ -415,18 +391,18 @@ import { Meta } from "@storybook/blocks"; <div className="ds-surface-demo"> <div className="ds-surface-card"> <div className="ds-text-demo"> - <p style={{ color: "var(--ds-gray-12)" }}> - <strong>Text primary</strong> → `--ds-gray-12` + <p style={{ color: "var(--ds-olive-12)" }}> + <strong>Text primary</strong> → `--ds-olive-12` </p> - <p style={{ color: "var(--ds-gray-11)" }}> - Text secondary → `--ds-gray-11` + <p style={{ color: "var(--ds-olive-11)" }}> + Text secondary → `--ds-olive-11` </p> - <p style={{ color: "var(--ds-gray-8)" }}>Text disabled → `--ds-gray-8`</p> + <p style={{ color: "var(--ds-olive-8)" }}>Text disabled → `--ds-olive-8`</p> </div> <div className="ds-divider" /> - <p style={{ margin: 0, color: "var(--ds-gray-11)" }}> - Canvas uses `--ds-gray-1` and surfaces use `--ds-gray-2`. Divider uses - `--ds-gray-6`. + <p style={{ margin: 0, color: "var(--ds-olive-11)" }}> + Canvas uses `--ds-olive-1` and surfaces use `--ds-olive-2`. Divider uses + `--ds-olive-6`. </p> </div> </div> diff --git a/src/styles/diamondDS/diamond-colors-primitives.css b/src/styles/diamondDS/diamond-colors-primitives.css index a9a898a..c57cbb8 100644 --- a/src/styles/diamondDS/diamond-colors-primitives.css +++ b/src/styles/diamondDS/diamond-colors-primitives.css @@ -29,9 +29,15 @@ --ds-whiteChannel: 255 255 255; /* Disabled tokens (semantic) */ - --ds-fg-disabled: var(--ds-gray-8); - --ds-border-disabled: var(--ds-gray-6); - --ds-bg-disabled: var(--ds-gray-2); + --ds-fg-disabled: var(--ds-olive-8); + --ds-border-disabled: var(--ds-olive-6); + --ds-bg-disabled: var(--ds-olive-a3); + + /* Borders */ + --ds-border-subtle: var(--ds-olive-6); /* Structural, non-interactive */ + --ds-border-strong: var(--ds-olive-7); /* Interactive baseline */ + --ds-border-stronger: var(--ds-olive-8); /* Hover emphasis */ + } :root, .light, :root[data-mode="light"] { /*LIGHT MODE */ @@ -59,10 +65,6 @@ --ds-bg-surface-1: var(--ds-olive-2); --ds-bg-surface-2: var(--ds-olive-3); - /* Borders */ - --ds-border-subtle: var(--ds-olive-6); - --ds-border-strong: var(--ds-olive-7); - /* Radix based colours */ --ds-gray-1:#fcfcfc; --ds-gray-2:#f9f9f9; @@ -359,6 +361,7 @@ --ds-red-5: #ffcdc2; --ds-red-6: #fdbdaf; --ds-red-7: #f5a898; + --ds-red-8: #ec8e7b; --ds-red-9: #e54d2e; --ds-red-10: #E10600; /* brand */ --ds-red-11: #d13415; @@ -486,10 +489,6 @@ --ds-bg-surface-1: var(--ds-olive-3); --ds-bg-surface-2: var(--ds-olive-4); - /* Borders */ - --ds-border-subtle: var(--ds-olive-6); - --ds-border-strong: var(--ds-olive-7); - /* Radix based colours */ --ds-gray-1:#111; --ds-gray-2:#191919; diff --git a/src/themes/DiamondDSTheme.ts b/src/themes/DiamondDSTheme.ts index 24e3a87..400879e 100644 --- a/src/themes/DiamondDSTheme.ts +++ b/src/themes/DiamondDSTheme.ts @@ -1,7 +1,26 @@ import "../styles/diamondDS/diamond-colors-primitives.css"; import type {} from "@mui/material/themeCssVarsAugmentation"; -import { createTheme, Theme } from "@mui/material/styles"; +import { createTheme } from "@mui/material/styles"; +import type { Theme } from "@mui/material/styles"; +import type { CSSObject } from "@mui/material/styles"; + +import type { ButtonProps } from "@mui/material/Button"; +import type { ChipProps } from "@mui/material/Chip"; +import type { CheckboxProps } from "@mui/material/Checkbox"; +import type { InputProps } from "@mui/material/Input"; +import type { InputBaseProps } from "@mui/material/InputBase"; +import type { FilledInputProps } from "@mui/material/FilledInput"; +import type { OutlinedInputProps } from "@mui/material/OutlinedInput"; +import type { InputLabelProps } from "@mui/material/InputLabel"; + +import { dark } from "@mui/material/styles/createPalette"; + +type OverrideArgs<OwnerState = unknown> = { + ownerState: OwnerState; + theme: Theme; +}; +type ThemeOnlyArgs = { theme: Theme }; import { mergeThemeOptions } from "./ThemeManager"; @@ -16,21 +35,65 @@ import { DsCheckboxIndeterminateIcon, } from "./icons"; +/** MUI module augmentation for custom properties */ declare module "@mui/material/styles" { interface TypeBackground { + default: string; + paper: string; surface1?: string; surface2?: string; } + + interface Palette { + brand?: PaletteColor; + + borders: { + subtle: string; + strong: string; + stronger: string; + }; + } + + interface PaletteOptions { + brand?: SimplePaletteColorOptions; + + borders?: { + subtle?: string; + strong?: string; + stronger?: string; + }; + } + interface PaletteColor { + lighter?: string; + darkest?: string; + darker?: string; + mainChannel?: string; + lightChannel?: string; + darkChannel?: string; + bgCanvas?: string; bgSurface1?: string; bgSurface2?: string; } + interface SimplePaletteColorOptions { + lighter?: string; + darkest?: string; + darker?: string; + mainChannel?: string; + lightChannel?: string; + darkChannel?: string; + bgCanvas?: string; bgSurface1?: string; bgSurface2?: string; } + + interface TypeText { + placeholder?: string; + placeholderFocus?: string; + } } export type DSMode = "light" | "dark"; @@ -53,8 +116,7 @@ export const createMuiTheme = (mode: DSMode): Theme => { logos: { normal: { - src: - mode === "dark" ? (logoImageDark ?? logoImageLight) : logoImageLight, + src: mode === "dark" ? (logoImageDark ?? logoImageLight) : logoImageLight, srcDark: logoImageDark ?? logoImageLight, alt: "Diamond Light Source Logo", width: "100", @@ -77,34 +139,44 @@ export const createMuiTheme = (mode: DSMode): Theme => { disabled: "var(--ds-overlay-disabled)", disabledBackground: "var(--ds-overlay-disabled-bg)", - hoverOpacity: 0.08, - selectedOpacity: 0.12, + hoverOpacity: 0.12, + selectedOpacity: 0.16, disabledOpacity: 0.38, - focusOpacity: 0.12, + focusOpacity: 0.16, }, text: { - primary: "var(--ds-gray-12)", - secondary: "var(--ds-gray-11)", - disabled: "var(--ds-gray-8)", + primary: "var(--ds-olive-12)", // main text, input value + secondary: "var(--ds-olive-11)", // secondary text, helper text, labels + disabled: "var(--ds-olive-9)", // disabled text + + placeholder: "var(--ds-olive-10)", // default hint text (if not secondary) + placeholderFocus: "var(--ds-olive-9)", // optional, calmer on focus }, background: { - default: "var(--ds-bg-canvas)", // page / app shell - paper: "var(--ds-bg-paper)", // cards, dialogs - outlinedBg: "var(--ds-bg-surface-2)", // inputs, outlined containers - surface1: "var(--ds-bg-surface-1)", - surface2: "var(--ds-bg-surface-2)", + default: "var(--ds-bg-canvas)", // page background + paper: "var(--ds-bg-paper)", // cards, sheets, menus, etc. + surface1: "var(--ds-bg-surface-1)", // e.g. cards + surface2: "var(--ds-bg-surface-2)", // e.g. inputs, outlined containers }, - divider: "var(--ds-border-subtle)", + divider: "var(--ds-border-subtle)", // Structural, non-interactive dividerInverse: "var(--ds-white-a4)", + borders: { + subtle: "var(--ds-border-subtle)", // Structural, non-interactive + strong: "var(--ds-border-strong)", // Interactive baseline + stronger: "var(--ds-border-stronger)", // hover emphasis + }, + primary: { - main: "var(--ds-indigo-9)", + lighter: "var(--ds-indigo-7)", light: "var(--ds-indigo-8)", + main: "var(--ds-indigo-9)", dark: "var(--ds-indigo-10)", darker: "var(--ds-indigo-11)", + darkest: "var(--ds-indigo-12)", contrastText: "var(--ds-fg-fixed-white)", mainChannel: "var(--ds-indigo-9Channel)", @@ -117,10 +189,12 @@ export const createMuiTheme = (mode: DSMode): Theme => { }, secondary: { - main: "var(--ds-navy-9)", + lighter: "var(--ds-navy-7)", light: "var(--ds-navy-8)", + main: "var(--ds-navy-9)", dark: "var(--ds-navy-10)", darker: "var(--ds-navy-11)", + darkest: "var(--ds-navy-12)", contrastText: "var(--ds-fg-fixed-white)", mainChannel: "var(--ds-navy-9Channel)", @@ -132,23 +206,18 @@ export const createMuiTheme = (mode: DSMode): Theme => { bgSurface2: "var(--ds-navy-3)", }, - brand: { - main: "var(--ds-navy-10)", - light: "var(--ds-navy-9)", - dark: "var(--ds-navy-11)", - darker: "var(--ds-navy-12)", + brand: { // Brand colore (same as ds-navy-10) for background use + main: "var(--ds-bg-brand)", // Stays the same on light/dark modes contrastText: "var(--ds-fg-fixed-white)", - - mainChannel: "var(--ds-navy-10Channel)", - lightChannel: "var(--ds-navy-9Channel)", - darkChannel: "var(--ds-navy-11Channel)", }, error: { - main: "var(--ds-red-10)", - light: "var(--ds-red-9)", - dark: "var(--ds-red-11)", + lighter: "var(--ds-red-7)", + light: "var(--ds-red-8)", + main: "var(--ds-red-9)", + dark: "var(--ds-red-10)", darker: "var(--ds-red-11)", + darkest: "var(--ds-red-12)", contrastText: "var(--ds-fg-fixed-white)", mainChannel: "var(--ds-red-9Channel)", @@ -161,10 +230,12 @@ export const createMuiTheme = (mode: DSMode): Theme => { }, warning: { - main: "var(--ds-orange-10)", - light: "var(--ds-orange-9)", - dark: "var(--ds-orange-11)", + lighter: "var(--ds-orange-7)", + light: "var(--ds-orange-8)", + main: "var(--ds-orange-9)", + dark: "var(--ds-orange-10)", darker: "var(--ds-orange-11)", + darkest: "var(--ds-orange-12)", contrastText: "var(--ds-fg-fixed-white)", mainChannel: "var(--ds-orange-9Channel)", @@ -177,10 +248,12 @@ export const createMuiTheme = (mode: DSMode): Theme => { }, success: { - main: "var(--ds-green-10)", - light: "var(--ds-green-9)", - dark: "var(--ds-green-11)", + lighter: "var(--ds-green-7)", + light: "var(--ds-green-8)", + main: "var(--ds-green-9)", + dark: "var(--ds-green-10)", darker: "var(--ds-green-11)", + darkest: "var(--ds-green-12)", contrastText: "var(--ds-fg-fixed-white)", mainChannel: "var(--ds-green-9Channel)", @@ -197,6 +270,7 @@ export const createMuiTheme = (mode: DSMode): Theme => { light: "var(--ds-indigo-8)", dark: "var(--ds-indigo-10)", darker: "var(--ds-indigo-11)", + darkest: "var(--ds-indigo-12)", contrastText: "var(--ds-fg-fixed-white)", mainChannel: "var(--ds-indigo-9Channel)", @@ -225,8 +299,10 @@ export const createMuiTheme = (mode: DSMode): Theme => { components: { MuiButton: { styleOverrides: { - root: ({ ownerState, theme }) => { - const base = { textTransform: "none" as const }; + root: ( + { ownerState, theme }: { ownerState: ButtonProps; theme: Theme } + ): CSSObject => { + const base: CSSObject = { textTransform: "none" }; const variant = ownerState.variant ?? "text"; @@ -264,14 +340,14 @@ export const createMuiTheme = (mode: DSMode): Theme => { "--variant-outlinedBorder": `rgba(${mainChannel} / 0.7)`, borderColor: `rgba(${mainChannel} / 0.7)`, }), - }; + } as CSSObject; } if (variant === "text") { return { ...base, ...(darker && { "--variant-textColor": darker, color: darker }), - }; + } as CSSObject; } return base; @@ -281,25 +357,21 @@ export const createMuiTheme = (mode: DSMode): Theme => { MuiChip: { styleOverrides: { - root: ({ ownerState }) => { - const base = { - "& .MuiChip-icon, & .MuiChip-deleteIcon": { - color: "currentColor", - }, - } as const; + root: ({ ownerState }: { ownerState: ChipProps }): CSSObject => { + const base: CSSObject = { + "& .MuiChip-icon, & .MuiChip-deleteIcon": { color: "currentColor" }, + }; const isDefault = (ownerState.color ?? "default") === "default"; const isOutlined = ownerState.variant === "outlined"; - const isInteractive = ownerState.clickable || ownerState.onDelete; + const isInteractive = !!(ownerState.clickable || ownerState.onDelete); if (isDefault) { return { ...base, color: "var(--ds-olive-12)", borderColor: "var(--ds-border-strong)", - backgroundColor: isOutlined - ? "transparent" - : "var(--ds-olive-4)", + backgroundColor: isOutlined ? "transparent" : "var(--ds-olive-4)", ...(isInteractive && { "&:hover": { @@ -308,33 +380,33 @@ export const createMuiTheme = (mode: DSMode): Theme => { : "var(--ds-olive-5)", }, }), - }; + } as CSSObject; } return base; }, - outlinedPrimary: ({ theme }) => ({ + outlinedPrimary: ({ theme }: { theme: Theme }): CSSObject => ({ color: theme.palette.primary.darker ?? theme.palette.primary.dark, borderColor: `rgba(${theme.palette.primary.darkChannel ?? theme.palette.primary.mainChannel} / 0.7)`, }), - outlinedSecondary: ({ theme }) => ({ + outlinedSecondary: ({ theme }: { theme: Theme }): CSSObject => ({ color: theme.palette.secondary.dark, borderColor: `rgba(${theme.palette.secondary.darkChannel ?? theme.palette.secondary.mainChannel} / 0.7)`, }), - outlinedError: ({ theme }) => ({ + outlinedError: ({ theme }: { theme: Theme }): CSSObject => ({ color: theme.palette.error.darker ?? theme.palette.error.dark, borderColor: `rgba(${theme.palette.error.darkChannel ?? theme.palette.error.mainChannel} / 0.7)`, }), - outlinedWarning: ({ theme }) => ({ + outlinedWarning: ({ theme }: { theme: Theme }): CSSObject => ({ color: theme.palette.warning.darker ?? theme.palette.warning.dark, borderColor: `rgba(${theme.palette.warning.darkChannel ?? theme.palette.warning.mainChannel} / 0.7)`, }), - outlinedInfo: ({ theme }) => ({ + outlinedInfo: ({ theme }: { theme: Theme }): CSSObject => ({ color: theme.palette.info.darker ?? theme.palette.info.dark, borderColor: `rgba(${theme.palette.info.darkChannel ?? theme.palette.info.mainChannel} / 0.7)`, }), - outlinedSuccess: ({ theme }) => ({ + outlinedSuccess: ({ theme }: { theme: Theme }): CSSObject => ({ color: theme.palette.success.darker ?? theme.palette.success.dark, borderColor: `rgba(${theme.palette.success.darkChannel ?? theme.palette.success.mainChannel} / 0.7)`, }), @@ -348,27 +420,24 @@ export const createMuiTheme = (mode: DSMode): Theme => { indeterminateIcon: React.createElement(DsCheckboxIndeterminateIcon), }, styleOverrides: { - root: ({ ownerState, theme }) => { - const base = { + root: ( + { ownerState, theme }: { ownerState: CheckboxProps; theme: Theme } + ): CSSObject => { + const base: CSSObject = { "&:hover, &.Mui-focusVisible": { backgroundColor: "transparent" }, - } as const; + }; - // ✅ Disabled wins over everything + // Disabled wins over everything if (ownerState.disabled) { return { ...base, - - // Force disabled look regardless of colour/default/anything color: "var(--ds-fg-disabled)", - // Ensure our DS icons render as outlined when disabled "--ds-checkbox-box-fill": "none", "--ds-checkbox-box-stroke": "var(--ds-fg-disabled)", "--ds-checkbox-box-strokeWidth": "2", - - // Disabled glyph colour (tick/bar) "--ds-checkbox-glyph": "var(--ds-fg-disabled)", - } as any; + } as unknown as CSSObject; } const raw = (ownerState.color ?? "default") as @@ -383,38 +452,29 @@ export const createMuiTheme = (mode: DSMode): Theme => { const isDefault = raw === "default"; const colour = raw as Exclude<typeof raw, "default">; - const varsPalette = !isDefault - ? (theme as any).vars?.palette?.[colour] - : null; - const fallbackPalette = !isDefault - ? (theme.palette as any)[colour] - : null; + const varsPalette = !isDefault ? (theme as any).vars?.palette?.[colour] : null; + const fallbackPalette = !isDefault ? (theme.palette as any)[colour] : null; const selectedMain = isDefault - ? "var(--ds-olive-9)" // if someone sets color="default", selected remains neutral + ? "var(--ds-olive-9)" : (varsPalette?.main ?? fallbackPalette?.main); const selectedMainChannel = isDefault ? null : (varsPalette?.mainChannel ?? fallbackPalette?.mainChannel); - // Unchecked (enabled) should always look "default" - const uncheckedOutline = "var(--ds-olive-9)"; // or var(--ds-gray-9) + const uncheckedOutline = "var(--ds-olive-9)"; return { ...base, - // ✅ Unchecked: neutral outline, regardless of intent colour "&:not(.Mui-checked):not(.MuiCheckbox-indeterminate)": { color: uncheckedOutline, - - // If DS icon variables are ever used pre-fill, keep it outlined "--ds-checkbox-box-fill": "none", "--ds-checkbox-box-stroke": uncheckedOutline, "--ds-checkbox-box-strokeWidth": "2", }, - // ✅ Checked: solid fill in intent colour + white tick "&.Mui-checked": { color: selectedMain, "--ds-checkbox-box-fill": "currentColor", @@ -423,7 +483,6 @@ export const createMuiTheme = (mode: DSMode): Theme => { "--ds-checkbox-glyph": "var(--ds-white)", }, - // ✅ Indeterminate: “outlined button feel” in intent colour "&.MuiCheckbox-indeterminate": { color: selectedMain, "--ds-checkbox-box-fill": "none", @@ -432,20 +491,287 @@ export const createMuiTheme = (mode: DSMode): Theme => { "--ds-checkbox-glyph": "currentColor", }, - // Optional: hover tint for selected states only ...(selectedMainChannel && { "&.Mui-checked:hover, &.MuiCheckbox-indeterminate:hover": { backgroundColor: `rgba(${selectedMainChannel} / ${theme.palette.action.hoverOpacity})`, }, }), + } as unknown as CSSObject; + }, + }, + }, + + // MUI Input focus color overrides + + MuiInput: { + styleOverrides: { + root: ({ ownerState, theme }: OverrideArgs<InputProps>) => { + const raw = ownerState.color ?? "primary"; + const colour = (ownerState.color ?? "primary") as + | "primary" + | "secondary" + | "error" + | "warning" + | "info" + | "success"; + + const p = theme.palette[colour]; + + return { + // REST (interactive baseline) + "&:before": { + borderBottomColor: theme.palette.borders.strong, + }, + + // HOVER (neutral hover emphasis) + "&:hover:not(.Mui-disabled):not(.Mui-error):before": { + borderBottomColor: theme.palette.borders.stronger, + }, + + // FOCUS (semantic colour + weight) + "&.Mui-focused:not(.Mui-error):after": { + borderBottomColor: p.light, + borderBottomWidth: 2, + }, + + // ERROR (rest) + "&.Mui-error:before": { + borderColor: theme.palette.error.lighter ?? theme.palette.error.light, + }, + + // ERROR hover + "&.Mui-error:hover:not(.Mui-disabled):before": { + borderBottomColor: theme.palette.error.light, + }, + + // ERROR + FOCUS (semantic colour + weight) + "&.Mui-error.Mui-focused:after": { + borderBottomColor: theme.palette.error.light, + borderBottomWidth: 2, + }, + + // DISABLED wins + "&.Mui-disabled:before": { + borderBottomStyle: "solid", + borderBottomColor: "var(--ds-border-disabled)", + }, + }; + }, + + input: ({ theme }: ThemeOnlyArgs) => ({ + "&::placeholder": { color: theme.palette.text.placeholder, opacity: 1 }, + "&:focus::placeholder": { color: theme.palette.text.placeholderFocus }, + }), + }, + }, + + + + MuiInputBase: { + styleOverrides: { + input: ({ theme }: ThemeOnlyArgs) => ({ + "&::placeholder": { color: theme.palette.text.placeholder, opacity: 1 }, + "&::-webkit-input-placeholder": { color: theme.palette.text.placeholder, opacity: 1 }, + "&::-moz-placeholder": { color: theme.palette.text.placeholder, opacity: 1 }, + + "&:focus::placeholder": { color: theme.palette.text.placeholderFocus }, + "&:focus::-webkit-input-placeholder": { color: theme.palette.text.placeholderFocus }, + "&:focus::-moz-placeholder": { color: theme.palette.text.placeholderFocus }, + }), + + root: ({ theme }: ThemeOnlyArgs) => ({ + "&.Mui-error input::placeholder, &.Mui-error input::-webkit-input-placeholder, &.Mui-error input::-moz-placeholder": { + color: theme.palette.error.light, + opacity: 1, + }, + "&.Mui-disabled input::placeholder, &.Mui-disabled input::-webkit-input-placeholder, &.Mui-disabled input::-moz-placeholder": { + color: theme.palette.text.disabled, + opacity: 1, + }, + }), + }, + }, + + MuiFilledInput: { + styleOverrides: { + root: ({ ownerState, theme }: OverrideArgs<FilledInputProps>) => { + const raw = ownerState.color ?? "primary"; + const colour = (ownerState.color ?? "primary") as + | "primary" + | "secondary" + | "error" + | "warning" + | "info" + | "success"; + + const p = theme.palette[colour]; + + return { + backgroundColor: theme.palette.background.surface2, + + "&:hover:not(.Mui-disabled)": { + backgroundColor: "var(--ds-overlay-hover)", + }, + + // REST (interactive baseline) + "&:before": { + borderBottomColor: theme.palette.borders.strong, + }, + + // HOVER (neutral hover emphasis) + "&:hover:not(.Mui-disabled):not(.Mui-error):before": { + borderBottomColor: theme.palette.borders.stronger, + }, + + // FOCUS (semantic colour + weight) + "&.Mui-focused:not(.Mui-error):after": { + borderBottomColor: p.light, + borderBottomWidth: 2, + }, + + // ERROR (rest) + "&.Mui-error:before": { + borderColor: theme.palette.error.lighter ?? theme.palette.error.light, + }, + + // ERROR hover + "&.Mui-error:hover:not(.Mui-disabled):before": { + borderBottomColor: theme.palette.error.light, + }, + + // ERROR + FOCUS + "&.Mui-error.Mui-focused:after": { + borderBottomColor: theme.palette.error.light, + borderBottomWidth: 2, + }, + + // DISABLED wins + "&.Mui-disabled": { + backgroundColor: "var(--ds-bg-disabled)", + color: "var(--ds-fg-disabled)", + borderColor: "var(--ds-border-disabled)", + }, + }; + }, + + input: ({ theme }: ThemeOnlyArgs) => ({ + "&::placeholder": { color: theme.palette.text.placeholder, opacity: 1 }, + "&:focus::placeholder": { color: theme.palette.text.placeholderFocus }, + }), + }, + }, + + MuiOutlinedInput: { + styleOverrides: { + root: ({ ownerState, theme }: OverrideArgs<OutlinedInputProps>) => { + const raw = ownerState.color ?? "primary"; + const colour = (ownerState.color ?? "primary") as + | "primary" + | "secondary" + | "error" + | "warning" + | "info" + | "success"; + + const p = theme.palette[colour]; + + return { + // REST (interactive baseline) + "& .MuiOutlinedInput-notchedOutline": { + borderColor: theme.palette.borders.strong, + }, + + // HOVER (neutral affordance) — ONLY when not focused + not error + not disabled + "&:hover:not(.Mui-disabled):not(.Mui-error):not(.Mui-focused) .MuiOutlinedInput-notchedOutline": { + borderColor: theme.palette.borders.stronger, + }, + + // FOCUS (semantic, and you want LIGHT) + "&.Mui-focused:not(.Mui-disabled):not(.Mui-error) .MuiOutlinedInput-notchedOutline": { + borderColor: p.light, + borderWidth: 2, + }, + + // Make sure FOCUSED + HOVER still uses semantic colour (belt & braces) + "&.Mui-focused:hover:not(.Mui-disabled):not(.Mui-error) .MuiOutlinedInput-notchedOutline": { + borderColor: p.light, + borderWidth: 2, + }, + + // ERROR (rest) + "&.Mui-error .MuiOutlinedInput-notchedOutline": { + borderColor: theme.palette.error.lighter ?? theme.palette.error.light, + }, + + // ERROR hover + "&.Mui-error:hover:not(.Mui-disabled):not(.Mui-focused) .MuiOutlinedInput-notchedOutline": { + borderColor: theme.palette.error.light, + }, + + // ERROR focus + "&.Mui-error.Mui-focused .MuiOutlinedInput-notchedOutline": { + borderColor: theme.palette.error.light, + borderWidth: 2, + }, + + // DISABLED wins + "&.Mui-disabled": { + backgroundColor: "var(--ds-bg-disabled)", + "& .MuiOutlinedInput-notchedOutline": { + borderColor: "var(--ds-border-disabled)", + }, + }, }; }, }, }, + + MuiInputLabel: { + styleOverrides: { + root: ({ theme }: ThemeOnlyArgs) => ({ + "&:not(.MuiInputLabel-shrink)": { + color: theme.palette.text.secondary, + }, + "&.Mui-disabled:not(.MuiInputLabel-shrink)": { + color: theme.palette.text.disabled, + }, + + "&.Mui-focused": { + color: theme.palette.primary.darker ?? theme.palette.primary.dark, + }, + + "&.Mui-focused.MuiFormLabel-colorSecondary": { + color: theme.palette.secondary.darker ?? theme.palette.secondary.dark, + }, + "&.Mui-focused.MuiFormLabel-colorSuccess": { + color: theme.palette.success.darker ?? theme.palette.success.dark, + }, + "&.Mui-focused.MuiFormLabel-colorWarning": { + color: theme.palette.warning.darker ?? theme.palette.warning.dark, + }, + "&.Mui-focused.MuiFormLabel-colorError": { + color: theme.palette.error.darker ?? theme.palette.error.dark, + }, + "&.Mui-focused.MuiFormLabel-colorInfo": { + color: theme.palette.info.darker ?? theme.palette.info.dark, + }, + + "&.Mui-focused.Mui-error": { + color: theme.palette.error.darker ?? theme.palette.error.dark, + }, + + "&.Mui-disabled": { + color: theme.palette.text.disabled, + }, + }), + }, + }, + }, }); return createTheme(DiamondDSThemeOptions); }; + export const DiamondDSTheme = createMuiTheme("light"); -export const DiamondDSThemeDark = createMuiTheme("dark"); +export const DiamondDSThemeDark = createMuiTheme("dark"); \ No newline at end of file diff --git a/src/themes/ThemeProvider.tsx b/src/themes/ThemeProvider.tsx index fdcf100..2652466 100644 --- a/src/themes/ThemeProvider.tsx +++ b/src/themes/ThemeProvider.tsx @@ -1,37 +1,33 @@ import React, { useLayoutEffect, useMemo } from "react"; import { CssBaseline } from "@mui/material"; import { ThemeProvider as MuiThemeProvider } from "@mui/material/styles"; -import { ThemeProviderProps as MuiThemeProviderProps } from "@mui/material/styles/ThemeProvider"; +import type { ThemeProviderProps as MuiThemeProviderProps } from "@mui/material/styles/ThemeProvider"; import { createMuiTheme } from "./DiamondDSTheme"; import type { DSMode } from "./DiamondDSTheme"; interface ThemeProviderProps extends Partial<MuiThemeProviderProps> { baseline?: boolean; - mode: DSMode; // controlled (source of truth) + mode?: DSMode; // 'light' | 'dark' (adding 'system' for future use) } export function ThemeProvider({ children, baseline = true, defaultMode = "system", - mode, + mode = "light", // default to light mode (for now) ...props }: ThemeProviderProps) { useLayoutEffect(() => { const root = document.documentElement; - // single source of truth for variables root.setAttribute("data-mode", mode); - - // optional: keep classes for convenience, but NOT for variables root.classList.toggle("dark", mode === "dark"); root.classList.toggle("light", mode === "light"); - - // help UA styles / scrollbars root.style.colorScheme = mode; }, [mode]); const theme = useMemo(() => createMuiTheme(mode), [mode]); + return ( <MuiThemeProvider theme={theme} defaultMode={defaultMode} {...props}> {baseline && <CssBaseline />} From 144c3e1e6300ed6988c99404b890caa7976e2410 Mon Sep 17 00:00:00 2001 From: Zohar Manor-Abel <zohar.manor-abel@diamond.ac.uk> Date: Tue, 3 Feb 2026 12:19:58 +0000 Subject: [PATCH 08/10] Updated border colour and rules, and updated colours documentation missed a token name change fix typo in storybook.css --- .storybook/storybook.css | 1 - src/storybook/foundation/colours.mdx | 234 +++++++++++++++--- .../diamondDS/diamond-colors-primitives.css | 2 +- src/themes/DiamondDSTheme.ts | 16 +- 4 files changed, 204 insertions(+), 49 deletions(-) diff --git a/.storybook/storybook.css b/.storybook/storybook.css index f409b9f..3ceb267 100644 --- a/.storybook/storybook.css +++ b/.storybook/storybook.css @@ -42,7 +42,6 @@ .token { font-family: var(--ds-font-mono); font-size: 1em; - f } /* Neutralise Storybook Docs inline preview background wrapper */ diff --git a/src/storybook/foundation/colours.mdx b/src/storybook/foundation/colours.mdx index 3b0ce84..e03d3fd 100644 --- a/src/storybook/foundation/colours.mdx +++ b/src/storybook/foundation/colours.mdx @@ -6,35 +6,41 @@ import { Meta } from "@storybook/blocks"; .ds-note { margin: 12px 0 20px; padding: 12px 14px; - border: 1px solid var(--ds-olive-6); - background: var(--ds-olive-2); + border: 1px solid var(--ds-border-subtle, var(--ds-olive-6)); + background: var(--ds-bg-surface-1, var(--ds-olive-2)); border-radius: 12px; } + .ds-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px; margin: 14px 0 24px; } + .ds-swatch { - border: 1px solid var(--ds-olive-6); + border: 1px solid var(--ds-border-subtle, var(--ds-olive-6)); border-radius: 14px; - background: var(--ds-olive-1); + background: var(--ds-bg-paper, var(--ds-olive-1)); overflow: hidden; } + .ds-swatch__chip { height: 56px; background: var(--swatch); - border-bottom: 1px solid var(--ds-olive-6); + border-bottom: 1px solid var(--ds-border-subtle, var(--ds-olive-6)); } + .ds-swatch__body { padding: 12px 12px 10px; } + .ds-swatch__name { font-weight: 600; margin: 0 0 6px; color: var(--ds-olive-12); } + .ds-swatch__meta { margin: 0; padding-left: 16px; @@ -42,31 +48,36 @@ import { Meta } from "@storybook/blocks"; font-size: 14px; line-height: 20px; } + .ds-swatch__meta li { margin: 2px 0; list-style-type: none; } + .ds-row { display: flex; gap: 10px; flex-wrap: wrap; margin: 10px 0 0; } + .ds-pill { display: inline-flex; align-items: center; gap: 8px; padding: 6px 10px; border-radius: 999px; - border: 1px solid var(--ds-olive-6); - background: var(--ds-olive-1); + border: 1px solid var(--ds-border-subtle, var(--ds-olive-6)); + background: var(--ds-bg-paper, var(--ds-olive-1)); color: var(--ds-olive-12); font-size: 13px; line-height: 18px; } + .text-inverse { color: var(--ds-olive-1); } + .ds-dot { width: 12px; height: 12px; @@ -75,58 +86,79 @@ import { Meta } from "@storybook/blocks"; border: 1px solid rgba(0,0,0,0.12); display: inline-block; } + li .ds-dot { margin-left: -16px; margin-right: 8px; } + .ds-surface-demo { - border: 1px solid var(--ds-olive-6); + border: 1px solid var(--ds-border-subtle, var(--ds-olive-6)); border-radius: 14px; - background: var(--ds-olive-1); + background: var(--ds-bg-paper, var(--ds-olive-1)); padding: 14px; margin: 14px 0 24px; } + .ds-surface-card { - border: 1px solid var(--ds-olive-6); - background: var(--ds-olive-2); + border: 1px solid var(--ds-border-subtle, var(--ds-olive-6)); + background: var(--ds-bg-surface-1, var(--ds-olive-2)); border-radius: 12px; padding: 12px; } + .ds-divider { height: 1px; - background: var(--ds-olive-6); + background: var(--ds-border-subtle, var(--ds-olive-6)); margin: 12px 0; } + .ds-text-demo p { margin: 8px 0; } + .ds-overlay-demo { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; margin-top: 12px; } + .ds-overlay-tile { - border: 1px solid var(--ds-olive-6); + border: 1px solid var(--ds-border-subtle, var(--ds-olive-6)); border-radius: 12px; - background: var(--ds-olive-2); + background: var(--ds-bg-surface-1, var(--ds-olive-2)); overflow: hidden; } + .ds-overlay-tile__top { height: 56px; - background: var(--ds-olive-2); + background: var(--ds-bg-surface-1, var(--ds-olive-2)); position: relative; } + .ds-overlay-tile__overlay { position: absolute; inset: 0; background: var(--overlay); } + .ds-overlay-tile__body { padding: 10px 12px; color: var(--ds-olive-12); font-size: 13px; } + + .ds-guidelines h3 code { + font-weight: 500; + border: 1px solid rgb(236, 244, 249); + color: rgba(46, 52, 56, 0.9); + background-color: rgb(255, 255, 255); + margin: 0 2px; + padding: 3px 5px; + white-space: nowrap; + border-radius: 6px; + } `}</style> <div> @@ -142,28 +174,149 @@ import { Meta } from "@storybook/blocks"; `diamond-colors-primitives.css`. </p> -<div className="ds-note"> - <strong>How to use colour roles</strong> - <ul style={{ margin: "8px 0 0 16px" }}> - <li> - <strong>light / main</strong> — solid backgrounds and emphasis - <small>Buttons, active states, strong accents</small> - </li> - <li> - <strong>bgCanvas / bgSurface*</strong> — light backgrounds and layout - <small>Pages, panels, cards, grouped content</small> - </li> - <li> - <strong>dark / darker</strong> — text, icons, and borders on light - surfaces - <small>High-contrast foreground usage</small> - </li> - </ul> - <p style={{ marginTop: 8 }}> - If something looks like a background, use <code>bg*</code>. If it looks like - a button, use <code>main</code>. If it’s text, use <code>dark</code>. - </p> -</div> +<section className="ds-guidelines"> + <h2>How to use colour roles</h2> + <div className="ds-note"> + <h3><code>light</code> / <code>main</code></h3> + <p><strong>Role:</strong> Solid backgrounds and emphasis.</p> + <p><strong>Use for:</strong></p> + <ul> + <li>Buttons and primary actions</li> + <li>Active states (selected tabs, toggles, current step)</li> + <li>Strong accents and highlights</li> + </ul> + <p> + <strong>Rule:</strong> + If it feels like a control or an action, use <code>main</code> + (or <code>light</code> for calmer emphasis). + </p> + </div> + <div className="ds-note"> + <h3><code>bgCanvas</code> / <code>bgSurface*</code></h3> + <p><strong>Role:</strong> Light backgrounds and layout surfaces.</p> + <p><strong>Use for:</strong></p> + <ul> + <li>Page backgrounds (<code>bgCanvas</code>)</li> + <li>Panels, cards, grouped sections (<code>bgSurface1</code>, <code>bgSurface2</code>)</li> + <li>Containers behind inputs or tables</li> + </ul> + <p> + <strong>Rule:</strong> + If it feels like a surface you place things on, use <code>bg*</code>. + </p> + </div> + <div className="ds-note"> + <h3><code>dark</code> / <code>darker</code></h3> + <p><strong>Role:</strong> High-contrast foregrounds on light surfaces.</p> + <p><strong>Use for:</strong></p> + <ul> + <li>Primary and secondary text</li> + <li>Icons and glyphs</li> + <li>High-contrast borders on light backgrounds</li> + </ul> + <p> + <strong>Rule:</strong> + If it communicates meaning or information, use <code>dark</code> or <code>darker</code>. + </p> + </div> + <div className="ds-note"> + <p> + <strong>Heuristic:</strong><br /> + Background → <code>bg*</code><br /> + Control or action → <code>main</code> / <code>light</code><br /> + Text or icon → <code>dark</code> / <code>darker</code> + </p> + </div> + + <h2>How to use dividers and borders</h2> + <div className="ds-note"> + <h3><code>divider</code></h3> + <p><strong>Role:</strong> Framework-level structural separator (MUI).</p> + <p><strong>Use for:</strong></p> + <ul> + <li>MUI <code><Divider /></code></li> + <li>Table row separators</li> + <li>List separators</li> + <li>Menu separators</li> + <li>Default MUI table borders</li> + </ul> + <p> + <strong>Rule:</strong> + Use when MUI needs a neutral separator by default. + </p> + </div> + <div className="ds-note"> + <h3><code>border.subtle</code></h3> + <p><strong>Role:</strong> Structural, non-interactive boundaries.</p> + <p><strong>Use for:</strong></p> + <ul> + <li>Card edges</li> + <li>Panel outlines</li> + <li>Table grid lines</li> + <li>Section boundaries</li> + <li>Non-interactive containers</li> + </ul> + <p> + <strong>Rule:</strong> + If it structures space but should not attract attention, use <code>border.subtle</code>. + </p> + <h3><code>border.strong</code></h3> + <p><strong>Role:</strong> Interactive baseline.</p> + <p><strong>Use for:</strong></p> + <ul> + <li>Input outlines (resting)</li> + <li>Outlined buttons (resting)</li> + <li>Selectable cards</li> + <li>Interactive panels</li> + </ul> + <p> + <strong>Rule:</strong> + If something can be interacted with, its resting border should be <code>strong</code>. + </p> + <h3><code>border.emphasis</code></h3> + <p><strong>Role:</strong> Interactive emphasis and discovery.</p> + <p><strong>Use for:</strong></p> + <ul> + <li>Hover state for inputs and outlined controls</li> + <li>Drag targets</li> + <li>Drop zones</li> + <li>Highlighted or previewed containers</li> + </ul> + <p> + <strong>Rule:</strong> + If the UI is signalling “you’re about to interact with this”, use <code>border.emphasis</code>. + </p> + </div> + <div className="ds-note"> + <h3>Key principles</h3> + <ul> + <li> + <code>divider</code> maps to <code>border.subtle</code>, but they are not the same concept: + <ul> + <li><code>divider</code> = framework behaviour</li> + <li><code>border.subtle</code> = design intent</li> + </ul> + </li> + <li> + Borders communicate affordance: + <ul> + <li>Structure → <code>subtle</code></li> + <li>Interactivity → <code>strong</code></li> + <li>Intent / discovery → <code>emphasis</code></li> + </ul> + </li> + <li> + Focus should not rely on border strength alone — + use semantic colour (primary, error, etc.) and/or thickness. + </li> + </ul> + + <p> + <strong>DiamondDS rule:</strong><br /> + <em>Surfaces hold content, colours express meaning, dividers structure space, and borders signal interactivity.</em> + </p> + </div> +</section> {" "} @@ -374,13 +527,16 @@ import { Meta } from "@storybook/blocks"; </div> </div> - {/* Divider */} + {/* Divider and borders */} <div className="ds-swatch" style={{ ['--swatch']: 'var(--ds-olive-6)' }}> <div className="ds-swatch__chip" /> <div className="ds-swatch__body"> - <p className="ds-swatch__name">Divider</p> + <p className="ds-swatch__name">Divider and borders</p> <ul className="ds-swatch__meta"> <li><strong>divider</strong>: `--ds-olive-6`</li> + <li><strong>Border subtle</strong>: `--ds-olive-6`</li> + <li><strong>Border strong</strong>: `--ds-olive-7`</li> + <li><strong>Border emphasis</strong>: `--ds-olive-8`</li> </ul> </div> </div> diff --git a/src/styles/diamondDS/diamond-colors-primitives.css b/src/styles/diamondDS/diamond-colors-primitives.css index c57cbb8..0edf659 100644 --- a/src/styles/diamondDS/diamond-colors-primitives.css +++ b/src/styles/diamondDS/diamond-colors-primitives.css @@ -36,7 +36,7 @@ /* Borders */ --ds-border-subtle: var(--ds-olive-6); /* Structural, non-interactive */ --ds-border-strong: var(--ds-olive-7); /* Interactive baseline */ - --ds-border-stronger: var(--ds-olive-8); /* Hover emphasis */ + --ds-border-emphasis: var(--ds-olive-8); /* Interactive emphasis */ } diff --git a/src/themes/DiamondDSTheme.ts b/src/themes/DiamondDSTheme.ts index 400879e..17549f9 100644 --- a/src/themes/DiamondDSTheme.ts +++ b/src/themes/DiamondDSTheme.ts @@ -50,7 +50,7 @@ declare module "@mui/material/styles" { borders: { subtle: string; strong: string; - stronger: string; + emphasis: string; }; } @@ -60,7 +60,7 @@ declare module "@mui/material/styles" { borders?: { subtle?: string; strong?: string; - stronger?: string; + emphasis?: string; }; } @@ -161,13 +161,13 @@ export const createMuiTheme = (mode: DSMode): Theme => { surface2: "var(--ds-bg-surface-2)", // e.g. inputs, outlined containers }, - divider: "var(--ds-border-subtle)", // Structural, non-interactive + divider: "var(--ds-border-subtle)", // Framework-level structural separator dividerInverse: "var(--ds-white-a4)", borders: { - subtle: "var(--ds-border-subtle)", // Structural, non-interactive + subtle: "var(--ds-border-subtle)", // Structural, non-interactive boundaries strong: "var(--ds-border-strong)", // Interactive baseline - stronger: "var(--ds-border-stronger)", // hover emphasis + emphasis: "var(--ds-border-emphasis)", // Interactive emphasis }, primary: { @@ -525,7 +525,7 @@ export const createMuiTheme = (mode: DSMode): Theme => { // HOVER (neutral hover emphasis) "&:hover:not(.Mui-disabled):not(.Mui-error):before": { - borderBottomColor: theme.palette.borders.stronger, + borderBottomColor: theme.palette.borders.emphasis, }, // FOCUS (semantic colour + weight) @@ -620,7 +620,7 @@ export const createMuiTheme = (mode: DSMode): Theme => { // HOVER (neutral hover emphasis) "&:hover:not(.Mui-disabled):not(.Mui-error):before": { - borderBottomColor: theme.palette.borders.stronger, + borderBottomColor: theme.palette.borders.emphasis, }, // FOCUS (semantic colour + weight) @@ -683,7 +683,7 @@ export const createMuiTheme = (mode: DSMode): Theme => { // HOVER (neutral affordance) — ONLY when not focused + not error + not disabled "&:hover:not(.Mui-disabled):not(.Mui-error):not(.Mui-focused) .MuiOutlinedInput-notchedOutline": { - borderColor: theme.palette.borders.stronger, + borderColor: theme.palette.borders.emphasis, }, // FOCUS (semantic, and you want LIGHT) From db1840f52005ea19447120b24985b27c79b0fc1b Mon Sep 17 00:00:00 2001 From: Zohar Manor-Abel <zohar.manor-abel@diamond.ac.uk> Date: Wed, 4 Feb 2026 12:11:55 +0000 Subject: [PATCH 09/10] Spilt semantic tokens and semantic colours to two distinct files +Simplified some DSTheme calls and added more semantic tokens + removed unused palette tokens css + slight upgrade to theme provider --- .../diamondDS/diamond-colors-primitives.css | 59 ---- .../diamondDS/diamond-mui-palette-tokens.css | 243 -------------- .../diamondDS/diamond-tokens-semantic.css | 68 ++++ src/themes/DiamondDSTheme.ts | 300 +++++++++--------- src/themes/ThemeProvider.tsx | 27 +- 5 files changed, 231 insertions(+), 466 deletions(-) delete mode 100644 src/styles/diamondDS/diamond-mui-palette-tokens.css create mode 100644 src/styles/diamondDS/diamond-tokens-semantic.css diff --git a/src/styles/diamondDS/diamond-colors-primitives.css b/src/styles/diamondDS/diamond-colors-primitives.css index 0edf659..ae0d81f 100644 --- a/src/styles/diamondDS/diamond-colors-primitives.css +++ b/src/styles/diamondDS/diamond-colors-primitives.css @@ -27,44 +27,9 @@ --ds-white-a11: #ffffffe6; --ds-white-a12: #fffffff2; --ds-whiteChannel: 255 255 255; - - /* Disabled tokens (semantic) */ - --ds-fg-disabled: var(--ds-olive-8); - --ds-border-disabled: var(--ds-olive-6); - --ds-bg-disabled: var(--ds-olive-a3); - - /* Borders */ - --ds-border-subtle: var(--ds-olive-6); /* Structural, non-interactive */ - --ds-border-strong: var(--ds-olive-7); /* Interactive baseline */ - --ds-border-emphasis: var(--ds-olive-8); /* Interactive emphasis */ - } :root, .light, :root[data-mode="light"] { /*LIGHT MODE */ - /* Semantic on-colour tokens */ - --ds-fg-fixed-white: var(--ds-white); /* Always white */ - --ds-fg-fixed-black: var(--ds-black); /* Always black */ - --ds-fg-inverse: var(--ds-white); /* White (light) → Black (dark) */ - --ds-fg-default: var(--ds-black); /* Black (light) → White (dark) */ - - --ds-overlay-hover: rgba(0, 0, 0, 0.06); - --ds-overlay-selected: rgba(0, 0, 0, 0.10); - --ds-overlay-focus: rgba(0, 0, 0, 0.12); - --ds-overlay-disabled: rgba(0, 0, 0, 0.26); - --ds-overlay-disabled-bg: rgba(0, 0, 0, 0.06); - - --ds-bg-brand: var(--ds-navy-10); /* Diamond Brand Blue */ - - /* Canvas (app shell) */ - --ds-bg-canvas: var(--ds-olive-1); - - /* Paper (main surface) */ - --ds-bg-paper: var(--ds-white); - - /* Layering surfaces */ - --ds-bg-surface-1: var(--ds-olive-2); - --ds-bg-surface-2: var(--ds-olive-3); - /* Radix based colours */ --ds-gray-1:#fcfcfc; --ds-gray-2:#f9f9f9; @@ -465,30 +430,6 @@ --ds-navy-12Channel: 12 14 28; } .dark, :root[data-mode="dark"] { /* Dark Mode */ - /* Semantic on-colour tokens */ - --ds-fg-fixed-white: var(--ds-white); /* Always white */ - --ds-fg-fixed-black: var(--ds-black); /* Always black */ - --ds-fg-inverse: var(--ds-black); /* White (light) → Black (dark) */ - --ds-fg-default: var(--ds-white); /* Black (light) → White (dark) */ - - --ds-bg-brand: var(--ds-navy-7); /* Diamond Brand Blue */ - - --ds-overlay-hover: rgba(255, 255, 255, 0.06); - --ds-overlay-selected: rgba(255, 255, 255, 0.10); - --ds-overlay-focus: rgba(255, 255, 255, 0.12); - --ds-overlay-disabled: rgba(255, 255, 255, 0.30); - --ds-overlay-disabled-bg: rgba(255, 255, 255, 0.08); - - /* Canvas (app shell) */ - --ds-bg-canvas: var(--ds-olive-1); - - /* Paper (main surface) */ - --ds-bg-paper: var(--ds-olive-2); - - /* Layering surfaces */ - --ds-bg-surface-1: var(--ds-olive-3); - --ds-bg-surface-2: var(--ds-olive-4); - /* Radix based colours */ --ds-gray-1:#111; --ds-gray-2:#191919; diff --git a/src/styles/diamondDS/diamond-mui-palette-tokens.css b/src/styles/diamondDS/diamond-mui-palette-tokens.css deleted file mode 100644 index f17fdc2..0000000 --- a/src/styles/diamondDS/diamond-mui-palette-tokens.css +++ /dev/null @@ -1,243 +0,0 @@ -/* ============================================================ - NEW DIAMOND THEME (Diamond + Radix) - NOT USED CURRENTLY - ============================================================ */ - :root { - - /* COMMON */ - --mui-palette-common-black: var(--ds-black); - --mui-palette-common-white: var(--ds-white); - - --mui-palette-common-blackChannel: var(--ds-blackChannel); - --mui-palette-common-whiteChannel: var(--ds-Channel); - - --mui-palette-common-background: var(--ds-olive-1); - --mui-palette-common-onBackground: var(--ds-navy-11); - - --mui-palette-common-backgroundChannel: var(--ds-olive-1Channel); - --mui-palette-common-onBackgroundChannel: var(--ds-navy-11Channel); - - /* PRIMARY = Indigo */ - --mui-palette-primary-lighter: var(--ds-indigo-3); - --mui-palette-primary-light: var(--ds-indigo-6); - --mui-palette-primary-main: var(--ds-indigo-9); - --mui-palette-primary-dark: var(--ds-indigo-10); - --mui-palette-primary-darker: var(--ds-indigo-12); - --mui-palette-primary-contrastText: var(--ds-mui-palette-common-white); - - --mui-palette-primary-lighterChannel: var(--ds-indigo-3Channel); - --mui-palette-primary-lightChannel: var(--ds-indigo-6Channel); - --mui-palette-primary-mainChannel: var(--ds-indigo-9Channel); - --mui-palette-primary-darkChannel: var(--ds-indigo-10Channel); - --mui-palette-primary-darkerChannel: var(--ds-indigo-12Channel); - --mui-palette-primary-contrastTextChannel: var(--ds-mui-palette-common-whiteChannel); - - /* SECONDARY = Gray */ - --mui-palette-secondary-lighter: var(--ds-navy-3); - --mui-palette-secondary-light: var(--ds-navy-6); - --mui-palette-secondary-main: var(--ds-navy-9); - --mui-palette-secondary-dark: var(--ds-navy-11); - --mui-palette-secondary-darker: var(--ds-navy-12); - --mui-palette-secondary-contrastText: var(--ds-mui-palette-common-white); - - --mui-palette-secondary-lighterChannel: var(--ds-navy-3Channel); - --mui-palette-secondary-lightChannel: var(--ds-navy-6Channel); - --mui-palette-secondary-mainChannel: var(--ds-navy-9Channel); - --mui-palette-secondary-darkChannel: var(--ds-navy-11Channel); - --mui-palette-secondary-darkerChannel: var(--ds-navy-12Channel); - --mui-palette-secondary-contrastTextChannel: var(--ds-mui-palette-common-whiteChannel); - - /* ERROR = Red */ - --mui-palette-error-lighter: var(--ds-red-3); - --mui-palette-error-light: var(--ds-red-6); - --mui-palette-error-main: var(--ds-red-9); - --mui-palette-error-dark: var(--ds-red-11); - --mui-palette-error-darker: var(--ds-red-12); - --mui-palette-error-contrastText: var(--ds-mui-palette-common-white); - - --mui-palette-error-lighterChannel: var(--ds-red-3Channel); - --mui-palette-error-lightChannel: var(--ds-red-6Channel); - --mui-palette-error-mainChannel: var(--ds-red-9Channel); - --mui-palette-error-darkChannel: var(--ds-red-11Channel); - --mui-palette-error-darkerChannel: var(--ds-red-12Channel); - --mui-palette-error-contrastTextChannel: var(--ds-mui-palette-common-whiteChannel); - - /* WARNING = Yellow */ - --mui-palette-warning-lighter: var(--ds-yellow-2); - --mui-palette-warning-light: var(--ds-yellow-6); - --mui-palette-warning-main: var(--ds-yellow-9); - --mui-palette-warning-dark: var(--ds-yellow-11); - --mui-palette-warning-darker: var(--ds-yellow-12); - --mui-palette-warning-contrastText: var(--ds-mui-palette-common-black); - - --mui-palette-warning-lighterChannel: var(--ds-yellow-2Channel); - --mui-palette-warning-lightChannel: var(--ds-yellow-6Channel); - --mui-palette-warning-mainChannel: var(--ds-yellow-9Channel); - --mui-palette-warning-darkChannel: var(--ds-yellow-11Channel); - --mui-palette-warning-darkerChannel: var(--ds-yellow-12Channel); - --mui-palette-warning-contrastTextChannel: var(--ds-mui-palette-common-blackChannel); - - /* INFO = Cyan */ - --mui-palette-info-lighter: var(--ds-cyan-2); - --mui-palette-info-light: var(--ds-cyan-6); - --mui-palette-info-main: var(--ds-cyan-9); - --mui-palette-info-dark: var(--ds-cyan-11); - --mui-palette-info-darker: var(--ds-cyan-12); - --mui-palette-info-contrastText: var(--ds-mui-palette-common-black); - - --mui-palette-info-lighterChannel: var(--ds-cyan-2Channel); - --mui-palette-info-lightChannel: var(--ds-cyan-6Channel); - --mui-palette-info-mainChannel: var(--ds-cyan-9Channel); - --mui-palette-info-darkChannel: var(--ds-cyan-11Channel); - --mui-palette-info-darkerChannel: var(--ds-cyan-12Channel); - --mui-palette-info-contrastTextChannel: var(--ds-mui-palette-common-blackChannel); - - /* SUCCESS = Green */ - --mui-palette-success-lighter: var(--ds-green-2); - --mui-palette-success-light: var(--ds-green-6); - --mui-palette-success-main: var(--ds-green-9); - --mui-palette-success-dark: var(--ds-green-11); - --mui-palette-success-darker: var(--ds-green-12); - --mui-palette-success-contrastText: var(--ds-mui-palette-common-black); - - --mui-palette-success-lighterChannel: var(--ds-green-2Channel); - --mui-palette-success-lightChannel: var(--ds-green-6Channel); - --mui-palette-success-mainChannel: var(--ds-green-9Channel); - --mui-palette-success-darkChannel: var(--ds-green-11Channel); - --mui-palette-success-darkerChannel: var(--ds-green-12Channel); - --mui-palette-success-contrastTextChannel: var(--ds-mui-palette-common-blackChannel); - - /* TEXT */ - --mui-palette-text-primary: var(--ds-navy-10); - --mui-palette-text-secondary: var(--ds-olive-9); - --mui-palette-text-disabled: var(--ds-olive-7); - - --mui-palette-text-primaryChannel: var(--ds-navy-11Channel); - --mui-palette-text-secondaryChannel: var(--ds-olive-9Channel); - - /* ACTIONS */ - --mui-palette-action-disabled: var(--ds-olive-6); - --mui-palette-action-active: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.54); - --mui-palette-action-hover: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.04); - --mui-palette-action-selected: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.08); - --mui-palette-action-disabledBackground: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.12); - --mui-palette-action-focus: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.12); - - --mui-palette-action-activeChannel: var(--ds-mui-palette-text-primaryChannel); - --mui-palette-action-selectedChannel: var(--ds-mui-palette-text-primaryChannel); - - /* BACKGROUNDS */ - --mui-palette-divider: var(--ds-olive-3); - --mui-palette-dividerChannel: var(--ds-olive-3Channel); - - --mui-palette-background-paper: var(--ds-mui-palette-common-white); - --mui-palette-background-default: var(--ds-olive-2); - - --mui-palette-background-defaultChannel: var(--ds-olive-2Channel); - --mui-palette-background-paperChannel: var(--ds-mui-palette-common-whiteChannel); - - /* ALERTS */ - --mui-palette-Alert-errorColor: var(--ds-mui-palette-error-dark); - --mui-palette-Alert-infoColor: var(--ds-mui-palette-info-dark); - --mui-palette-Alert-successColor: var(--ds-mui-palette-success-dark); - --mui-palette-Alert-warningColor: var(--ds-mui-palette-warning-dark); - - --mui-palette-Alert-errorFilledBg: var(--ds-mui-palette-error-main); - --mui-palette-Alert-infoFilledBg: var(--ds-mui-palette-info-main); - --mui-palette-Alert-successFilledBg: var(--ds-mui-palette-success-main); - --mui-palette-Alert-warningFilledBg: var(--ds-mui-palette-warning-main); - - --mui-palette-Alert-errorFilledColor: var(--ds-mui-palette-common-white); - --mui-palette-Alert-infoFilledColor: rgba(var(--ds-mui-palette-common-blackChannel) / 0.87); - --mui-palette-Alert-successFilledColor: rgba(var(--ds-mui-palette-common-blackChannel) / 0.87); - --mui-palette-Alert-warningFilledColor: rgba(var(--ds-mui-palette-common-blackChannel) / 0.87); - - --mui-palette-Alert-errorStandardBg: var(--ds-mui-palette-error-lighter); - --mui-palette-Alert-infoStandardBg: var(--ds-mui-palette-info-lighter); - --mui-palette-Alert-successStandardBg: var(--ds-mui-palette-success-lighter); - --mui-palette-Alert-warningStandardBg: var(--ds-mui-palette-warning-lighter); - - --mui-palette-Alert-errorIconColor: var(--ds-mui-palette-error-main); - --mui-palette-Alert-infoIconColor: var(--ds-mui-palette-info-main); - --mui-palette-Alert-successIconColor: var(--ds-mui-palette-success-main); - --mui-palette-Alert-warningIconColor: var(--ds-mui-palette-warning-main); - - /* COMPONENTS */ - --mui-palette-AppBar-defaultBg: var(--ds-navy-10); - - --mui-palette-Avatar-defaultBg: var(--ds-olive-5); - - --mui-palette-Button-inheritContainedBg: var(--ds-olive-4); - --mui-palette-Button-inheritContainedHoverBg: var(--ds-olive-2); - - --mui-palette-Chip-defaultBorder: var(--ds-olive-5); - --mui-palette-Chip-defaultAvatarColor: var(--ds-olive-11); - --mui-palette-Chip-defaultIconColor: var(--ds-olive-11); - - --mui-palette-FilledInput-bg: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.06); - --mui-palette-FilledInput-hoverBg: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.09); - --mui-palette-FilledInput-disabledBg: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.12); - - --mui-palette-LinearProgress-primaryBg: var(--ds-mui-palette-primary-lighter); - --mui-palette-LinearProgress-secondaryBg: var(--ds-mui-palette-secondary-lighter); - --mui-palette-LinearProgress-errorBg: var(--ds-mui-palette-error-lighter); - --mui-palette-LinearProgress-infoBg: var(--ds-mui-palette-info-lighter); - --mui-palette-LinearProgress-successBg: var(--ds-mui-palette-success-lighter); - --mui-palette-LinearProgress-warningBg: var(--ds-mui-palette-warning-lighter); - - --mui-palette-Skeleton-bg: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.11); - - --mui-palette-Slider-primaryTrack: var(--ds-mui-palette-primary-lighter); - --mui-palette-Slider-secondaryTrack: var(--ds-mui-palette-secondary-lighter); - --mui-palette-Slider-errorTrack: var(--ds-mui-palette-error-lighter); - --mui-palette-Slider-infoTrack: var(--ds-mui-palette-info-lighter); - --mui-palette-Slider-successTrack: var(--ds-mui-palette-success-lighter); - --mui-palette-Slider-warningTrack: var(--ds-mui-palette-warning-lighter); - - --mui-palette-SnackbarContent-bg: var(--ds-navy-11); - --mui-palette-SnackbarContent-color: var(--ds-mui-palette-common-white); - - --mui-palette-SpeedDialAction-fabHoverBg: var(--ds-olive-4); - - --mui-palette-StepConnector-border: var(--ds-olive-5); - --mui-palette-StepContent-border: var(--ds-olive-5); - - --mui-palette-Switch-defaultColor: var(--ds-mui-palette-common-white); - --mui-palette-Switch-defaultDisabledColor: var(--ds-olive-2); - --mui-palette-Switch-primaryDisabledColor: var(--ds-mui-palette-primary-lighter); - --mui-palette-Switch-secondaryDisabledColor: var(--ds-mui-palette-secondary-lighter); - --mui-palette-Switch-errorDisabledColor: var(--ds-mui-palette-error-lighter); - --mui-palette-Switch-infoDisabledColor: var(--ds-mui-palette-info-lighter); - --mui-palette-Switch-successDisabledColor: var(--ds-mui-palette-success-lighter); - --mui-palette-Switch-warningDisabledColor: var(--ds-mui-palette-warning-lighter); - - --mui-palette-TableCell-border: var(--ds-olive-1); - - --mui-palette-Tooltip-bg: rgba(var(--ds-mui-palette-text-primaryChannel) / 0.92); - - /* SHADOWS */ - --customShadows-button: 0 2px #0000000b; - --customShadows-text: 0 -1px 0 rgba(var(--ds-mui-palette-common-blackChannel) / 0.12); - --customShadows-z1: 0px 1px 4px rgba(var(--ds-mui-palette-common-blackChannel) / 0.08); - - --customShadows-primary: 0 0 0 2px rgba(var(--ds-mui-palette-primary-mainChannel) / 0.2); - --customShadows-secondary: 0 0 0 2px rgba(var(--ds-mui-palette-secondary-mainChannel) / 0.2); - --customShadows-error: 0 0 0 2px rgba(var(--ds-mui-palette-error-mainChannel) / 0.2); - --customShadows-warning: 0 0 0 2px rgba(var(--ds-mui-palette-warning-mainChannel) / 0.2); - --customShadows-info: 0 0 0 2px rgba(var(--ds-mui-palette-info-mainChannel) / 0.2); - --customShadows-success: 0 0 0 2px rgba(var(--ds-mui-palette-success-mainChannel) / 0.2); - --customShadows-grey: 0 0 0 2px rgba(var(--ds-mui-palette-secondary-mainChannel) / 0.2); - - --customShadows-primaryButton: 0 14px 12px rgba(var(--ds-mui-palette-primary-mainChannel) / 0.2); - --customShadows-secondaryButton: 0 14px 12px rgba(var(--ds-mui-palette-secondary-mainChannel) / 0.2); - --customShadows-errorButton: 0 14px 12px rgba(var(--ds-mui-palette-error-mainChannel) / 0.2); - --customShadows-warningButton: 0 14px 12px rgba(var(--ds-mui-palette-warning-mainChannel) / 0.2); - --customShadows-infoButton: 0 14px 12px rgba(var(--ds-mui-palette-info-mainChannel) / 0.2); - --customShadows-successButton: 0 14px 12px rgba(var(--ds-mui-palette-success-mainChannel) / 0.2); - --customShadows-greyButton: 0 14px 12px rgba(var(--ds-mui-palette-secondary-mainChannel) / 0.2); - - /* OPACITY */ - --opacity-inputPlaceholder: 0.42; - --opacity-inputUnderline: 0.42; - --opacity-switchTrackDisabled: 0.12; - --opacity-switchTrack: 0.38; - } \ No newline at end of file diff --git a/src/styles/diamondDS/diamond-tokens-semantic.css b/src/styles/diamondDS/diamond-tokens-semantic.css new file mode 100644 index 0000000..61a9bdd --- /dev/null +++ b/src/styles/diamondDS/diamond-tokens-semantic.css @@ -0,0 +1,68 @@ +:root { /* Semantic tokens that can be defined once */ + /* Borders */ + --ds-border-subtle: var(--ds-olive-6); /* Structural, non-interactive */ + --ds-border-strong: var(--ds-olive-7); /* Interactive baseline */ + --ds-border-emphasis: var(--ds-olive-8); /* Interactive emphasis */ + /* Borders for focus states */ + --ds-border-focus-primary: var(--ds-indigo-8); + --ds-border-focus-secondary: var(--ds-navy-8); + --ds-border-focus-success: var(--ds-green-8); + --ds-border-focus-warning: var(--ds-orange-8); + --ds-border-focus-error: var(--ds-red-8); + --ds-border-focus-info: var(--ds-indigo-8); + + /* Background tokens */ + --ds-bg-canvas: var(--ds-olive-1); + --ds-bg-paper: var(--ds-white); + --ds-bg-surface-1: var(--ds-olive-2); + --ds-bg-surface-2: var(--ds-olive-3); + + --ds-bg-interactive-rest: var(--ds-olive-3); + --ds-bg-interactive-hover: var(--ds-olive-4); + + /* Text hierarchy tokens */ + --ds-fg-primary: var(--ds-olive-12); + --ds-fg-secondary: var(--ds-olive-11); + --ds-fg-tertiary: var(--ds-olive-10); + + /* Disabled tokens */ + --ds-fg-disabled: var(--ds-olive-8); + --ds-border-disabled: var(--ds-olive-6); + --ds-bg-disabled: var(--ds-olive-a3); +} + +:root, .light, :root[data-mode="light"] { /* Light mode */ + /* On-colour tokens */ + --ds-fg-fixed-white: var(--ds-white); /* Always white */ + --ds-fg-fixed-black: var(--ds-black); /* Always black */ + --ds-fg-inverse: var(--ds-white); /* White (light) → Black (dark) */ + --ds-fg-default: var(--ds-black); /* Black (light) → White (dark) */ + + --ds-overlay-hover: rgba(0, 0, 0, 0.06); + --ds-overlay-selected: rgba(0, 0, 0, 0.10); + --ds-overlay-focus: rgba(0, 0, 0, 0.12); + --ds-overlay-disabled: rgba(0, 0, 0, 0.26); + --ds-overlay-disabled-bg: rgba(0, 0, 0, 0.06); + + --ds-bg-brand: var(--ds-navy-10); /* Diamond Brand Blue */ +} + +.dark, :root[data-mode="dark"] { /* dark mode semantic overrides */ + /* On-colour tokens */ + --ds-fg-fixed-white: var(--ds-white); /* Always white */ + --ds-fg-fixed-black: var(--ds-black); /* Always black */ + --ds-fg-inverse: var(--ds-black); /* White (light) → Black (dark) */ + --ds-fg-default: var(--ds-white); /* Black (light) → White (dark) */ + + --ds-bg-brand: var(--ds-navy-7); /* Diamond Brand Blue */ + + --ds-overlay-hover: rgba(255, 255, 255, 0.06); + --ds-overlay-selected: rgba(255, 255, 255, 0.10); + --ds-overlay-focus: rgba(255, 255, 255, 0.12); + --ds-overlay-disabled: rgba(255, 255, 255, 0.30); + --ds-overlay-disabled-bg: rgba(255, 255, 255, 0.08); + + /* Paper (main surface override) */ + --ds-bg-paper: var(--ds-olive-2); + +} \ No newline at end of file diff --git a/src/themes/DiamondDSTheme.ts b/src/themes/DiamondDSTheme.ts index 17549f9..ec5d75b 100644 --- a/src/themes/DiamondDSTheme.ts +++ b/src/themes/DiamondDSTheme.ts @@ -1,4 +1,6 @@ +// src/themes/DiamondDSTheme.ts import "../styles/diamondDS/diamond-colors-primitives.css"; +import "../styles/diamondDS/diamond-tokens-semantic.css"; import type {} from "@mui/material/themeCssVarsAugmentation"; import { createTheme } from "@mui/material/styles"; @@ -9,18 +11,8 @@ import type { ButtonProps } from "@mui/material/Button"; import type { ChipProps } from "@mui/material/Chip"; import type { CheckboxProps } from "@mui/material/Checkbox"; import type { InputProps } from "@mui/material/Input"; -import type { InputBaseProps } from "@mui/material/InputBase"; import type { FilledInputProps } from "@mui/material/FilledInput"; import type { OutlinedInputProps } from "@mui/material/OutlinedInput"; -import type { InputLabelProps } from "@mui/material/InputLabel"; - -import { dark } from "@mui/material/styles/createPalette"; - -type OverrideArgs<OwnerState = unknown> = { - ownerState: OwnerState; - theme: Theme; -}; -type ThemeOnlyArgs = { theme: Theme }; import { mergeThemeOptions } from "./ThemeManager"; @@ -35,6 +27,12 @@ import { DsCheckboxIndeterminateIcon, } from "./icons"; +type OverrideArgs<OwnerState = unknown> = { + ownerState: OwnerState; + theme: Theme; +}; +type ThemeOnlyArgs = { theme: Theme }; + /** MUI module augmentation for custom properties */ declare module "@mui/material/styles" { interface TypeBackground { @@ -46,8 +44,8 @@ declare module "@mui/material/styles" { interface Palette { brand?: PaletteColor; - - borders: { + + border: { subtle: string; strong: string; emphasis: string; @@ -57,11 +55,11 @@ declare module "@mui/material/styles" { interface PaletteOptions { brand?: SimplePaletteColorOptions; - borders?: { + border?: { subtle?: string; strong?: string; emphasis?: string; - }; + }; } interface PaletteColor { @@ -98,6 +96,16 @@ declare module "@mui/material/styles" { export type DSMode = "light" | "dark"; +/** + * Prefer vars-backed palette (CSS variables) when present, otherwise fall back to palette. + * This prevents “default MUI hex” leaking into overrides when vars are available. + */ +type MuiIntent = "primary" | "secondary" | "error" | "warning" | "info" | "success"; +function resolveIntentPalette(theme: Theme, colour: MuiIntent) { + const t = theme as any; + return t.vars?.palette?.[colour] ?? (theme.palette as any)[colour]; +} + export const createMuiTheme = (mode: DSMode): Theme => { const DiamondDSThemeOptions = mergeThemeOptions({ typography: { @@ -150,13 +158,13 @@ export const createMuiTheme = (mode: DSMode): Theme => { secondary: "var(--ds-olive-11)", // secondary text, helper text, labels disabled: "var(--ds-olive-9)", // disabled text - placeholder: "var(--ds-olive-10)", // default hint text (if not secondary) - placeholderFocus: "var(--ds-olive-9)", // optional, calmer on focus + placeholder: "var(--ds-olive-10)", // default hint text (if not secondary) + placeholderFocus: "var(--ds-olive-9)", // optional, calmer on focus }, background: { default: "var(--ds-bg-canvas)", // page background - paper: "var(--ds-bg-paper)", // cards, sheets, menus, etc. + paper: "var(--ds-bg-paper)", // cards, sheets, menus, etc. surface1: "var(--ds-bg-surface-1)", // e.g. cards surface2: "var(--ds-bg-surface-2)", // e.g. inputs, outlined containers }, @@ -164,14 +172,14 @@ export const createMuiTheme = (mode: DSMode): Theme => { divider: "var(--ds-border-subtle)", // Framework-level structural separator dividerInverse: "var(--ds-white-a4)", - borders: { + border: { subtle: "var(--ds-border-subtle)", // Structural, non-interactive boundaries - strong: "var(--ds-border-strong)", // Interactive baseline + strong: "var(--ds-border-strong)", // Interactive baseline emphasis: "var(--ds-border-emphasis)", // Interactive emphasis }, primary: { - lighter: "var(--ds-indigo-7)", + lighter: "var(--ds-indigo-7)", light: "var(--ds-indigo-8)", main: "var(--ds-indigo-9)", dark: "var(--ds-indigo-10)", @@ -189,7 +197,7 @@ export const createMuiTheme = (mode: DSMode): Theme => { }, secondary: { - lighter: "var(--ds-navy-7)", + lighter: "var(--ds-navy-7)", light: "var(--ds-navy-8)", main: "var(--ds-navy-9)", dark: "var(--ds-navy-10)", @@ -206,7 +214,8 @@ export const createMuiTheme = (mode: DSMode): Theme => { bgSurface2: "var(--ds-navy-3)", }, - brand: { // Brand colore (same as ds-navy-10) for background use + brand: { + // Brand colour (same as ds-navy-10) for background use main: "var(--ds-bg-brand)", // Stays the same on light/dark modes contrastText: "var(--ds-fg-fixed-white)", }, @@ -309,13 +318,7 @@ export const createMuiTheme = (mode: DSMode): Theme => { const rawColour = ownerState.color ?? "primary"; if (rawColour === "inherit") return base; - const colour = rawColour as - | "primary" - | "secondary" - | "error" - | "warning" - | "info" - | "success"; + const colour = rawColour as MuiIntent; const varsPalette = (theme as any).vars?.palette?.[colour]; const fallbackPalette = (theme.palette as any)[colour]; @@ -386,30 +389,54 @@ export const createMuiTheme = (mode: DSMode): Theme => { return base; }, - outlinedPrimary: ({ theme }: { theme: Theme }): CSSObject => ({ - color: theme.palette.primary.darker ?? theme.palette.primary.dark, - borderColor: `rgba(${theme.palette.primary.darkChannel ?? theme.palette.primary.mainChannel} / 0.7)`, - }), - outlinedSecondary: ({ theme }: { theme: Theme }): CSSObject => ({ - color: theme.palette.secondary.dark, - borderColor: `rgba(${theme.palette.secondary.darkChannel ?? theme.palette.secondary.mainChannel} / 0.7)`, - }), - outlinedError: ({ theme }: { theme: Theme }): CSSObject => ({ - color: theme.palette.error.darker ?? theme.palette.error.dark, - borderColor: `rgba(${theme.palette.error.darkChannel ?? theme.palette.error.mainChannel} / 0.7)`, - }), - outlinedWarning: ({ theme }: { theme: Theme }): CSSObject => ({ - color: theme.palette.warning.darker ?? theme.palette.warning.dark, - borderColor: `rgba(${theme.palette.warning.darkChannel ?? theme.palette.warning.mainChannel} / 0.7)`, - }), - outlinedInfo: ({ theme }: { theme: Theme }): CSSObject => ({ - color: theme.palette.info.darker ?? theme.palette.info.dark, - borderColor: `rgba(${theme.palette.info.darkChannel ?? theme.palette.info.mainChannel} / 0.7)`, - }), - outlinedSuccess: ({ theme }: { theme: Theme }): CSSObject => ({ - color: theme.palette.success.darker ?? theme.palette.success.dark, - borderColor: `rgba(${theme.palette.success.darkChannel ?? theme.palette.success.mainChannel} / 0.7)`, - }), + outlinedPrimary: ({ theme }: { theme: Theme }): CSSObject => { + const p = resolveIntentPalette(theme, "primary"); + return { + color: p.darker ?? p.dark, + borderColor: `rgba(${p.darkChannel ?? p.mainChannel} / 0.7)`, + }; + }, + + outlinedSecondary: ({ theme }: { theme: Theme }): CSSObject => { + const p = resolveIntentPalette(theme, "secondary"); + return { + color: p.darker ?? p.dark, + borderColor: `rgba(${p.darkChannel ?? p.mainChannel} / 0.7)`, + }; + }, + + outlinedError: ({ theme }: { theme: Theme }): CSSObject => { + const p = resolveIntentPalette(theme, "error"); + return { + color: p.darker ?? p.dark, + borderColor: `rgba(${p.darkChannel ?? p.mainChannel} / 0.7)`, + }; + }, + + outlinedWarning: ({ theme }: { theme: Theme }): CSSObject => { + const p = resolveIntentPalette(theme, "warning"); + return { + color: p.darker ?? p.dark, + borderColor: `rgba(${p.darkChannel ?? p.mainChannel} / 0.7)`, + }; + }, + + outlinedInfo: ({ theme }: { theme: Theme }): CSSObject => { + const p = resolveIntentPalette(theme, "info"); + return { + color: p.darker ?? p.dark, + borderColor: `rgba(${p.darkChannel ?? p.mainChannel} / 0.7)`, + }; + }, + + outlinedSuccess: ({ theme }: { theme: Theme }): CSSObject => { + const p = resolveIntentPalette(theme, "success"); + return { + color: p.darker ?? p.dark, + borderColor: `rgba(${p.darkChannel ?? p.mainChannel} / 0.7)`, + }; + }, + }, }, @@ -442,12 +469,7 @@ export const createMuiTheme = (mode: DSMode): Theme => { const raw = (ownerState.color ?? "default") as | "default" - | "primary" - | "secondary" - | "error" - | "warning" - | "info" - | "success"; + | MuiIntent; const isDefault = raw === "default"; const colour = raw as Exclude<typeof raw, "default">; @@ -501,36 +523,27 @@ export const createMuiTheme = (mode: DSMode): Theme => { }, }, - // MUI Input focus color overrides - + // MUI Input focus colour overrides MuiInput: { styleOverrides: { root: ({ ownerState, theme }: OverrideArgs<InputProps>) => { - const raw = ownerState.color ?? "primary"; - const colour = (ownerState.color ?? "primary") as - | "primary" - | "secondary" - | "error" - | "warning" - | "info" - | "success"; - - const p = theme.palette[colour]; + const colour = (ownerState.color ?? "primary") as MuiIntent; + const p = resolveIntentPalette(theme, colour); return { // REST (interactive baseline) "&:before": { - borderBottomColor: theme.palette.borders.strong, + borderBottomColor: theme.palette.border.strong, }, // HOVER (neutral hover emphasis) "&:hover:not(.Mui-disabled):not(.Mui-error):before": { - borderBottomColor: theme.palette.borders.emphasis, + borderBottomColor: theme.palette.border.emphasis, }, // FOCUS (semantic colour + weight) "&.Mui-focused:not(.Mui-error):after": { - borderBottomColor: p.light, + borderBottomColor: "var(--ds-border-focus-primary)", borderBottomWidth: 2, }, @@ -565,8 +578,6 @@ export const createMuiTheme = (mode: DSMode): Theme => { }, }, - - MuiInputBase: { styleOverrides: { input: ({ theme }: ThemeOnlyArgs) => ({ @@ -593,111 +604,89 @@ export const createMuiTheme = (mode: DSMode): Theme => { }, MuiFilledInput: { - styleOverrides: { - root: ({ ownerState, theme }: OverrideArgs<FilledInputProps>) => { - const raw = ownerState.color ?? "primary"; - const colour = (ownerState.color ?? "primary") as - | "primary" - | "secondary" - | "error" - | "warning" - | "info" - | "success"; - - const p = theme.palette[colour]; - - return { - backgroundColor: theme.palette.background.surface2, - - "&:hover:not(.Mui-disabled)": { - backgroundColor: "var(--ds-overlay-hover)", - }, + styleOverrides: { + root: ({ ownerState, theme }: OverrideArgs<FilledInputProps>) => { + const colour = (ownerState.color ?? "primary") as MuiIntent; + const p = resolveIntentPalette(theme, colour); - // REST (interactive baseline) - "&:before": { - borderBottomColor: theme.palette.borders.strong, - }, + return { + backgroundColor: theme.palette.background.surface2, - // HOVER (neutral hover emphasis) - "&:hover:not(.Mui-disabled):not(.Mui-error):before": { - borderBottomColor: theme.palette.borders.emphasis, - }, + "&:hover:not(.Mui-disabled)": { + backgroundColor: "var(--ds-overlay-hover)", + }, - // FOCUS (semantic colour + weight) - "&.Mui-focused:not(.Mui-error):after": { - borderBottomColor: p.light, - borderBottomWidth: 2, - }, + // REST (interactive baseline) + "&:before": { + borderBottomColor: theme.palette.border.strong, + }, - // ERROR (rest) - "&.Mui-error:before": { - borderColor: theme.palette.error.lighter ?? theme.palette.error.light, - }, + // HOVER (neutral hover emphasis) + "&:hover:not(.Mui-disabled):not(.Mui-error):before": { + borderBottomColor: theme.palette.border.emphasis, + }, - // ERROR hover - "&.Mui-error:hover:not(.Mui-disabled):before": { - borderBottomColor: theme.palette.error.light, - }, + // FOCUS (semantic colour + weight) + "&.Mui-focused:not(.Mui-error):after": { + borderBottomColor: "var(--ds-border-focus-primary)", + borderBottomWidth: 2, + }, - // ERROR + FOCUS - "&.Mui-error.Mui-focused:after": { - borderBottomColor: theme.palette.error.light, - borderBottomWidth: 2, - }, + // ERROR (rest) + "&.Mui-error:before": { + borderColor: theme.palette.error.lighter ?? theme.palette.error.light, + }, - // DISABLED wins - "&.Mui-disabled": { - backgroundColor: "var(--ds-bg-disabled)", - color: "var(--ds-fg-disabled)", - borderColor: "var(--ds-border-disabled)", - }, - }; - }, + // ERROR hover + "&.Mui-error:hover:not(.Mui-disabled):before": { + borderBottomColor: theme.palette.error.light, + }, + + // ERROR + FOCUS + "&.Mui-error.Mui-focused:after": { + borderBottomColor: theme.palette.error.light, + borderBottomWidth: 2, + }, + + // DISABLED wins + "&.Mui-disabled": { + backgroundColor: "var(--ds-bg-disabled)", + color: "var(--ds-fg-disabled)", + borderColor: "var(--ds-border-disabled)", + }, + }; + }, - input: ({ theme }: ThemeOnlyArgs) => ({ - "&::placeholder": { color: theme.palette.text.placeholder, opacity: 1 }, - "&:focus::placeholder": { color: theme.palette.text.placeholderFocus }, - }), + input: ({ theme }: ThemeOnlyArgs) => ({ + "&::placeholder": { color: theme.palette.text.placeholder, opacity: 1 }, + "&:focus::placeholder": { color: theme.palette.text.placeholderFocus }, + }), + }, }, - }, MuiOutlinedInput: { styleOverrides: { root: ({ ownerState, theme }: OverrideArgs<OutlinedInputProps>) => { - const raw = ownerState.color ?? "primary"; - const colour = (ownerState.color ?? "primary") as - | "primary" - | "secondary" - | "error" - | "warning" - | "info" - | "success"; - - const p = theme.palette[colour]; + const colour = (ownerState.color ?? "primary") as MuiIntent; + const p = resolveIntentPalette(theme, colour); return { // REST (interactive baseline) "& .MuiOutlinedInput-notchedOutline": { - borderColor: theme.palette.borders.strong, + borderColor: theme.palette.border.strong, }, // HOVER (neutral affordance) — ONLY when not focused + not error + not disabled "&:hover:not(.Mui-disabled):not(.Mui-error):not(.Mui-focused) .MuiOutlinedInput-notchedOutline": { - borderColor: theme.palette.borders.emphasis, + borderColor: theme.palette.border.emphasis, }, - // FOCUS (semantic, and you want LIGHT) + // FOCUS (semantic colour + weight) "&.Mui-focused:not(.Mui-disabled):not(.Mui-error) .MuiOutlinedInput-notchedOutline": { borderColor: p.light, borderWidth: 2, }, - // Make sure FOCUSED + HOVER still uses semantic colour (belt & braces) - "&.Mui-focused:hover:not(.Mui-disabled):not(.Mui-error) .MuiOutlinedInput-notchedOutline": { - borderColor: p.light, - borderWidth: 2, - }, - // ERROR (rest) "&.Mui-error .MuiOutlinedInput-notchedOutline": { borderColor: theme.palette.error.lighter ?? theme.palette.error.light, @@ -708,7 +697,7 @@ export const createMuiTheme = (mode: DSMode): Theme => { borderColor: theme.palette.error.light, }, - // ERROR focus + // ERROR focus "&.Mui-error.Mui-focused .MuiOutlinedInput-notchedOutline": { borderColor: theme.palette.error.light, borderWidth: 2, @@ -766,7 +755,6 @@ export const createMuiTheme = (mode: DSMode): Theme => { }), }, }, - }, }); @@ -774,4 +762,4 @@ export const createMuiTheme = (mode: DSMode): Theme => { }; export const DiamondDSTheme = createMuiTheme("light"); -export const DiamondDSThemeDark = createMuiTheme("dark"); \ No newline at end of file +export const DiamondDSThemeDark = createMuiTheme("dark"); diff --git a/src/themes/ThemeProvider.tsx b/src/themes/ThemeProvider.tsx index 2652466..dd9c1e9 100644 --- a/src/themes/ThemeProvider.tsx +++ b/src/themes/ThemeProvider.tsx @@ -7,26 +7,37 @@ import type { DSMode } from "./DiamondDSTheme"; interface ThemeProviderProps extends Partial<MuiThemeProviderProps> { baseline?: boolean; - mode?: DSMode; // 'light' | 'dark' (adding 'system' for future use) + mode?: DSMode | "system"; +} + +function resolveMode(mode: DSMode | "system"): DSMode { + if (mode !== "system") return mode; + return window.matchMedia?.("(prefers-color-scheme: dark)")?.matches ? "dark" : "light"; } export function ThemeProvider({ children, baseline = true, defaultMode = "system", - mode = "light", // default to light mode (for now) + mode = "light", ...props }: ThemeProviderProps) { + const resolvedMode = useMemo(() => resolveMode(mode), [mode]); + useLayoutEffect(() => { const root = document.documentElement; - root.setAttribute("data-mode", mode); - root.classList.toggle("dark", mode === "dark"); - root.classList.toggle("light", mode === "light"); - root.style.colorScheme = mode; - }, [mode]); + root.setAttribute("data-mode", resolvedMode); + + // compatibility classes + root.classList.toggle("dark", resolvedMode === "dark"); + root.classList.toggle("light", resolvedMode === "light"); + + // browser-native UI (scrollbars, form controls) + root.style.colorScheme = resolvedMode; + }, [resolvedMode]); - const theme = useMemo(() => createMuiTheme(mode), [mode]); + const theme = useMemo(() => createMuiTheme(resolvedMode), [resolvedMode]); return ( <MuiThemeProvider theme={theme} defaultMode={defaultMode} {...props}> From b55b419fd3b5de0ddc90d61bf248f07c554b3ddc Mon Sep 17 00:00:00 2001 From: Zohar Manor-Abel <zohar.manor-abel@diamond.ac.uk> Date: Thu, 12 Feb 2026 12:33:15 +0000 Subject: [PATCH 10/10] updated colours and borders --- .../diamondDS/diamond-colors-primitives.css | 12 ++-- .../diamondDS/diamond-tokens-semantic.css | 24 ++++--- src/themes/DiamondDSTheme.ts | 63 +++++++++++-------- 3 files changed, 58 insertions(+), 41 deletions(-) diff --git a/src/styles/diamondDS/diamond-colors-primitives.css b/src/styles/diamondDS/diamond-colors-primitives.css index ae0d81f..8975a93 100644 --- a/src/styles/diamondDS/diamond-colors-primitives.css +++ b/src/styles/diamondDS/diamond-colors-primitives.css @@ -402,8 +402,8 @@ --ds-navy-8: #777C98; --ds-navy-9: #586084; --ds-navy-10: #202945; /* brand */ - --ds-navy-11: #1D263F; - --ds-navy-12: #0C0E1C; + --ds-navy-11: #586084; + --ds-navy-12: #202945; /* brand */ --ds-navy-a1: #58608405; --ds-navy-a2: #5860840A; --ds-navy-a3: #58608410; @@ -414,8 +414,8 @@ --ds-navy-a8: #58608447; --ds-navy-a9: #58608463; --ds-navy-a10: #5860847D; - --ds-navy-a11: #586084A2; - --ds-navy-a12: #586084DE; + --ds-navy-a11: #58608463; + --ds-navy-a12: #5860847D; --ds-navy-1Channel: 249 250 253; --ds-navy-2Channel: 239 241 247; --ds-navy-3Channel: 224 226 237; @@ -426,8 +426,8 @@ --ds-navy-8Channel: 119 124 152; --ds-navy-9Channel: 88 96 132; --ds-navy-10Channel: 32 41 69; - --ds-navy-11Channel: 29 38 63; - --ds-navy-12Channel: 12 14 28; + --ds-navy-11Channel: 88 96 132; + --ds-navy-12Channel: 32 41 69; } .dark, :root[data-mode="dark"] { /* Dark Mode */ /* Radix based colours */ diff --git a/src/styles/diamondDS/diamond-tokens-semantic.css b/src/styles/diamondDS/diamond-tokens-semantic.css index 61a9bdd..416fc4b 100644 --- a/src/styles/diamondDS/diamond-tokens-semantic.css +++ b/src/styles/diamondDS/diamond-tokens-semantic.css @@ -1,15 +1,21 @@ :root { /* Semantic tokens that can be defined once */ /* Borders */ --ds-border-subtle: var(--ds-olive-6); /* Structural, non-interactive */ - --ds-border-strong: var(--ds-olive-7); /* Interactive baseline */ - --ds-border-emphasis: var(--ds-olive-8); /* Interactive emphasis */ - /* Borders for focus states */ - --ds-border-focus-primary: var(--ds-indigo-8); - --ds-border-focus-secondary: var(--ds-navy-8); - --ds-border-focus-success: var(--ds-green-8); - --ds-border-focus-warning: var(--ds-orange-8); - --ds-border-focus-error: var(--ds-red-8); - --ds-border-focus-info: var(--ds-indigo-8); + --ds-border-emphasis: var(--ds-olive-7); /* Interactive baseline */ + --ds-border-strong: var(--ds-olive-8); /* Interactive emphasis */ + /* Borders for intent states */ + --ds-border-emphasis-primary: var(--ds-indigo-7); + --ds-border-emphasis-secondary: var(--ds-navy-7); + --ds-border-emphasis-success: var(--ds-green-7); + --ds-border-emphasis-warning: var(--ds-orange-7); + --ds-border-emphasis-error: var(--ds-red-7); + --ds-border-emphasis-info: var(--ds-indigo-7); + --ds-border-strong-primary: var(--ds-indigo-8); + --ds-border-strong-secondary: var(--ds-navy-8); + --ds-border-strong-success: var(--ds-green-8); + --ds-border-strong-warning: var(--ds-orange-8); + --ds-border-strong-error: var(--ds-red-8); + --ds-border-strong-info: var(--ds-indigo-8); /* Background tokens */ --ds-bg-canvas: var(--ds-olive-1); diff --git a/src/themes/DiamondDSTheme.ts b/src/themes/DiamondDSTheme.ts index ec5d75b..4ccf7cd 100644 --- a/src/themes/DiamondDSTheme.ts +++ b/src/themes/DiamondDSTheme.ts @@ -1,4 +1,3 @@ -// src/themes/DiamondDSTheme.ts import "../styles/diamondDS/diamond-colors-primitives.css"; import "../styles/diamondDS/diamond-tokens-semantic.css"; @@ -26,6 +25,7 @@ import { DsCheckboxCheckedIcon, DsCheckboxIndeterminateIcon, } from "./icons"; +import { light } from "@mui/material/styles/createPalette"; type OverrideArgs<OwnerState = unknown> = { ownerState: OwnerState; @@ -47,8 +47,8 @@ declare module "@mui/material/styles" { border: { subtle: string; - strong: string; emphasis: string; + strong: string; }; } @@ -57,8 +57,8 @@ declare module "@mui/material/styles" { border?: { subtle?: string; - strong?: string; emphasis?: string; + strong?: string; }; } @@ -147,6 +147,8 @@ export const createMuiTheme = (mode: DSMode): Theme => { disabled: "var(--ds-overlay-disabled)", disabledBackground: "var(--ds-overlay-disabled-bg)", + selectedChannel: undefined, + hoverOpacity: 0.12, selectedOpacity: 0.16, disabledOpacity: 0.38, @@ -158,6 +160,9 @@ export const createMuiTheme = (mode: DSMode): Theme => { secondary: "var(--ds-olive-11)", // secondary text, helper text, labels disabled: "var(--ds-olive-9)", // disabled text + primaryChannel: "var(--ds-olive-12Channel)", + secondaryChannel: "var(--ds-olive-11Channel)", + placeholder: "var(--ds-olive-10)", // default hint text (if not secondary) placeholderFocus: "var(--ds-olive-9)", // optional, calmer on focus }, @@ -167,15 +172,21 @@ export const createMuiTheme = (mode: DSMode): Theme => { paper: "var(--ds-bg-paper)", // cards, sheets, menus, etc. surface1: "var(--ds-bg-surface-1)", // e.g. cards surface2: "var(--ds-bg-surface-2)", // e.g. inputs, outlined containers + + defaultChannel: "var(--ds-olive-1Channel)", // for calculating hover/active states in components like Button + paperChannel: "var(--ds-whiteChannel)", // for overlays on paper (e.g. popover backdrop) }, + primaryChannel: "var(--ds-indigo-9Channel)", // for calculating hover/active states in components like Button + divider: "var(--ds-border-subtle)", // Framework-level structural separator dividerInverse: "var(--ds-white-a4)", + dividerChannel: "var(--ds-olive-6Channel)", border: { subtle: "var(--ds-border-subtle)", // Structural, non-interactive boundaries - strong: "var(--ds-border-strong)", // Interactive baseline - emphasis: "var(--ds-border-emphasis)", // Interactive emphasis + emphasis: "var(--ds-border-emphasis)", // Interactive baseline + strong: "var(--ds-border-strong)", // Interactive hover }, primary: { @@ -215,8 +226,8 @@ export const createMuiTheme = (mode: DSMode): Theme => { }, brand: { - // Brand colour (same as ds-navy-10) for background use - main: "var(--ds-bg-brand)", // Stays the same on light/dark modes + main: "var(--ds-bg-brand)", // navy-10 Stays the same on light/dark modes + light: "var(--ds-navy-9)", contrastText: "var(--ds-fg-fixed-white)", }, @@ -292,16 +303,16 @@ export const createMuiTheme = (mode: DSMode): Theme => { }, grey: { - 50: "var(--ds-olive-1)", - 100: "var(--ds-olive-2)", - 200: "var(--ds-olive-3)", - 300: "var(--ds-olive-4)", - 400: "var(--ds-olive-5)", - 500: "var(--ds-olive-6)", - 600: "var(--ds-olive-7)", - 700: "var(--ds-olive-8)", - 800: "var(--ds-olive-9)", - 900: "var(--ds-olive-10)", + 50: "var(--ds-olive-2)", + 100: "var(--ds-olive-3)", + 200: "var(--ds-olive-4)", + 300: "var(--ds-olive-5)", + 400: "var(--ds-olive-7)", + 500: "var(--ds-olive-8)", + 600: "var(--ds-olive-9)", + 700: "var(--ds-olive-11)", + 800: "var(--ds-olive-10)", + 900: "var(--ds-olive-12)", }, }, @@ -373,7 +384,7 @@ export const createMuiTheme = (mode: DSMode): Theme => { return { ...base, color: "var(--ds-olive-12)", - borderColor: "var(--ds-border-strong)", + borderColor: "var(--ds-border-emphasis)", backgroundColor: isOutlined ? "transparent" : "var(--ds-olive-4)", ...(isInteractive && { @@ -533,12 +544,12 @@ export const createMuiTheme = (mode: DSMode): Theme => { return { // REST (interactive baseline) "&:before": { - borderBottomColor: theme.palette.border.strong, + borderBottomColor: theme.palette.border.emphasis, }, - // HOVER (neutral hover emphasis) + // HOVER (neutral hover strong) "&:hover:not(.Mui-disabled):not(.Mui-error):before": { - borderBottomColor: theme.palette.border.emphasis, + borderBottomColor: theme.palette.border.strong, }, // FOCUS (semantic colour + weight) @@ -618,12 +629,12 @@ export const createMuiTheme = (mode: DSMode): Theme => { // REST (interactive baseline) "&:before": { - borderBottomColor: theme.palette.border.strong, + borderBottomColor: theme.palette.border.emphasis, }, - // HOVER (neutral hover emphasis) + // HOVER (neutral hover strong) "&:hover:not(.Mui-disabled):not(.Mui-error):before": { - borderBottomColor: theme.palette.border.emphasis, + borderBottomColor: theme.palette.border.strong, }, // FOCUS (semantic colour + weight) @@ -673,12 +684,12 @@ export const createMuiTheme = (mode: DSMode): Theme => { return { // REST (interactive baseline) "& .MuiOutlinedInput-notchedOutline": { - borderColor: theme.palette.border.strong, + borderColor: theme.palette.border.emphasis, }, // HOVER (neutral affordance) — ONLY when not focused + not error + not disabled "&:hover:not(.Mui-disabled):not(.Mui-error):not(.Mui-focused) .MuiOutlinedInput-notchedOutline": { - borderColor: theme.palette.border.emphasis, + borderColor: theme.palette.border.strong, }, // FOCUS (semantic colour + weight)