|
1 | 1 | --- |
2 | | -interface Props { |
3 | | - href: string; |
4 | | -} |
5 | | -
|
6 | | -const { href } = Astro.props; |
| 2 | +import Pill from "./Pill.astro"; |
| 3 | +import Icon from "./Icon.astro"; |
7 | 4 | --- |
| 5 | +<form id="my-form" action={import.meta.env.FORM_URL} method="POST"> |
| 6 | + <label>Name:</label> |
| 7 | + <input type="text" name="name" /> |
| 8 | + <label>Email:</label> |
| 9 | + <input type="email" name="email" /> |
| 10 | + <label>Message:</label> |
| 11 | + <textarea name="message" rows="5" style="resize: none;"></textarea> |
| 12 | + <button id="my-form-button"> |
| 13 | + <Pill>Send <Icon icon="paper-plane-tilt" /></Pill></button |
| 14 | + > |
| 15 | +</form> |
8 | 16 |
|
9 | | -<a href={href}><slot /></a> |
| 17 | +<script> |
| 18 | + var form = document.getElementById("my-form") as HTMLFormElement; |
| 19 | + |
| 20 | + async function handleSubmit(event: Event) { |
| 21 | + event.preventDefault(); |
| 22 | + var data = new FormData(event.target as HTMLFormElement); |
| 23 | + if (!event.target) return; |
| 24 | + fetch((event.target as HTMLFormElement).action, { |
| 25 | + method: form.method, |
| 26 | + body: data, |
| 27 | + headers: { |
| 28 | + Accept: "application/json", |
| 29 | + }, |
| 30 | + }) |
| 31 | + .then((response) => { |
| 32 | + if (response.ok) { |
| 33 | + window.alert("Thanks for your submission!"); |
| 34 | + form.reset(); |
| 35 | + } else { |
| 36 | + response.json().then((data) => { |
| 37 | + if (Object.hasOwn(data, "errors")) { |
| 38 | + window.alert( |
| 39 | + data["errors"].map((error: any) => error["message"]).join(", ") |
| 40 | + ); |
| 41 | + } else { |
| 42 | + window.alert("Oops! There was a problem submitting your form"); |
| 43 | + } |
| 44 | + }); |
| 45 | + } |
| 46 | + }) |
| 47 | + .catch((error) => { |
| 48 | + window.alert("Oops! There was a problem submitting your form"); |
| 49 | + }); |
| 50 | + } |
| 51 | + form.addEventListener("submit", handleSubmit); |
| 52 | +</script> |
10 | 53 |
|
11 | 54 | <style> |
12 | | - a { |
13 | | - position: relative; |
| 55 | + .alert { |
| 56 | + position: fixed; |
| 57 | + top: 1rem; |
| 58 | + right: 1rem; |
| 59 | + padding: 1rem; |
| 60 | + background-color: var(--gray-900); |
| 61 | + color: var(--gray-100); |
| 62 | + border-radius: 0.25rem; |
| 63 | + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
| 64 | + z-index: 9999; |
| 65 | + } |
| 66 | + form { |
14 | 67 | display: flex; |
15 | | - place-content: center; |
16 | | - text-align: center; |
17 | | - padding: 0.56em 2em; |
18 | | - gap: 0.8em; |
19 | | - color: var(--accent-text-over); |
20 | | - text-decoration: none; |
21 | | - line-height: 1.1; |
22 | | - border-radius: 999rem; |
23 | | - overflow: hidden; |
24 | | - background: var(--gradient-accent-orange); |
25 | | - box-shadow: var(--shadow-md); |
26 | | - white-space: nowrap; |
| 68 | + flex-direction: column; |
| 69 | + width: 100%; |
27 | 70 | } |
28 | | - |
29 | | - @media (min-width: 20em) { |
30 | | - a { |
31 | | - font-size: var(--text-lg); |
32 | | - } |
| 71 | + label { |
| 72 | + margin: 1rem 0 0.25rem 0; |
| 73 | + font-size: var(--text-sm); |
| 74 | + font-weight: 600; |
| 75 | + } |
| 76 | + input { |
| 77 | + padding: 0.5rem; |
| 78 | + border: 1px solid var(--gray-900); |
| 79 | + border-radius: 0.25rem; |
| 80 | + background-color: var(--gray-800); |
| 81 | + color: var(--gray-100); |
| 82 | + } |
| 83 | + input:focus { |
| 84 | + outline: none; |
33 | 85 | } |
34 | 86 |
|
35 | | - /* Overlay for hover effects. */ |
36 | | - a::after { |
37 | | - content: ""; |
38 | | - position: absolute; |
39 | | - inset: 0; |
40 | | - pointer-events: none; |
41 | | - transition: background-color var(--theme-transition); |
42 | | - mix-blend-mode: overlay; |
| 87 | + button { |
| 88 | + padding: 0; |
| 89 | + background-color: transparent; |
| 90 | + color: inherit; |
| 91 | + border: none; |
| 92 | + cursor: pointer; |
| 93 | + width: max-content; |
| 94 | + margin: 1rem auto 0 auto; |
| 95 | + } |
| 96 | + textarea { |
| 97 | + padding: 0.5rem; |
| 98 | + border: 1px solid var(--gray-900); |
| 99 | + border-radius: 0.25rem; |
| 100 | + background-color: var(--gray-800); |
| 101 | + color: var(--gray-100); |
| 102 | + width: 100%; |
| 103 | + scrollbar-color: var(--gray-300) var(--gray-800); |
| 104 | + overflow: -moz-hidden-unscrollable; |
| 105 | + } |
| 106 | + textarea:focus { |
| 107 | + outline: none; |
43 | 108 | } |
44 | 109 |
|
45 | | - a:focus::after, |
46 | | - a:hover::after { |
47 | | - background-color: hsla(var(--gray-999-basis), 0.3); |
| 110 | + p { |
| 111 | + font-size: var(--text-sm); |
| 112 | + } |
| 113 | + .Pill { |
| 114 | + width: fit-content; |
48 | 115 | } |
49 | 116 |
|
50 | 117 | @media (min-width: 50em) { |
51 | | - a { |
52 | | - padding: 1.125rem 2.5rem; |
53 | | - font-size: var(--text-xl); |
| 118 | + form { |
| 119 | + display: flex; |
| 120 | + flex-direction: column; |
| 121 | + } |
| 122 | + |
| 123 | + label { |
| 124 | + font-size: var(--text-sm); |
| 125 | + } |
| 126 | + |
| 127 | + input { |
| 128 | + padding: 0.5rem; |
| 129 | + border: 1px solid var(--gray-900); |
| 130 | + border-radius: 0.25rem; |
| 131 | + background-color: var(--gray-800); |
| 132 | + color: var(--gray-100); |
| 133 | + } |
| 134 | + input:focus { |
| 135 | + outline: none; |
| 136 | + } |
| 137 | + textarea { |
| 138 | + padding: 0.5rem; |
| 139 | + border: 1px solid var(--gray-900); |
| 140 | + border-radius: 0.25rem; |
| 141 | + background-color: var(--gray-800); |
| 142 | + color: var(--gray-100); |
| 143 | + scrollbar-color: var(--gray-300) var(--gray-800); |
| 144 | + overflow: -moz-hidden-unscrollable; |
| 145 | + } |
| 146 | + textarea:focus { |
| 147 | + outline: none; |
| 148 | + } |
| 149 | + |
| 150 | + button { |
| 151 | + padding: 0; |
| 152 | + background-color: transparent; |
| 153 | + color: inherit; |
| 154 | + border: none; |
| 155 | + cursor: pointer; |
| 156 | + width: max-content; |
| 157 | + } |
| 158 | + |
| 159 | + p { |
| 160 | + font-size: var(--text-sm); |
| 161 | + } |
| 162 | + |
| 163 | + .Pill { |
| 164 | + width: fit-content; |
54 | 165 | } |
55 | 166 | } |
56 | 167 | </style> |
0 commit comments