<div>
<h1 class="title">Canopy Components Examples</h1>
<section id="example1" class="container fade">
<div class="example">
<form>
<fieldset class="hidden">
<div id="username-parent"></div>
</fieldset>
<fieldset class="hidden">
<div id="password-parent"></div>
</fieldset>
<fieldset class="hidden">
<div id="thirdfield-parent"></div>
</fieldset>
<button id="ccsubmit" class="hidden"><span>Submit Form »</span></button>
<div id="username-error" class="error hidden"></div>
<div id="password-error" class="error hidden"></div>
<div id="thirdfield-error" class="error hidden"></div>
</form>
</div>
</section>
<div id="result"></div>
</div>
xxxxxxxxxx
body,
button {
font-family: Outfit, sans-serif;
}
.hidden {
display: none;
}
.fade {
opacity: 0;
transition: opacity 0.3s cubic-bezier(0, 0.45, 0.55, 1);
}
.fade.fade-in {
opacity: 1 !important;
}
.title {
font-size: 50px;
font-weight: 300;
text-align: center;
}
.container {
display: flexbox;
display: flex;
flex-wrap: wrap;
flex-wrap: wrap;
position: relative;
max-width: 750px;
padding-top: 60px;
padding-bottom: 60px;
margin: 0 auto;
width: 100%;
}
.example {
/* background-color: #6772e5; */
background-color: #0e0578;
flex-align: center;
align-items: center;
border-radius: 4px;
box-shadow: 0 7px 14px rgba(50, 50, 93, 0.1), 0 3px 6px rgba(0, 0, 0, 0.08);
padding: 80px 0px;
display: flexbox;
display: flex;
flex-direction: column;
flex-direction: column;
flex-pack: center;
justify-content: center;
position: relative;
flex: auto;
flex: auto;
min-height: 500px;
padding: 0 40px;
}
.example form {
position: relative;
width: 100%;
max-width: 500px;
transition-property: opacity, transform;
transition-duration: 0.35s;
transition-timing-function: cubic-bezier(0.165, 0.84, 0.44, 1);
}
.example button:hover {
background-color: #e04f16;
}
.example button {
display: block;
position: relative;
width: calc(100% - 30px);
height: 40px;
margin: 40px 15px 0;
background-color: #ff8540;
border: solid 1px #3f3681;
border-radius: 8px;
color: #fff;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
appearance: none;
appearance: none;
appearance: none;
outline: none;
border-style: none;
transition-property: background-color;
transition-duration: 0.35s;
transition-timing-function: cubic-bezier(0.165, 0.84, 0.44, 1);
}
.example button.loading {
cursor: default;
background-color: #e1b8dc;
}
.example button.loading::after {
content: "";
position: absolute;
width: 16px;
height: 16px;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
border: 4px solid transparent;
border-top-color: #ffffff;
border-radius: 50%;
animation: button-loading-spinner 1s ease infinite;
}
@keyframes button-loading-spinner {
from {
transform: rotate(0turn);
}
to {
transform: rotate(1turn);
}
}
.example button.loading span {
visibility: hidden;
opacity: 0;
}
fieldset {
margin: 0 15px 20px;
padding: 0;
border-style: none;
background-color: #fff;
box-shadow: 0 6px 9px rgba(50, 50, 93, 0.06), 0 2px 5px rgba(0, 0, 0, 0.08),
inset 0 1px 0 #829fff;
border-radius: 4px;
cursor: text;
}
#username-parent,
#password-parent,
#thirdfield-parent {
padding: 11px 15px;
}
.error span {
color: #fff;
}
.error {
display: flex !important;
justify-content: center;
width: 100%;
margin-top: 20px;
padding: 0 15px;
font-size: 13px !important;
transition-property: opacity, transform;
transition-duration: 0.35s;
transition-timing-function: cubic-bezier(0.165, 0.84, 0.44, 1);
opacity: 1;
transform: none;
}
.error.hidden {
opacity: 0;
transform: translateY(10px);
}
xxxxxxxxxx
/**
Canopy Connect Components implementation below using custom a font and styles
**/
window.addEventListener("load", () => {
const form = CanopyConnectComponents.form({
carrierConfig: {
name: "AAA",
usernameFieldPlaceholder: "Email",
thirdFieldPlaceholder: "Zip Code",
thirdFieldValidatorError: "Must be a valid zip code",
thirdFieldValidatorRgx: "^\\d{5}$",
disablePasswordField: false
},
fonts: [
// Latin-ext
{
family: "Outfit",
src:
"url(https://fonts.gstatic.com/s/outfit/v11/QGYyz_MVcBeNP4NjuGObqx1XmO1I4W61O4i0FQItq6fNIhnL.woff) format('woff')",
weight: "300",
style: "normal",
unicodeRange:
"U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF"
},
// Latin
{
family: "Outfit",
src:
"url(https://fonts.gstatic.com/s/outfit/v11/QGYyz_MVcBeNP4NjuGObqx1XmO1I4W61O4a0FQItq6fNIg.woff) format('woff')",
weight: "300",
style: "normal",
unicodeRange:
"U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD"
}
],
styles: {
base: {
color: "rgb(16, 24, 40)",
fontWeight: "300",
fontFamily: "Outfit, sans-serif",
fontSize: "1rem",
fontSmoothing: "antialiased",
":autofill": {
color: "#fce883"
},
"::placeholder": {
color: "rgb(71, 84, 103)"
}
},
invalid: {
color: "#ED637A"
}
}
});
const submitButton = document.querySelector("#ccsubmit");
const submitForm = async (event) => {
if (event) {
event.preventDefault();
}
submitButton.disabled = true;
submitButton.classList.add("loading");
try {
const result = await form.submit();
const resultElem = document.getElementById("result");
if (result.errors) {
for (const type of Object.keys(result.errors)) {
const errorElem = document.getElementById(`${type}-error`);
errorElem.innerHTML = `<span>${result.errors[type].error}</span>`;
errorElem.classList.remove("hidden");
}
} else {
console.log("Successfully submitted and got tokens", result.tokens);
const jsonStr = JSON.stringify(result.tokens, null, 2);
resultElem.innerText = jsonStr;
window.alert(jsonStr);
}
} catch (err) {
console.error(err, err.inputType);
} finally {
submitButton.disabled = false;
submitButton.classList.remove("loading");
}
};
submitButton.addEventListener("click", submitForm);
submitButton.classList.remove("hidden");
form.on("submit", () => submitForm());
form.on("ready", () =>
document.getElementById("example1").classList.add("fade-in")
);
const { username, password, thirdfield } = form.components;
const types = ["username", "password", "thirdfield"].filter(
(type) => type in form.components
);
for (let i = 0; i < types.length; i += 1) {
const type = types[i];
if (!(type in form.components)) {
continue;
}
const parentElem = document.getElementById(`${type}-parent`);
const errorElem = document.getElementById(`${type}-error`);
const fieldsetElem = parentElem.parentElement;
const component = form.components[type];
component.mount(parentElem);
fieldsetElem.classList.remove("hidden");
component.on("change", ({ error }) => {
if (error) {
errorElem.innerHTML = `<span>${error}</span>`;
errorElem.classList.remove("hidden");
} else {
errorElem.innerHTML = null;
errorElem.classList.add("hidden");
}
});
}
});