This custom code is completely free to use, but please note it does not include 1-on-1 technical support. If you need a bespoke, done-for-you solution to customize your Shopify store, my team is here to help! Head to my channel homepage and use the link in the trailer to reach out.
{% comment %}
<!-- Designed by ONHOW Studio - Anas El Medlaoui -->
{% endcomment %}
{%- assign file_accept = 'image/*' -%}
{%- if section.settings.onhow_studio_file_mode == 'pdf' -%}
{%- assign file_accept = 'application/pdf' -%}
{%- elsif section.settings.onhow_studio_file_mode == 'all' -%}
{%- assign file_accept = '*' -%}
{%- endif -%}
<div
id="onhow-studio-upload-config"
data-mode="{{ section.settings.onhow_studio_file_mode }}"
data-accept="{{ file_accept }}"
data-label="{{ section.settings.onhow_studio_property_label | escape }}"
data-max-size="{{ section.settings.onhow_studio_max_file_size }}"
data-btn-text="{{ section.settings.onhow_studio_btn_text | escape }}"
data-helper-text="{{ section.settings.onhow_studio_helper_text | escape }}"
data-error-type="{{ section.settings.onhow_studio_error_type | escape }}"
data-error-size="{{ section.settings.onhow_studio_error_size | escape }}"
data-primary="{{ section.settings.onhow_studio_primary_color }}"
data-bg="{{ section.settings.onhow_studio_upload_bg_color }}"
data-radius="{{ section.settings.onhow_studio_border_radius }}"
data-border-style="{{ section.settings.onhow_studio_border_style }}"
data-text-input="{{ section.settings.onhow_studio_enable_text_input }}"
data-text-label="{{ section.settings.onhow_studio_text_input_label | escape }}"
hidden
></div>
{% schema %}
{
"name": "OnHOW Upload Config",
"settings": [
{
"type": "header",
"content": "✨ Built by ONHOW Studio"
},
{
"type": "paragraph",
"content": "Get free sections & tutorials at youtube.com/@ONHOWStudio"
},
{
"type": "text",
"id": "onhow_studio_core_logic",
"label": "Section Architecture (Do Not Edit)",
"default": "built-by-onhow-studio",
"info": "Modifying this will break the section's CSS layout."
},
{
"type": "header",
"content": "Functional"
},
{
"type": "select",
"id": "onhow_studio_file_mode",
"label": "File Type",
"options": [
{ "value": "image", "label": "Image only" },
{ "value": "pdf", "label": "PDF only" },
{ "value": "all", "label": "All files" }
],
"default": "image"
},
{
"type": "text",
"id": "onhow_studio_property_label",
"label": "Property Label",
"default": "Upload File",
"info": "Appears as the line item property name on the order"
},
{
"type": "range",
"id": "onhow_studio_max_file_size",
"label": "Max File Size (MB)",
"min": 1,
"max": 50,
"step": 1,
"default": 10
},
{
"type": "header",
"content": "UI Text"
},
{
"type": "text",
"id": "onhow_studio_btn_text",
"label": "Browse Button Text",
"default": "Browse Files"
},
{
"type": "text",
"id": "onhow_studio_helper_text",
"label": "Helper Text",
"default": "Drag & drop or click to upload"
},
{
"type": "text",
"id": "onhow_studio_error_type",
"label": "Wrong File Type Message",
"default": "Invalid file type."
},
{
"type": "text",
"id": "onhow_studio_error_size",
"label": "File Too Large Message",
"default": "File exceeds the maximum size."
},
{
"type": "header",
"content": "Text Input Field"
},
{
"type": "checkbox",
"id": "onhow_studio_enable_text_input",
"label": "Enable text input field",
"default": false
},
{
"type": "text",
"id": "onhow_studio_text_input_label",
"label": "Text Input Label",
"default": "Special Instructions",
"info": "Also used as the line item property name on the order"
},
{
"type": "header",
"content": "Visual"
},
{
"type": "color",
"id": "onhow_studio_primary_color",
"label": "Primary Color",
"default": "#000000"
},
{
"type": "color",
"id": "onhow_studio_upload_bg_color",
"label": "Upload Zone Background",
"default": "#f9f9f9"
},
{
"type": "range",
"id": "onhow_studio_border_radius",
"label": "Border Radius (px)",
"min": 0,
"max": 20,
"step": 1,
"default": 8
},
{
"type": "select",
"id": "onhow_studio_border_style",
"label": "Border Style",
"options": [
{ "value": "dashed", "label": "Dashed" },
{ "value": "solid", "label": "Solid" }
],
"default": "dashed"
}
],
"presets": [
{
"name": "OnHOW Upload Config (By ONHOW Studio)"
}
]
}
{% endschema %}
{% comment %}
<!-- Designed by ONHOW Studio - Anas El Medlaoui -->
{% endcomment %}
Block :
{% comment %}
<!-- Designed by ONHOW Studio - Anas El Medlaoui -->
{% endcomment %}
<div class="onhow-studio-upload-wrapper">
<div class="onhow-studio-upload-text-group onhow-studio-upload-hidden">
<label class="onhow-studio-upload-text-label" for="onhow-studio-upload-text-input"></label>
<input type="text" id="onhow-studio-upload-text-input" class="onhow-studio-upload-text-input" autocomplete="off">
</div>
<label class="onhow-studio-upload-label" for="onhow-studio-upload-input"></label>
<div class="onhow-studio-upload-zone">
<input
type="file"
id="onhow-studio-upload-input"
class="onhow-studio-upload-input"
>
<svg class="onhow-studio-upload-icon" xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<polyline points="16 16 12 12 8 16"></polyline>
<line x1="12" y1="12" x2="12" y2="21"></line>
<path d="M20.39 18.39A5 5 0 0 0 18 9h-1.26A8 8 0 1 0 3 16.3"></path>
</svg>
<span class="onhow-studio-upload-hint"></span>
<button type="button" class="onhow-studio-upload-btn"></button>
</div>
<div class="onhow-studio-upload-preview onhow-studio-upload-hidden">
<img class="onhow-studio-upload-img" src="" alt="Uploaded image preview">
<div class="onhow-studio-upload-card">
<svg class="onhow-studio-upload-card-icon" xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
</svg>
<div class="onhow-studio-upload-card-info">
<span class="onhow-studio-upload-card-name"></span>
<span class="onhow-studio-upload-card-size"></span>
</div>
</div>
<button type="button" class="onhow-studio-upload-remove" aria-label="Remove file">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<line x1="18" y1="6" x2="6" y2="18"></line>
<line x1="6" y1="6" x2="18" y2="18"></line>
</svg>
</button>
</div>
<p class="onhow-studio-upload-error onhow-studio-upload-hidden" role="alert"></p>
</div>
<style>
.onhow-studio-upload-wrapper {
--onhow-studio-upload-primary: #000000;
--onhow-studio-upload-bg: #f9f9f9;
--onhow-studio-upload-radius: 8px;
--onhow-studio-upload-border-style: dashed;
display: block;
width: 100%;
font-family: inherit;
margin-block: 0;
}
.onhow-studio-upload-label {
display: block;
font-size: 0.875rem;
font-weight: 600;
margin-bottom: 0.5rem;
color: currentColor;
}
.onhow-studio-upload-zone {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 0.5rem;
padding: 1.25rem 1.5rem;
border: 2px var(--onhow-studio-upload-border-style) rgba(0, 0, 0, 0.2);
border-radius: var(--onhow-studio-upload-radius);
background-color: var(--onhow-studio-upload-bg);
cursor: pointer;
transition: border-color 0.2s ease, background-color 0.2s ease;
}
.onhow-studio-upload-zone:hover {
border-color: var(--onhow-studio-upload-primary);
}
.onhow-studio-upload-zone.onhow-studio-upload-drag-over {
border-color: var(--onhow-studio-upload-primary);
background-color: var(--onhow-studio-upload-bg);
opacity: 0.75;
}
.onhow-studio-upload-input {
display: none;
}
.onhow-studio-upload-icon {
color: var(--onhow-studio-upload-primary);
opacity: 0.5;
}
.onhow-studio-upload-hint {
font-size: 0.8125rem;
color: currentColor;
opacity: 0.55;
text-align: center;
}
.onhow-studio-upload-btn {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.4375rem 1.125rem;
margin-top: 0.25rem;
font-size: 0.8125rem;
font-weight: 600;
font-family: inherit;
border: 1.5px solid var(--onhow-studio-upload-primary);
border-radius: var(--onhow-studio-upload-radius);
background: transparent;
color: var(--onhow-studio-upload-primary);
cursor: pointer;
transition: background-color 0.2s ease, color 0.2s ease;
}
.onhow-studio-upload-btn:hover {
background-color: var(--onhow-studio-upload-primary);
color: #ffffff;
}
.onhow-studio-upload-preview {
position: relative;
width: 100%;
border-radius: var(--onhow-studio-upload-radius);
overflow: hidden;
}
.onhow-studio-upload-img {
display: block;
width: 100%;
height: auto;
max-height: 280px;
object-fit: contain;
border-radius: var(--onhow-studio-upload-radius);
background-color: var(--onhow-studio-upload-bg);
}
.onhow-studio-upload-card {
display: flex;
align-items: center;
gap: 0.75rem;
padding: 1rem;
border: 2px var(--onhow-studio-upload-border-style) var(--onhow-studio-upload-primary);
border-radius: var(--onhow-studio-upload-radius);
background-color: var(--onhow-studio-upload-bg);
}
.onhow-studio-upload-card-icon {
color: var(--onhow-studio-upload-primary);
flex-shrink: 0;
}
.onhow-studio-upload-card-info {
display: flex;
flex-direction: column;
gap: 0.125rem;
min-width: 0;
flex: 1;
}
.onhow-studio-upload-card-name {
display: block;
font-size: 0.875rem;
font-weight: 600;
color: currentColor;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.onhow-studio-upload-card-size {
display: block;
font-size: 0.75rem;
opacity: 0.55;
color: currentColor;
}
.onhow-studio-upload-remove {
position: absolute;
top: 0.5rem;
right: 0.5rem;
display: flex;
align-items: center;
justify-content: center;
width: 1.75rem;
height: 1.75rem;
padding: 0;
border: none;
border-radius: 50%;
background-color: rgba(0, 0, 0, 0.6);
color: #ffffff;
cursor: pointer;
transition: background-color 0.2s ease;
}
.onhow-studio-upload-remove:hover {
background-color: rgba(0, 0, 0, 0.85);
}
.onhow-studio-upload-error {
margin-top: 0.5rem;
margin-bottom: 0;
font-size: 0.8125rem;
color: #c0392b;
}
.onhow-studio-upload-wrapper .onhow-studio-upload-hidden {
display: none;
}
.onhow-studio-upload-text-group {
margin-bottom: 0.75rem;
}
.onhow-studio-upload-text-label {
display: block;
font-size: 0.875rem;
font-weight: 600;
margin-bottom: 0.5rem;
color: currentColor;
}
.onhow-studio-upload-wrapper .onhow-studio-upload-text-input {
display: block;
width: 100%;
padding: 0.625rem 0.75rem;
font-size: 0.875rem;
font-family: inherit;
color: currentColor;
background: transparent;
border: 1.5px solid rgba(0, 0, 0, 0.2);
border-radius: var(--onhow-studio-upload-radius);
outline: none;
box-sizing: border-box;
transition: border-color 0.2s ease;
-webkit-appearance: none;
appearance: none;
}
.onhow-studio-upload-wrapper .onhow-studio-upload-text-input:focus {
border-color: var(--onhow-studio-upload-primary);
}
.onhow-studio-upload-wrapper .onhow-studio-upload-text-input::placeholder {
opacity: 0.4;
}
</style>
<script>
document.addEventListener('DOMContentLoaded', function () {
(function() {
var onhowStudioCredit = atob("RGVzaWduZWQgYnkgT05IT1cgU3R1ZGlvIC0gU3Vic2NyaWJlIQ==");
console.log('%c ' + onhowStudioCredit, 'background: #222; color: #00ff00; padding: 4px; border-radius: 4px;');
})();
var config = document.getElementById('onhow-studio-upload-config');
if (!config) return;
var wrapper = document.querySelector('.onhow-studio-upload-wrapper');
if (!wrapper) return;
var productForm = document.querySelector('form[action*="/cart/add"]');
if (!productForm) return;
var mode = config.dataset.mode;
var accept = config.dataset.accept;
var label = config.dataset.label;
var maxSize = parseInt(config.dataset.maxSize, 10);
var btnText = config.dataset.btnText;
var helperText = config.dataset.helperText;
var errorType = config.dataset.errorType;
var errorSize = config.dataset.errorSize;
var textEnabled = config.dataset.textInput === 'true';
var textLabel = config.dataset.textLabel;
wrapper.style.setProperty('--onhow-studio-upload-primary', config.dataset.primary);
wrapper.style.setProperty('--onhow-studio-upload-bg', config.dataset.bg);
wrapper.style.setProperty('--onhow-studio-upload-radius', config.dataset.radius + 'px');
wrapper.style.setProperty('--onhow-studio-upload-border-style', config.dataset.borderStyle);
var labelEl = wrapper.querySelector('.onhow-studio-upload-label');
var zone = wrapper.querySelector('.onhow-studio-upload-zone');
var input = wrapper.querySelector('.onhow-studio-upload-input');
var hint = wrapper.querySelector('.onhow-studio-upload-hint');
var btn = wrapper.querySelector('.onhow-studio-upload-btn');
var preview = wrapper.querySelector('.onhow-studio-upload-preview');
var imgEl = wrapper.querySelector('.onhow-studio-upload-img');
var card = wrapper.querySelector('.onhow-studio-upload-card');
var cardName = wrapper.querySelector('.onhow-studio-upload-card-name');
var cardSize = wrapper.querySelector('.onhow-studio-upload-card-size');
var removeBtn = wrapper.querySelector('.onhow-studio-upload-remove');
var errorEl = wrapper.querySelector('.onhow-studio-upload-error');
var textGroup = wrapper.querySelector('.onhow-studio-upload-text-group');
var textLabelEl = wrapper.querySelector('.onhow-studio-upload-text-label');
var textInput = wrapper.querySelector('.onhow-studio-upload-text-input');
if (textEnabled) {
textLabelEl.textContent = textLabel;
textInput.placeholder = textLabel;
textGroup.classList.remove('onhow-studio-upload-hidden');
var hiddenText = document.createElement('input');
hiddenText.type = 'text';
hiddenText.id = 'onhow-studio-upload-hidden-text';
hiddenText.name = 'properties[' + textLabel + ']';
hiddenText.style.display = 'none';
productForm.appendChild(hiddenText);
textInput.addEventListener('input', function () {
hiddenText.value = textInput.value;
});
}
labelEl.textContent = label;
hint.textContent = helperText;
btn.textContent = btnText;
input.setAttribute('name', 'properties[' + label + ']');
input.setAttribute('accept', accept);
if (mode === 'image') {
card.classList.add('onhow-studio-upload-hidden');
} else {
imgEl.classList.add('onhow-studio-upload-hidden');
}
function formatSize(bytes) {
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' KB';
return (bytes / (1024 * 1024)).toFixed(1) + ' MB';
}
function showError(msg) {
errorEl.textContent = msg;
errorEl.classList.remove('onhow-studio-upload-hidden');
}
function clearError() {
errorEl.textContent = '';
errorEl.classList.add('onhow-studio-upload-hidden');
}
function clearPreview() {
removeHiddenInput();
preview.classList.add('onhow-studio-upload-hidden');
zone.classList.remove('onhow-studio-upload-hidden');
imgEl.src = '';
cardName.textContent = '';
cardSize.textContent = '';
input.value = '';
}
function validateFile(file) {
if (accept !== '*') {
var types = accept.split(',').map(function (t) { return t.trim(); });
var valid = types.some(function (t) {
if (t.slice(-2) === '/*') return file.type.startsWith(t.slice(0, -2));
return file.type === t;
});
if (!valid) { showError(errorType); return false; }
}
if (file.size > maxSize * 1024 * 1024) { showError(errorSize); return false; }
return true;
}
function injectHiddenInput(file) {
var existing = productForm.querySelector('#onhow-studio-upload-hidden');
if (existing) existing.remove();
var hidden = document.createElement('input');
hidden.type = 'file';
hidden.id = 'onhow-studio-upload-hidden';
hidden.name = 'properties[' + label + ']';
hidden.style.display = 'none';
var dt = new DataTransfer();
dt.items.add(file);
hidden.files = dt.files;
productForm.appendChild(hidden);
}
function removeHiddenInput() {
var existing = productForm.querySelector('#onhow-studio-upload-hidden');
if (existing) existing.remove();
}
function handleFile(file) {
clearError();
if (!validateFile(file)) { clearPreview(); return; }
injectHiddenInput(file);
if (mode === 'image') {
var reader = new FileReader();
reader.onload = function (e) {
imgEl.src = e.target.result;
zone.classList.add('onhow-studio-upload-hidden');
preview.classList.remove('onhow-studio-upload-hidden');
};
reader.readAsDataURL(file);
} else {
cardName.textContent = file.name;
cardSize.textContent = formatSize(file.size);
zone.classList.add('onhow-studio-upload-hidden');
preview.classList.remove('onhow-studio-upload-hidden');
}
}
input.addEventListener('change', function () {
if (this.files[0]) handleFile(this.files[0]);
});
removeBtn.addEventListener('click', clearPreview);
zone.addEventListener('click', function () {
input.click();
});
btn.addEventListener('click', function (e) {
e.stopPropagation();
input.click();
});
zone.addEventListener('dragover', function (e) {
e.preventDefault();
zone.classList.add('onhow-studio-upload-drag-over');
});
zone.addEventListener('dragleave', function () {
zone.classList.remove('onhow-studio-upload-drag-over');
});
zone.addEventListener('drop', function (e) {
e.preventDefault();
zone.classList.remove('onhow-studio-upload-drag-over');
var file = e.dataTransfer.files[0];
if (!file) return;
var dt = new DataTransfer();
dt.items.add(file);
input.files = dt.files;
handleFile(file);
});
});
</script>
{% comment %}
<!-- Designed by ONHOW Studio - Anas El Medlaoui -->
{% endcomment %}

