diff --git a/src/components/ValidationButton.tsx b/src/components/ValidationButton.tsx
index 3212872..2ebdfea 100644
--- a/src/components/ValidationButton.tsx
+++ b/src/components/ValidationButton.tsx
@@ -1,149 +1,80 @@
import { DeveloperService } from "../spicedb-common/services/developerservice";
-import Button from "@material-ui/core/Button";
-import { Theme, createStyles, makeStyles } from "@material-ui/core/styles";
-import { alpha } from "@material-ui/core/styles/colorManipulator";
-import CheckCircleIcon from "@material-ui/icons/CheckCircle";
-import CheckCircleOutlineIcon from "@material-ui/icons/CheckCircleOutline";
-import ErrorIcon from "@material-ui/icons/Error";
-import PlayCircleFilledIcon from "@material-ui/icons/PlayCircleFilled";
-import clsx from "clsx";
-import "react-reflex/styles.css";
+import { Button } from "./ui/button";
import { DataStore } from "../services/datastore";
import { ValidationState, ValidationStatus } from "../services/validation";
-import { TourElementClass } from "./GuidedTour";
+import { CheckCircle, CircleX, CirclePlay } from "lucide-react";
-const useStyles = makeStyles((theme: Theme) =>
- createStyles({
- gcm: {
- color: "green",
- display: "inherit",
- },
- rem: {
- color: "red",
- display: "inherit",
- },
- gray: {
- color: "gray",
- display: "inherit",
- },
- lastRun: {
- display: "grid",
- gridTemplateColumns: "auto 150px",
- alignItems: "center",
- columnGap: theme.spacing(1),
- backgroundColor: "rgba(255, 255, 255, 0.05)",
- height: "100%",
- padding: "4px",
- paddingLeft: "8px",
- },
- validated: {
- backgroundColor: alpha(theme.palette.success.light, 0.2),
- },
- validationError: {
- backgroundColor: alpha(theme.palette.error.light, 0.2),
- },
- validationDisplay: {
- display: "grid",
- gridTemplateColumns: "auto auto",
- alignItems: "center",
- columnGap: theme.spacing(1),
- },
- }),
-);
-
-export function ValidateButton(props: {
+export function ValidateButton({
+ conductValidation,
+ datastore,
+ validationState,
+ developerService,
+}: {
conductValidation: () => void;
datastore: DataStore;
validationState: ValidationState;
developerService: DeveloperService;
}) {
- const validated =
- props.validationState.status === ValidationStatus.VALIDATED ||
- props.validationState.status === ValidationStatus.VALIDATION_ERROR;
const upToDate =
- validated &&
- props.validationState.validationDatastoreIndex ===
- props.datastore.currentIndex();
-
- const classes = useStyles();
+ validationState.validationDatastoreIndex === datastore.currentIndex();
+ const valid =
+ upToDate && validationState.status === ValidationStatus.VALIDATED;
+ const invalid =
+ upToDate && validationState.status === ValidationStatus.VALIDATION_ERROR;
+ const loading = validationState.status === ValidationStatus.CALL_ERROR;
+ const notRun =
+ validationState.status !== ValidationStatus.CALL_ERROR && !upToDate;
return (
-
-
+
+
- {upToDate &&
- props.validationState.status === ValidationStatus.VALIDATED &&
- "Validated!"}
- {upToDate &&
- props.validationState.status === ValidationStatus.VALIDATION_ERROR &&
- "Failed to Validate"}
- {props.validationState.status === ValidationStatus.CALL_ERROR &&
- "Dev service loading"}
- {props.validationState.status !== ValidationStatus.CALL_ERROR &&
- !upToDate &&
- "Validation not run"}
+ {valid && "Validated!"}
+ {invalid && "Failed to Validate"}
+ {loading && "Dev service loading"}
+ {notRun && "Validation not run"}
}
- className={TourElementClass.run}
disabled={
- props.developerService.state.status !== "ready" ||
- props.validationState.status === ValidationStatus.RUNNING
+ developerService.state.status !== "ready" ||
+ validationState.status === ValidationStatus.RUNNING
}
- onClick={props.conductValidation}
+ onClick={conductValidation}
+ variant="outline"
>
+
Run
);
}
-export function ValidationIcon(props: {
- small?: boolean;
+export function ValidationIcon({
+ datastore,
+ validationState,
+ className,
+}: {
datastore: DataStore;
validationState: ValidationState;
+ className: string;
}) {
- const classes = useStyles();
if (
- props.validationState.status === ValidationStatus.VALIDATED &&
- props.datastore.currentIndex() ===
- props.validationState.validationDatastoreIndex
+ validationState.status === ValidationStatus.VALIDATED &&
+ datastore.currentIndex() === validationState.validationDatastoreIndex
) {
- return (
-
-
-
- );
+ return
;
}
if (
- props.validationState.status === ValidationStatus.VALIDATION_ERROR &&
- props.datastore.currentIndex() ===
- props.validationState.validationDatastoreIndex
+ validationState.status === ValidationStatus.VALIDATION_ERROR &&
+ datastore.currentIndex() === validationState.validationDatastoreIndex
) {
- return (
-
-
-
- );
+ return
;
}
- return (
-
-
-
- );
+ return
;
}
diff --git a/src/index.css b/src/index.css
index 28b919e..bd1b1c4 100644
--- a/src/index.css
+++ b/src/index.css
@@ -1,7 +1,7 @@
@import "tailwindcss";
@import "tw-animate-css";
-@custom-variant dark (&:is(.dark *));
+@custom-variant dark (&:where(.dark, .dark *));
body {
margin: 0;
@@ -52,73 +52,75 @@ code {
--color-sidebar-ring: var(--sidebar-ring);
}
-:root {
- --radius: 0.625rem;
- --background: oklch(1 0 0);
- --foreground: oklch(0.147 0.004 49.25);
- --card: oklch(1 0 0);
- --card-foreground: oklch(0.147 0.004 49.25);
- --popover: oklch(1 0 0);
- --popover-foreground: oklch(0.147 0.004 49.25);
- --primary: oklch(0.216 0.006 56.043);
- --primary-foreground: oklch(0.985 0.001 106.423);
- --secondary: oklch(0.97 0.001 106.424);
- --secondary-foreground: oklch(0.216 0.006 56.043);
- --muted: oklch(0.97 0.001 106.424);
- --muted-foreground: oklch(0.553 0.013 58.071);
- --accent: oklch(0.97 0.001 106.424);
- --accent-foreground: oklch(0.216 0.006 56.043);
- --destructive: oklch(0.577 0.245 27.325);
- --border: oklch(0.923 0.003 48.717);
- --input: oklch(0.923 0.003 48.717);
- --ring: oklch(0.709 0.01 56.259);
- --chart-1: oklch(0.646 0.222 41.116);
- --chart-2: oklch(0.6 0.118 184.704);
- --chart-3: oklch(0.398 0.07 227.392);
- --chart-4: oklch(0.828 0.189 84.429);
- --chart-5: oklch(0.769 0.188 70.08);
- --sidebar: oklch(0.985 0.001 106.423);
- --sidebar-foreground: oklch(0.147 0.004 49.25);
- --sidebar-primary: oklch(0.216 0.006 56.043);
- --sidebar-primary-foreground: oklch(0.985 0.001 106.423);
- --sidebar-accent: oklch(0.97 0.001 106.424);
- --sidebar-accent-foreground: oklch(0.216 0.006 56.043);
- --sidebar-border: oklch(0.923 0.003 48.717);
- --sidebar-ring: oklch(0.709 0.01 56.259);
-}
+@layer theme {
+ :root {
+ --radius: 0.625rem;
+ --background: oklch(1 0 0);
+ --foreground: oklch(0.147 0.004 49.25);
+ --card: oklch(1 0 0);
+ --card-foreground: oklch(0.147 0.004 49.25);
+ --popover: oklch(1 0 0);
+ --popover-foreground: oklch(0.147 0.004 49.25);
+ --primary: oklch(0.216 0.006 56.043);
+ --primary-foreground: oklch(0.985 0.001 106.423);
+ --secondary: oklch(0.97 0.001 106.424);
+ --secondary-foreground: oklch(0.216 0.006 56.043);
+ --muted: oklch(0.97 0.001 106.424);
+ --muted-foreground: oklch(0.553 0.013 58.071);
+ --accent: oklch(0.97 0.001 106.424);
+ --accent-foreground: oklch(0.216 0.006 56.043);
+ --destructive: oklch(0.577 0.245 27.325);
+ --border: oklch(0.923 0.003 48.717);
+ --input: oklch(0.923 0.003 48.717);
+ --ring: oklch(0.709 0.01 56.259);
+ --chart-1: oklch(0.646 0.222 41.116);
+ --chart-2: oklch(0.6 0.118 184.704);
+ --chart-3: oklch(0.398 0.07 227.392);
+ --chart-4: oklch(0.828 0.189 84.429);
+ --chart-5: oklch(0.769 0.188 70.08);
+ --sidebar: oklch(0.985 0.001 106.423);
+ --sidebar-foreground: oklch(0.147 0.004 49.25);
+ --sidebar-primary: oklch(0.216 0.006 56.043);
+ --sidebar-primary-foreground: oklch(0.985 0.001 106.423);
+ --sidebar-accent: oklch(0.97 0.001 106.424);
+ --sidebar-accent-foreground: oklch(0.216 0.006 56.043);
+ --sidebar-border: oklch(0.923 0.003 48.717);
+ --sidebar-ring: oklch(0.709 0.01 56.259);
+ }
-.dark {
- --background: oklch(0.147 0.004 49.25);
- --foreground: oklch(0.985 0.001 106.423);
- --card: oklch(0.216 0.006 56.043);
- --card-foreground: oklch(0.985 0.001 106.423);
- --popover: oklch(0.216 0.006 56.043);
- --popover-foreground: oklch(0.985 0.001 106.423);
- --primary: oklch(0.923 0.003 48.717);
- --primary-foreground: oklch(0.216 0.006 56.043);
- --secondary: oklch(0.268 0.007 34.298);
- --secondary-foreground: oklch(0.985 0.001 106.423);
- --muted: oklch(0.268 0.007 34.298);
- --muted-foreground: oklch(0.709 0.01 56.259);
- --accent: oklch(0.268 0.007 34.298);
- --accent-foreground: oklch(0.985 0.001 106.423);
- --destructive: oklch(0.704 0.191 22.216);
- --border: oklch(1 0 0 / 10%);
- --input: oklch(1 0 0 / 15%);
- --ring: oklch(0.553 0.013 58.071);
- --chart-1: oklch(0.488 0.243 264.376);
- --chart-2: oklch(0.696 0.17 162.48);
- --chart-3: oklch(0.769 0.188 70.08);
- --chart-4: oklch(0.627 0.265 303.9);
- --chart-5: oklch(0.645 0.246 16.439);
- --sidebar: oklch(0.216 0.006 56.043);
- --sidebar-foreground: oklch(0.985 0.001 106.423);
- --sidebar-primary: oklch(0.488 0.243 264.376);
- --sidebar-primary-foreground: oklch(0.985 0.001 106.423);
- --sidebar-accent: oklch(0.268 0.007 34.298);
- --sidebar-accent-foreground: oklch(0.985 0.001 106.423);
- --sidebar-border: oklch(1 0 0 / 10%);
- --sidebar-ring: oklch(0.553 0.013 58.071);
+ .dark {
+ --background: oklch(0.147 0.004 49.25);
+ --foreground: oklch(0.985 0.001 106.423);
+ --card: oklch(0.216 0.006 56.043);
+ --card-foreground: oklch(0.985 0.001 106.423);
+ --popover: oklch(0.216 0.006 56.043);
+ --popover-foreground: oklch(0.985 0.001 106.423);
+ --primary: oklch(0.923 0.003 48.717);
+ --primary-foreground: oklch(0.216 0.006 56.043);
+ --secondary: oklch(0.268 0.007 34.298);
+ --secondary-foreground: oklch(0.985 0.001 106.423);
+ --muted: oklch(0.268 0.007 34.298);
+ --muted-foreground: oklch(0.709 0.01 56.259);
+ --accent: oklch(0.268 0.007 34.298);
+ --accent-foreground: oklch(0.985 0.001 106.423);
+ --destructive: oklch(0.704 0.191 22.216);
+ --border: oklch(1 0 0 / 10%);
+ --input: oklch(1 0 0 / 15%);
+ --ring: oklch(0.553 0.013 58.071);
+ --chart-1: oklch(0.488 0.243 264.376);
+ --chart-2: oklch(0.696 0.17 162.48);
+ --chart-3: oklch(0.769 0.188 70.08);
+ --chart-4: oklch(0.627 0.265 303.9);
+ --chart-5: oklch(0.645 0.246 16.439);
+ --sidebar: oklch(0.216 0.006 56.043);
+ --sidebar-foreground: oklch(0.985 0.001 106.423);
+ --sidebar-primary: oklch(0.488 0.243 264.376);
+ --sidebar-primary-foreground: oklch(0.985 0.001 106.423);
+ --sidebar-accent: oklch(0.268 0.007 34.298);
+ --sidebar-accent-foreground: oklch(0.985 0.001 106.423);
+ --sidebar-border: oklch(1 0 0 / 10%);
+ --sidebar-ring: oklch(0.553 0.013 58.071);
+ }
}
@layer base {
diff --git a/src/playground-ui/PlaygroundUIThemed.tsx b/src/playground-ui/PlaygroundUIThemed.tsx
index 326e99b..367c563 100644
--- a/src/playground-ui/PlaygroundUIThemed.tsx
+++ b/src/playground-ui/PlaygroundUIThemed.tsx
@@ -21,10 +21,12 @@ export default function PlaygroundUIThemed({
forceDarkMode,
children,
}: PlaygroundUIThemedProps) {
- const { setTheme } = useTheme();
+ const { theme: currentTheme, setTheme } = useTheme();
// Determine whether the user prefers dark or light mode.
const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)");
- const darkMode = prefersDarkMode || forceDarkMode === true;
+ const darkMode =
+ forceDarkMode === true ||
+ (currentTheme === "system" ? prefersDarkMode : currentTheme === "dark");
useEffect(() => {
if (forceDarkMode) {