Write instructions to help users complete labeling tasks.
The instruction field supports HTML markup and it allows use of images, iframes (pdf).
diff --git a/web/apps/labelstudio/src/pages/Settings/MachineLearningSettings/MachineLearningList.scss b/web/apps/labelstudio/src/pages/Settings/MachineLearningSettings/MachineLearningList.scss
index 50173edbf90e..d057162f968b 100644
--- a/web/apps/labelstudio/src/pages/Settings/MachineLearningSettings/MachineLearningList.scss
+++ b/web/apps/labelstudio/src/pages/Settings/MachineLearningSettings/MachineLearningList.scss
@@ -1,8 +1,8 @@
.backend-card {
padding: 15px;
- border-radius: 5px;
- background: var(--sand_100);
- border: 1px solid var(--sand_300);
+ border-radius: var(--radius-small);
+ background: var(--color-neutral-surface);
+ border: 1px solid var(--color-neutral-border);
&__title-container {
display: flex;
@@ -14,6 +14,7 @@
margin-top: 15px;
margin-left: 2px;
font-weight: 500;
+ color: var(--color-neutral-content);
}
&__meta {
@@ -21,7 +22,7 @@
flex-flow: row wrap;
justify-content: space-between;
gap: 20px;
- color: var(--sand_600);
+ color: var(--color-neutral-content-subtler);
margin-top: 5px;
margin-left: 2px;
}
diff --git a/web/apps/labelstudio/src/pages/Settings/MachineLearningSettings/MachineLearningSettings.scss b/web/apps/labelstudio/src/pages/Settings/MachineLearningSettings/MachineLearningSettings.scss
index 74fbd1bc30fa..4f6fb490cc4e 100644
--- a/web/apps/labelstudio/src/pages/Settings/MachineLearningSettings/MachineLearningSettings.scss
+++ b/web/apps/labelstudio/src/pages/Settings/MachineLearningSettings/MachineLearningSettings.scss
@@ -23,8 +23,9 @@
overflow-y: scroll;
padding: 10px;
border-radius: 4px;
- background: var(--sand_0);
- border: 1px solid var(--sand_300);
+ background: var(--color-neutral-surface);
+ border: 1px solid var(--color-neutral-border);
+ color: var(--color-neutral-content);
pre {
white-space: pre-wrap;
@@ -69,7 +70,7 @@
align-items: center;
margin-right: 10px;
font-size: 12px;
- border: 1px solid var(--sand_300);
+ border: 1px solid var(--color-neutral-border);
padding: 3px 6px;
border-radius: 10px;
max-width: 100px;
@@ -88,20 +89,20 @@
background-color: var(--indicator-color);
&_state_CO {
- --indicator-color: var(--success_color);
+ --indicator-color: var(--color-positive-surface);
}
&_state_DI {
- --indicator-color: var(--canteloupe_400);
+ --indicator-color: var(--color-warning-surface);
}
&_state_ER {
- --indicator-color: var(--danger_color);
+ --indicator-color: var(--color-negative-surface);
}
&_state_TR,
&_state_PR {
- --indicator-color: var(--grape_500);
+ --indicator-color: var(--color-primary-surface);
position: relative;
diff --git a/web/apps/labelstudio/src/pages/Settings/PredictionsSettings/PredictionsList.scss b/web/apps/labelstudio/src/pages/Settings/PredictionsSettings/PredictionsList.scss
index d2df7332ff77..dd2f07c7e79a 100644
--- a/web/apps/labelstudio/src/pages/Settings/PredictionsSettings/PredictionsList.scss
+++ b/web/apps/labelstudio/src/pages/Settings/PredictionsSettings/PredictionsList.scss
@@ -2,8 +2,8 @@
width: 100%;
padding: 1rem;
border-radius: 4px;
- background: var(--sand_100);
- border: 1px solid var(--sand_300);
+ background: var(--color-neutral-surface);
+ border: 1px solid var(--color-neutral-border);
display: flex;
justify-content: space-between;
@@ -11,7 +11,7 @@
display: flex;
flex-flow: row wrap;
gap: 20px;
- color: var(--sand_600);
+ color: var(--color-neutral-content-subtler);
margin-top: 7px;
}
@@ -29,11 +29,12 @@
font-size: 16px;
line-height: 18px;
justify-content: space-between;
- box-shadow: 0 1px 0 0 var(--sand_300);
+ border: 1px solid vare(--color-neutral-border);
}
&__title {
font-weight: 500;
+ color: var(--color-neutral-content);
&-content {
display: flex;
diff --git a/web/apps/labelstudio/src/pages/Settings/PredictionsSettings/PredictionsSettings.scss b/web/apps/labelstudio/src/pages/Settings/PredictionsSettings/PredictionsSettings.scss
index d876f513eee5..b18165ed986d 100644
--- a/web/apps/labelstudio/src/pages/Settings/PredictionsSettings/PredictionsSettings.scss
+++ b/web/apps/labelstudio/src/pages/Settings/PredictionsSettings/PredictionsSettings.scss
@@ -5,16 +5,17 @@
&__model-exists-info {
margin-bottom: 20px;
- background: var(--sand_0);
+ background: var(--color-neutral-background);
+ color: var(--color-negative-content);
padding: 10px 20px;
- border: 1px solid var(--sand_300);
+ border: 1px solid var(--color-neutral-border);
border-radius: 8px;
display: flex;
justify-content: center;
align-items: center;
gap: 10px;
}
-
+
&__title-block {
margin: 20px 0;
margin-top: 0;
@@ -22,6 +23,7 @@
&__title {
font-weight: 500;
+ color: var(--color-neutral-content);
}
}
@@ -40,7 +42,7 @@
}
&__status {
- color: var(--sand_500);
+ color: var(--color-neutral-content);
display: flex;
align-items: center;
margin-right: 10px;
@@ -59,20 +61,20 @@
background-color: var(--indicator-color);
&_state_CO {
- --indicator-color: var(--success_color);
+ --indicator-color: var(--color-positive-surface);
}
&_state_DI {
- --indicator-color: var(--canteloupe_400);
+ --indicator-color: var(--color-warning-surface);
}
&_state_ER {
- --indicator-color: var(--danger_color);
+ --indicator-color: var(--color-negative-surface);
}
&_state_TR,
&_state_PR {
- --indicator-color: var(--grape_500);
+ --indicator-color: var(--color-primary-surface);
position: relative;
diff --git a/web/apps/labelstudio/src/pages/Settings/StorageSettings/StorageSettings.scss b/web/apps/labelstudio/src/pages/Settings/StorageSettings/StorageSettings.scss
index c18cb363070b..7167b250bb53 100644
--- a/web/apps/labelstudio/src/pages/Settings/StorageSettings/StorageSettings.scss
+++ b/web/apps/labelstudio/src/pages/Settings/StorageSettings/StorageSettings.scss
@@ -39,7 +39,7 @@
&__info {
display: flex;
align-items: center;
- color: var(--danger_color);
+ color: var(--color-negative-content);
font-size: 14px;
line-height: 22px;
diff --git a/web/apps/labelstudio/src/pages/Settings/settings.scss b/web/apps/labelstudio/src/pages/Settings/settings.scss
index a9340dad5d79..bcd4ed194326 100644
--- a/web/apps/labelstudio/src/pages/Settings/settings.scss
+++ b/web/apps/labelstudio/src/pages/Settings/settings.scss
@@ -12,16 +12,23 @@
font-weight: 500;
margin-top: 0;
font-size: 1.75rem;
+ color: var(--color-neutral-content);
}
}
+.settings-description {
+ color: var(--color-neutral-content-subtler);
+}
+
.settings-wrapper {
--column-count: 1;
- border: 1px solid var(--sand_300);
+ border: 1px solid var(--color-neutral-border);
border-radius: 0.5rem;
padding: 1.5rem;
width: 40rem;
+ color: var(--color-neutral-content-subtle);
+
& +.settings-wrapper,
& +.form-wrapper {
@@ -31,13 +38,16 @@
& h3 {
margin: 0 0 0.5rem;
font-weight: 500;
+ color: var(--color-neutral-content);
}
&__header {
font-weight: 500;
font-size: 1.5rem;
margin-bottom: 0;
+ color: var(--color-neutral-content);
}
+
}
.general-settings {
@@ -70,13 +80,13 @@
&__title {
font-size: 0.875rem;
- color: var(--sand_900);
+ color: var(--color-neutral-content);
font-weight: 500;
}
}
.settings-caption {
- color: var(--sand_700);
+ color: var(--color-neutral-content-subtler);
font-size: 12px;
font-style: normal;
font-weight: 400;
@@ -84,7 +94,7 @@
letter-spacing: 0.4px;
a {
- color: var(--primary_link);
+ color: var(--color-primary-surface-content);
font-size: 12px;
font-style: normal;
font-weight: 500;
@@ -106,7 +116,7 @@
margin: 0;
a {
- color: var(--primary_link);
+ color: var(--color-primary-surface-content);
font-size: 14px;
font-style: normal;
font-weight: 500;
@@ -142,7 +152,7 @@
margin-top: 5px;
font-size: 14px;
line-height: 22px;
- color: var(--sand_600);
+ color: var(--color-neutral-content-subtle);
font-weight: 500;
padding: 0 16px;
height: 22px;
diff --git a/web/apps/labelstudio/src/pages/WebhookPage/WebhookPage.scss b/web/apps/labelstudio/src/pages/WebhookPage/WebhookPage.scss
index e3aeb39774c5..d01f7f09a7bb 100644
--- a/web/apps/labelstudio/src/pages/WebhookPage/WebhookPage.scss
+++ b/web/apps/labelstudio/src/pages/WebhookPage/WebhookPage.scss
@@ -21,17 +21,18 @@
flex: none;
width: 100%;
height: 112px - 24px;
- background: var(--sand_100);
- border: 1px var(--sand_300) solid;
+ background: var(--color-primary-background);
+ border: 1px var(--color-primary-border-subtlest) solid;
margin-left: -2px;
display: flex;
padding-top: 24px;
+ border-radius: var(--radius-small);
}
&__footer-text {
width: 42rem;
font-size: 0.875rem;
- color: var(--sand_600);
+ color: var(--color-neutral-content-subtle);
& p {
margin: 0;
@@ -39,7 +40,7 @@
}
& a {
- color: var(--grape_600);
+ color: var(--color-primary-content);
text-decoration: underline;
}
}
@@ -53,10 +54,11 @@
&__title {
font-weight: 500;
margin-bottom: 24px;
+ color: var(--color-neutral-content);
}
&__title-base {
- color: var(--sand_600);
+ color: var(--color-neutral-content-subtler);
cursor: pointer;
}
@@ -84,11 +86,11 @@
align-items: center;
padding: 0.5rem;
font-size: 16px;
- border: 1px solid var(--sand_300);
+ border: 1px solid var(--color-neutral-border);
border-radius: 0.5rem;
&:hover {
- background-color: var(--sand_100);
+ background-color: var(--color-neutral-surface);
}
&:hover .webhook-list__item-control {
@@ -147,7 +149,7 @@
}
&__black-text {
- color: var(--sand_900);
+ color: var(--color-neutral-content);
}
&__activator {
@@ -184,7 +186,7 @@
}
&__headers {
- border: 1px solid var(--sand_300);
+ border: 1px solid var(--color-neutral-border);
padding: 1rem;
border-radius: 0.5rem;
margin-bottom: 1rem;
@@ -224,7 +226,7 @@
}
.webhook-payload {
- border: 1px solid var(--sand_300);
+ border: 1px solid var(--color-neutral-border);
padding: 1rem;
border-radius: 0.5rem;
margin-bottom: 1rem;
diff --git a/web/apps/labelstudio/src/pages/index.js b/web/apps/labelstudio/src/pages/index.js
index 1f696787930b..675168603f69 100644
--- a/web/apps/labelstudio/src/pages/index.js
+++ b/web/apps/labelstudio/src/pages/index.js
@@ -1,9 +1,15 @@
import { ProjectsPage } from "./Projects/Projects";
+import { HomePage } from "./Home/HomePage";
import { OrganizationPage } from "./Organization";
import { ModelsPage } from "./Organization/Models/ModelsPage";
-import { AccountSettingsPage } from "@humansignal/core";
+import { FF_HOMEPAGE } from "../utils/feature-flags";
+import { pages } from "@humansignal/core";
import { FF_AUTH_TOKENS, isFF } from "../utils/feature-flags";
-export const Pages = [ProjectsPage, OrganizationPage, ModelsPage, isFF(FF_AUTH_TOKENS) && AccountSettingsPage].filter(
- Boolean,
-);
+export const Pages = [
+ isFF(FF_HOMEPAGE) && HomePage,
+ ProjectsPage,
+ OrganizationPage,
+ ModelsPage,
+ isFF(FF_AUTH_TOKENS) && pages.AccountSettingsPage,
+].filter(Boolean);
diff --git a/web/apps/labelstudio/src/providers/ApiProvider.d.ts b/web/apps/labelstudio/src/providers/ApiProvider.d.ts
new file mode 100644
index 000000000000..e7bd4ccf9f2c
--- /dev/null
+++ b/web/apps/labelstudio/src/providers/ApiProvider.d.ts
@@ -0,0 +1,27 @@
+import type { APIProxy } from "libs/datamanager/src/utils/api-proxy";
+
+export interface Meta {
+ headers: Map;
+ status: number;
+ url: string;
+ ok: boolean;
+}
+
+export type WrappedResponse = T & {
+ $meta: Meta;
+};
+
+export type Unwrap = P extends WrappedResponse ? T : never;
+
+export function useAPI(): {
+ callApi: (
+ api: string,
+ options?: {
+ params?: Record;
+ errorFilter?: (result: unknown) => boolean;
+ body?: FormData | Record;
+ },
+ ) => Promise>;
+};
+
+export const API: APIProxy;
diff --git a/web/apps/labelstudio/src/providers/ApiProvider.jsx b/web/apps/labelstudio/src/providers/ApiProvider.jsx
new file mode 100644
index 000000000000..079ba31f44d0
--- /dev/null
+++ b/web/apps/labelstudio/src/providers/ApiProvider.jsx
@@ -0,0 +1,121 @@
+import { createContext, forwardRef, useCallback, useContext, useEffect, useMemo, useState } from "react";
+import { ErrorWrapper } from "../components/Error/Error";
+import { modal } from "../components/Modal/Modal";
+import { API_CONFIG } from "../config/ApiConfig";
+import { APIProxy } from "../utils/api-proxy";
+import { absoluteURL } from "../utils/helpers";
+
+export const API = new APIProxy(API_CONFIG);
+
+export const ApiContext = createContext();
+ApiContext.displayName = "ApiContext";
+
+let apiLocked = false;
+
+const errorFormatter = (result) => {
+ const { response } = result;
+ const isShutdown = String(response?.detail ?? result?.error) === "Failed to fetch";
+
+ return {
+ isShutdown,
+ title: result.error ? "Runtime error" : "Server error",
+ message: response?.detail ?? result?.error,
+ stacktrace: response?.exc_info ?? null,
+ version: response?.version,
+ validation: Object.entries(response?.validation_errors ?? {}),
+ };
+};
+
+const handleError = async (response, showModal = true) => {
+ let result = response;
+
+ if (result instanceof Response) {
+ result = await API.generateError(response);
+ }
+
+ if (response.status === 401) {
+ location.href = absoluteURL("/");
+ return;
+ }
+
+ const { isShutdown, ...formattedError } = errorFormatter(result);
+
+ if (showModal) {
+ modal({
+ allowClose: !isShutdown,
+ body: isShutdown ? (
+
+ ) : (
+
+ ),
+ simple: true,
+ style: { width: 680 },
+ });
+ }
+
+ return isShutdown;
+};
+
+export const ApiProvider = forwardRef(({ children }, ref) => {
+ const [error, setError] = useState(null);
+
+ const callApi = useCallback(async (method, { params = {}, errorFilter, ...rest } = {}) => {
+ if (apiLocked) return;
+
+ setError(null);
+
+ const result = await API[method](params, rest);
+
+ if (result.status === 401) {
+ apiLocked = true;
+ location.href = absoluteURL("/");
+ return;
+ }
+
+ if (result.error) {
+ const shouldCatchError = errorFilter?.(result) === false;
+
+ if (!errorFilter || shouldCatchError) {
+ setError(result);
+ const isShutdown = await handleError(result, contextValue.showModal);
+
+ apiLocked = apiLocked || isShutdown;
+
+ return null;
+ }
+ }
+
+ return result;
+ }, []);
+
+ const contextValue = useMemo(
+ () => ({
+ api: API,
+ callApi,
+ handleError,
+ error,
+ showModal: true,
+ errorFormatter,
+ isValidMethod(...args) {
+ return API.isValidMethod(...args);
+ },
+ }),
+ [error],
+ );
+
+ useEffect(() => {
+ if (ref) {
+ ref.current = contextValue;
+ }
+ }, [ref]);
+
+ return {children};
+});
+
+export const useAPI = () => {
+ return useContext(ApiContext);
+};
diff --git a/web/apps/labelstudio/src/providers/RoutesProvider.jsx b/web/apps/labelstudio/src/providers/RoutesProvider.jsx
index 5e2525b6cab0..ee33c9351b80 100644
--- a/web/apps/labelstudio/src/providers/RoutesProvider.jsx
+++ b/web/apps/labelstudio/src/providers/RoutesProvider.jsx
@@ -11,15 +11,22 @@ export const RoutesContext = createContext();
const findMacthingComponents = (path, routesMap, parentPath = "") => {
const result = [];
- const match = routesMap.find((route) => {
- const matchingPath = `${parentPath}${route.path}`;
- const match = matchPath(path, { path: matchingPath });
+ const match =
+ path === "/"
+ ? routesMap.at(0)
+ : routesMap.find((route) => {
+ // if (route.path === "/") return false;
- return match;
- });
+ const isRoot = route.path === "/";
+ const matchingPath = `${parentPath}${route.path}`;
+ const match = matchPath(path, { path: matchingPath, exact: isRoot });
+
+ return match;
+ });
if (match) {
const routePath = `${parentPath}${match.path}`;
+
result.push({ ...match, path: routePath });
if (match.routes) {
@@ -93,6 +100,7 @@ export const RoutesProvider = ({ children }) => {
}
}, [location, routesMap, currentContextProps, routesChain, lastRoute]);
+ console.log(breadcrumbs);
return {children};
};
@@ -105,7 +113,7 @@ export const useFindRouteComponent = () => {
};
export const useBreadcrumbs = () => {
- return useContext(RoutesContext)?.breadcrumbs ?? [];
+ return useBreadcrumbControls();
};
export const useCurrentPath = () => {
diff --git a/web/apps/labelstudio/src/services/breadrumbs.js b/web/apps/labelstudio/src/services/breadrumbs.js
index b97b6ce13f6d..c1308914401f 100644
--- a/web/apps/labelstudio/src/services/breadrumbs.js
+++ b/web/apps/labelstudio/src/services/breadrumbs.js
@@ -1,6 +1,6 @@
-import { useCallback, useState } from "react";
-import { singletonHook } from "react-singleton-hook";
import { isDefined } from "../utils/helpers";
+import { atom, useAtomValue } from "jotai";
+import { JotaiStore } from "../utils/jotai-store";
const initialBreadcrumbs = [];
@@ -10,78 +10,43 @@ const noop = () => {
}
};
-export let setBreadcrumbs = noop;
+const crumbsAtom = atom([]);
-export let addCrumb = noop;
-
-export let deleteCrumb = noop;
-
-export let addAction = noop;
-
-export let deleteAction = noop;
-
-let localCrumbs = [];
-
-export const useBreadcrumbControls = singletonHook(initialBreadcrumbs, () => {
- const [breadcrumbs, setBreadcrumbsState] = useState(initialBreadcrumbs);
-
- localCrumbs = breadcrumbs;
- setBreadcrumbs = (newCrumbs) => {
- const crumbs = [...(newCrumbs ?? [])];
-
- setBreadcrumbsState(crumbs);
- localCrumbs = crumbs;
- };
-
- addCrumb = useCallback(
- (crumb) => {
- if (!isDefined(crumb?.key)) throw Error("Crumb must have a key");
- const crumbs = [...localCrumbs, crumb];
-
- setBreadcrumbs(crumbs);
- localCrumbs = crumbs;
- },
- [breadcrumbs],
- );
+export const setBreadcrumbs = (newCrumbs) => {
+ JotaiStore.set(crumbsAtom, newCrumbs ?? []);
+};
- deleteCrumb = useCallback(
- (key) => {
- const crumbs = localCrumbs.filter((c) => c.key !== key);
+export const addCrumb = (crumb) => {
+ if (!isDefined(crumb?.key)) throw Error("Crumb must have a key");
- setBreadcrumbs(crumbs);
- localCrumbs = crumbs;
- },
- [breadcrumbs],
- );
+ JotaiStore.set(crumbsAtom, (crumbs) => [...crumbs, crumb]);
+};
- addAction = useCallback(
- (key, onClick) => {
- const crumbs = localCrumbs.map((crumb) => {
- if (crumb.key === key) {
- return { ...crumb, onClick };
- }
- return crumb;
- });
+export const deleteCrumb = (key) => {
+ JotaiStore.set(crumbsAtom, (crumbs) => crumbs.filter((c) => c.key !== key));
+};
- setBreadcrumbs(crumbs);
- localCrumbs = crumbs;
- },
- [breadcrumbs],
+export const addAction = (key, onClick) => {
+ JotaiStore.set(crumbsAtom, (crumbs) =>
+ crumbs.map((crumb) => {
+ if (crumb.key === key) {
+ return { ...crumb, onClick };
+ }
+ return crumb;
+ }),
);
+};
- deleteAction = useCallback(
- (key) => {
- const crumbs = localCrumbs.map((crumb) => {
- if (crumb.key === key) delete crumb.onClick;
-
- return crumb;
- });
+export const deleteAction = (key) => {
+ JotaiStore.set(crumbsAtom, (crumbs) =>
+ crumbs.map((crumb) => {
+ if (crumb.key === key) delete crumb.onClick;
- setBreadcrumbs(crumbs);
- localCrumbs = crumbs;
- },
- [breadcrumbs],
+ return crumb;
+ }),
);
+};
- return breadcrumbs;
-});
+export const useBreadcrumbControls = () => {
+ return useAtomValue(crumbsAtom);
+};
diff --git a/web/apps/labelstudio/src/types/Project.d.ts b/web/apps/labelstudio/src/types/Project.d.ts
index b2ed5689e232..962391ae9719 100644
--- a/web/apps/labelstudio/src/types/Project.d.ts
+++ b/web/apps/labelstudio/src/types/Project.d.ts
@@ -52,7 +52,7 @@ declare type APIProject = {
num_tasks_with_annotations?: string;
/** Total task number in project */
- task_number?: string;
+ task_number?: number;
/** Useful annotation number in project not including skipped_annotations_number and ground_truth_number. Total annotations = annotation_number + skipped_annotations_number + ground_truth_number */
useful_annotation_number?: string;
@@ -66,6 +66,9 @@ declare type APIProject = {
/** Total annotations number in project including skipped_annotations_number and ground_truth_number. */
total_annotations_number?: string;
+ /** Total number of tasks with at least one annotation */
+ finished_task_number: number;
+
/** Total predictions number in project including skipped_annotations_number and ground_truth_number. */
total_predictions_number?: string;
sampling?: "Sequential sampling" | "Uniform sampling" | "Uncertainty sampling" | null;
diff --git a/web/apps/labelstudio/src/utils/jotai-store.ts b/web/apps/labelstudio/src/utils/jotai-store.ts
new file mode 100644
index 000000000000..a8e811787f5d
--- /dev/null
+++ b/web/apps/labelstudio/src/utils/jotai-store.ts
@@ -0,0 +1,5 @@
+import { Provider, createStore } from "jotai";
+
+export const JotaiStore = createStore();
+
+export { Provider as JotaiProvider };
diff --git a/web/components.json b/web/components.json
new file mode 100644
index 000000000000..ed85462d2abb
--- /dev/null
+++ b/web/components.json
@@ -0,0 +1,21 @@
+{
+ "$schema": "https://ui.shadcn.com/schema.json",
+ "style": "default",
+ "rsc": false,
+ "tsx": true,
+ "tailwind": {
+ "config": "libs/ui/src/tailwind.config.js",
+ "css": "libs/ui/src/tailwind.css",
+ "baseColor": "slate",
+ "cssVariables": true,
+ "prefix": ""
+ },
+ "aliases": {
+ "components": "@humansignal/shad/components",
+ "ui": "@humansignal/shad/components/ui",
+ "utils": "@humansignal/shad/utils",
+ "lib": "@humansignal/shad/lib",
+ "hooks": "@humansignal/shad/hooks"
+ },
+ "iconLibrary": "lucide"
+}
diff --git a/web/jest.config.ts b/web/jest.config.ts
index 3e2c3e47c0b3..11c2c9516a86 100644
--- a/web/jest.config.ts
+++ b/web/jest.config.ts
@@ -1,5 +1,19 @@
import { getJestProjects } from "@nx/jest";
+import { pathsToModuleNameMapper } from "ts-jest";
export default {
projects: getJestProjects(),
+ moduleNameMapper: pathsToModuleNameMapper(
+ {
+ "@humansignal/core": ["libs/core/src/index.ts"],
+ "@humansignal/datamanager": ["libs/datamanager/src/index.js"],
+ "@humansignal/editor": ["libs/editor/src/index.js"],
+ "@humansignal/frontend-test/*": ["libs/frontend-test/src/*"],
+ "@humansignal/ui": ["libs/ui/src/index.ts"],
+ "@humansignal/icons": ["libs/ui/src/assets/icons"],
+ "@humansignal/typography": ["libs/ui/src/typography"],
+ "@humansignal/shad/*": ["./libs/ui/src/shad/*"],
+ },
+ { prefix: "/../../" },
+ ),
};
diff --git a/web/jest.preset.js b/web/jest.preset.js
index 0640263d2c6d..88105ab3e404 100644
--- a/web/jest.preset.js
+++ b/web/jest.preset.js
@@ -1,3 +1,13 @@
const nxPreset = require("@nx/jest/preset").default;
+const tsconfig = require("./tsconfig.base.json");
+const { pathsToModuleNameMapper } = require("ts-jest");
-module.exports = { ...nxPreset };
+console.log(__dirname);
+
+module.exports = {
+ ...nxPreset,
+ moduleNameMapper: {
+ ...nxPreset.moduleNameMapper,
+ ...pathsToModuleNameMapper(tsconfig.compilerOptions.paths, { prefix: "/../../" }),
+ },
+};
diff --git a/web/libs/core/src/index.ts b/web/libs/core/src/index.ts
index 9f38e0a7db69..fafcb49feb10 100644
--- a/web/libs/core/src/index.ts
+++ b/web/libs/core/src/index.ts
@@ -1,6 +1,7 @@
import * as ff from "./lib/utils/feature-flags";
-export * from "./lib/utils/analytics";
-export * from "./pages";
+import * as pages from "./pages";
+
export * from "./lib/Tour";
+export * from "./lib/utils/analytics";
-export { ff };
+export { ff, pages };
diff --git a/web/libs/core/src/lib/utils/feature-flags.ts b/web/libs/core/src/lib/utils/feature-flags.ts
index f30d3c890d82..7526c0b38f6c 100644
--- a/web/libs/core/src/lib/utils/feature-flags.ts
+++ b/web/libs/core/src/lib/utils/feature-flags.ts
@@ -37,6 +37,11 @@ export const FF_UNSAVED_CHANGES = "fflag_feat_front_leap_1198_unsaved_changes_18
*/
export const FF_AUTH_TOKENS = "fflag__feature_develop__prompts__dia_1829_jwt_token_auth";
+/**
+ * Enable new home page for LSO and LSE
+ */
+export const FF_HOMEPAGE = "fflag_all_feat_dia_1777_ls_homepage_short";
+
export function isFF(id: string) {
// TODO: remove the override + if statement once LSE and LSO start building react the same way and fflag_fix_front_lsdv_4620_memory_leaks_100723_short is removed
const override: Record = {
diff --git a/web/libs/core/src/pages/AccountSettings/AccountSettings.tsx b/web/libs/core/src/pages/AccountSettings/AccountSettings.tsx
index 31d458a556b2..19d04c337280 100644
--- a/web/libs/core/src/pages/AccountSettings/AccountSettings.tsx
+++ b/web/libs/core/src/pages/AccountSettings/AccountSettings.tsx
@@ -11,9 +11,9 @@ import { settingsAtom } from "./atoms";
* FIXME: This is legacy imports. We're not supposed to use such statements
* each one of these eventually has to be migrated to core/ui
*/
-import { SidebarMenu } from "/apps/labelstudio/src/components/SidebarMenu/SidebarMenu";
+import { SidebarMenu } from "apps/labelstudio/src/components/SidebarMenu/SidebarMenu";
-export const AccountSettingsPage = () => {
+const AccountSettingsPage = () => {
const settings = useAtomValue(settingsAtom);
const contentClassName = clsx(styles.accountSettings__content, {
[styles.accountSettingsPadding]: window.APP_SETTINGS.billing !== undefined,
@@ -75,3 +75,5 @@ AccountSettingsPage.routes = () => [
// },
},
];
+
+export { AccountSettingsPage };
diff --git a/web/libs/core/src/pages/AccountSettings/sections/EmailPreferences.tsx b/web/libs/core/src/pages/AccountSettings/sections/EmailPreferences.tsx
index 7bbfdf3dc06d..2aef2952f7ed 100644
--- a/web/libs/core/src/pages/AccountSettings/sections/EmailPreferences.tsx
+++ b/web/libs/core/src/pages/AccountSettings/sections/EmailPreferences.tsx
@@ -1,14 +1,13 @@
import { useCallback, useState } from "react";
-import { Checkbox } from "@humansignal/ui";
-import { useAPI } from "apps/labelstudio/src/providers/ApiProvider";
+import { Checkbox, Spinner } from "@humansignal/ui";
/**
* FIXME: This is legacy imports. We're not supposed to use such statements
* each one of these eventually has to be migrated to core/ui
*/
-import { useConfig } from "/apps/labelstudio/src/providers/ConfigProvider";
-import { useCurrentUser } from "/apps/labelstudio/src/providers/CurrentUser";
-import { Spinner } from "/apps/labelstudio/src/components/Spinner/Spinner";
+import { useAPI } from "apps/labelstudio/src/providers/ApiProvider";
+import { useConfig } from "apps/labelstudio/src/providers/ConfigProvider";
+import { useCurrentUser } from "apps/labelstudio/src/providers/CurrentUser";
export const EmailPreferences = () => {
const config = useConfig();
diff --git a/web/libs/core/src/pages/AccountSettings/sections/MembershipInfo.tsx b/web/libs/core/src/pages/AccountSettings/sections/MembershipInfo.tsx
index b7bbbe495ad8..5fa35c13dad7 100644
--- a/web/libs/core/src/pages/AccountSettings/sections/MembershipInfo.tsx
+++ b/web/libs/core/src/pages/AccountSettings/sections/MembershipInfo.tsx
@@ -7,8 +7,8 @@ import styles from "./MembershipInfo.module.scss";
* FIXME: This is legacy imports. We're not supposed to use such statements
* each one of these eventually has to be migrated to core/ui
*/
-import { useCurrentUser } from "/apps/labelstudio/src/providers/CurrentUser";
-import { useAPI } from "/apps/labelstudio/src/providers/ApiProvider";
+import { useCurrentUser } from "apps/labelstudio/src/providers/CurrentUser";
+import { useAPI } from "apps/labelstudio/src/providers/ApiProvider";
export const MembershipInfo = () => {
const api = useAPI();
diff --git a/web/libs/core/src/pages/AccountSettings/sections/PersonalAccessToken.tsx b/web/libs/core/src/pages/AccountSettings/sections/PersonalAccessToken.tsx
index d307167cb32e..94615f38b0ef 100644
--- a/web/libs/core/src/pages/AccountSettings/sections/PersonalAccessToken.tsx
+++ b/web/libs/core/src/pages/AccountSettings/sections/PersonalAccessToken.tsx
@@ -9,8 +9,8 @@ import { useCopyText } from "../../../lib/hooks/useCopyText";
* FIXME: This is legacy imports. We're not supposed to use such statements
* each one of these eventually has to be migrated to core/ui
*/
-import { Input, TextArea } from "/apps/labelstudio/src/components/Form";
-import { Button } from "/apps/labelstudio/src/components/Button/Button";
+import { Input, TextArea } from "apps/labelstudio/src/components/Form";
+import { Button } from "apps/labelstudio/src/components/Button/Button";
const tokenAtom = atomWithQuery(() => ({
queryKey: ["access-token"],
diff --git a/web/libs/core/src/pages/AccountSettings/sections/PersonalInfo.tsx b/web/libs/core/src/pages/AccountSettings/sections/PersonalInfo.tsx
index b35ad7907adb..55aca80afef9 100644
--- a/web/libs/core/src/pages/AccountSettings/sections/PersonalInfo.tsx
+++ b/web/libs/core/src/pages/AccountSettings/sections/PersonalInfo.tsx
@@ -1,13 +1,18 @@
import { useCallback, useEffect, useRef, useState } from "react";
import clsx from "clsx";
import { InputFile, useToast } from "@humansignal/ui";
-import { Input } from "/apps/labelstudio/src/components/Form/Elements";
-import { Userpic } from "/apps/labelstudio/src/components/Userpic/Userpic";
-import { useCurrentUser } from "/apps/labelstudio/src/providers/CurrentUser";
-import { Button } from "/apps/labelstudio/src/components/Button/Button";
import { useAPI } from "apps/labelstudio/src/providers/ApiProvider";
import styles from "../AccountSettings.module.scss";
+/**
+ * FIXME: This is legacy imports. We're not supposed to use such statements
+ * each one of these eventually has to be migrated to core/ui
+ */
+import { Input } from "apps/labelstudio/src/components/Form/Elements";
+import { Userpic } from "apps/labelstudio/src/components/Userpic/Userpic";
+import { useCurrentUser } from "apps/labelstudio/src/providers/CurrentUser";
+import { Button } from "apps/labelstudio/src/components/Button/Button";
+
export const PersonalInfo = () => {
const api = useAPI();
const toast = useToast();
diff --git a/web/libs/core/src/pages/AccountSettings/sections/PersonalJWTToken.tsx b/web/libs/core/src/pages/AccountSettings/sections/PersonalJWTToken.tsx
index 80b6875cca74..2f0da43cfbaf 100644
--- a/web/libs/core/src/pages/AccountSettings/sections/PersonalJWTToken.tsx
+++ b/web/libs/core/src/pages/AccountSettings/sections/PersonalJWTToken.tsx
@@ -12,11 +12,11 @@ import styles from "./PersonalJWTToken.module.scss";
* FIXME: This is legacy imports. We're not supposed to use such statements
* each one of these eventually has to be migrated to core/ui
*/
-import { API } from "/apps/labelstudio/src/providers/ApiProvider";
-import { modal, confirm } from "/apps/labelstudio/src/components/Modal/Modal";
-import { Button } from "/apps/labelstudio/src/components/Button/Button";
-import { Input, Label } from "/apps/labelstudio/src/components/Form/Elements";
-import { Tooltip } from "/apps/labelstudio/src/components/Tooltip/Tooltip";
+import { API } from "apps/labelstudio/src/providers/ApiProvider";
+import { modal, confirm } from "apps/labelstudio/src/components/Modal/Modal";
+import { Button } from "apps/labelstudio/src/components/Button/Button";
+import { Input, Label } from "apps/labelstudio/src/components/Form/Elements";
+import { Tooltip } from "apps/labelstudio/src/components/Tooltip/Tooltip";
type Token = {
token: string;
diff --git a/web/libs/datamanager/public/index.html b/web/libs/datamanager/public/index.html
index f30a765bb0e4..0306ccb80a8f 100644
--- a/web/libs/datamanager/public/index.html
+++ b/web/libs/datamanager/public/index.html
@@ -54,13 +54,13 @@
::-webkit-scrollbar-track {
box-shadow: inset 0 0 8px rgba(178, 178, 178, 0.3) !important;
- background-color: #F5F5F5 !important;
+ background-color: var(--color-neutral-background) !important;
}
::-webkit-scrollbar {
width: 8px !important;
height: 8px !important;
- background-color: #F5F5F5 !important;
+ background-color: var(--color-neutral-border-boldest) !important;
}
::-webkit-scrollbar-thumb {
diff --git a/web/libs/datamanager/src/assets/icons/gear_new_menu.svg b/web/libs/datamanager/src/assets/icons/gear_new_menu.svg
index 74ed2ff81e80..140ffe3b589a 100644
--- a/web/libs/datamanager/src/assets/icons/gear_new_menu.svg
+++ b/web/libs/datamanager/src/assets/icons/gear_new_menu.svg
@@ -1,5 +1,5 @@
diff --git a/web/libs/datamanager/src/components/App/App.scss b/web/libs/datamanager/src/components/App/App.scss
index 6e69443adbcd..02db815bc7a5 100644
--- a/web/libs/datamanager/src/components/App/App.scss
+++ b/web/libs/datamanager/src/components/App/App.scss
@@ -1,15 +1,16 @@
.root {
height: 100%;
box-sizing: border-box;
- background-color: #f0f0f0;
+ background-color: var(--color-neutral-background);
}
.tab-panel {
display: flex;
padding: 12px 16px;
- background-color: var(--sand_0);
+ background-color: var(--color-neutral-background);
+ color: var(--color-neutral-content-subtle);
justify-content: space-between;
- border-bottom: 1px solid var(--sand_300);
+ border-bottom: 1px solid var(--color-neutral-border);
&_newUI {
padding: 8px;
@@ -55,7 +56,7 @@
position: absolute;
width: 100vw;
height: 100vh;
- background-color: var(--sand_0);
+ background-color: var(--color-neutral-background);
z-index: 100000;
}
diff --git a/web/libs/datamanager/src/components/Common/Badge/Badge.scss b/web/libs/datamanager/src/components/Common/Badge/Badge.scss
index 91f07b29e068..4df0b00c9e38 100644
--- a/web/libs/datamanager/src/components/Common/Badge/Badge.scss
+++ b/web/libs/datamanager/src/components/Common/Badge/Badge.scss
@@ -6,7 +6,7 @@
align-items: center;
justify-content: center;
padding: 0 7px;
- color: var(--sand_0);
+ color: var(--color-neutral-background);
background-color: var(--accent_color);
&_size_small {
diff --git a/web/libs/datamanager/src/components/Common/Button/Button.scss b/web/libs/datamanager/src/components/Common/Button/Button.scss
index 513dacc1c9ce..0859baff5165 100644
--- a/web/libs/datamanager/src/components/Common/Button/Button.scss
+++ b/web/libs/datamanager/src/components/Common/Button/Button.scss
@@ -1,32 +1,31 @@
.button-dm {
- --button-color: var(--black);
+ --button-color: var(--color-neutral-content);
height: 32px;
- border: none;
cursor: pointer;
- padding: 0 15px;
+ padding: 0 12px;
outline: none;
display: inline-flex;
- background-color: var(--white);
+ background-color: var(--color-neutral-background);
align-items: center;
border-radius: 5px;
text-align: center;
text-decoration: none;
- transition: all 100ms ease;
justify-content: center;
color: var(--button-color);
- box-shadow: inset 0 -1px 0 var(--black_10), inset 0 0 0 1px var(--black_15);
font-weight: 500;
font-size: 14px;
+ border: 1px solid var(--color-neutral-border);
+ transition: all 150ms ease-out;
&_newUI {
box-shadow: none;
- border: 1px solid rgb(65 60 74 / 16%);
+ border: 1px solid var(--color-neutral-border);
font-weight: 400;
&.button-dm {
&_withIcon {
- border: 0 none;
+ border: 0;
}
}
@@ -38,8 +37,8 @@
&_disabled,
&:disabled,
&[disabled] {
- border: 1px solid rgb(65 60 74 / 16%);
- background-color: #FFF;
+ border: 1px solid var(--color-neutral-border);
+ background-color: var(--color-neutral-background);
}
}
}
@@ -47,7 +46,7 @@
&.dropdown-dm {
&__trigger {
font-weight: 400;
- background-color: #FAFAFA;
+ background-color: var(--color-neutral-background);
}
}
}
@@ -60,19 +59,20 @@
&_disabled,
&:disabled,
&[disabled] {
- --button-color: rgb(var(--black-raw) / 50%);
+ --button-color: var(--color-neutral-content-subtlest);
pointer-events: none;
- background-color: #efefef;
+ background-color: var(--color-neutral-background);
+ border:1px solid var(--color-neutral-border);
}
&:hover {
- box-shadow: 0 2px 4px var(--black_5), inset 0 -1px 0 var(--black_10), inset 0 0 0 1px var(--black_20);
+ border:1px solid var(--color-neutral-border);
+ color: var(--color-neutral-content);
}
&:active {
- background: linear-gradient(0deg, var(--black_2), var(--black_2)), #FFF;
- box-shadow: inset 0 1px 0 var(--black_10), inset 0 0 0 1px var(--black_20);
+ background: var(--color-neutral-surface-active);
}
&:focus {
@@ -156,7 +156,7 @@
--button-color: var(--white);
background-color: var(--grape_500);
- box-shadow: none;
+ border: 0;
box-shadow: inset 0 -1px 0 var(--black_10);
&:disabled {
@@ -183,13 +183,13 @@
}
&_danger {
- --button-color: var(--danger_color);
+ --button-color: var(--color-negative-content);
}
&_destructive {
--button-color: var(--white);
- background-color: var(--danger_color);
+ background-color: var(--color-negative-content);
}
}
@@ -197,7 +197,7 @@
&_look_destructive.button-dm_waiting {
--button-color: rgb(var(--white-raw) / 50%);
- background-color: var(--danger_color);
+ background-color: var(--color-negative-content);
}
&_size {
@@ -218,6 +218,7 @@
font-size: 12px;
line-height: 12px;
padding: 0 10px;
+ border: 0;
}
&_large {
diff --git a/web/libs/datamanager/src/components/Common/Dropdown/Dropdown.scss b/web/libs/datamanager/src/components/Common/Dropdown/Dropdown.scss
index 2b0e50efaa76..3d29c9a4d085 100644
--- a/web/libs/datamanager/src/components/Common/Dropdown/Dropdown.scss
+++ b/web/libs/datamanager/src/components/Common/Dropdown/Dropdown.scss
@@ -8,9 +8,10 @@
display: none;
position: absolute;
box-sizing: border-box;
- background-color: var(--sand_0);
- box-shadow: 0 5px 20px var(--black_20);
+ background-color: var(--color-neutral-background);
+ box-shadow: 0 4px 16px rgba(var(--color-neutral-shadow-raw) / 12%), 0 2px 4px rgba(var(--color-neutral-shadow-raw) / 8%);
will-change: transform, opacity;
+ border-radius: var(--radius-small);
&_align {
&_left {
@@ -24,6 +25,7 @@
&__trigger {
position: relative;
+ padding-right: 8px;
}
&.before-appear,
diff --git a/web/libs/datamanager/src/components/Common/Form/Elements/Input/Input.scss b/web/libs/datamanager/src/components/Common/Form/Elements/Input/Input.scss
index 2fc452b38a3e..0bb616664f51 100644
--- a/web/libs/datamanager/src/components/Common/Form/Elements/Input/Input.scss
+++ b/web/libs/datamanager/src/components/Common/Form/Elements/Input/Input.scss
@@ -3,10 +3,10 @@
.textarea-dm {
height: 40px;
min-height: 40px;
- background: #FAFAFA;
+ background: var(--color-neutral-background);
font-size: 16px;
line-height: 22px;
- border: 1px solid var(--sand_300);
+ border: 1px solid var(--color-neutral-border);
box-sizing: border-box;
border-radius: 5px;
padding: 0 16px;
diff --git a/web/libs/datamanager/src/components/Common/Form/Elements/RadioGroup/RadioGroup.scss b/web/libs/datamanager/src/components/Common/Form/Elements/RadioGroup/RadioGroup.scss
index 0d2990b9fa2a..b106f32362d7 100644
--- a/web/libs/datamanager/src/components/Common/Form/Elements/RadioGroup/RadioGroup.scss
+++ b/web/libs/datamanager/src/components/Common/Form/Elements/RadioGroup/RadioGroup.scss
@@ -4,12 +4,12 @@
--padding: 4px;
--font-size: 16px;
--button-padding: 0 10px;
- --button-checked-shadow: 0px 1px 0px var(--black_10), 0px 0px 0px 1px var(--black_2), 0px 5px 10px var(--black_15);
+ --button-checked-shadow: 0 1px 0 var(--black_10), 0 0 0 1px var(--black_2), 0 5px 10px var(--black_15);
height: var(--height);
border-radius: var(--radius);
padding: var(--padding);
- background: var(--sand_100);
+ background: var(--color-neutral-surface);
box-shadow: inset 0 1px 0 var(--black_5), inset 0 0 0 1px var(--black_5);
box-sizing: border-box;
@@ -97,7 +97,7 @@
--padding: 2px;
--font-size: 12px;
--button-padding: 0 5px;
- --button-checked-shadow: 0px 1px 0px var(--black_10), 0px 0px 0px 1px var(--black_2), 0px 2px 4px var(--black_15);
+ --button-checked-shadow: 0 1px 0 var(--black_10), 0 0 0 1px var(--black_2), 0 2px 4px var(--black_15);
}
}
diff --git a/web/libs/datamanager/src/components/Common/Form/Elements/Select/Select.scss b/web/libs/datamanager/src/components/Common/Form/Elements/Select/Select.scss
index 57c1e84aab95..55606b2eda70 100644
--- a/web/libs/datamanager/src/components/Common/Form/Elements/Select/Select.scss
+++ b/web/libs/datamanager/src/components/Common/Form/Elements/Select/Select.scss
@@ -30,7 +30,7 @@
}
&:hover {
- border: 1px solid var(--sand_300);
+ border: 1px solid var(--color-neutral-border-bold);
}
}
}
diff --git a/web/libs/datamanager/src/components/Common/Form/Form.scss b/web/libs/datamanager/src/components/Common/Form/Form.scss
index 780106906fe9..5e4432b35b61 100644
--- a/web/libs/datamanager/src/components/Common/Form/Form.scss
+++ b/web/libs/datamanager/src/components/Common/Form/Form.scss
@@ -76,7 +76,7 @@
}
&_fail {
- color: var(--danger_color);
+ color: var(--color-negative-content);
}
}
}
diff --git a/web/libs/datamanager/src/components/Common/Input/Input.scss b/web/libs/datamanager/src/components/Common/Input/Input.scss
index 8efe20772f53..5e6a92a143fa 100644
--- a/web/libs/datamanager/src/components/Common/Input/Input.scss
+++ b/web/libs/datamanager/src/components/Common/Input/Input.scss
@@ -2,9 +2,9 @@
.textarea-dm {
height: 32px;
width: 100%;
- background: #FAFAFA;
+ background: var(--color-neutral-background);
font-size: 14px;
- border: 1px solid var(--sand_300);
+ border: 1px solid var(--color-neutral-border);
box-sizing: border-box;
border-radius: 5px;
padding: 0 16px;
@@ -38,6 +38,6 @@
.input-dm:focus,
.textarea-dm:focus {
outline: none;
- box-shadow: 0 0 0 6px rgb(var(--accent_color-raw) / 20%), inset 0 -1px 0 var(--black_10), inset 0 0 0 1px var(--black_15), inset 0 0 0 1px rgb(var(--accent_color-raw) / 20%);
- border-color: rgb(var(--accent_color-raw) / 20%);
+ box-shadow: 0 0 0 6px var(--color-primary-focus-outline), inset 0 -1px 0 var(--black_10), inset 0 0 0 1px var(--black_15), inset 0 0 0 1px rgb(var(--accent_color-raw) / 20%);
+ border-color: var(--color-primary-border);
}
diff --git a/web/libs/datamanager/src/components/Common/MediaPlayer/MediaPlayer.scss b/web/libs/datamanager/src/components/Common/MediaPlayer/MediaPlayer.scss
index d60adeb1e4ee..13e684455d2c 100644
--- a/web/libs/datamanager/src/components/Common/MediaPlayer/MediaPlayer.scss
+++ b/web/libs/datamanager/src/components/Common/MediaPlayer/MediaPlayer.scss
@@ -6,8 +6,8 @@
min-width: 240px;
border-radius: 4px;
align-items: center;
- background-color: var(--white);
- box-shadow: 0 0 0 1px var(--black_20) inset, 0 0 2px 2px var(--black_5);
+ background-color: var(--color-neutral-background);
+ box-shadow: 0 0 0 1px var(--color-neutral-border) inset, 0 2px 4px rgba(var(--color-neutral-shadow-raw) / 8%);
video {
width: 140px;
@@ -38,13 +38,13 @@
cursor: pointer;
align-items: center;
justify-content: center;
- color: var(--accent_color);
+ color: var(--color-primary-icon);
}
&__track,
&__time {
font-size: 12px;
- color: rgb(var(--black-raw) / 70%);
+ color: var(--color-neutral-content-subtler);
}
&__track {
diff --git a/web/libs/datamanager/src/components/Common/Menu/Menu.scss b/web/libs/datamanager/src/components/Common/Menu/Menu.scss
index ddd3c020a474..b6def4c2ae31 100644
--- a/web/libs/datamanager/src/components/Common/Menu/Menu.scss
+++ b/web/libs/datamanager/src/components/Common/Menu/Menu.scss
@@ -28,7 +28,7 @@
border-radius: 3px;
align-items: center;
box-sizing: border-box;
- color: var(--sand_600);
+ color: var(--color-neutral-content-subtler);
font-size: 14px;
white-space: nowrap;
user-select: none;
@@ -36,20 +36,19 @@
&-icon {
margin-right: 10px;
object-fit: contain;
- opacity: 0.5;
display: flex;
align-items: center;
justify-content: center;
}
&:not(.menu-dm__item_look_danger):hover {
- color: var(--grape_700);
- background-color: var(--grape_0);
+ color: var(--color-neutral-content);
+ background-color: var(--color-primary-emphasis-subtle);
}
&_active {
- color: var(--grape_700);
- background-color: var(--grape_0);
+ color: var(--color-primary-content);
+ background-color: var(--color-primary-emphasis);
}
&_active:not(.sidebar__pin, .menu-dm__item_clickable) {
@@ -63,10 +62,10 @@
&_look {
&_danger {
- color: var(--danger_color);
+ color: var(--color-negative-content);
&:hover {
- background-color: var(--red_1);
+ background-color: var(--color-negative-emphasis-subtle);
}
}
}
diff --git a/web/libs/datamanager/src/components/Common/Modal/Modal.scss b/web/libs/datamanager/src/components/Common/Modal/Modal.scss
index 5e44454f7726..8446ae430eca 100644
--- a/web/libs/datamanager/src/components/Common/Modal/Modal.scss
+++ b/web/libs/datamanager/src/components/Common/Modal/Modal.scss
@@ -10,8 +10,9 @@
position: absolute;
align-items: center;
justify-content: center;
- background-color: rgb(var(--black-raw) / 30%);
+ background-color: rgba(var(--color-neutral-shadow-raw) / 30%);
will-change: opacity;
+ border-radius: var(-radius-small);
&__wrapper {
width: 100%;
@@ -27,7 +28,7 @@
min-width: 400px;
min-height: 100px;
margin: 0 auto;
- background-color: var(--white);
+ background-color: var(--color-neutral-background);
border-radius: 5px;
box-shadow: 0 10px 30px rgb(var(--black-raw) / 30%);
}
@@ -41,7 +42,7 @@
box-sizing: content-box;
&_divided {
- border-bottom: 1px solid var(--black_5);
+ border-bottom: 1px solid var(--color-neutral-border);
}
}
@@ -49,10 +50,12 @@
margin: 0;
margin-right: auto;
font-size: 20px;
+ color: var(--color-neutral-content);
}
&__body {
padding: 0 40px 32px;
+ color: var(--color-neutral-content);
&_bare {
padding: 0;
@@ -64,11 +67,14 @@
&__footer {
padding: 16px 32px;
- background: rgb(0 0 0 / 3%);
+ background: var(--color-neutral-surface);
box-shadow: inset 0 1px 0 var(--black_5);
text-align: center;
font-size: 14px;
line-height: 22px;
+ border-bottom-left-radius: var(--radius-small);
+ border-bottom-right-radius: var(--radius-small);
+ overflow: hidden;
}
&_fullscreen &__content {
diff --git a/web/libs/datamanager/src/components/Common/RadioGroup/RadioGroup.scss b/web/libs/datamanager/src/components/Common/RadioGroup/RadioGroup.scss
index 773067eaa6be..f805039d6b35 100644
--- a/web/libs/datamanager/src/components/Common/RadioGroup/RadioGroup.scss
+++ b/web/libs/datamanager/src/components/Common/RadioGroup/RadioGroup.scss
@@ -1,16 +1,16 @@
.radio-group-dm {
- --radius: 8px;
+ --radius: var(--radius-small);
--height: 40px;
- --padding: 4px;
+ --padding: 3px;
--font-size: 16px;
--button-padding: 0 10px;
- --button-checked-shadow: 0px 1px 0px var(--black_10), 0px 0px 0px 1px var(--black_2), 0px 5px 10px var(--black_15);
+ --button-checked-shadow: 0 1px 0 var(--black_10), 0 0 0 1px var(--black_2), 0 5px 10px var(--black_15);
height: var(--height);
border-radius: var(--radius);
padding: var(--padding);
- background: var(--sand_100);
- box-shadow: inset 0 1px 0 var(--black_5), inset 0 0 0 1px var(--black_5);
+ background: linear-gradient(0deg, var(--color-neutral-surface), var(--color-neutral-surface)), var(--color-neutral-background);
+ border: 1px solid var(--color-neutral-border);
&__buttons {
height: calc(var(--height) - calc(var(--padding) * 2));
@@ -30,17 +30,21 @@
justify-content: center;
font-size: var(--font-size);
border-radius: calc(var(--radius) - var(--padding));
- height: calc(var(--height) - calc(var(--padding) * 2));
+ height: calc(var(--height) - calc(var(--padding) * 2) - 2px);
+ color: var(--color-neutral-content-subtler);
+ transition: all 100ms ease-out;
cursor: pointer;
&_checked {
opacity: 1;
- background-color: var(--white);
+ background-color: var(--color-neutral-surface-hover);
box-shadow: var(--button-checked-shadow);
+ color: var(--color-neutral-content);
}
&_disabled {
opacity: 0.3;
+ color: var(--color-neutral-subtlest);
cursor: not-allowed;
}
@@ -71,7 +75,7 @@
--padding: 2px;
--font-size: 12px;
--button-padding: 0 5px;
- --button-checked-shadow: 0px 1px 0px var(--black_10), 0px 0px 0px 1px var(--black_2), 0px 2px 4px var(--black_15);
+ --button-checked-shadow: 0 1px 0 var(--black_10), 0 0 0 1px var(--black_2), 0 2px 4px var(--black_15);
}
}
diff --git a/web/libs/datamanager/src/components/Common/Range/Range.scss b/web/libs/datamanager/src/components/Common/Range/Range.scss
index d34545c06f1f..b92ab2444277 100644
--- a/web/libs/datamanager/src/components/Common/Range/Range.scss
+++ b/web/libs/datamanager/src/components/Common/Range/Range.scss
@@ -48,8 +48,8 @@
}
&__line {
- background: linear-gradient(0deg, var(--black_5), var(--black_5)), #FFF;
- box-shadow: inset 0 1px 0 var(--black_5), inset 0 0 0 1px var(--black_5);
+ background: linear-gradient(0deg, var(--color-neutral-surface-active), var(--color-neutral-surface-active)), #FFF;
+ box-shadow: inset 0 1px 0 rgba(var(--color-neutral-shadow-raw) / 5%), inset 0 0 0 1px rgba(var(--color-neutral-shadow-raw) / 5%);
border-radius: 8px;
.range_align_horizontal & {
@@ -66,7 +66,7 @@
&__indicator {
border-radius: 8px;
position: absolute;
- background-color: rgb(var(--accent_color-raw) / 50%);
+ background-color: var(--color-primary-emphasis);
.range_align_horizontal & {
top: 0;
@@ -87,9 +87,9 @@
&::before {
content: '';
position: absolute;
- background: var(--grape_500);
- box-shadow: 0 5px 10px rgb(0 153 255 / 30%), inset 0 -1px 0 var(--black_10);
- border-radius: 2px;
+ background: var(--color-primary-surface);
+ box-shadow: 0 5px 10px rgba(var(--color-primary-shadow-raw) / 30%);
+ border-radius: 8px;
transform: translate3d(-50%, -50%, 0);
}
@@ -106,7 +106,7 @@
cursor: col-resize;
&::before {
- width: 10px;
+ width: 16px;
height: 16px;
}
}
@@ -117,7 +117,7 @@
&::before {
width: 16px;
- height: 10px;
+ height: 16px;
}
}
}
diff --git a/web/libs/datamanager/src/components/Common/Resizer/Resizer.scss b/web/libs/datamanager/src/components/Common/Resizer/Resizer.scss
index 2e520d1ee3ed..4ac7edf59dbf 100644
--- a/web/libs/datamanager/src/components/Common/Resizer/Resizer.scss
+++ b/web/libs/datamanager/src/components/Common/Resizer/Resizer.scss
@@ -30,7 +30,7 @@
content: "";
z-index: 5;
display: block;
- background: #bdbdbd;
+ background: var(--color-neutral-border);
position: absolute;
}
@@ -42,8 +42,8 @@
&_resizing::before {
top: 0;
bottom: 0;
- background-color: var(--accent_color);
- box-shadow: 0 0 0 1px var(--accent_color);
+ background-color: var(--color-primary-border);
+ box-shadow: 0 0 0 1px var(--color-primary-border);
}
}
}
diff --git a/web/libs/datamanager/src/components/Common/Select/Select.scss b/web/libs/datamanager/src/components/Common/Select/Select.scss
index 50471316fc29..1b23fd7e4280 100644
--- a/web/libs/datamanager/src/components/Common/Select/Select.scss
+++ b/web/libs/datamanager/src/components/Common/Select/Select.scss
@@ -2,10 +2,10 @@
.select-dm {
height: 40px;
- background: #FAFAFA;
+ background: var(--color-neutral-background);
font-size: 16px;
line-height: 22px;
- border: 1px solid var(--sand_300);
+ border: 1px solid var(--color-neutral-border);
box-sizing: border-box;
border-radius: 5px;
cursor: pointer;
@@ -46,20 +46,21 @@
&__option {
cursor: pointer;
padding: 4px 16px;
+ color: var(--color-neutral-content-subtle);
&:hover,
&_focused {
- background-color: #f7f7f7;
+ background-color: var(--color-primary-emphasis-subtle);
}
&_selected {
- color: white;
- background-color: var(--accent_color);
+ color: var(--color-neutral-content);
+ background-color: var(--color-primary-emphasis);
}
&_selected:hover,
&_selected.select-dm__option_focused {
- background-color: hsl(var(--accent_color), 10%);
+ background-color: hsl(var(--color-primary-emphasis), 10%);
color: var(--accent_color);
}
}
diff --git a/web/libs/datamanager/src/components/Common/Space/Space.scss b/web/libs/datamanager/src/components/Common/Space/Space.scss
index c12931c2c9ba..f3c40110e947 100644
--- a/web/libs/datamanager/src/components/Common/Space/Space.scss
+++ b/web/libs/datamanager/src/components/Common/Space/Space.scss
@@ -1,6 +1,7 @@
.space-dm {
display: grid;
grid-gap: 16px;
+ color: var(--color-neutral-subtler);
&_direction {
&_horizontal {
diff --git a/web/libs/datamanager/src/components/Common/Table/Table.scss b/web/libs/datamanager/src/components/Common/Table/Table.scss
index a4708adb6252..14b5f77f9cfb 100644
--- a/web/libs/datamanager/src/components/Common/Table/Table.scss
+++ b/web/libs/datamanager/src/components/Common/Table/Table.scss
@@ -10,7 +10,7 @@
z-index: 1000;
height: 28px;
width: 28px;
- background-color: var(--white);
+ background-color: var(--color-neutral-background);
box-shadow: 0 2px 5px 0 var(--black_20);
margin: 6.5px 20px;
border-radius: 4px;
@@ -18,10 +18,15 @@
&:hover {
border: none;
filter: none;
- background: #ebf3fc;
+ background: var(--color-primary-emphasis-subtle);
+
+ &__icon {
+ color: var(--color-neutral-content);
+ }
}
&:active {
+ color: var(--color-neutral-content);
background: linear-gradient(0deg, var(--black_2), var(--black_2)), #FFF;
box-shadow: 0 0 5px 0 var(--black_20);
}
@@ -34,7 +39,7 @@
display: flex;
flex-direction: column;
overflow: auto;
- background-color: var(--white);
+ background-color: var(--color-neutral-background);
&_fit {
width: max-content;
@@ -66,7 +71,7 @@
min-width: fit-content;
position: relative;
cursor: pointer;
- background-color: var(--sand_0);
+ background-color: var(--color-neutral-background);
&_disabled,
&_loading {
@@ -75,15 +80,15 @@
}
&_even:not(.table__row_wrapper_selected) {
- background-color: var(--sand_100);
+ background-color: var(--color-neutral-emphasis-subtle);
}
&_selected {
- background-color: var(--grape_0);
+ background-color: var(--color-primary-emphasis);
}
&:not(.table__row_wrapper_selected):hover {
- background-color: var(--grape_0);
+ background-color: var(--color-primary-emphasis-subtle);
}
&_highlighted:not(.table__row_wrapper_selected)::after {
@@ -111,6 +116,7 @@
position: relative;
overflow: hidden;
word-break: break-word;
+ color: var(--color-neutral-content-subtler);
}
&__cell-content {
@@ -118,6 +124,7 @@
display: flex;
white-space: nowrap;
align-items: center;
+ color: var(--color-neutral-content);
&_disabled {
opacity: 0.6;
diff --git a/web/libs/datamanager/src/components/Common/Table/TableHead/TableHead.scss b/web/libs/datamanager/src/components/Common/Table/TableHead/TableHead.scss
index 2e3fb3da573a..e5694bda0f5f 100644
--- a/web/libs/datamanager/src/components/Common/Table/TableHead/TableHead.scss
+++ b/web/libs/datamanager/src/components/Common/Table/TableHead/TableHead.scss
@@ -5,10 +5,11 @@
z-index: 150;
font-weight: 500;
overflow: visible;
- background-color: var(--white);
+ background-color: var(--color-neutral-background);
min-width: fit-content;
font-size: 14px;
- border-bottom: 1px solid #D8D5DD;
+ border-bottom: 1px solid var(--color-neutral-border);
+ color: var(--color-neutral-content);
&__extra {
flex: 1;
diff --git a/web/libs/datamanager/src/components/Common/TableOld/Table.scss b/web/libs/datamanager/src/components/Common/TableOld/Table.scss
index a4708adb6252..b42ffb501577 100644
--- a/web/libs/datamanager/src/components/Common/TableOld/Table.scss
+++ b/web/libs/datamanager/src/components/Common/TableOld/Table.scss
@@ -34,7 +34,7 @@
display: flex;
flex-direction: column;
overflow: auto;
- background-color: var(--white);
+ background-color: var(--color-neutral-background);
&_fit {
width: max-content;
@@ -75,7 +75,7 @@
}
&_even:not(.table__row_wrapper_selected) {
- background-color: var(--sand_100);
+ background-color: var(--color-neutral-surface);
}
&_selected {
diff --git a/web/libs/datamanager/src/components/Common/Tabs/Tabs.scss b/web/libs/datamanager/src/components/Common/Tabs/Tabs.scss
index 21d2f5a023cd..1bccfba32951 100644
--- a/web/libs/datamanager/src/components/Common/Tabs/Tabs.scss
+++ b/web/libs/datamanager/src/components/Common/Tabs/Tabs.scss
@@ -3,8 +3,9 @@
display: flex;
align-items: stretch;
justify-content: space-between;
- box-shadow: 0 -1px 0 #D9D9D9 inset;
- background: var(--sand_200);
+ box-shadow: 0 -1px 0 var(--color-neutral-border) inset;
+ background: var(--color-neutral-surface-inset);
+ padding: 2px 0 0 2px;
&-content {
&__draggable {
@@ -19,26 +20,31 @@
&__droppable {
display: flex;
overflow: hidden;
+ gap: 2px;
}
&__list {
display: flex;
min-width: 0;
+ gap: 2px;
}
&__item {
- color: rgb(0 0 0 / 50%);
+ background-color: var(--color-neutral-surface);
+ color: var(--color-neutral-content-subtler);
width: 100%;
overflow: hidden;
cursor: pointer;
position: relative;
- box-shadow: -0.5px 0 0 #D9D9D9 inset, 0.5px 0 0 #D9D9D9 inset;
+ box-shadow: -1px 0 0 var(--color-neutral-border) inset, 1px 0 0 var(--color-neutral-border) inset, 0 1px 0 var(--color-neutral-border-subtle) inset, 0 -3px 0 var(--color-neutral-border) inset;
+ border-top-left-radius: var(--radius-small);
+ border-top-right-radius: var(--radius-small);
&_active {
- color: black;
+ color: var(--color-neutral-content);
cursor: default;
- background-color: var(--white);
- box-shadow: -0.5px 0 0 #D9D9D9 inset, 0.5px 0 0 #D9D9D9 inset;
+ background-color: var(--color-neutral-background);
+ box-shadow: -1px 0 0 var(--color-neutral-border) inset, 1px 0 0 var(--color-neutral-border) inset, 0 1px 0 var(--color-neutral-border) inset;
& .tabs-dm__item-right-button {
display: flex;
@@ -98,20 +104,24 @@
padding: 0;
border: none;
outline: none;
- width: 36px;
- height: 36px;
+ width: 30px;
+ height: 30px;
display: flex;
align-items: center;
justify-content: center;
- color: var(--black_15) !important;
+ align-self: center;
+ color: var(--color-neutral-content-subtler);
background: none;
+ transition: all 150ms ease-out;
&:focus {
box-shadow: none;
}
&:hover {
- color: rgb(0 0 0 / 35%) !important;
+ background-color: var(--color-primary-emphasis-subtle);
+ color: var(--color-primary-content);
+ border: 0;
}
}
@@ -125,8 +135,8 @@
width: 100%;
right: 0;
left: 0;
- background: var(--sand_200);
- border-top: 1px solid var(--sand_300);
+ background: var(--color-neutral-background);
+ border-top: 1px solid var(--color-neutral-border);
padding: .625rem 1rem;
}
}
diff --git a/web/libs/datamanager/src/components/Common/Tooltip/Tooltip.scss b/web/libs/datamanager/src/components/Common/Tooltip/Tooltip.scss
index 61415993cce9..9cae10a2dc42 100644
--- a/web/libs/datamanager/src/components/Common/Tooltip/Tooltip.scss
+++ b/web/libs/datamanager/src/components/Common/Tooltip/Tooltip.scss
@@ -5,13 +5,13 @@
top: -1000px;
left: -1000px;
- color: var(--white);
+ color: var(--color-neutral-inverted-content);
display: none;
z-index: 10000;
padding: 4px 10px;
position: absolute;
pointer-events: none;
- background-color: var(--black);
+ background-color: var(--color-neutral-inverted-background);
border-radius: 3px;
&::before {
@@ -22,7 +22,7 @@
height: 10px;
display: block;
position: absolute;
- background-color: var(--black);
+ background-color: inherit;
transform: translate(-50%, 50%) rotate(45deg);
}
diff --git a/web/libs/datamanager/src/components/DataManager/DataManager.jsx b/web/libs/datamanager/src/components/DataManager/DataManager.jsx
index 33d8b9cb421d..90e2c82fdbfd 100644
--- a/web/libs/datamanager/src/components/DataManager/DataManager.jsx
+++ b/web/libs/datamanager/src/components/DataManager/DataManager.jsx
@@ -45,7 +45,7 @@ const switchInjector = inject(({ store }) => {
const ProjectSummary = summaryInjector((props) => {
return (
-
+
{props.cloudSync && (
Storage sync
@@ -97,7 +97,7 @@ const TabsSwitch = switchInjector(
{...provided.draggableProps}
{...provided.dragHandleProps}
style={{
- background: snapshot.isDragging && "#ddd",
+ background: snapshot.isDragging,
...provided.draggableProps.style,
}}
>
diff --git a/web/libs/datamanager/src/components/DataManager/Toolbar/TabPanel.scss b/web/libs/datamanager/src/components/DataManager/Toolbar/TabPanel.scss
index 1efd3ea6a19d..a9d690d96b3d 100644
--- a/web/libs/datamanager/src/components/DataManager/Toolbar/TabPanel.scss
+++ b/web/libs/datamanager/src/components/DataManager/Toolbar/TabPanel.scss
@@ -1,7 +1,7 @@
.tab-panel {
display: flex;
padding: 12px 16px;
- background-color: var(--white);
+ background-color: var(--color-neutral-background);
justify-content: space-between;
&_newUI {
diff --git a/web/libs/datamanager/src/components/Filters/Filters.scss b/web/libs/datamanager/src/components/Filters/Filters.scss
index 390a8882d863..20e2aca10a82 100644
--- a/web/libs/datamanager/src/components/Filters/Filters.scss
+++ b/web/libs/datamanager/src/components/Filters/Filters.scss
@@ -1,5 +1,5 @@
.filters {
- background-color: white;
+ background-color: var(--color-neutral-background);
position: relative;
&:not(&_sidebar) {
diff --git a/web/libs/datamanager/src/components/Label/Label.scss b/web/libs/datamanager/src/components/Label/Label.scss
index fb5d615960c8..97e9d80a36df 100644
--- a/web/libs/datamanager/src/components/Label/Label.scss
+++ b/web/libs/datamanager/src/components/Label/Label.scss
@@ -5,6 +5,7 @@
width: 100%;
display: flex;
flex-direction: column;
+ color: var(--color-neutral-content);
&__waiting {
top: 50%;
@@ -17,7 +18,7 @@
transform: translate(-50%, -50%);
box-shadow: 0 5px 20px var(--black_20);
- @include waiting(var(--accent_color));
+ @include waiting(var(--color-primary-surface));
}
&__header {
@@ -86,7 +87,7 @@
overflow-y: auto;
& > div {
- --main-bg-color: var(--sand_100);
+ --main-bg-color: var(--color-neutral-surface);
flex: 1;
height: auto;
diff --git a/web/libs/datamanager/src/components/MainView/DataView/Table.scss b/web/libs/datamanager/src/components/MainView/DataView/Table.scss
index 5f742378aa59..8cf60ef28a9d 100644
--- a/web/libs/datamanager/src/components/MainView/DataView/Table.scss
+++ b/web/libs/datamanager/src/components/MainView/DataView/Table.scss
@@ -3,7 +3,7 @@
display: flex;
overflow: hidden;
flex-direction: column;
- background: var(--sand_0);
+ background: var(--color-neutral-background);
margin-bottom: 2.5rem;
}
@@ -15,9 +15,14 @@
align-items: center;
&__description {
+ h3 {
+ color: var(--color-neutral-content);
+ }
+
font-size: 16px;
text-align: center;
- color: rgb(var(--black-raw) / 60%);
+ color: var(--color-neutral-content-subtler);
+ margin-bottom: 8px;
}
}
diff --git a/web/libs/datamanager/src/components/MainView/GridView/GridView.scss b/web/libs/datamanager/src/components/MainView/GridView/GridView.scss
index 826fe75b9142..420efc139cc9 100644
--- a/web/libs/datamanager/src/components/MainView/GridView/GridView.scss
+++ b/web/libs/datamanager/src/components/MainView/GridView/GridView.scss
@@ -47,7 +47,7 @@
position: absolute;
pointer-events: none;
border-radius: 8px;
- border: 1px solid var(--sand_300);
+ border: 1px solid var(--color-neutral-border);
}
}
@@ -67,6 +67,6 @@
& .grid-image-wrapper {
text-align: center;
- background: var(--sand_100);
+ background: var(--color-neutral-surface);
}
}
diff --git a/web/libs/editor/jest.config.js b/web/libs/editor/jest.config.js
index 7bd549bbb24b..af7b7b00a4be 100644
--- a/web/libs/editor/jest.config.js
+++ b/web/libs/editor/jest.config.js
@@ -1,3 +1,5 @@
+const { pathsToModuleNameMapper } = require("ts-jest");
+const tsconfig = require("../../tsconfig.base.json");
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
module.exports = {
bail: true,
@@ -57,6 +59,7 @@ module.exports = {
"^react-konva-utils": "identity-obj-proxy",
"\\.(s[ac]ss|css|svg|png|jpe?g)$": "identity-obj-proxy",
"^@humansignal/ui": "/../ui/src/index.ts",
+ ...pathsToModuleNameMapper(tsconfig.compilerOptions.paths, { prefix: "/../../" }),
},
testPathIgnorePatterns: ["/node_modules/", "/e2e/"],
testRegex: "__tests__/.*.test.[tj]sx?",
diff --git a/web/libs/editor/src/assets/icons/details.svg b/web/libs/editor/src/assets/icons/details.svg
index 945f5d444c92..23c59ed86f8f 100644
--- a/web/libs/editor/src/assets/icons/details.svg
+++ b/web/libs/editor/src/assets/icons/details.svg
@@ -1,4 +1,4 @@
diff --git a/web/libs/editor/src/assets/icons/duplicate.svg b/web/libs/editor/src/assets/icons/duplicate.svg
index 93179e22d2b5..90cad163989d 100644
--- a/web/libs/editor/src/assets/icons/duplicate.svg
+++ b/web/libs/editor/src/assets/icons/duplicate.svg
@@ -1,3 +1,5 @@
-