Date pickers, form alignment, and input patterns.
<form method="post">
{% csrf_token %}
<div class="form-row">
<div class="form-group">
<label for="full_name">Full Name</label>
<input type="text" id="full_name" name="full_name"
class="vTextField" placeholder="Jane Smith">
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" name="email"
class="vTextField" placeholder="jane@example.com">
<span class="helptext">Help text below input</span>
</div>
</div>
<div class="form-row">
<div class="form-group">
<label for="bio">Bio</label>
<textarea id="bio" name="bio" class="vLargeTextField"
rows="3" placeholder="..."></textarea>
</div>
</div>
<div class="form-row" style="margin-top: 16px;">
<button type="button" class="button button-secondary">Cancel</button>
<button type="submit" class="button button-primary">Save</button>
</div>
</form>
<form method="post">
{% csrf_token %}
<div class="form-row form-row-2col">
<div class="form-group">
<label for="first_name">First Name</label>
<input type="text" id="first_name" name="first_name"
class="vTextField" placeholder="Jane">
</div>
<div class="form-group">
<label for="last_name">Last Name</label>
<input type="text" id="last_name" name="last_name"
class="vTextField" placeholder="Smith">
</div>
</div>
<div class="form-row form-row-2col">
<div class="form-group">
<label for="department">Department</label>
<select id="department" name="department" class="vTextField">
<option value="">Choose...</option>
<option value="eng">Engineering</option>
</select>
</div>
<div class="form-group">
<label for="role">Role</label>
<select id="role" name="role" class="vTextField">
<option value="">Choose...</option>
<option value="ic">Individual Contributor</option>
</select>
</div>
</div>
<div class="form-row" style="margin-top: 16px;">
<button type="button" class="button button-secondary">Cancel</button>
<button type="submit" class="button button-primary">Save</button>
</div>
</form>
<!-- Include admin widgets CSS in extra_css block -->
<link rel="stylesheet" href="{% static 'admin/css/widgets.css' %}">
<div class="form-row form-row-2col">
<div class="form-group">
<label for="start_date">Start Date</label>
<div class="date-input-wrapper">
<input type="date" id="start_date" name="start_date"
class="vTextField vDateField">
<button type="button" class="date-picker-btn"
data-target="start_date" aria-label="Open calendar">
<svg viewBox="0 0 24 24" width="20" height="20"
fill="currentColor">
<path d="M19 3h-1V1h-2v2H8V1H6v2H5c-1.11 0-1.99
.9-1.99 2L3 19c0 1.1.89 2 2 2h14c1.1 0 2-.9
2-2V5c0-1.1-.9-2-2-2zm0 16H5V8h14v11z..."/>
</svg>
</button>
</div>
<span class="helptext">Click the calendar icon</span>
</div>
<div class="form-group">
<label for="end_date">End Date</label>
<div class="date-input-wrapper">
<input type="date" id="end_date" name="end_date"
class="vTextField vDateField">
<button type="button" class="date-picker-btn"
data-target="end_date">...</button>
</div>
</div>
</div>
<!-- datetime-local for combined date+time -->
<input type="datetime-local" id="meeting_time"
class="vTextField vDateField">
<!-- JS for date picker buttons (add to extra_js block) -->
<script>
document.querySelectorAll('.date-picker-btn').forEach(function(btn) {
btn.addEventListener('click', function() {
var input = document.getElementById(this.dataset.target);
if (input.showPicker) {
input.showPicker();
} else {
input.focus();
input.click();
}
});
});
</script>
<!-- Basic file input -->
<input type="file" id="attachment" name="attachment" class="vTextField">
<!-- Drag & drop upload zone -->
<div class="file-upload-wrapper">
<div class="file-upload-dropzone" id="avatar-dropzone">
<svg viewBox="0 0 24 24" width="32" height="32"
fill="currentColor"
style="color: var(--body-quiet-color);">
<path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2
2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5
3.01L14.5 12l4.5 6H5l3.5-4.5z"/>
</svg>
<span class="dropzone-text">
Drag & drop an image or click to browse
</span>
<span class="dropzone-filename" id="avatar-filename"
style="display: none;"></span>
<input type="file" id="avatar" name="avatar"
accept="image/*" class="file-upload-input">
</div>
</div>
<!-- CSS needed (add to extra_css block) -->
<style>
.file-upload-wrapper { width: 100%; }
.file-upload-dropzone {
position: relative;
display: flex; flex-direction: column;
align-items: center; justify-content: center;
gap: 8px; padding: 24px 16px;
border: 2px dashed var(--card-border);
border-radius: var(--radius-md);
background: var(--body-bg); cursor: pointer;
}
.file-upload-dropzone:hover,
.file-upload-dropzone.dragover {
border-color: var(--primary);
background: color-mix(in srgb, var(--primary) 5%, var(--body-bg));
}
.file-upload-input {
position: absolute; inset: 0;
width: 100%; height: 100%;
opacity: 0; cursor: pointer;
}
</style>
<!-- JS for dropzone (add to extra_js block) -->
<script>
document.querySelectorAll('.file-upload-dropzone')
.forEach(function(zone) {
var input = zone.querySelector('.file-upload-input');
var text = zone.querySelector('.dropzone-text');
var filename = zone.querySelector('.dropzone-filename');
input.addEventListener('change', function() {
if (this.files.length > 0) {
text.style.display = 'none';
filename.textContent = this.files[0].name;
filename.style.display = '';
}
});
zone.addEventListener('dragover', function(e) {
e.preventDefault();
zone.classList.add('dragover');
});
zone.addEventListener('dragleave', function() {
zone.classList.remove('dragover');
});
zone.addEventListener('drop', function(e) {
e.preventDefault();
zone.classList.remove('dragover');
if (e.dataTransfer.files.length > 0) {
input.files = e.dataTransfer.files;
input.dispatchEvent(new Event('change'));
}
});
});
</script>
Choose the color mode for your app.
The accent color for your app.
Choose the font family that fits your app.
Choose the gray shade for your app.
Choose the border radius factor for your app.
Choose the page layout for your app.