Added lots of tailwind styling

This commit is contained in:
Ozzie Gooen 2022-05-30 13:10:25 -07:00
parent afbc0199aa
commit 6b80118e7e
6 changed files with 269 additions and 87 deletions

View File

@ -3,6 +3,8 @@
"version": "0.2.20", "version": "0.2.20",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@headlessui/react": "^1.6.4",
"@heroicons/react": "^1.0.6",
"@hookform/resolvers": "^2.8.10", "@hookform/resolvers": "^2.8.10",
"@quri/squiggle-lang": "^0.2.8", "@quri/squiggle-lang": "^0.2.8",
"@react-hook/size": "^2.1.2", "@react-hook/size": "^2.1.2",

View File

@ -29,6 +29,7 @@ export let CodeEditor: FC<CodeEditorProps> = ({
mode="golang" mode="golang"
theme="github" theme="github"
width={"100%"} width={"100%"}
fontSize={14}
height={String(height) + "px"} height={String(height) + "px"}
minLines={oneLine ? lineCount : undefined} minLines={oneLine ? lineCount : undefined}
maxLines={oneLine ? lineCount : undefined} maxLines={oneLine ? lineCount : undefined}

View File

@ -1,12 +1,21 @@
import * as React from "react"; import * as React from "react";
import { XCircleIcon } from "@heroicons/react/solid";
export const ErrorBox: React.FC<{ export const ErrorBox: React.FC<{
heading: string; heading: string;
children: React.ReactNode; children: React.ReactNode;
}> = ({ heading = "Error", children }) => { }> = ({ heading = "Error", children }) => {
return ( return (
<div className="border border-red-200 bg-gray-50 p-4"> <div className="rounded-md bg-red-100 p-4 m-4">
<h3>{heading}</h3> <div className="flex">
{children} <div className="flex-shrink-0">
<XCircleIcon className="h-5 w-5 text-red-400" aria-hidden="true" />
</div>
<div className="ml-3">
<h3 className="text-sm font-medium text-red-800">{heading}</h3>
<div className="mt-2 text-sm text-red-700">{children}</div>
</div>
</div>
</div> </div>
); );
}; };

View File

@ -54,7 +54,7 @@ export const VariableBox: React.FC<VariableBoxProps> = ({
return ( return (
<div className="bg-white border border-grey-200 m-2"> <div className="bg-white border border-grey-200 m-2">
<div className="border-b border-grey-200 p-3"> <div className="border-b border-grey-200 p-3">
<h3>{heading}</h3> <h3 className="font-mono">{heading}</h3>
</div> </div>
<div className="p-3">{children}</div> <div className="p-3">{children}</div>
</div> </div>

View File

@ -8,6 +8,9 @@ import { useForm, useWatch } from "react-hook-form";
import * as yup from "yup"; import * as yup from "yup";
import { yupResolver } from "@hookform/resolvers/yup"; import { yupResolver } from "@hookform/resolvers/yup";
import { defaultBindings, environment } from "@quri/squiggle-lang"; import { defaultBindings, environment } from "@quri/squiggle-lang";
import { Tab } from "@headlessui/react";
import { CodeIcon } from "@heroicons/react/solid";
import { CogIcon } from "@heroicons/react/solid";
interface ShowBoxProps { interface ShowBoxProps {
height: number; height: number;
@ -15,9 +18,7 @@ interface ShowBoxProps {
} }
const ShowBox: React.FC<ShowBoxProps> = ({ height, children }) => ( const ShowBox: React.FC<ShowBoxProps> = ({ height, children }) => (
<div className="border border-grey-100" style={{ height: height + "px" }}> <div className="border border-gray-500">{children}</div>
{children}
</div>
); );
interface TitleProps { interface TitleProps {
@ -26,12 +27,7 @@ interface TitleProps {
} }
const Display: React.FC<TitleProps> = ({ maxHeight, children }) => ( const Display: React.FC<TitleProps> = ({ maxHeight, children }) => (
<div <div style={{ maxHeight: maxHeight + "px" }}>{children}</div>
className="bg-gray-50 border-l border-grey-100 p-2"
style={{ maxHeight: maxHeight + "px" }}
>
{children}
</div>
); );
interface PlaygroundProps { interface PlaygroundProps {
@ -88,12 +84,70 @@ type InputProps = {
}; };
const InputItem: React.FC<InputProps> = ({ label, children }) => ( const InputItem: React.FC<InputProps> = ({ label, children }) => (
<div> <div className="col-span-3">
<label>{label}</label> <label className="block text-sm font-medium text-gray-600">{label}</label>
{children} <div className="mt-1">{children}</div>
</div> </div>
); );
let numberStyle =
"max-w-lg block w-full shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:max-w-xs sm:text-sm border-gray-300 rounded-md";
let checkboxStyle =
"focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded";
const tabs = [
{ name: "Editor", href: "#", current: true },
{ name: "Settings", href: "#", current: false },
];
function classNames(...classes) {
return classes.filter(Boolean).join(" ");
}
function Example() {
return (
<div>
<div className="sm:hidden">
<label htmlFor="tabs" className="sr-only">
Select a tab
</label>
{/* Use an "onChange" listener to redirect the user to the selected tab URL. */}
<select
id="tabs"
name="tabs"
className="block w-full pl-3 pr-10 py-2 text-base border-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm rounded-md"
defaultValue={"Editor"}
>
{tabs.map((tab) => (
<option key={tab.name}>{tab.name}</option>
))}
</select>
</div>
<div className="hidden sm:block">
<div className="border-b border-gray-200">
<nav className="-mb-px flex space-x-8" aria-label="Tabs">
{tabs.map((tab) => (
<a
key={tab.name}
href={tab.href}
className={classNames(
tab.current
? "border-indigo-500 text-indigo-600"
: "border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300",
"whitespace-nowrap py-4 px-1 border-b-2 font-medium text-sm"
)}
aria-current={tab.current ? "page" : undefined}
>
{tab.name}
</a>
))}
</nav>
</div>
</div>
</div>
);
}
let SquigglePlayground: FC<PlaygroundProps> = ({ let SquigglePlayground: FC<PlaygroundProps> = ({
initialSquiggleString = "", initialSquiggleString = "",
height = 500, height = 500,
@ -142,30 +196,96 @@ let SquigglePlayground: FC<PlaygroundProps> = ({
setImportsAreValid(false); setImportsAreValid(false);
} }
}; };
let tab = (key, icon) => (
<Tab
key={key}
className={({ selected }) =>
classNames(
"whitespace-nowrap pb-1 pt-2 px-1 border-b-2 font-medium text-sm focus-within:outline-none group inline-flex items-center",
selected
? "border-slate-400 text-gray-500"
: "border-transparent text-gray-400 hover:text-gray-600 hover:border-slate-300"
)
}
>
{icon}
<span>{key}</span>
</Tab>
);
return ( return (
<ShowBox height={height}> <div className="border border-slate-300 rounded-sm">
<input type="checkbox" {...register("showSettingsPage")} /> <Tab.Group>
<div className="columns-2"> <div className="bg-slate-200 rounded-tl-sm rounded-tr-sm">
<div className="break-inside-avoid"> <div className="pb-3 pl-3">
{vars.showSettingsPage ? ( <div className="border-b border-gray-200">
<Tab.List className="-mb-px flex space-x-4">
{tab(
"Code",
<CodeIcon
className="text-gray-400 group-hover:text-gray-500 -ml-0.5 mr-2 h-4 w-4"
aria-hidden="true"
/>
)}
{tab(
"Settings",
<CogIcon
className="text-gray-400 group-hover:text-gray-500 -ml-0.5 mr-2 h-4 w-4"
aria-hidden="true"
/>
)}
</Tab.List>
</div>
</div>
</div>
<div className="flex" style={{ height: height + "px" }}>
<div className="w-1/2">
<Tab.Panels>
<Tab.Panel>
<CodeEditor
value={squiggleString}
onChange={setSquiggleString}
oneLine={false}
showGutter={true}
height={height - 1}
/>
</Tab.Panel>
<Tab.Panel>
<> <>
<form className="space-y-6 p-3">
<InputItem label="Sample Count"> <InputItem label="Sample Count">
<input type="number" {...register("sampleCount")} /> <>
<input
type="number"
{...register("sampleCount")}
className={numberStyle}
/>
<p className="mt-2 text-sm text-gray-500">
How many samples to use for Monte Carlo simulations.
This can be overridden by specific programs.
</p>
</>
</InputItem> </InputItem>
<InputItem label="XYPointLength Count"> <InputItem label="Coordinate Count (For PointSet Shapes)">
<input type="number" {...register("xyPointLength")} /> <>
<input
type="number"
{...register("xyPointLength")}
className={numberStyle}
/>
<p className="mt-2 text-sm text-gray-500">
When distributions are converted into PointSet shapes,
we need to know how many coordinates to use.
</p>
</>
</InputItem> </InputItem>
<InputItem label="Chart Height (in Pixels)"> <InputItem label="Chart Height (in Pixels)">
<input type="number" {...register("chartHeight")} /> <input
</InputItem> type="number"
<InputItem label="Show Types"> {...register("chartHeight")}
<input type="checkbox" {...register("showTypes")} /> className={numberStyle}
</InputItem> />
<InputItem label="Show Controls">
<input type="checkbox" {...register("showControls")} />
</InputItem>
<InputItem label="Show Summary Statistics">
<input type="checkbox" {...register("showSummary")} />
</InputItem> </InputItem>
<InputItem label="Editor Width"> <InputItem label="Editor Width">
<input <input
@ -176,6 +296,50 @@ let SquigglePlayground: FC<PlaygroundProps> = ({
{...register("leftSizePercent")} {...register("leftSizePercent")}
/> />
</InputItem> </InputItem>
<fieldset className="space-y-2">
<div className="relative flex items-start">
<div className="flex items-center h-5">
<input
type="checkbox"
{...register("showTypes")}
className="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
/>
</div>
<div className="ml-3 text-sm">
<label className="font-medium text-gray-700">
Type Names
</label>
</div>
</div>
<div className="relative flex items-start">
<div className="flex items-center h-5">
<input
type="checkbox"
{...register("showControls")}
className="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
/>
</div>
<div className="ml-3 text-sm">
<label className="font-medium text-gray-700">
X-Y Coordinate Scales
</label>
</div>
</div>
<div className="relative flex items-start">
<div className="flex items-center h-5">
<input
type="checkbox"
{...register("showSummary")}
className="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
/>
</div>
<div className="ml-3 text-sm">
<label className="font-medium text-gray-700">
Summary Statistics
</label>
</div>
</div>
</fieldset>
<InputItem label="Json Editor for imports"> <InputItem label="Json Editor for imports">
<> <>
<JsonEditor <JsonEditor
@ -188,19 +352,14 @@ let SquigglePlayground: FC<PlaygroundProps> = ({
{importsAreValid ? "Valid" : "Invalid"} {importsAreValid ? "Valid" : "Invalid"}
</> </>
</InputItem> </InputItem>
</form>
</> </>
) : ( </Tab.Panel>
<CodeEditor </Tab.Panels>
value={squiggleString}
onChange={setSquiggleString}
oneLine={false}
showGutter={true}
height={height - 3}
/>
)}
</div> </div>
<div>
<Display maxHeight={height - 3}> <div className="w-1/2 border-l border-gray-300 p-2">
<div style={{ maxHeight: height + "px" }}>
<SquiggleChart <SquiggleChart
squiggleString={squiggleString} squiggleString={squiggleString}
environment={env} environment={env}
@ -212,10 +371,11 @@ let SquigglePlayground: FC<PlaygroundProps> = ({
jsImports={imports} jsImports={imports}
showSummary={vars.showSummary} showSummary={vars.showSummary}
/> />
</Display>
</div> </div>
</div> </div>
</ShowBox> </div>
</Tab.Group>
</div>
); );
}; };
export default SquigglePlayground; export default SquigglePlayground;

View File

@ -1824,6 +1824,16 @@
dependencies: dependencies:
"@hapi/hoek" "^9.0.0" "@hapi/hoek" "^9.0.0"
"@headlessui/react@^1.6.4":
version "1.6.4"
resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.6.4.tgz#c73084e23386bef5fb86cd16da3352c3a844bb4c"
integrity sha512-0yqz1scwbFtwljmbbKjXsSGl5ABEYNICVHZnMCWo0UtOZodo2Tpu94uOVgCRjRZ77l2WcTi2S0uidINDvG7lsA==
"@heroicons/react@^1.0.6":
version "1.0.6"
resolved "https://registry.yarnpkg.com/@heroicons/react/-/react-1.0.6.tgz#35dd26987228b39ef2316db3b1245c42eb19e324"
integrity sha512-JJCXydOFWMDpCP4q13iEplA503MQO3xLoZiKum+955ZCtHINWnx26CUxVxxFQu/uLb4LW3ge15ZpzIkXKkJ8oQ==
"@hookform/resolvers@^2.8.10": "@hookform/resolvers@^2.8.10":
version "2.8.10" version "2.8.10"
resolved "https://registry.yarnpkg.com/@hookform/resolvers/-/resolvers-2.8.10.tgz#b66d7a7848b1b1dd5b976a73fff36bb366666e7d" resolved "https://registry.yarnpkg.com/@hookform/resolvers/-/resolvers-2.8.10.tgz#b66d7a7848b1b1dd5b976a73fff36bb366666e7d"