sage-nexus-ui 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/.storybook/main.ts +22 -0
  2. package/.storybook/preview.ts +21 -0
  3. package/dist/index.d.ts +21 -0
  4. package/dist/index.mjs +140 -0
  5. package/dist/index.mjs.map +1 -0
  6. package/dist/src/components/ActionBar.d.ts +8 -0
  7. package/dist/src/components/NexusHome.d.ts +1 -0
  8. package/dist/src/components/TextHighlightAi.d.ts +7 -0
  9. package/dist/src/components/ThemeToggle.d.ts +1 -0
  10. package/dist/src/components/index.d.ts +4 -0
  11. package/dist/src/index.d.ts +1 -0
  12. package/dist/src/stories/Button.d.ts +15 -0
  13. package/dist/src/stories/Button.stories.d.ts +23 -0
  14. package/dist/src/stories/EmTestComponent.stories.d.ts +6 -0
  15. package/dist/src/stories/Header.d.ts +12 -0
  16. package/dist/src/stories/Header.stories.d.ts +18 -0
  17. package/dist/src/stories/Page.d.ts +3 -0
  18. package/dist/src/stories/Page.stories.d.ts +12 -0
  19. package/dist/src/theme/MuiAppThemeProvider.d.ts +7 -0
  20. package/dist/src/theme/ThemeContext.d.ts +9 -0
  21. package/dist/src/theme/sageTheme.d.ts +49 -0
  22. package/dist/src/theme/sxHelpers.d.ts +13 -0
  23. package/package.json +57 -0
  24. package/rollup-plugins.d.ts +5 -0
  25. package/rollup.config.ts +39 -0
  26. package/src/assets/fonts/SageHeadline-Black.otf +0 -0
  27. package/src/assets/fonts/SageText-Bold.otf +0 -0
  28. package/src/assets/fonts/SageText-BoldItalic.otf +0 -0
  29. package/src/assets/fonts/SageText-Light.otf +0 -0
  30. package/src/assets/fonts/SageText-LightItalic.otf +0 -0
  31. package/src/assets/fonts/SageText-Medium.otf +0 -0
  32. package/src/assets/fonts/SageText-MediumItalic.otf +0 -0
  33. package/src/assets/fonts/SageText-Regular.otf +0 -0
  34. package/src/assets/fonts/SageText-RegularItalic.otf +0 -0
  35. package/src/assets/fonts/SageUI-Bold.otf +0 -0
  36. package/src/assets/fonts/SageUI-Medium.otf +0 -0
  37. package/src/assets/fonts/SageUI-Regular.otf +0 -0
  38. package/src/assets/images/Logo.svg +3 -0
  39. package/src/assets/images/S-sage-logo-nobg.svg +3 -0
  40. package/src/assets/images/S-sage-logo.svg +4 -0
  41. package/src/assets/images/nexus-logo-icon.svg +31 -0
  42. package/src/components/ActionBar.tsx +105 -0
  43. package/src/components/NexusHome.tsx +36 -0
  44. package/src/components/TextHighlightAi.tsx +34 -0
  45. package/src/components/ThemeToggle.tsx +22 -0
  46. package/src/components/index.ts +11 -0
  47. package/src/index.ts +1 -0
  48. package/src/stories/Button.stories.ts +54 -0
  49. package/src/stories/Button.tsx +37 -0
  50. package/src/stories/Configure.mdx +388 -0
  51. package/src/stories/EmTestComponent.stories.ts +14 -0
  52. package/src/stories/Header.stories.ts +34 -0
  53. package/src/stories/Header.tsx +56 -0
  54. package/src/stories/Page.stories.ts +33 -0
  55. package/src/stories/Page.tsx +91 -0
  56. package/src/stories/assets/accessibility.png +0 -0
  57. package/src/stories/assets/accessibility.svg +1 -0
  58. package/src/stories/assets/addon-library.png +0 -0
  59. package/src/stories/assets/assets.png +0 -0
  60. package/src/stories/assets/avif-test-image.avif +0 -0
  61. package/src/stories/assets/context.png +0 -0
  62. package/src/stories/assets/discord.svg +1 -0
  63. package/src/stories/assets/docs.png +0 -0
  64. package/src/stories/assets/figma-plugin.png +0 -0
  65. package/src/stories/assets/github.svg +1 -0
  66. package/src/stories/assets/share.png +0 -0
  67. package/src/stories/assets/styling.png +0 -0
  68. package/src/stories/assets/testing.png +0 -0
  69. package/src/stories/assets/theming.png +0 -0
  70. package/src/stories/assets/tutorials.svg +1 -0
  71. package/src/stories/assets/youtube.svg +1 -0
  72. package/src/stories/button.css +30 -0
  73. package/src/stories/header.css +32 -0
  74. package/src/stories/page.css +68 -0
  75. package/src/theme/MuiAppThemeProvider.tsx +21 -0
  76. package/src/theme/ThemeContext.tsx +27 -0
  77. package/src/theme/sageTheme.ts +565 -0
  78. package/src/theme/sxHelpers.ts +14 -0
  79. package/src/vite-env.d.ts +1 -0
  80. package/tsconfig.json +27 -0
  81. package/vite.config.ts +12 -0
  82. package/vitest.config.ts +36 -0
  83. package/vitest.shims.d.ts +1 -0
@@ -0,0 +1,8 @@
1
+ import type { ReactNode, ReactElement } from "react";
2
+ interface ActionBarProps {
3
+ title?: ReactNode;
4
+ extraLeft?: ReactNode;
5
+ extraRight?: ReactNode;
6
+ }
7
+ export declare const ActionBar: ({ title, extraLeft, extraRight, }: ActionBarProps) => ReactElement;
8
+ export {};
@@ -0,0 +1 @@
1
+ export declare const NexusHome: React.FC;
@@ -0,0 +1,7 @@
1
+ interface TextHighlightAiProps extends React.HTMLAttributes<HTMLElement> {
2
+ children?: React.ReactNode;
3
+ component?: React.ElementType;
4
+ style?: React.CSSProperties;
5
+ }
6
+ export declare const TextHighlightAi: React.FC<TextHighlightAiProps>;
7
+ export {};
@@ -0,0 +1 @@
1
+ export declare const ThemeToggle: React.FC;
@@ -0,0 +1,4 @@
1
+ export { ActionBar } from "./ActionBar";
2
+ export { NexusHome } from "./NexusHome";
3
+ export { TextHighlightAi } from "./TextHighlightAi";
4
+ export { ThemeToggle } from "./ThemeToggle";
@@ -0,0 +1 @@
1
+ export * from "./components";
@@ -0,0 +1,15 @@
1
+ import './button.css';
2
+ export interface ButtonProps {
3
+ /** Is this the principal call to action on the page? */
4
+ primary?: boolean;
5
+ /** What background color to use */
6
+ backgroundColor?: string;
7
+ /** How large should the button be? */
8
+ size?: 'small' | 'medium' | 'large';
9
+ /** Button contents */
10
+ label: string;
11
+ /** Optional click handler */
12
+ onClick?: () => void;
13
+ }
14
+ /** Primary UI component for user interaction */
15
+ export declare const Button: ({ primary, size, backgroundColor, label, ...props }: ButtonProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,23 @@
1
+ import type { StoryObj } from "@storybook/react-vite";
2
+ declare const meta: {
3
+ title: string;
4
+ component: ({ primary, size, backgroundColor, label, ...props }: import("./Button").ButtonProps) => import("react/jsx-runtime").JSX.Element;
5
+ parameters: {
6
+ layout: string;
7
+ };
8
+ tags: string[];
9
+ argTypes: {
10
+ backgroundColor: {
11
+ control: "color";
12
+ };
13
+ };
14
+ args: {
15
+ onClick: import("storybook/test").Mock<(...args: any[]) => any>;
16
+ };
17
+ };
18
+ export default meta;
19
+ type Story = StoryObj<typeof meta>;
20
+ export declare const Primary: Story;
21
+ export declare const Secondary: Story;
22
+ export declare const Large: Story;
23
+ export declare const Small: Story;
@@ -0,0 +1,6 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { EmTestComponent } from "../components/EmTestComponent";
3
+ declare const meta: Meta<typeof EmTestComponent>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof EmTestComponent>;
6
+ export declare const Default: Story;
@@ -0,0 +1,12 @@
1
+ import './header.css';
2
+ type User = {
3
+ name: string;
4
+ };
5
+ export interface HeaderProps {
6
+ user?: User;
7
+ onLogin?: () => void;
8
+ onLogout?: () => void;
9
+ onCreateAccount?: () => void;
10
+ }
11
+ export declare const Header: ({ user, onLogin, onLogout, onCreateAccount }: HeaderProps) => import("react/jsx-runtime").JSX.Element;
12
+ export {};
@@ -0,0 +1,18 @@
1
+ import type { StoryObj } from '@storybook/react-vite';
2
+ declare const meta: {
3
+ title: string;
4
+ component: ({ user, onLogin, onLogout, onCreateAccount }: import("./Header").HeaderProps) => import("react/jsx-runtime").JSX.Element;
5
+ tags: string[];
6
+ parameters: {
7
+ layout: string;
8
+ };
9
+ args: {
10
+ onLogin: import("storybook/test").Mock<(...args: any[]) => any>;
11
+ onLogout: import("storybook/test").Mock<(...args: any[]) => any>;
12
+ onCreateAccount: import("storybook/test").Mock<(...args: any[]) => any>;
13
+ };
14
+ };
15
+ export default meta;
16
+ type Story = StoryObj<typeof meta>;
17
+ export declare const LoggedIn: Story;
18
+ export declare const LoggedOut: Story;
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ import "./page.css";
3
+ export declare const Page: React.FC;
@@ -0,0 +1,12 @@
1
+ import type { StoryObj } from '@storybook/react-vite';
2
+ declare const meta: {
3
+ title: string;
4
+ component: import("react").FC<{}>;
5
+ parameters: {
6
+ layout: string;
7
+ };
8
+ };
9
+ export default meta;
10
+ type Story = StoryObj<typeof meta>;
11
+ export declare const LoggedOut: Story;
12
+ export declare const LoggedIn: Story;
@@ -0,0 +1,7 @@
1
+ import { type PropsWithChildren } from 'react';
2
+ import { type ThemeMode } from './sageTheme';
3
+ type MuiAppThemeProviderProps = PropsWithChildren<{
4
+ mode?: ThemeMode;
5
+ }>;
6
+ declare const MuiAppThemeProvider: ({ children, mode }: MuiAppThemeProviderProps) => import("react/jsx-runtime").JSX.Element;
7
+ export default MuiAppThemeProvider;
@@ -0,0 +1,9 @@
1
+ import { type PropsWithChildren } from 'react';
2
+ import type { ThemeMode } from './sageTheme';
3
+ type ThemeModeContextValue = {
4
+ mode: ThemeMode;
5
+ toggleMode: () => void;
6
+ };
7
+ export declare const useThemeMode: () => ThemeModeContextValue;
8
+ export declare const ThemeModeProvider: ({ children }: PropsWithChildren) => import("react/jsx-runtime").JSX.Element;
9
+ export {};
@@ -0,0 +1,49 @@
1
+ import "@mui/x-data-grid/themeAugmentation";
2
+ import { type Theme } from "@mui/material/styles";
3
+ export type ThemeMode = "light" | "dark";
4
+ export type GradientBorderOptions = {
5
+ borderRadius?: number;
6
+ padding?: number;
7
+ };
8
+ export declare const colours: {
9
+ readonly brilliantGreen: "#00D639";
10
+ readonly primaryGreenHover: "#00BE32";
11
+ readonly primaryGreenActive: "#00AA2D";
12
+ readonly jade: "#00A65C";
13
+ readonly teal: "#006362";
14
+ readonly navy: "#00293F";
15
+ readonly cherry: "#cc0f4b";
16
+ readonly terra: "#A13829";
17
+ readonly amber: "#E9875B";
18
+ readonly gold: "#F5C518";
19
+ readonly black: "#000000";
20
+ readonly white: "#FFFFFF";
21
+ readonly darkGrey: "#55616D";
22
+ readonly lightGrey: "#ffffffc2";
23
+ };
24
+ export declare const gradients: {
25
+ readonly brand: "linear-gradient(135deg, #00D639 0%, #00A65C 42%, #006362 100%)";
26
+ readonly nexus: "linear-gradient(135deg, #00D639 0%, #00D6DE 40%, #2D60FF 100%)";
27
+ readonly textHighlightAi: "linear-gradient(30deg, #00D639 0%, #00D6DE 40%, #9D60FF 90%)";
28
+ readonly mesh: `radial-gradient(circle at top right, ${string} 0%, transparent 34%), linear-gradient(135deg, ${string} 0%, ${string} 100%)`;
29
+ };
30
+ export declare const getGradientBorderStyles: (theme: Theme, options?: GradientBorderOptions) => {
31
+ position: string;
32
+ borderRadius: string | number;
33
+ border: string;
34
+ background: string;
35
+ backgroundClip: string;
36
+ "&::before": {
37
+ content: string;
38
+ position: string;
39
+ inset: number;
40
+ borderRadius: string;
41
+ padding: string;
42
+ background: "linear-gradient(135deg, #00D639 0%, #00A65C 42%, #006362 100%)";
43
+ WebkitMask: string;
44
+ WebkitMaskComposite: string;
45
+ maskComposite: string;
46
+ pointerEvents: string;
47
+ };
48
+ };
49
+ export declare const createSageTheme: (mode?: ThemeMode) => Theme;
@@ -0,0 +1,13 @@
1
+ export declare const leftPipe: {
2
+ borderLeft: (theme: any) => string;
3
+ pl: number;
4
+ };
5
+ export declare const expandableText: (isExpanded: boolean) => {
6
+ color: string;
7
+ lineHeight: number;
8
+ whiteSpace: string;
9
+ overflow: string;
10
+ display: string;
11
+ WebkitBoxOrient: string;
12
+ WebkitLineClamp: string | number;
13
+ };
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "sage-nexus-ui",
3
+ "version": "1.0.0",
4
+ "description": "Nexus core components",
5
+ "license": "ISC",
6
+ "author": "emsmart-sage",
7
+ "type": "module",
8
+ "main": "dist/index.mjs",
9
+ "module": "dist/index.mjs",
10
+ "types": "dist/index.d.ts",
11
+ "scripts": {
12
+ "test": "echo \"Error: no test specified\" && exit 1",
13
+ "build": "rollup -c",
14
+ "storybook": "set BROWSER=\"google-chrome\" && storybook dev -p 6006",
15
+ "build-storybook": "storybook build"
16
+ },
17
+ "devDependencies": {
18
+ "@chromatic-com/storybook": "^5.1.1",
19
+ "@rollup/plugin-commonjs": "^29.0.2",
20
+ "@rollup/plugin-node-resolve": "^16.0.3",
21
+ "@rollup/plugin-terser": "^1.0.0",
22
+ "@rollup/plugin-typescript": "^12.3.0",
23
+ "@storybook/addon-a11y": "^10.3.5",
24
+ "@storybook/addon-docs": "^10.3.5",
25
+ "@storybook/addon-onboarding": "^10.3.5",
26
+ "@storybook/addon-vitest": "^10.3.5",
27
+ "@storybook/react-vite": "^10.3.5",
28
+ "@types/node": "^25.6.0",
29
+ "@types/react": "^19.2.14",
30
+ "@types/rollup-plugin-peer-deps-external": "^2.2.6",
31
+ "@vitest/browser-playwright": "^4.1.4",
32
+ "@vitest/coverage-v8": "^4.1.4",
33
+ "playwright": "^1.59.1",
34
+ "react": "^19.2.5",
35
+ "react-dom": "^19.2.5",
36
+ "rollup": "^4.60.1",
37
+ "rollup-plugin-dts": "^6.4.1",
38
+ "rollup-plugin-peer-deps-external": "^2.2.4",
39
+ "rollup-plugin-postcss": "^4.0.2",
40
+ "storybook": "^10.3.5",
41
+ "tslib": "^2.8.1",
42
+ "typescript": "^6.0.2",
43
+ "vitest": "^4.1.4"
44
+ },
45
+ "peerDependencies": {
46
+ "react": ">=18",
47
+ "react-dom": ">=18"
48
+ },
49
+ "dependencies": {
50
+ "@emotion/react": "^11.14.0",
51
+ "@emotion/styled": "^11.14.1",
52
+ "@mui/icons-material": "^9.0.0",
53
+ "@mui/material": "^9.0.0",
54
+ "@mui/x-data-grid": "^9.0.1",
55
+ "@vitejs/plugin-react": "^6.0.1"
56
+ }
57
+ }
@@ -0,0 +1,5 @@
1
+ declare module "rollup-plugin-peer-deps-external" {
2
+ import { Plugin } from "rollup";
3
+ function peerDepsExternal(): Plugin;
4
+ export default peerDepsExternal;
5
+ }
@@ -0,0 +1,39 @@
1
+ import peerDepsExternal from "rollup-plugin-peer-deps-external";
2
+ import resolve from "@rollup/plugin-node-resolve";
3
+ import commonjs from "@rollup/plugin-commonjs";
4
+ import postcss from "rollup-plugin-postcss";
5
+ import typescript from "@rollup/plugin-typescript";
6
+ import terser from "@rollup/plugin-terser";
7
+ import dts from "rollup-plugin-dts";
8
+ import packageJson from "./package.json" with { type: "json" };
9
+
10
+ export default [
11
+ {
12
+ input: "src/index.ts",
13
+ output: {
14
+ file: packageJson.module,
15
+ format: "esm",
16
+ sourcemap: true,
17
+ },
18
+ plugins: [
19
+ peerDepsExternal(),
20
+ resolve(),
21
+ commonjs(),
22
+ postcss(),
23
+ typescript({
24
+ tsconfig: "./tsconfig.json",
25
+ outDir: "dist",
26
+ declaration: true,
27
+ declarationDir: "dist",
28
+ }),
29
+ terser(),
30
+ ],
31
+ external: ["react", "react-dom"],
32
+ },
33
+ {
34
+ input: "src/index.ts",
35
+ output: { file: packageJson.types, format: "esm" },
36
+ plugins: [dts()],
37
+ external: [/\.css$/],
38
+ },
39
+ ];
Binary file
@@ -0,0 +1,3 @@
1
+ <svg width="68" height="38" viewBox="0 0 68 38" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M15.2062 6.9913C15.1288 2.92301 11.6876 0 7.46542 0C3.2388 0 0 3.16051 0 7.18922C0 11.6525 3.12093 13.2727 6.87343 14.6186C10.231 15.8043 11.8504 16.8704 11.8504 19.3985C11.8504 21.4524 10.231 23.151 7.78209 23.151C5.45107 23.151 3.39713 21.5316 3.39713 19.0035C3.39713 18.1877 3.61739 17.7237 3.80556 17.3274C3.94585 17.0319 4.06829 16.774 4.06829 16.4359C4.06829 15.5237 3.43672 14.8526 2.40931 14.8526C1.22445 14.8526 0 16.6303 0 19.1583C0 23.2266 3.51852 26.2288 7.78209 26.227C12.1266 26.227 15.2475 23.027 15.2475 19.0378C15.2475 14.4558 11.9691 12.9147 8.37408 11.6111C5.01389 10.3884 3.39713 9.32408 3.39537 6.91301C3.39537 4.70074 5.13704 3.08134 7.42408 3.08134C9.87385 3.08134 11.809 4.78343 11.8486 7.07047C11.8882 8.13746 12.6385 8.76903 13.5076 8.76903C14.4145 8.76903 15.2457 8.13482 15.2062 6.9913ZM16.8827 18.4467C16.8827 22.7921 20.4382 26.2288 24.7044 26.2288C26.6 26.2288 28.0619 25.5963 28.0619 24.3719C28.0619 23.4632 27.272 22.8317 26.5217 22.8317C26.2792 22.8317 26.0671 22.8771 25.8288 22.9282C25.5235 22.9936 25.1752 23.0683 24.6648 23.0683C22.215 23.0683 20.2798 20.9352 20.2798 18.4467C20.2798 15.7612 22.2555 13.6677 24.744 13.6677C27.5482 13.6677 29.326 15.8008 29.326 18.9208V24.5698C29.326 25.5568 30.1159 26.2288 31.0641 26.2288C31.971 26.2288 32.7627 25.5568 32.7627 24.5698V18.8021C32.7627 14.0626 29.4852 10.5863 24.8231 10.5863C20.4778 10.5863 16.8827 13.9439 16.8827 18.4467ZM42.4958 38C38.0713 38 34.3979 34.8395 34.3979 30.7316C34.3979 29.3488 35.1896 28.7173 36.0965 28.7173C37.0034 28.7173 37.7555 29.3101 37.7951 30.4554C37.8346 33.0231 39.8886 34.9187 42.4571 34.9187C45.184 34.9187 46.9599 33.1805 46.9599 30.9295C46.9599 28.3619 44.9852 27.2949 41.6276 26.2288C37.7168 24.9648 34.3988 23.2266 34.3988 18.4071C34.3988 13.9835 37.7959 10.5863 42.2205 10.5863C46.6837 10.5863 50.3571 13.8251 50.3571 18.0913C50.3571 20.6986 49.291 22.7129 47.829 22.7129C46.8421 22.7129 46.17 22.0022 46.17 21.1296C46.17 20.7404 46.3152 20.4455 46.4813 20.1083C46.7029 19.658 46.9617 19.1324 46.9617 18.2066C46.9617 15.4797 44.8295 13.6642 42.2618 13.6642C39.7725 13.6642 37.7977 15.5598 37.7977 18.0482C37.7977 20.8534 39.8121 22.0382 43.1309 23.1439C46.9617 24.408 50.3588 25.9878 50.3588 30.6093C50.3588 34.7577 47.0804 37.9982 42.4985 37.9982L42.4958 38ZM51.9923 18.4072C51.9923 22.7525 55.6261 26.2288 60.0506 26.2288H60.0533C62.2655 26.2288 64.0433 25.636 65.2281 24.8856C66.413 24.1353 66.8871 23.5029 66.8871 22.7921C66.8871 22.0418 66.3312 21.3698 65.3038 21.3698C64.8266 21.3698 64.3854 21.6398 63.847 21.9694C63.0039 22.4854 61.9223 23.1475 60.0902 23.1475C59.4694 23.1482 58.8545 23.0258 58.2813 22.7873C57.708 22.5489 57.1878 22.1991 56.7506 21.7583C56.3135 21.3174 55.9681 20.7943 55.7344 20.219C55.5008 19.6438 55.3835 19.028 55.3895 18.4072C55.3895 15.8008 57.4434 13.6281 59.9715 13.6281C62.6974 13.6281 64.1585 15.4076 64.1585 16.5511C64.1585 16.8669 63.9219 17.0253 63.6052 17.0253H60.2081C59.2968 17.0253 58.6247 17.6551 58.6247 18.4467C58.6247 19.2762 59.3003 19.9087 60.2081 19.9087H64.7514C66.4895 19.9087 67.5556 19 67.5556 17.4994C67.5556 13.6281 64.2377 10.5864 59.8527 10.5864C58.8224 10.5814 57.8013 10.78 56.8479 11.1708C55.8946 11.5615 55.0279 12.1368 54.2975 12.8635C53.5671 13.5902 52.9875 14.454 52.5919 15.4054C52.1963 16.3567 51.9925 17.3768 51.9923 18.4072Z" fill="#00D639"/>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M23.8299 4.5C17.6748 4.5 13 9.25863 13 15.366C13 22.0623 17.6748 24.645 22.8612 26.2321C27.7619 27.8164 30.0993 29.5802 30.0993 33.0462C30.0993 36.5682 27.5333 39.0358 24.1728 39.0358C20.8095 39.0358 17.9034 36.5682 17.9034 32.7517C17.9034 30.6374 18.8721 30.1074 18.8721 28.9325C18.8721 27.5809 17.9578 26.5854 16.4776 26.5854C14.7687 26.5854 13 29.2269 13 32.9845C13 39.0358 18.0748 43.5 24.1728 43.5C30.3279 43.5 35 38.7414 35 32.634C35 25.9966 30.3279 23.3522 25.0844 21.7679C20.2381 20.2425 17.9034 18.4198 17.9034 14.9538C17.9034 11.4907 20.4095 9.02308 23.7728 9.02308C27.2503 9.02308 30.0422 11.5496 30.0993 15.0127C30.1565 16.5999 31.2395 17.5393 32.4939 17.5393C33.8027 17.5393 35 16.5999 34.9429 14.895C34.8286 8.84641 29.8707 4.5 23.8299 4.5Z" fill="#00D639"/>
3
+ </svg>
@@ -0,0 +1,4 @@
1
+ <svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path d="M42.4043 0H5.59573C2.50529 0 0 2.50529 0 5.59573V42.4043C0 45.4947 2.50529 48 5.59573 48H42.4043C45.4947 48 48 45.4947 48 42.4043V5.59573C48 2.50529 45.4947 0 42.4043 0Z" fill="black"/>
3
+ <path d="M23.8299 4.5C17.6748 4.5 13 9.25863 13 15.366C13 22.0623 17.6748 24.645 22.8612 26.2321C27.7619 27.8164 30.0993 29.5802 30.0993 33.0462C30.0993 36.5682 27.5333 39.0358 24.1728 39.0358C20.8095 39.0358 17.9034 36.5682 17.9034 32.7517C17.9034 30.6374 18.8721 30.1074 18.8721 28.9325C18.8721 27.5809 17.9578 26.5854 16.4776 26.5854C14.7687 26.5854 13 29.2269 13 32.9845C13 39.0358 18.0748 43.5 24.1728 43.5C30.3279 43.5 35 38.7414 35 32.634C35 25.9966 30.3279 23.3522 25.0844 21.7679C20.2381 20.2425 17.9034 18.4198 17.9034 14.9538C17.9034 11.4907 20.4095 9.02308 23.7728 9.02308C27.2503 9.02308 30.0422 11.5496 30.0993 15.0127C30.1565 16.5999 31.2395 17.5393 32.4939 17.5393C33.8027 17.5393 35 16.5999 34.9429 14.895C34.8286 8.84641 29.8707 4.5 23.8299 4.5Z" fill="#00D639"/>
4
+ </svg>
@@ -0,0 +1,31 @@
1
+ <svg width="20" height="20" viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false">
2
+ <g id="nexus-icon" transform="translate(60, 60)" fill="#05D505">
3
+ <circle cx="0" cy="0" r="12"/>
4
+ <g stroke="#05D505" stroke-width="4.5">
5
+ <g transform="rotate(0)">
6
+ <line x1="12" y1="0" x2="36" y2="0" />
7
+ <circle cx="44" cy="0" r="8"/>
8
+ </g>
9
+ <g transform="rotate(60)">
10
+ <line x1="12" y1="0" x2="36" y2="0" />
11
+ <circle cx="44" cy="0" r="8"/>
12
+ </g>
13
+ <g transform="rotate(120)">
14
+ <line x1="12" y1="0" x2="36" y2="0" />
15
+ <circle cx="44" cy="0" r="8"/>
16
+ </g>
17
+ <g transform="rotate(180)">
18
+ <line x1="12" y1="0" x2="36" y2="0" />
19
+ <circle cx="44" cy="0" r="8"/>
20
+ </g>
21
+ <g transform="rotate(240)">
22
+ <line x1="12" y1="0" x2="36" y2="0" />
23
+ <circle cx="44" cy="0" r="8"/>
24
+ </g>
25
+ <g transform="rotate(300)">
26
+ <line x1="12" y1="0" x2="36" y2="0" />
27
+ <circle cx="44" cy="0" r="8"/>
28
+ </g>
29
+ </g>
30
+ </g>
31
+ </svg>
@@ -0,0 +1,105 @@
1
+ import { AppBar, Box, Toolbar, useMediaQuery, useTheme } from "@mui/material";
2
+ import { NexusHome, TextHighlightAi, ThemeToggle } from ".";
3
+ import SageLogo from "@/assets/images/Logo.svg";
4
+ import type { ReactNode, ReactElement } from "react";
5
+ import { useState, useEffect, useRef } from "react";
6
+
7
+ interface ActionBarProps {
8
+ title?: ReactNode;
9
+ extraLeft?: ReactNode;
10
+ extraRight?: ReactNode;
11
+ }
12
+
13
+ export const ActionBar = ({
14
+ title,
15
+ extraLeft,
16
+ extraRight,
17
+ }: ActionBarProps): ReactElement => {
18
+ const [isExpanded, setIsExpanded] = useState(true);
19
+ const lastScrollY = useRef(0);
20
+ const theme = useTheme();
21
+ const isMd = useMediaQuery(theme.breakpoints.up("md"));
22
+
23
+ useEffect(() => {
24
+ const handleScroll = () => {
25
+ const currentScrollY = window.scrollY;
26
+ if (currentScrollY > lastScrollY.current) {
27
+ setIsExpanded(false);
28
+ } else {
29
+ setIsExpanded(true);
30
+ }
31
+ lastScrollY.current = currentScrollY;
32
+ };
33
+
34
+ window.addEventListener("scroll", handleScroll, { passive: true });
35
+ return () => window.removeEventListener("scroll", handleScroll);
36
+ }, []);
37
+
38
+ return (
39
+ <AppBar position="sticky" component="header">
40
+ <Toolbar
41
+ variant="dense"
42
+ sx={{
43
+ display: "flex",
44
+ flexDirection: { xs: "column", md: "row" },
45
+ flexWrap: "wrap",
46
+ alignItems: "center",
47
+ justifyContent: { xs: "center", md: "space-between" },
48
+ py: { xs: 1, md: 0 },
49
+ }}
50
+ >
51
+ <Box
52
+ sx={{
53
+ width: { xs: "100%", md: "auto" },
54
+ textAlign: "center",
55
+ display: { xs: "block", md: "none" },
56
+ }}
57
+ >
58
+ <TextHighlightAi component="h2">{title}</TextHighlightAi>
59
+ </Box>
60
+
61
+ <Box
62
+ sx={{
63
+ display: "block",
64
+ width: "100%",
65
+ maxHeight: { xs: isMd || isExpanded ? "300px" : "0px", md: "none" },
66
+ overflow: { xs: "hidden", md: "visible" },
67
+ transition: { xs: "max-height 0.2s ease-in-out", md: "none" },
68
+ }}
69
+ >
70
+ <Box
71
+ sx={{
72
+ display: "flex",
73
+ flexDirection: { xs: "column", md: "row" },
74
+ alignItems: "center",
75
+ justifyContent: { xs: "center", md: "space-between" },
76
+ width: "100%",
77
+ gap: { xs: 1, md: 0 },
78
+ }}
79
+ >
80
+ <Box sx={{ height: "38px", pt: 0.5 }}>
81
+ <img src={SageLogo} alt="Logo" />
82
+ </Box>
83
+ <Box>{extraLeft}</Box>
84
+ <Box sx={{ display: { xs: "none", md: "block" } }}>
85
+ <TextHighlightAi component="h2">{title}</TextHighlightAi>
86
+ </Box>
87
+ <Box>{extraRight}</Box>
88
+ <Box
89
+ sx={{
90
+ flex: "0 0 auto",
91
+ display: "flex",
92
+ alignItems: "center",
93
+ gap: 1,
94
+ ml: { xs: 0, sm: 2 },
95
+ }}
96
+ >
97
+ <NexusHome />
98
+ <ThemeToggle />
99
+ </Box>
100
+ </Box>
101
+ </Box>
102
+ </Toolbar>
103
+ </AppBar>
104
+ );
105
+ };
@@ -0,0 +1,36 @@
1
+ import { IconButton, Tooltip } from "@mui/material";
2
+ import { useTheme } from "@mui/material/styles";
3
+ import nexusLogoIcon from "@/assets/images/nexus-logo-icon.svg";
4
+
5
+ export const NexusHome: React.FC = () => {
6
+ const theme = useTheme();
7
+
8
+ return (
9
+ <Tooltip title="Go to Nexus Home" placement="bottom">
10
+ <IconButton
11
+ component="a"
12
+ href="https://ai-nexus.sage.com/"
13
+ size="small"
14
+ aria-label="Nexus home"
15
+ sx={{
16
+ width: 32,
17
+ height: 32,
18
+ borderRadius: "50%",
19
+ p: 0.5,
20
+ display: "inline-flex",
21
+ alignItems: "center",
22
+ justifyContent: "center",
23
+ "&:hover": {
24
+ backgroundColor: theme.palette.action.hover,
25
+ },
26
+ }}
27
+ >
28
+ <img
29
+ src={nexusLogoIcon}
30
+ alt="Nexus Logo"
31
+ style={{ width: 20, height: 20, display: "block" }}
32
+ />
33
+ </IconButton>
34
+ </Tooltip>
35
+ );
36
+ };
@@ -0,0 +1,34 @@
1
+ import { gradients } from "@/theme/sageTheme";
2
+
3
+ interface TextHighlightAiProps extends React.HTMLAttributes<HTMLElement> {
4
+ children?: React.ReactNode;
5
+ component?: React.ElementType;
6
+ style?: React.CSSProperties;
7
+ }
8
+
9
+ export const TextHighlightAi: React.FC<TextHighlightAiProps> = ({
10
+ children,
11
+ component = "h1",
12
+ style = {},
13
+ ...props
14
+ }) => {
15
+ const Tag = component as any;
16
+ return (
17
+ <Tag
18
+ style={{
19
+ display: "inline-flex",
20
+ width: "fit-content",
21
+ maxWidth: "100%",
22
+ background: gradients.textHighlightAi,
23
+ backgroundClip: "text",
24
+ WebkitBackgroundClip: "text",
25
+ WebkitTextFillColor: "transparent",
26
+ color: "transparent",
27
+ ...style,
28
+ }}
29
+ {...props}
30
+ >
31
+ {children}
32
+ </Tag>
33
+ );
34
+ };
@@ -0,0 +1,22 @@
1
+ import { useThemeMode } from '@/theme/ThemeContext';
2
+ import { IconButton, Tooltip, useTheme } from '@mui/material';
3
+ import LightModeIcon from '@mui/icons-material/LightMode';
4
+ import DarkModeIcon from '@mui/icons-material/DarkMode';
5
+
6
+ export const ThemeToggle: React.FC = () => {
7
+ const { mode, toggleMode } = useThemeMode();
8
+ const theme = useTheme();
9
+
10
+ return (
11
+ <Tooltip title={`Switch to ${mode === 'dark' ? 'light' : 'dark'} mode`} placement="bottom">
12
+ <IconButton
13
+ onClick={toggleMode}
14
+ size="small"
15
+ aria-label={`Switch to ${mode === 'dark' ? 'light' : 'dark'} mode`}
16
+ sx={{ color: theme.palette.warning?.main ?? theme.palette.primary.main }}
17
+ >
18
+ {mode === 'dark' ? <LightModeIcon fontSize="small" /> : <DarkModeIcon fontSize="small" />}
19
+ </IconButton>
20
+ </Tooltip>
21
+ );
22
+ };
@@ -0,0 +1,11 @@
1
+ export { ActionBar } from "./ActionBar";
2
+ // export { CheckboxGroup } from './CheckboxGroup.tsx';
3
+ // export { IconActionButton } from './IconActionButton.tsx';
4
+ // export { LocationMultiSelect } from './LocationMultiSelect.tsx';
5
+ export { NexusHome } from "./NexusHome";
6
+ // export { SecondaryButton } from './SecondaryButton.tsx';
7
+ // export { SearchInput } from './SearchInput.tsx';
8
+ // export { SkillChip } from './SkillChip.tsx';
9
+ // export { StatusChip } from './StatusChip.tsx';
10
+ export { TextHighlightAi } from "./TextHighlightAi";
11
+ export { ThemeToggle } from "./ThemeToggle";
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./components";