Skip to content

Commit e098dcb

Browse files
authored
feat: add border radius input to gradient border generator (#125)
* Append checkbox input to `index.html`. * feat(index.html, style.css, gradient-border.ts, general.ts): add radius option to gradient-border This changes provide users the with the option of including a radius in the generated gradient border BREAKING CHANGE: The copied code is empty. When user clicks on copy code button, the clipboard is empty * style(index.html, style.css, general.ts, gradient-border.ts): format code with prettier Applies the recommended prettier styling to code as required by Author * fix(index.html): fix typo in index.html correct the for attribute for gradient-border checkbox * feat(index.html, gradient-border.ts): add text-input to border radius These changes introduce a text input for allowing the User to specify the radius of the generated border gradient re #68
1 parent 21b8996 commit e098dcb

File tree

5 files changed

+153
-10
lines changed

5 files changed

+153
-10
lines changed

index.html

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,14 @@ <h1 id="head">Code Magic</h1>
215215
</label>
216216
</div>
217217

218+
<label class="radius" for="gradient-border-radius">
219+
<input type="checkbox" id="gradient-border-radius" name="check" />
220+
<span> Include Radius </span>
221+
<label id="radius-input-label" for="gradient-border-input">
222+
<input type="number" id="gradient-border-input" name="desired-radius" placeholder="Enter a number e.g. 50" autofocus required />
223+
</label>
224+
</label>
225+
218226
<label id="degree">
219227
<span>Degree</span>
220228
<input
@@ -426,7 +434,7 @@ <h2>Results</h2>
426434

427435
<!-- Gradient Border -->
428436
<div class="download-output" data-result="gradient-border">
429-
<div class="output"></div>
437+
<div class="output gradient-border"></div>
430438
<div class="download-btn">
431439
<button class="btn" data-download="gradient-border-code">
432440
<iconify-icon

src/lib/general.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,22 @@ export const getRange = (attribute: string): HTMLInputElement =>
152152
export const getInputText = (attribute: string) =>
153153
<HTMLInputElement>document.getElementById(`${attribute}-text`);
154154

155+
export const getCheckbox = (attribute: string): HTMLInputElement =>
156+
<HTMLInputElement>document.getElementById(`${attribute}-radius`);
157+
158+
export const getRadiusInput = (attribute: string) =>
159+
<HTMLInputElement>document.getElementById(`${attribute}-input`);
160+
161+
export const showRadius = (attribute: string): void =>
162+
document
163+
.querySelectorAll<HTMLElement>(`#${attribute}-input`)[0]
164+
.style.setProperty('display', 'inline');
165+
166+
export const hideRadius = (attribute: string): void =>
167+
document
168+
.querySelectorAll<HTMLElement>(`#${attribute}-input`)[0]
169+
.style.setProperty('display', 'none');
170+
155171
export const getInputSpinner = (attribute: string) =>
156172
<HTMLInputElement>document.getElementById(`${attribute}-duration`);
157173

@@ -168,6 +184,11 @@ export const getStyleSheet = () => {
168184
return <CSSStyleSheet>stylesheet[0];
169185
};
170186

187+
/* |||| CONSIDER RENAMING getOutput above TO getGradientBorder ||||
188+
* (for example) export const getGradientBorder = (attribute: string): HTMLElement =>
189+
* <HTMLElement>document.querySelector(`${attribute}`);
190+
*/
191+
171192
function createDownloadLink(fileName: string, url: string) {
172193
const link = document.createElement('a');
173194
link.download = fileName;

src/main.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,13 +213,17 @@ function showResult(attribute: string | null) {
213213
// removeOrAddGeneratorContent(attributeValue, 'none');
214214
// }
215215

216-
// adding an event listeners to all generators card
216+
// add event listener to generator icons
217217

218218
generators.forEach((generator) => {
219219
generator?.addEventListener('click', (): void => {
220220
sidebar.style.left = '100%';
221221
const checking = generator.getAttribute('data-gen');
222-
if (checking === null) return;
222+
if (checking === 'gradient-border') {
223+
generatorsFunction(checking);
224+
} else if (checking === null) {
225+
return;
226+
}
223227

224228
attributeValue = checking;
225229
showContent(attributeValue, 'flex');

src/pages/gradient-border.ts

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ type Values = {
44
firstColor: string;
55
secondColor: string;
66
degree: string;
7+
radius: string;
78
};
89

910
export function gradientBorderGenerator(): void {
@@ -12,11 +13,25 @@ export function gradientBorderGenerator(): void {
1213
const color2 = utils.getColorInput2(attribute);
1314
const getOutputElement = utils.getOutput(attribute);
1415
const getRangeElement = utils.getRange(attribute);
16+
const getCheckboxElement = utils.getCheckbox(attribute);
17+
const getBorderRadiusInput = utils.getRadiusInput(attribute);
18+
const showRadiusInput = utils.showRadius;
19+
const hideRadiusInput = utils.hideRadius;
1520

16-
const values = {
21+
getCheckboxElement.addEventListener('change', (e: Event): void => {
22+
const target = e.target as HTMLInputElement;
23+
if (target.checked) {
24+
showRadiusInput(attribute);
25+
} else {
26+
hideRadiusInput(attribute);
27+
}
28+
});
29+
30+
const values: Values = {
1731
firstColor: color1.value,
1832
secondColor: color2.value,
1933
degree: getRangeElement.value,
34+
radius: getBorderRadiusInput.value,
2035
};
2136
getGradientBorderResult(attribute, values, getOutputElement);
2237
}
@@ -33,10 +48,27 @@ function getGradientBorderResult(
3348
values: Values,
3449
outputElement: HTMLElement
3550
): void {
36-
outputElement.style.border = 'solid';
37-
outputElement.style.borderWidth = '5px';
38-
outputElement.style.borderImageSlice = '1';
39-
outputElement.style.borderImageSource = `linear-gradient(${values.degree}deg, ${values.firstColor}, ${values.secondColor})`;
51+
outputElement.style.setProperty(
52+
`--${attribute}-color-1`,
53+
`${values.firstColor}`
54+
);
55+
outputElement.style.setProperty(
56+
`--${attribute}-color-2`,
57+
`${values.secondColor}`
58+
);
59+
outputElement.style.setProperty(
60+
`--${attribute}-degree`,
61+
`${values.degree}deg`
62+
);
63+
64+
outputElement.style.setProperty(
65+
`--${attribute}-radius`,
66+
`${values.radius}px`
67+
);
68+
69+
outputElement.style.backgroundColor = 'transparent';
70+
outputElement.style.visibility = 'visible';
71+
utils.getCheckbox(attribute).checked = false;
4072

4173
const getCodeButtonElement = utils.getCopyCodeButton(attribute);
4274
getCodeButtonElement.addEventListener('click', () => {

src/style.css

Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@
22
/* Colors */
33
--primary-color: #081121;
44
--text-color: #edf2f4;
5+
--input-color: #000000;
56
--secondary-color: #0e213c;
67
--tertiary-color: #2196f3;
8+
--gradient-border-color-1: red;
9+
--gradient-border-color-2: blue;
710

811
/* Heights */
912
--generator-height: 14rem;
@@ -13,8 +16,12 @@
1316
--generator-width: 12rem;
1417
--content-container: 100%;
1518
--input-width: 300px;
16-
--output-width: 400px;
19+
--output-width: 300px;
1720
--pseudo-footer-height: 70px;
21+
22+
/* GRADIENT BORDER SECTION */
23+
--gradient-border-radius: 0;
24+
--gradient-border-degree: 45deg;
1825
}
1926

2027
*,
@@ -152,7 +159,7 @@ textarea {
152159
}
153160

154161
::placeholder {
155-
color: var(--text-color);
162+
color: var(--input-color);
156163
font-size: 1rem;
157164
}
158165

@@ -229,11 +236,30 @@ textarea {
229236
padding-right: 8px;
230237
}
231238

239+
#radius-input-label {
240+
display: flex;
241+
justify-content: center;
242+
}
243+
244+
#gradient-border-input {
245+
display: none;
246+
min-width: 0;
247+
}
248+
232249
#degree {
233250
display: flex;
234251
flex-direction: column;
235252
background-color: var(--primary-color);
236253
padding: 0.8rem;
254+
margin-top: 2rem;
255+
border-radius: 5px;
256+
width: min(45%, 55%);
257+
}
258+
259+
.radius {
260+
text-align: center;
261+
background-color: var(--primary-color);
262+
padding: 0.8rem;
237263
border-radius: 5px;
238264
width: min(45%, 55%);
239265
}
@@ -310,6 +336,58 @@ textarea {
310336
margin-bottom: auto;
311337
}
312338

339+
.gradient-border {
340+
visibility: hidden;
341+
position: relative;
342+
width: var(--output-width);
343+
height: 300px;
344+
word-wrap: break-word;
345+
margin-bottom: 1rem;
346+
}
347+
348+
/*
349+
* NOTE: The border-radius property is not supported with border-image, therefore,
350+
* the css for the gradient-border below relies on CSS Mask property applied to a pseudo background.
351+
*
352+
* The code below uses a trick based on using a pseudo element to circumvent
353+
* the restriction posed by using border-image.
354+
* 1. The before pseudo element represents the background-image placed on the .gradient-border div.
355+
* We apply a gradient as background and we make its origin the border box
356+
* (by default it's the padding box).
357+
* 2. Using the mask property, we apply two opaque layers.
358+
* The bottom one will cover the whole element and
359+
* the top one will cover only the content box (so it will not cover the border area).
360+
* 3. Using the mask-composite property, we exclude the content area from the border area
361+
* so that only the border will remain visible.
362+
* 4. -webkit-mask-composite: xor; this line is required for compatibility with Chrome browser.
363+
@demo: https://stackoverflow.com/questions/51496204/border-gradient-with-border-radius
364+
@credit: https://dev.to/afif/border-with-gradient-and-radius-387f
365+
*/
366+
367+
.gradient-border::before {
368+
content: '';
369+
position: absolute;
370+
inset: 0;
371+
border-radius: var(--gradient-border-radius);
372+
padding: 6px;
373+
background: linear-gradient(
374+
var(--gradient-border-degree, 45deg),
375+
var(--gradient-border-color-1, red),
376+
var(--gradient-border-color-2, blue)
377+
)
378+
border-box;
379+
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
380+
-webkit-mask-composite: xor;
381+
mask-composite: exclude;
382+
}
383+
384+
.bg-output {
385+
width: var(--output-width);
386+
height: 300px;
387+
word-wrap: break-word;
388+
margin-bottom: 1rem;
389+
}
390+
313391
.download-output > p {
314392
font-size: 0.7rem;
315393
}

0 commit comments

Comments
 (0)