Skip to content

Commit 385212c

Browse files
authored
Merge pull request #12 from coder/brett/snippets
feat: add snippets and fix component styling
2 parents 89530f3 + d8f39c7 commit 385212c

File tree

11 files changed

+154
-50
lines changed

11 files changed

+154
-50
lines changed

preview/scripts/types/main.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,12 @@ func main() {
4343
}
4444

4545
ts, err := gen.ToTypescript()
46-
ts.ApplyMutations(config.ExportTypes, config.NullUnionSlices, config.SimplifyOmitEmpty)
46+
ts.ApplyMutations(
47+
config.ExportTypes,
48+
config.NullUnionSlices,
49+
config.SimplifyOmitEmpty,
50+
config.EnumAsTypes,
51+
)
4752

4853
if err != nil {
4954
log.Fatalf("to typescript: %v", err)

src/client/Editor.tsx

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import {
1515
} from "@/client/components/Tooltip";
1616
import { useStore } from "@/client/store";
1717
import {
18-
BookIcon,
1918
CheckIcon,
2019
ChevronDownIcon,
2120
CopyIcon,
@@ -25,8 +24,9 @@ import {
2524
SquareMousePointerIcon,
2625
TextCursorInputIcon,
2726
ToggleLeftIcon,
27+
ZapIcon,
2828
} from "lucide-react";
29-
import { type FC, useEffect, useRef, useState } from "react";
29+
import { type FC, useCallback, useEffect, useRef, useState } from "react";
3030
import CodeEditor from "react-simple-code-editor";
3131

3232
// The following imports can't be re-ordered otherwise things break
@@ -35,6 +35,8 @@ import { highlight, languages } from "prismjs/components/prism-core";
3535
import "prismjs/components/prism-hcl";
3636
import "prismjs/themes/prism.css";
3737
import { cn } from "@/utils/cn";
38+
import type { ParameterFormType } from "@/gen/types";
39+
import { multiSelect, radio, switchInput, textInput } from "@/client/snippets";
3840

3941
// Adds line numbers to the highlight.
4042
const hightlightWithLineNumbers = (input: string, language: unknown) =>
@@ -62,6 +64,20 @@ export const Editor: FC = () => {
6264
setCodeCopied(() => true);
6365
};
6466

67+
const onAddSnippet = useCallback(
68+
(formType: ParameterFormType) => {
69+
if (formType === "input") {
70+
$setCode(`${$code.trimEnd()}\n\n${textInput}\n`);
71+
} else if (formType === "radio") {
72+
$setCode(`${$code.trimEnd()}\n\n${radio}\n`);
73+
} else if (formType === "multi-select") {
74+
$setCode(`${$code.trimEnd()}\n\n${multiSelect}\n`);
75+
} else if (formType === "switch") {
76+
$setCode(`${$code.trimEnd()}\n\n${switchInput}\n`);
77+
}
78+
},
79+
[$code, $setCode],
80+
);
6581

6682
useEffect(() => {
6783
if (!codeCopied) {
@@ -105,27 +121,29 @@ export const Editor: FC = () => {
105121
<DropdownMenu>
106122
<DropdownMenuTrigger className="flex w-fit min-w-[140px] cursor-pointer items-center justify-between rounded-md border bg-surface-primary px-2 py-1.5 text-content-secondary transition-colors hover:text-content-primary data-[state=open]:text-content-primary">
107123
<div className="flex items-center justify-center gap-2">
108-
<BookIcon width={18} height={18} />
109-
<p className="text-xs">Examples</p>
124+
<ZapIcon width={18} height={18} />
125+
<p className="text-xs">Snippets</p>
110126
</div>
111127
<ChevronDownIcon width={18} height={18} />
112128
</DropdownMenuTrigger>
113129

114130
<DropdownMenuPortal>
115131
<DropdownMenuContent align="start">
116-
<DropdownMenuItem>
132+
<DropdownMenuItem onClick={() => onAddSnippet("input")}>
117133
<TextCursorInputIcon width={24} height={24} />
118134
Text input
119135
</DropdownMenuItem>
120-
<DropdownMenuItem>
136+
<DropdownMenuItem
137+
onClick={() => onAddSnippet("multi-select")}
138+
>
121139
<SquareMousePointerIcon width={24} height={24} />
122140
Multi-select
123141
</DropdownMenuItem>
124-
<DropdownMenuItem>
142+
<DropdownMenuItem onClick={() => onAddSnippet("radio")}>
125143
<RadioIcon width={24} height={24} />
126144
Radio
127145
</DropdownMenuItem>
128-
<DropdownMenuItem>
146+
<DropdownMenuItem onClick={() => onAddSnippet("switch")}>
129147
<ToggleLeftIcon width={24} height={24} /> Switches
130148
</DropdownMenuItem>
131149
</DropdownMenuContent>

src/client/components/Markdown.tsx

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ export const Markdown: FC<MarkdownProps> = (props) => {
4646
p: ({ children }) => {
4747
return <p className="text-xs">{children}</p>;
4848
},
49+
4950
a: ({ href, children }) => {
5051
const isExternal = href?.startsWith("http");
5152

@@ -56,6 +57,8 @@ export const Markdown: FC<MarkdownProps> = (props) => {
5657
);
5758
},
5859

60+
hr: () => <hr className="my-3"/>,
61+
5962
pre: ({ node, children }) => {
6063
if (!node || !node.children) {
6164
return <pre>{children}</pre>;
@@ -92,6 +95,13 @@ export const Markdown: FC<MarkdownProps> = (props) => {
9295
);
9396
},
9497

98+
ul: ({ children }) => {
99+
return <ul className="list-inside list-disc">{children}</ul>;
100+
},
101+
li: ({ children }) => {
102+
return <li className="text-sm">{children}</li>;
103+
},
104+
95105
table: ({ children }) => {
96106
return <Table>{children}</Table>;
97107
},
@@ -117,27 +127,27 @@ export const Markdown: FC<MarkdownProps> = (props) => {
117127
},
118128

119129
h1: ({ children }) => {
120-
return <h1 className="mt-8 mb-4 font-bold text-lg">{children}</h1>;
130+
return <h1 className="my-3 font-bold text-xl">{children}</h1>;
121131
},
122132

123133
h2: ({ children }) => {
124-
return <h2 className="mt-8 mb-4">{children}</h2>;
134+
return <h2 className="my-2 font-semibold">{children}</h2>;
125135
},
126136

127137
h3: ({ children }) => {
128-
return <h3 className="mt-8 mb-4">{children}</h3>;
138+
return <h3 className="my-2 font-medium">{children}</h3>;
129139
},
130140

131141
h4: ({ children }) => {
132-
return <h4 className="mt-8 mb-4">{children}</h4>;
142+
return <h4 className="">{children}</h4>;
133143
},
134144

135145
h5: ({ children }) => {
136-
return <h5 className="mt-8 mb-4">{children}</h5>;
146+
return <h5 className="">{children}</h5>;
137147
},
138148

139149
h6: ({ children }) => {
140-
return <h6 className="mt-8 mb-4">{children}</h6>;
150+
return <h6 className="">{children}</h6>;
141151
},
142152

143153
/**

src/client/components/MultiSelectCombobox.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -460,7 +460,7 @@ export const MultiSelectCombobox = forwardRef<
460460
{/* biome-ignore lint/a11y/useKeyWithClickEvents: onKeyDown is not needed here */}
461461
<div
462462
className={cn(
463-
"min-h-10 rounded-md border border-border border-solid pr-3 text-sm focus-within:ring-2 focus-within:ring-content-link",
463+
"h-10 min-h-10 rounded-md border border-border border-solid pr-3 text-sm focus-within:ring-2 focus-within:ring-content-link",
464464
{
465465
"py-1 pl-3": selected.length !== 0,
466466
"cursor-text": !disabled && selected.length !== 0,
@@ -472,7 +472,7 @@ export const MultiSelectCombobox = forwardRef<
472472
inputRef?.current?.focus();
473473
}}
474474
>
475-
<div className="flex items-center justify-between">
475+
<div className="flex items-center justify-between h-full">
476476
<div className="relative flex flex-wrap gap-1">
477477
{selected.map((option) => {
478478
return (
@@ -540,7 +540,7 @@ export const MultiSelectCombobox = forwardRef<
540540
"flex-1 border-none bg-transparent outline-none placeholder:text-content-secondary",
541541
{
542542
"w-full": hidePlaceholderWhenSelected,
543-
"px-3 py-2.5": selected.length === 0,
543+
"px-3": selected.length === 0,
544544
"ml-1": selected.length !== 0,
545545
},
546546
inputProps?.className,
@@ -562,7 +562,7 @@ export const MultiSelectCombobox = forwardRef<
562562
}
563563
}}
564564
className={cn(
565-
"mt-1 cursor-pointer rounded-sm border-none bg-transparent text-content-secondary outline-none hover:text-content-primary focus:ring-2 focus:ring-content-link",
565+
"cursor-pointer rounded-sm border-none bg-transparent text-content-secondary outline-none hover:text-content-primary focus:ring-2 focus:ring-content-link",
566566
(hideClearAllButton ||
567567
disabled ||
568568
selected.length < 1 ||

src/client/components/Switch.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export const Switch = forwardRef<
2020
>
2121
<SwitchPrimitives.Thumb
2222
className={cn(
23-
"data-[state=unchecked]:-translate-x-1.5 pointer-events-none block h-4 w-4 rounded-full bg-surface-primary shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-2.5",
23+
"pointer-events-none block h-4 w-4 rounded-full bg-surface-primary shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4",
2424
)}
2525
/>
2626
</SwitchPrimitives.Root>

src/client/snippets.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
export const defaultCode = `terraform {
2+
required_providers {
3+
coder = {
4+
source = "coder/coder"
5+
}
6+
}
7+
}`;
8+
9+
export const textInput = `data "coder_parameter" "project-name" {
10+
display_name = "An input"
11+
name = "an-input"
12+
description = "What is the name of your project?"
13+
order = 1
14+
15+
form_type = "input"
16+
type = "string"
17+
default = "An input value"
18+
}`;
19+
20+
export const radio = `data "coder_parameter" "radio" {
21+
name = "radio"
22+
display_name = "An example of a radio input"
23+
description = "The next parameter supports a single value."
24+
type = "string"
25+
form_type = "radio"
26+
order = 1
27+
default = "option-1"
28+
29+
option {
30+
name = "Option 1"
31+
value = "option-1"
32+
description = "A description for Option 1"
33+
}
34+
35+
option {
36+
name = "Option 2"
37+
value = "option-2"
38+
description = "A description for Option 2"
39+
}
40+
41+
option {
42+
name = "Option 3"
43+
value = "option-3"
44+
description = "A description for Option 3"
45+
}
46+
47+
option {
48+
name = "Option 4"
49+
value = "option-4"
50+
description = "A description for Option 4"
51+
}
52+
}`;
53+
54+
export const multiSelect = `data "coder_parameter" "multi-select" {
55+
name = "multi-select"
56+
display_name = "An example of a multi-select"
57+
description = "The next parameter supports multiple values."
58+
type = "list(string)"
59+
form_type = "multi-select"
60+
order = 1
61+
62+
option {
63+
name = "Option 1"
64+
value = "option-1"
65+
description = "A description for Option 1"
66+
}
67+
68+
option {
69+
name = "Option 2"
70+
value = "option-2"
71+
description = "A description for Option 2"
72+
}
73+
74+
option {
75+
name = "Option 3"
76+
value = "option-3"
77+
description = "A description for Option 3"
78+
}
79+
80+
option {
81+
name = "Option 4"
82+
value = "option-4"
83+
description = "A description for Option 4"
84+
}
85+
}`;
86+
87+
export const switchInput = `data "coder_parameter" "switch" {
88+
name = "switch"
89+
display_name = "An example of a switch"
90+
description = "The next parameter can be on or off"
91+
type = "bool"
92+
form_type = "switch"
93+
defalt = true
94+
order = 1
95+
}`

src/client/store.tsx

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,7 @@
11
import { create } from "zustand";
22
import type { Diagnostic } from "@/client/diagnostics";
33
import type { Parameter } from "@/gen/types";
4-
5-
const defaultCode = `terraform {
6-
required_providers {
7-
coder = {
8-
source = "coder/coder"
9-
}
10-
}
11-
}`;
4+
import { defaultCode } from "./snippets";
125

136
type FormState = Record<string, string>;
147

src/gen/types.ts

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,7 @@ export interface NullHCLString {
4040
}
4141

4242
// From apitypes/apitypes.go
43-
export enum OptionType {
44-
OptionTypeBoolean = "bool",
45-
OptionTypeListString = "list(string)",
46-
OptionTypeNumber = "number",
47-
OptionTypeString = "string"
48-
}
43+
export type OptionType = "bool" | "list(string)" | "number" | "string";
4944

5045
// From preview/preview.go
5146
export interface Output {
@@ -80,19 +75,7 @@ export interface ParameterData {
8075
}
8176

8277
// From provider/formtype.go
83-
export enum ParameterFormType {
84-
ParameterFormTypeCheckbox = "checkbox",
85-
ParameterFormTypeDefault = "",
86-
ParameterFormTypeDropdown = "dropdown",
87-
ParameterFormTypeError = "error",
88-
ParameterFormTypeInput = "input",
89-
ParameterFormTypeMultiSelect = "multi-select",
90-
ParameterFormTypeRadio = "radio",
91-
ParameterFormTypeSlider = "slider",
92-
ParameterFormTypeSwitch = "switch",
93-
ParameterFormTypeTagSelect = "tag-select",
94-
ParameterFormTypeTextArea = "textarea"
95-
}
78+
export type ParameterFormType = "checkbox" | "" | "dropdown" | "error" | "input" | "multi-select" | "radio" | "slider" | "switch" | "tag-select" | "textarea";
9679

9780
// From types/parameter.go
9881
export interface ParameterOption {

tsconfig.app.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"strict": true,
2828
"noUnusedLocals": true,
2929
"noUnusedParameters": true,
30-
"erasableSyntaxOnly": false,
30+
"erasableSyntaxOnly": true,
3131
"noFallthroughCasesInSwitch": true,
3232
"noUncheckedSideEffectImports": false
3333
},

tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"files": [],
3-
"erasableSyntaxOnly": false,
3+
"erasableSyntaxOnly": true,
44
"references": [
55
{
66
"path": "./tsconfig.app.json"

0 commit comments

Comments
 (0)