vanta-admin 0.7.0__tar.gz → 0.8.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. {vanta_admin-0.7.0/vanta_admin.egg-info → vanta_admin-0.8.0}/PKG-INFO +5 -3
  2. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/README.md +4 -2
  3. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/pyproject.toml +1 -1
  4. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/static/admin/css/theme.admin.css +262 -10
  5. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/static/admin/css/theme.responsive.css +4 -0
  6. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/static/admin/css/two_factor.css +49 -1
  7. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/static/admin/js/sidebar.js +156 -0
  8. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/templates/admin/nav_sidebar.html +30 -1
  9. vanta_admin-0.8.0/vanta_admin/templates/two_factor/profile/disable.html +25 -0
  10. {vanta_admin-0.7.0 → vanta_admin-0.8.0/vanta_admin.egg-info}/PKG-INFO +5 -3
  11. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin.egg-info/SOURCES.txt +1 -0
  12. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/LICENSE +0 -0
  13. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/MANIFEST.in +0 -0
  14. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/setup.cfg +0 -0
  15. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/__init__.py +0 -0
  16. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/apps.py +0 -0
  17. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/static/admin/css/theme.base.css +0 -0
  18. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/static/admin/css/theme.css +0 -0
  19. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/static/admin/css/theme.login.css +0 -0
  20. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/static/admin/css/theme.tokens.css +0 -0
  21. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/static/admin/img/favicon.png +0 -0
  22. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/static/admin/js/changelist.js +0 -0
  23. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/static/admin/js/forms.js +0 -0
  24. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/static/admin/js/messages.js +0 -0
  25. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/static/admin/js/vanta-theme.js +0 -0
  26. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/templates/admin/app_index.html +0 -0
  27. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/templates/admin/base.html +0 -0
  28. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/templates/admin/base_site.html +0 -0
  29. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/templates/admin/change_form.html +0 -0
  30. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/templates/admin/change_list.html +0 -0
  31. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/templates/admin/filter.html +0 -0
  32. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/templates/admin/includes/breadcrumbs.html +0 -0
  33. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/templates/admin/index.html +0 -0
  34. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/templates/admin/login.html +0 -0
  35. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/templates/two_factor/_base.html +0 -0
  36. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/templates/two_factor/_base_focus.html +0 -0
  37. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/templates/two_factor/_wizard_actions.html +0 -0
  38. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/templates/two_factor/core/login.html +0 -0
  39. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/templates/two_factor/core/setup_complete.html +0 -0
  40. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/templates/two_factor/profile/profile.html +0 -0
  41. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/templatetags/__init__.py +0 -0
  42. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin/templatetags/admin_theme.py +0 -0
  43. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin.egg-info/dependency_links.txt +0 -0
  44. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin.egg-info/requires.txt +0 -0
  45. {vanta_admin-0.7.0 → vanta_admin-0.8.0}/vanta_admin.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vanta-admin
3
- Version: 0.7.0
3
+ Version: 0.8.0
4
4
  Summary: A sharp, dark, and portable Django admin theme forged for builders who want the admin to feel less default.
5
5
  Author: oli-dev0
6
6
  License-Expression: MIT
@@ -36,6 +36,8 @@ feels more deliberate in everyday use.
36
36
 
37
37
  - A cleaner admin layout with a fixed sidebar that remembers how you left it.
38
38
  - A sidebar navigation filter that lets users quickly narrow large admin menus by app or model name.
39
+ - A resizable desktop sidebar that remembers each user's preferred width in the browser.
40
+ - A sidebar expand/collapse-all control for quickly opening or closing visible navigation sections.
39
41
  - Light and dark mode, using the same calm Vanta look across the admin.
40
42
  - A more settled light-mode palette with clearer search focus states and stronger changelist table headers.
41
43
  - Less visual noise on the main admin screens, login pages, cards, filters, and
@@ -58,7 +60,7 @@ feels more deliberate in everyday use.
58
60
  multi-select fields stay unchanged.
59
61
  - Built-in icons for common admin areas, models, and recent actions.
60
62
  - A cleaner account menu with display preferences, project links, password
61
- access, logout, and a Vanta support link.
63
+ access, 2FA settings, logout, and a Vanta support link.
62
64
  - A 12-hour and 24-hour time-format preference for changelist date/time values,
63
65
  stored in the browser for each admin user.
64
66
  - Shorter changelist date formatting that makes date-heavy tables easier to
@@ -68,7 +70,7 @@ feels more deliberate in everyday use.
68
70
  - A mobile sidebar overlay that makes the admin easier to use on smaller
69
71
  screens.
70
72
  - Optional matching templates for `django-two-factor-auth` login, setup
71
- completion, account security, and backup-token screens.
73
+ completion, account security, disable confirmation, and backup-token screens.
72
74
 
73
75
  Vanta Admin does not replace Django admin, change your permissions, or configure
74
76
  two-factor authentication for you. If your project uses `django-two-factor-auth`,
@@ -11,6 +11,8 @@ feels more deliberate in everyday use.
11
11
 
12
12
  - A cleaner admin layout with a fixed sidebar that remembers how you left it.
13
13
  - A sidebar navigation filter that lets users quickly narrow large admin menus by app or model name.
14
+ - A resizable desktop sidebar that remembers each user's preferred width in the browser.
15
+ - A sidebar expand/collapse-all control for quickly opening or closing visible navigation sections.
14
16
  - Light and dark mode, using the same calm Vanta look across the admin.
15
17
  - A more settled light-mode palette with clearer search focus states and stronger changelist table headers.
16
18
  - Less visual noise on the main admin screens, login pages, cards, filters, and
@@ -33,7 +35,7 @@ feels more deliberate in everyday use.
33
35
  multi-select fields stay unchanged.
34
36
  - Built-in icons for common admin areas, models, and recent actions.
35
37
  - A cleaner account menu with display preferences, project links, password
36
- access, logout, and a Vanta support link.
38
+ access, 2FA settings, logout, and a Vanta support link.
37
39
  - A 12-hour and 24-hour time-format preference for changelist date/time values,
38
40
  stored in the browser for each admin user.
39
41
  - Shorter changelist date formatting that makes date-heavy tables easier to
@@ -43,7 +45,7 @@ feels more deliberate in everyday use.
43
45
  - A mobile sidebar overlay that makes the admin easier to use on smaller
44
46
  screens.
45
47
  - Optional matching templates for `django-two-factor-auth` login, setup
46
- completion, account security, and backup-token screens.
48
+ completion, account security, disable confirmation, and backup-token screens.
47
49
 
48
50
  Vanta Admin does not replace Django admin, change your permissions, or configure
49
51
  two-factor authentication for you. If your project uses `django-two-factor-auth`,
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "vanta-admin"
7
- version = "0.7.0"
7
+ version = "0.8.0"
8
8
  description = "A sharp, dark, and portable Django admin theme forged for builders who want the admin to feel less default."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -5,7 +5,9 @@
5
5
  top: 0;
6
6
  z-index: 20;
7
7
  display: flex;
8
+ flex: 0 0 var(--admin-sidebar-width);
8
9
  width: var(--admin-sidebar-width);
10
+ min-width: var(--admin-sidebar-width);
9
11
  min-height: 100vh;
10
12
  max-height: 100vh;
11
13
  flex-direction: column;
@@ -14,6 +16,82 @@
14
16
  transition: width 160ms var(--ease), transform 160ms var(--ease);
15
17
  }
16
18
 
19
+ .admin-sidebar__resize-handle {
20
+ position: absolute;
21
+ top: 0;
22
+ right: -0.34rem;
23
+ z-index: 4;
24
+ width: 0.68rem;
25
+ height: 100%;
26
+ cursor: ew-resize;
27
+ touch-action: none;
28
+ }
29
+
30
+ .admin-sidebar__resize-handle::before,
31
+ .admin-sidebar__resize-handle::after {
32
+ content: "";
33
+ position: absolute;
34
+ opacity: 0;
35
+ transition:
36
+ opacity var(--admin-transition),
37
+ background-color var(--admin-transition),
38
+ transform var(--admin-transition);
39
+ }
40
+
41
+ .admin-sidebar__resize-handle::before {
42
+ top: 50%;
43
+ right: 0.5rem;
44
+ z-index: 2;
45
+ width: 0.3rem;
46
+ height: 1.35rem;
47
+ border-radius: 999px;
48
+ background: color-mix(in srgb, var(--admin-muted) 70%, var(--admin-border-strong));
49
+ transform: translateY(-50%);
50
+ }
51
+
52
+ .admin-sidebar__resize-handle::after {
53
+ top: 0.85rem;
54
+ right: 0.26rem;
55
+ bottom: 0.85rem;
56
+ z-index: 1;
57
+ width: 1px;
58
+ border-radius: 999px;
59
+ background: transparent;
60
+ }
61
+
62
+ .admin-sidebar__resize-handle:hover::before,
63
+ .admin-sidebar__resize-handle:focus-visible::before,
64
+ body.admin-sidebar-resizing .admin-sidebar__resize-handle::before,
65
+ .admin-sidebar__resize-handle:hover::after,
66
+ .admin-sidebar__resize-handle:focus-visible::after,
67
+ body.admin-sidebar-resizing .admin-sidebar__resize-handle::after {
68
+ opacity: 1;
69
+ }
70
+
71
+ .admin-sidebar__resize-handle:hover::after,
72
+ .admin-sidebar__resize-handle:focus-visible::after,
73
+ body.admin-sidebar-resizing .admin-sidebar__resize-handle::after {
74
+ background: color-mix(in srgb, var(--admin-border-strong) 80%, var(--admin-muted));
75
+ }
76
+
77
+ .admin-sidebar__resize-handle:focus-visible {
78
+ outline: none;
79
+ }
80
+
81
+ body.admin-sidebar-collapsed .admin-sidebar__resize-handle {
82
+ display: none;
83
+ }
84
+
85
+ body.admin-sidebar-resizing,
86
+ body.admin-sidebar-resizing * {
87
+ cursor: ew-resize !important;
88
+ user-select: none;
89
+ }
90
+
91
+ body.admin-sidebar-resizing .admin-sidebar {
92
+ transition: none;
93
+ }
94
+
17
95
  .admin-sidebar__brand-row,
18
96
  .admin-sidebar-header {
19
97
  display: flex;
@@ -114,14 +192,17 @@ body.admin-sidebar-collapsed .admin-sidebar__collapse-arrow {
114
192
 
115
193
  .admin-sidebar__filter {
116
194
  position: relative;
117
- display: flex;
195
+ display: grid;
196
+ grid-template-columns: minmax(0, 1fr) 2rem;
118
197
  align-items: center;
198
+ gap: 0.55rem;
119
199
  padding: 0.85rem 1rem 0;
120
200
  }
121
201
 
122
202
  .admin-sidebar__filter::before {
123
203
  content: "";
124
204
  position: absolute;
205
+ top: calc(0.85rem + 1rem);
125
206
  left: 1.72rem;
126
207
  width: 0.95rem;
127
208
  height: 0.95rem;
@@ -129,6 +210,7 @@ body.admin-sidebar-collapsed .admin-sidebar__collapse-arrow {
129
210
  mask: url("../img/search.svg") center / contain no-repeat;
130
211
  -webkit-mask: url("../img/search.svg") center / contain no-repeat;
131
212
  pointer-events: none;
213
+ transform: translateY(-50%);
132
214
  }
133
215
 
134
216
  #nav-sidebar .admin-sidebar__filter input[type="search"] {
@@ -147,6 +229,46 @@ body.admin-sidebar-collapsed .admin-sidebar__collapse-arrow {
147
229
  color var(--admin-transition);
148
230
  }
149
231
 
232
+ .admin-sidebar__sections-toggle {
233
+ display: inline-grid;
234
+ place-items: center;
235
+ width: 2rem;
236
+ min-width: 2rem;
237
+ height: 2rem;
238
+ border: 0;
239
+ border-radius: 0.27rem;
240
+ background: var(--surface-muted);
241
+ color: var(--accent);
242
+ cursor: pointer;
243
+ transition:
244
+ background-color var(--admin-transition),
245
+ color var(--admin-transition),
246
+ transform var(--admin-transition);
247
+ }
248
+
249
+ .admin-sidebar__sections-toggle svg {
250
+ width: 1.12rem;
251
+ height: 1.12rem;
252
+ stroke-width: 2.45;
253
+ transition: transform var(--admin-transition);
254
+ }
255
+
256
+ .admin-sidebar__sections-toggle.is-collapse-mode svg {
257
+ transform: rotate(180deg);
258
+ }
259
+
260
+ .admin-sidebar__sections-toggle:hover,
261
+ .admin-sidebar__sections-toggle:focus-visible {
262
+ background: var(--surface);
263
+ color: var(--accent-strong);
264
+ outline: none;
265
+ transform: translateY(-2px);
266
+ }
267
+
268
+ .admin-sidebar__sections-toggle:active {
269
+ transform: translateY(0);
270
+ }
271
+
150
272
  #nav-sidebar .admin-sidebar__filter input[type="search"]::placeholder {
151
273
  color: var(--admin-muted);
152
274
  opacity: 0.82;
@@ -511,8 +633,8 @@ html[data-theme="light"] .admin-sidebar__time-button[aria-pressed="true"] {
511
633
  align-items: center;
512
634
  gap: 0.68rem;
513
635
  width: 100%;
514
- min-height: 2.22rem;
515
- padding: 0.46rem;
636
+ min-height: 2rem;
637
+ padding: 0.34rem 0.46rem;
516
638
  border: 0;
517
639
  border-radius: 0.28rem;
518
640
  background: transparent;
@@ -1099,6 +1221,48 @@ fieldset.module,
1099
1221
  transform: none;
1100
1222
  }
1101
1223
 
1224
+ .helptext,
1225
+ .help {
1226
+ color: var(--admin-muted);
1227
+ font-size: 0.82rem;
1228
+ line-height: 1.12;
1229
+ }
1230
+
1231
+ ul.helptext,
1232
+ .help ul {
1233
+ display: grid;
1234
+ gap: 0.06rem;
1235
+ margin: 0;
1236
+ padding: 0;
1237
+ list-style: none;
1238
+ }
1239
+
1240
+ ul.helptext li,
1241
+ .help li {
1242
+ position: relative;
1243
+ margin: 0;
1244
+ padding-left: 0.95rem;
1245
+ }
1246
+
1247
+ fieldset.module .form-row .help li,
1248
+ fieldset.module .form-row ul.helptext li {
1249
+ line-height: 1.12;
1250
+ padding-top: 0;
1251
+ padding-bottom: 0;
1252
+ }
1253
+
1254
+ ul.helptext li::before,
1255
+ .help li::before {
1256
+ content: "";
1257
+ position: absolute;
1258
+ top: 0.36em;
1259
+ left: 0.12rem;
1260
+ width: 0.32rem;
1261
+ height: 0.32rem;
1262
+ border-radius: 999px;
1263
+ background: var(--admin-accent);
1264
+ }
1265
+
1102
1266
  .delete-confirmation form {
1103
1267
  display: flex;
1104
1268
  flex-wrap: wrap;
@@ -1785,6 +1949,94 @@ input[type="checkbox"]:focus-visible {
1785
1949
  padding: 0 0.8rem;
1786
1950
  }
1787
1951
 
1952
+ body:not(.change-form) .submit-row input[type="submit"],
1953
+ body:not(.change-form) .submit-row button,
1954
+ body:not(.change-form) .submit-row .button {
1955
+ display: inline-flex;
1956
+ align-items: center;
1957
+ justify-content: center;
1958
+ min-height: 2.05rem;
1959
+ margin: 0;
1960
+ padding: 0 0.8rem;
1961
+ border: 0;
1962
+ border-radius: 0.27rem;
1963
+ background: var(--admin-accent);
1964
+ color: var(--admin-button-text);
1965
+ cursor: pointer;
1966
+ font: inherit;
1967
+ font-size: 0.82rem;
1968
+ font-weight: 720;
1969
+ line-height: 1.2;
1970
+ text-decoration: none;
1971
+ box-shadow: none;
1972
+ transition:
1973
+ background-color var(--admin-transition),
1974
+ border-color var(--admin-transition),
1975
+ color var(--admin-transition),
1976
+ transform var(--admin-transition);
1977
+ }
1978
+
1979
+ body:not(.change-form) .submit-row input[type="submit"]:hover,
1980
+ body:not(.change-form) .submit-row input[type="submit"]:focus-visible,
1981
+ body:not(.change-form) .submit-row button:hover,
1982
+ body:not(.change-form) .submit-row button:focus-visible,
1983
+ body:not(.change-form) .submit-row .button:hover,
1984
+ body:not(.change-form) .submit-row .button:focus-visible {
1985
+ border-color: var(--admin-accent-border);
1986
+ background: var(--admin-accent-strong);
1987
+ color: var(--admin-button-text);
1988
+ filter: none;
1989
+ box-shadow: none;
1990
+ transform: translateY(-2px);
1991
+ }
1992
+
1993
+ body:not(.change-form) .submit-row input[type="submit"]:active,
1994
+ body:not(.change-form) .submit-row button:active,
1995
+ body:not(.change-form) .submit-row .button:active {
1996
+ transform: scale(0.97);
1997
+ }
1998
+
1999
+ html[data-theme="dark"] body:not(.change-form) .submit-row,
2000
+ body[data-theme="dark"]:not(.change-form) .submit-row,
2001
+ body.theme-dark:not(.change-form) .submit-row {
2002
+ background: #2c3435;
2003
+ }
2004
+
2005
+ html[data-theme="dark"] body:not(.change-form) .submit-row input[type="submit"],
2006
+ html[data-theme="dark"] body:not(.change-form) .submit-row button,
2007
+ html[data-theme="dark"] body:not(.change-form) .submit-row .button,
2008
+ body[data-theme="dark"]:not(.change-form) .submit-row input[type="submit"],
2009
+ body[data-theme="dark"]:not(.change-form) .submit-row button,
2010
+ body[data-theme="dark"]:not(.change-form) .submit-row .button,
2011
+ body.theme-dark:not(.change-form) .submit-row input[type="submit"],
2012
+ body.theme-dark:not(.change-form) .submit-row button,
2013
+ body.theme-dark:not(.change-form) .submit-row .button {
2014
+ background: var(--admin-accent);
2015
+ color: var(--admin-button-text);
2016
+ }
2017
+
2018
+ html[data-theme="dark"] body:not(.change-form) .submit-row input[type="submit"]:hover,
2019
+ html[data-theme="dark"] body:not(.change-form) .submit-row input[type="submit"]:focus-visible,
2020
+ html[data-theme="dark"] body:not(.change-form) .submit-row button:hover,
2021
+ html[data-theme="dark"] body:not(.change-form) .submit-row button:focus-visible,
2022
+ html[data-theme="dark"] body:not(.change-form) .submit-row .button:hover,
2023
+ html[data-theme="dark"] body:not(.change-form) .submit-row .button:focus-visible,
2024
+ body[data-theme="dark"]:not(.change-form) .submit-row input[type="submit"]:hover,
2025
+ body[data-theme="dark"]:not(.change-form) .submit-row input[type="submit"]:focus-visible,
2026
+ body[data-theme="dark"]:not(.change-form) .submit-row button:hover,
2027
+ body[data-theme="dark"]:not(.change-form) .submit-row button:focus-visible,
2028
+ body[data-theme="dark"]:not(.change-form) .submit-row .button:hover,
2029
+ body[data-theme="dark"]:not(.change-form) .submit-row .button:focus-visible,
2030
+ body.theme-dark:not(.change-form) .submit-row input[type="submit"]:hover,
2031
+ body.theme-dark:not(.change-form) .submit-row input[type="submit"]:focus-visible,
2032
+ body.theme-dark:not(.change-form) .submit-row button:hover,
2033
+ body.theme-dark:not(.change-form) .submit-row button:focus-visible,
2034
+ body.theme-dark:not(.change-form) .submit-row .button:hover,
2035
+ body.theme-dark:not(.change-form) .submit-row .button:focus-visible {
2036
+ background: var(--admin-accent-strong);
2037
+ color: var(--admin-button-text);
2038
+ }
2039
+
1788
2040
  #changelist .actions .admin-action-select__button,
1789
2041
  #changelist .actions .admin-action-select__option {
1790
2042
  font-size: 0.72rem;
@@ -1860,13 +2112,13 @@ input[type="checkbox"]:focus-visible {
1860
2112
  display: inline-flex;
1861
2113
  align-items: center;
1862
2114
  justify-content: center;
1863
- min-height: 1.82rem;
1864
- padding: 0.26rem 0.5rem;
2115
+ min-height: 1.55rem;
2116
+ padding: 0.22rem 0.43rem;
1865
2117
  border: 1px solid var(--admin-accent-border);
1866
2118
  border-radius: var(--admin-radius-sm);
1867
2119
  background: var(--admin-accent);
1868
2120
  color: var(--admin-button-text);
1869
- font-size: 0.88rem;
2121
+ font-size: 0.75rem;
1870
2122
  font-weight: 760;
1871
2123
  line-height: 1.2;
1872
2124
  text-decoration: none;
@@ -2679,8 +2931,8 @@ html[data-theme="light"] #changelist-filter {
2679
2931
  input:not([type="checkbox"]):not([type="radio"]):focus,
2680
2932
  textarea:focus,
2681
2933
  select:focus {
2682
- outline: 2px solid var(--accent);
2683
- outline-offset: 2px;
2934
+ outline: 1px solid var(--admin-accent-border);
2935
+ outline-offset: 1px;
2684
2936
  }
2685
2937
 
2686
2938
  :where(a, button, summary, input[type="submit"], input[type="button"], input[type="reset"]):focus:not(:focus-visible) {
@@ -2689,8 +2941,8 @@ select:focus {
2689
2941
  }
2690
2942
 
2691
2943
  :where(a, button, input:not([type="checkbox"]):not([type="radio"]), select, textarea, summary):focus-visible {
2692
- outline: 3px solid var(--admin-accent-soft);
2693
- outline-offset: 2px;
2944
+ outline: 1px solid var(--admin-accent-border);
2945
+ outline-offset: 1px;
2694
2946
  box-shadow: none;
2695
2947
  }
2696
2948
 
@@ -144,6 +144,10 @@
144
144
  transform: translateX(-100%);
145
145
  }
146
146
 
147
+ .admin-sidebar__resize-handle {
148
+ display: none;
149
+ }
150
+
147
151
  body.admin-sidebar-mobile-open .admin-sidebar {
148
152
  transform: translateX(0);
149
153
  }
@@ -44,11 +44,15 @@ body.vanta-two-factor {
44
44
  line-height: 1.2;
45
45
  text-decoration: none;
46
46
  white-space: nowrap;
47
+ transition:
48
+ color var(--admin-transition),
49
+ transform var(--admin-transition);
47
50
  }
48
51
 
49
52
  .vanta-two-factor-admin-link:hover,
50
53
  .vanta-two-factor-admin-link:focus-visible {
51
54
  color: var(--admin-link-strong);
55
+ transform: translateY(-2px);
52
56
  }
53
57
 
54
58
  .vanta-two-factor-admin-link__arrow {
@@ -58,6 +62,33 @@ body.vanta-two-factor {
58
62
  transform: translateY(-0.20rem);
59
63
  }
60
64
 
65
+ .vanta-two-factor-back-link {
66
+ display: inline-flex;
67
+ align-items: center;
68
+ gap: 0.18rem;
69
+ color: var(--admin-link);
70
+ font-size: 0.8rem;
71
+ font-weight: 700;
72
+ line-height: 1.2;
73
+ text-decoration: none;
74
+ transition:
75
+ color var(--admin-transition),
76
+ transform var(--admin-transition);
77
+ }
78
+
79
+ .vanta-two-factor-back-link:hover,
80
+ .vanta-two-factor-back-link:focus-visible {
81
+ color: var(--admin-link-strong);
82
+ transform: translateY(-2px);
83
+ }
84
+
85
+ .vanta-two-factor-back-link__arrow {
86
+ display: inline-block;
87
+ font-size: 1.08rem;
88
+ line-height: 1;
89
+ transform: translateY(-0.22rem);
90
+ }
91
+
61
92
 
62
93
  .vanta-two-factor-brand {
63
94
  display: inline-flex;
@@ -232,7 +263,7 @@ body.vanta-two-factor {
232
263
  .vanta-two-factor .btn-warning,
233
264
  .vanta-two-factor .btn-info {
234
265
  border-color: var(--admin-border-strong);
235
- background: var(--admin-surface-muted);
266
+ background: var(--input-bg);
236
267
  color: var(--admin-text);
237
268
  box-shadow: none;
238
269
  }
@@ -307,6 +338,8 @@ body.vanta-two-factor {
307
338
  .vanta-two-factor .btn-warning:focus-visible,
308
339
  .vanta-two-factor .btn-info:hover,
309
340
  .vanta-two-factor .btn-info:focus-visible {
341
+ background: var(--admin-surface-muted);
342
+ border-color: var(--admin-accent-border);
310
343
  box-shadow: none;
311
344
  }
312
345
 
@@ -342,6 +375,21 @@ body.vanta-two-factor {
342
375
  box-shadow: none;
343
376
  }
344
377
 
378
+ .vanta-two-factor a.float-right.btn-link {
379
+ border-color: var(--admin-border-strong);
380
+ background: var(--input-bg);
381
+ color: var(--admin-text);
382
+ padding-right: 0.82rem;
383
+ padding-left: 0.82rem;
384
+ }
385
+
386
+ .vanta-two-factor a.float-right.btn-link:hover,
387
+ .vanta-two-factor a.float-right.btn-link:focus-visible {
388
+ background: var(--admin-surface-muted);
389
+ color: var(--admin-text);
390
+ transform: translateY(-2px);
391
+ }
392
+
345
393
  .vanta-two-factor .btn-block {
346
394
  display: flex;
347
395
  width: 100%;
@@ -2,13 +2,19 @@
2
2
 
3
3
  {
4
4
  const sidebarStateKey = 'django.admin.theme.sidebar.isCollapsed';
5
+ const sidebarWidthStateKey = 'django.admin.theme.sidebar.width';
5
6
  const navSectionsStateKey = 'django.admin.theme.sidebar.openSections';
7
+ const minSidebarWidth = 220;
8
+ const maxSidebarWidth = 420;
9
+ const sidebarResizeStep = 16;
6
10
 
7
11
  const body = document.body;
8
12
  const root = document.documentElement;
9
13
  const sidebar = document.getElementById('nav-sidebar');
10
14
  const collapseButton = document.getElementById('admin-sidebar-collapse');
15
+ const resizeHandle = document.getElementById('admin-sidebar-resize-handle');
11
16
  const menuButton = document.getElementById('admin-sidebar-menu-button');
17
+ const sectionsToggle = document.getElementById('admin-sidebar-sections-toggle');
12
18
  const accountDetails = document.querySelector('.admin-sidebar__account');
13
19
  const navFilter = document.getElementById('admin-nav-filter');
14
20
  const mobileQuery = window.matchMedia('(max-width: 1024px)');
@@ -16,6 +22,50 @@
16
22
  const programmaticSectionToggles = new WeakSet();
17
23
  let filterBaselineOpenSections = null;
18
24
  let hadFilterQuery = false;
25
+ let resizeStartX = 0;
26
+ let resizeStartWidth = 0;
27
+
28
+ function clampSidebarWidth(width) {
29
+ return Math.min(maxSidebarWidth, Math.max(minSidebarWidth, width));
30
+ }
31
+
32
+ function getStoredSidebarWidth() {
33
+ const width = Number.parseInt(localStorage.getItem(sidebarWidthStateKey), 10);
34
+ return Number.isFinite(width) ? clampSidebarWidth(width) : null;
35
+ }
36
+
37
+ function setSidebarWidth(width, shouldPersist) {
38
+ const nextWidth = clampSidebarWidth(width);
39
+
40
+ root.style.setProperty('--admin-sidebar-width', `${nextWidth}px`);
41
+
42
+ if (resizeHandle) {
43
+ resizeHandle.setAttribute('aria-valuemin', String(minSidebarWidth));
44
+ resizeHandle.setAttribute('aria-valuemax', String(maxSidebarWidth));
45
+ resizeHandle.setAttribute('aria-valuenow', String(nextWidth));
46
+ }
47
+
48
+ if (shouldPersist) {
49
+ localStorage.setItem(sidebarWidthStateKey, String(nextWidth));
50
+ }
51
+ }
52
+
53
+ function getCurrentSidebarWidth() {
54
+ if (!sidebar) {
55
+ return getStoredSidebarWidth() || minSidebarWidth;
56
+ }
57
+
58
+ return clampSidebarWidth(Math.round(sidebar.getBoundingClientRect().width));
59
+ }
60
+
61
+ function canResizeSidebar() {
62
+ return (
63
+ sidebar
64
+ && resizeHandle
65
+ && !mobileQuery.matches
66
+ && !body.classList.contains('admin-sidebar-collapsed')
67
+ );
68
+ }
19
69
 
20
70
  function setCollapsed(isCollapsed, shouldPersist) {
21
71
  body.classList.toggle('admin-sidebar-collapsed', isCollapsed);
@@ -52,6 +102,10 @@
52
102
  sidebar.setAttribute('aria-hidden', String(isHiddenOnMobile));
53
103
  sidebar.toggleAttribute('inert', isHiddenOnMobile);
54
104
  }
105
+
106
+ if (resizeHandle) {
107
+ resizeHandle.hidden = mobileQuery.matches;
108
+ }
55
109
  }
56
110
 
57
111
  function isSectionOpen(section) {
@@ -73,6 +127,23 @@
73
127
  }
74
128
  }
75
129
 
130
+ function hasOpenSections() {
131
+ return navSections.some((section) => !section.hidden && isSectionOpen(section));
132
+ }
133
+
134
+ function syncSectionsToggle() {
135
+ if (!sectionsToggle) {
136
+ return;
137
+ }
138
+
139
+ const shouldCollapse = hasOpenSections();
140
+ const label = shouldCollapse ? 'Collapse all' : 'Expand all';
141
+
142
+ sectionsToggle.classList.toggle('is-collapse-mode', shouldCollapse);
143
+ sectionsToggle.setAttribute('aria-label', label);
144
+ sectionsToggle.setAttribute('title', label);
145
+ }
146
+
76
147
  function getCurrentOpenSections() {
77
148
  return new Set(navSections
78
149
  .filter(isSectionOpen)
@@ -181,10 +252,12 @@
181
252
  }
182
253
 
183
254
  hadFilterQuery = hasQuery;
255
+ syncSectionsToggle();
184
256
  }
185
257
 
186
258
  function applyOpenSections(openSections, shouldPersist) {
187
259
  if (!openSections) {
260
+ syncSectionsToggle();
188
261
  root.classList.remove('admin-nav-state-pending');
189
262
  return;
190
263
  }
@@ -209,6 +282,7 @@
209
282
  localStorage.setItem(navSectionsStateKey, JSON.stringify(Array.from(nextOpenSections)));
210
283
  }
211
284
 
285
+ syncSectionsToggle();
212
286
  root.classList.remove('admin-nav-state-pending');
213
287
  }
214
288
 
@@ -217,9 +291,73 @@
217
291
  }
218
292
 
219
293
  const storedCollapsed = localStorage.getItem(sidebarStateKey);
294
+ const storedSidebarWidth = getStoredSidebarWidth();
295
+ if (storedSidebarWidth) {
296
+ setSidebarWidth(storedSidebarWidth, false);
297
+ } else if (resizeHandle) {
298
+ setSidebarWidth(getCurrentSidebarWidth(), false);
299
+ }
220
300
  setCollapsed(storedCollapsed === 'true', false);
221
301
  setMobileOpen(false);
222
302
  applyStoredOpenSections();
303
+ syncSectionsToggle();
304
+
305
+ if (resizeHandle) {
306
+ resizeHandle.addEventListener('pointerdown', (event) => {
307
+ if (!canResizeSidebar()) {
308
+ return;
309
+ }
310
+
311
+ resizeStartX = event.clientX;
312
+ resizeStartWidth = getCurrentSidebarWidth();
313
+ body.classList.add('admin-sidebar-resizing');
314
+ resizeHandle.setPointerCapture(event.pointerId);
315
+ event.preventDefault();
316
+ });
317
+
318
+ resizeHandle.addEventListener('pointermove', (event) => {
319
+ if (!body.classList.contains('admin-sidebar-resizing')) {
320
+ return;
321
+ }
322
+
323
+ setSidebarWidth(resizeStartWidth + event.clientX - resizeStartX, false);
324
+ });
325
+
326
+ resizeHandle.addEventListener('pointerup', (event) => {
327
+ if (!body.classList.contains('admin-sidebar-resizing')) {
328
+ return;
329
+ }
330
+
331
+ body.classList.remove('admin-sidebar-resizing');
332
+ setSidebarWidth(getCurrentSidebarWidth(), true);
333
+ resizeHandle.releasePointerCapture(event.pointerId);
334
+ });
335
+
336
+ resizeHandle.addEventListener('pointercancel', () => {
337
+ body.classList.remove('admin-sidebar-resizing');
338
+ setSidebarWidth(getCurrentSidebarWidth(), true);
339
+ });
340
+
341
+ resizeHandle.addEventListener('keydown', (event) => {
342
+ if (!canResizeSidebar()) {
343
+ return;
344
+ }
345
+
346
+ if (event.key === 'ArrowLeft') {
347
+ setSidebarWidth(getCurrentSidebarWidth() - sidebarResizeStep, true);
348
+ event.preventDefault();
349
+ } else if (event.key === 'ArrowRight') {
350
+ setSidebarWidth(getCurrentSidebarWidth() + sidebarResizeStep, true);
351
+ event.preventDefault();
352
+ } else if (event.key === 'Home') {
353
+ setSidebarWidth(minSidebarWidth, true);
354
+ event.preventDefault();
355
+ } else if (event.key === 'End') {
356
+ setSidebarWidth(maxSidebarWidth, true);
357
+ event.preventDefault();
358
+ }
359
+ });
360
+ }
223
361
 
224
362
  if (collapseButton) {
225
363
  collapseButton.addEventListener('click', () => {
@@ -238,10 +376,28 @@
238
376
  });
239
377
  }
240
378
 
379
+ if (sectionsToggle) {
380
+ sectionsToggle.addEventListener('click', () => {
381
+ const shouldOpen = !hasOpenSections();
382
+
383
+ navSections.forEach((section) => {
384
+ if (section.hidden) {
385
+ return;
386
+ }
387
+
388
+ setSectionOpen(section, shouldOpen, true);
389
+ });
390
+
391
+ persistOpenSections();
392
+ syncSectionsToggle();
393
+ });
394
+ }
395
+
241
396
  navSections.forEach((section) => {
242
397
  syncSectionAria(section);
243
398
  section.addEventListener('toggle', () => {
244
399
  syncSectionAria(section);
400
+ syncSectionsToggle();
245
401
  if (programmaticSectionToggles.has(section)) {
246
402
  programmaticSectionToggles.delete(section);
247
403
  return;
@@ -2,6 +2,7 @@
2
2
 
3
3
  <svg aria-hidden="true" class="admin-svg-defs" xmlns="http://www.w3.org/2000/svg">
4
4
  <symbol id="admin-icon-menu" viewBox="0 0 24 24"><path d="M4 7h16M4 12h16M4 17h16" /></symbol>
5
+ <symbol id="admin-icon-chevrons-down" viewBox="0 0 24 24"><path d="m7 6 5 5 5-5" /><path d="m7 13 5 5 5-5" /></symbol>
5
6
  <symbol id="admin-icon-arrow-left" viewBox="0 0 24 24"><path d="m15 18-6-6 6-6" /></symbol>
6
7
  <symbol id="admin-icon-chevron" viewBox="0 0 24 24"><path d="m6 15 6-6 6 6" /></symbol>
7
8
  <symbol id="admin-icon-plus" viewBox="0 0 24 24"><path d="M12 5v14M5 12h14" /></symbol>
@@ -31,10 +32,22 @@
31
32
  </symbol>
32
33
  <symbol id="admin-icon-external" viewBox="0 0 24 24"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" /><path d="M15 3h6v6M10 14 21 3" /></symbol>
33
34
  <symbol id="admin-icon-lock" viewBox="0 0 24 24"><rect x="4" y="11" width="16" height="10" rx="2" /><path d="M8 11V7a4 4 0 0 1 8 0v4" /></symbol>
35
+ <symbol id="admin-icon-2fa-settings" viewBox="0 0 444 512.36">
36
+ <path fill="currentColor" stroke="none" fill-rule="evenodd" clip-rule="evenodd" d="M75.33 320.47h294.33c29.56-56.91 43.93-129.92 39.5-219.58-53.23 4.86-119.13-19.6-187.78-63.12-54.92 42.67-118.12 63.87-187.08 60.26-2.43 92.68 12.43 166.09 41.03 222.44zm328.53.58c14.79 2.87 26.06 16 26.06 31.53v127.66c0 17.59-14.52 32.12-32.12 32.12H46.18c-17.59 0-32.11-14.46-32.11-32.12V352.58c0-15.96 11.87-29.43 27.32-31.75C12.17 255.78-2.41 172.49.33 67.99 75.67 71.94 149.6 55.65 221.23 0 304.03 52.48 378.81 77.3 443 71.44c5.01 101.3-8.95 184.06-39.14 249.61zM161.67 177.27h6.01v-13.91c0-15.4 6.07-29.44 15.84-39.64 9.87-10.28 23.48-16.66 38.48-16.66 14.99 0 28.62 6.38 38.47 16.66 9.78 10.2 15.85 24.23 15.85 39.64v13.91h6c4.88 0 8.87 3.99 8.87 8.86v93.66c0 4.88-3.99 8.87-8.87 8.87H161.67c-4.88 0-8.86-3.99-8.86-8.87v-93.66c-.01-4.87 3.98-8.86 8.86-8.86zm22.78 0h75.09v-13.91c0-10.96-4.27-20.88-11.14-28.04-6.79-7.09-16.14-11.48-26.41-11.48-10.26 0-19.62 4.39-26.4 11.48-6.88 7.16-11.14 17.08-11.14 28.04v13.91zm30.27 59.82-9.56 25.05h33.68l-8.86-25.4c5.62-2.89 9.47-8.75 9.47-15.51 0-9.64-7.81-17.45-17.46-17.45-9.63 0-17.44 7.81-17.44 17.45 0 7.03 4.17 13.1 10.17 15.86zM105.2 397.93l-3.62-20.7c11.68-3.52 23.3-5.28 34.89-5.28 4.63 0 8.49.13 11.6.41 3.1.28 6.32.97 9.66 2.08 3.33 1.12 5.97 2.64 7.91 4.59 4.46 4.44 6.68 11.26 6.68 20.43s-2.6 15.93-7.79 20.29c-5.18 4.35-16.12 9.35-32.79 15v3.9h39.18v22.23H99.64v-17.37c0-5.19.97-10.14 2.91-14.87 1.21-2.69 4.13-5.93 8.76-9.73 2.5-2.13 5.86-4.17 10.07-6.11 4.22-1.95 8.2-3.78 11.96-5.49 3.75-1.71 6.78-3.13 9.1-4.24v-7.5c-4.17-.46-8.02-.7-11.54-.7-8.52 0-17.09 1.02-25.7 3.06zm140.7 33.06h-23.62v29.89h-27.8v-86.86h56.98l-3.48 22.25h-25.7v14.01h23.62v20.71zm38.64 29.89h-28.15l22.52-86.86h42.94l22.51 86.86h-28.15l-3.2-13.75h-25.27l-3.2 13.75zm12.13-60.17-3.93 24.32h15.13l-3.8-24.32h-7.4z"/>
37
+ </symbol>
34
38
  <symbol id="admin-icon-log-out" viewBox="0 0 24 24"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" /><path d="M16 17l5-5-5-5M21 12H9" /></symbol>
35
39
  </svg>
36
40
 
37
41
  <nav class="admin-sidebar" id="nav-sidebar" aria-label="Admin navigation">
42
+ <div
43
+ class="admin-sidebar__resize-handle"
44
+ id="admin-sidebar-resize-handle"
45
+ role="separator"
46
+ aria-orientation="vertical"
47
+ aria-label="Resize admin navigation"
48
+ aria-controls="nav-sidebar"
49
+ tabindex="0"
50
+ ></div>
38
51
  <div class="admin-sidebar__brand-row admin-sidebar-header">
39
52
  <a class="admin-sidebar__brand" href="{% url 'admin:index' %}">{{ site_header|default:'Django admin' }}</a>
40
53
  <div class="admin-sidebar__controls admin-sidebar-actions">
@@ -60,8 +73,17 @@
60
73
  id="admin-nav-filter"
61
74
  autocomplete="off"
62
75
  spellcheck="false"
63
- placeholder="Start typing to filter..."
76
+ placeholder="Type to filter..."
77
+ >
78
+ <button
79
+ class="admin-sidebar__sections-toggle"
80
+ id="admin-sidebar-sections-toggle"
81
+ type="button"
82
+ aria-label="Collapse all"
83
+ title="Collapse all"
64
84
  >
85
+ <svg aria-hidden="true"><use href="#admin-icon-chevrons-down"></use></svg>
86
+ </button>
65
87
  </div>
66
88
  {% endif %}
67
89
 
@@ -163,6 +185,13 @@
163
185
  <span>Change password</span>
164
186
  </a>
165
187
  {% endif %}
188
+ {% url 'two_factor:profile' as two_factor_profile_url %}
189
+ {% if two_factor_profile_url %}
190
+ <a href="{{ two_factor_profile_url }}">
191
+ <svg class="admin-sidebar__2fa-icon" aria-hidden="true"><use href="#admin-icon-2fa-settings"></use></svg>
192
+ <span>2FA settings</span>
193
+ </a>
194
+ {% endif %}
166
195
  <a class="admin-sidebar__donation-link donation-button" href="https://www.vanta-admin.org/en/donate/" target="_blank" rel="noopener noreferrer" aria-label="Buy me a coffee">
167
196
  <span class="donation-button__cup" aria-hidden="true">
168
197
  <span class="donation-button__steam"></span>
@@ -0,0 +1,25 @@
1
+ {% extends "two_factor/_base_focus.html" %}
2
+ {% load i18n %}
3
+
4
+ {% block content_wrapper %}
5
+ <main id="content-start" class="vanta-two-factor-shell" tabindex="-1">
6
+ <section class="vanta-two-factor-panel" aria-label="Two-factor authentication">
7
+ <div class="vanta-two-factor-header">
8
+ <div class="vanta-two-factor-brand">
9
+ <span class="vanta-two-factor-brand__mark" aria-hidden="true"></span>
10
+ <span>Vanta Admin</span>
11
+ </div>
12
+ <a href="{% url 'two_factor:profile' %}" class="vanta-two-factor-back-link"><span class="vanta-two-factor-back-link__arrow" aria-hidden="true">&larr;</span><span>{% trans "Back" %}</span></a>
13
+ </div>
14
+ <h1>{% block title %}{% trans "Disable Two-factor Authentication" %}{% endblock %}</h1>
15
+ <p>{% blocktrans trimmed %}You are about to disable two-factor authentication. This
16
+ weakens your account security, are you sure?{% endblocktrans %}</p>
17
+ <form method="post">
18
+ {% csrf_token %}
19
+ <table>{{ form.as_table }}</table>
20
+ <button class="btn btn-danger"
21
+ type="submit">{% trans "Disable" %}</button>
22
+ </form>
23
+ </section>
24
+ </main>
25
+ {% endblock %}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vanta-admin
3
- Version: 0.7.0
3
+ Version: 0.8.0
4
4
  Summary: A sharp, dark, and portable Django admin theme forged for builders who want the admin to feel less default.
5
5
  Author: oli-dev0
6
6
  License-Expression: MIT
@@ -36,6 +36,8 @@ feels more deliberate in everyday use.
36
36
 
37
37
  - A cleaner admin layout with a fixed sidebar that remembers how you left it.
38
38
  - A sidebar navigation filter that lets users quickly narrow large admin menus by app or model name.
39
+ - A resizable desktop sidebar that remembers each user's preferred width in the browser.
40
+ - A sidebar expand/collapse-all control for quickly opening or closing visible navigation sections.
39
41
  - Light and dark mode, using the same calm Vanta look across the admin.
40
42
  - A more settled light-mode palette with clearer search focus states and stronger changelist table headers.
41
43
  - Less visual noise on the main admin screens, login pages, cards, filters, and
@@ -58,7 +60,7 @@ feels more deliberate in everyday use.
58
60
  multi-select fields stay unchanged.
59
61
  - Built-in icons for common admin areas, models, and recent actions.
60
62
  - A cleaner account menu with display preferences, project links, password
61
- access, logout, and a Vanta support link.
63
+ access, 2FA settings, logout, and a Vanta support link.
62
64
  - A 12-hour and 24-hour time-format preference for changelist date/time values,
63
65
  stored in the browser for each admin user.
64
66
  - Shorter changelist date formatting that makes date-heavy tables easier to
@@ -68,7 +70,7 @@ feels more deliberate in everyday use.
68
70
  - A mobile sidebar overlay that makes the admin easier to use on smaller
69
71
  screens.
70
72
  - Optional matching templates for `django-two-factor-auth` login, setup
71
- completion, account security, and backup-token screens.
73
+ completion, account security, disable confirmation, and backup-token screens.
72
74
 
73
75
  Vanta Admin does not replace Django admin, change your permissions, or configure
74
76
  two-factor authentication for you. If your project uses `django-two-factor-auth`,
@@ -37,6 +37,7 @@ vanta_admin/templates/two_factor/_base_focus.html
37
37
  vanta_admin/templates/two_factor/_wizard_actions.html
38
38
  vanta_admin/templates/two_factor/core/login.html
39
39
  vanta_admin/templates/two_factor/core/setup_complete.html
40
+ vanta_admin/templates/two_factor/profile/disable.html
40
41
  vanta_admin/templates/two_factor/profile/profile.html
41
42
  vanta_admin/templatetags/__init__.py
42
43
  vanta_admin/templatetags/admin_theme.py
File without changes
File without changes
File without changes