The Bulma form/checkbox-radio partial only defined two selectors: .checkbox
(consumed exclusively by FormCheckbox.vue) and .radio (consumed by
ViewEditForm.vue and user/settings/Avatar.vue). Ports the %checkbox-radio
placeholder rules (cursor, line-height, position, hover/disabled states,
and the input cursor override) into FormCheckbox's scoped style for the
.checkbox side, and into scoped style blocks on the two remaining .radio
call-sites for the .radio side (including the 0.5em sibling margin via
margin-inline-start). Drops the now-unused @import. Pixel-perfect verified
on /login, /user/settings/general, and /user/settings/avatar: every
measured label/input getBoundingClientRect and computed style matches the
baseline exactly (0px deltas across all 5 sampled checkboxes and all 5
avatar radios).
The Bulma partial applied justify-content: space-between on .pagination and
flex-order 1/2/3 on prev/list/next inside a tablet media query under
.is-centered — the port missed both. Pixel-diff against main is now zero.
BasePagination was reaching across slot boundaries with :deep() to style
.pagination-previous / -next / -link — markup it doesn't actually render.
Move that markup and the related scoped rules into a new PaginationItem
component that polymorphically renders RouterLink (when `to` is given)
or BaseButton (emit-based). BasePagination keeps only the scaffold it
actually owns: .pagination, .pagination-list, .pagination-ellipsis.
Pagination.vue and PaginationEmit.vue become thin wrappers around
BasePagination + PaginationItem; no more raw pagination-* class usage or
BaseButton imports in the emit wrapper.
The .app-container.has-background / .link-share-container.has-background
theme override moves with the .pagination-link rules into PaginationItem
as its own unscoped <style> block.
Result: 0 remaining :deep(.pagination-*) selectors (was 14).
The Bulma components/pagination partial is only used by BasePagination
and its two wrappers (Pagination.vue, PaginationEmit.vue); no other
component renders raw .pagination-* markup. Ports the rules we actually
use (base layout, item sizing, hover/focus/disabled states, is-current
styling, mobile/tablet breakpoints) into BasePagination's scoped styles,
using :deep() to reach slotted children. The theme override for
.pagination-link on .has-background containers moves into an unscoped
style block on the same component. Drops the now-unused @import.
.navbar and .navbar-end are only used in AppHeader.vue. Ports the
relevant rules (z-index 30 and min-block-size: $navbar-height) into
its scoped <style> block and drops the partial import.
The .media / .media-left / .media-content classes are only used in
Comments.vue. Ports the relevant rules into its scoped <style> block
and drops the partial import.
Only .is-pulled-right is used (3 callsites); .is-pulled-left and
.is-clearfix from Bulma's helpers/float partial have zero usage. Ports the
one needed rule into theme/helpers.scss so the Bulma import can go.
typeof null === 'object', so null slipped past the type guards in
objectToCamelCase/objectToSnakeCase/prepareParams. The original
for...in loops silently iterated nothing on null; Object.keys(null)
throws. Also guard saveCollapsedBucketState where state[projectId]
may be undefined.
Replaces 33 for...in loops across 18 files with for...of + Object.keys/entries
or indexed for loops. for...in iterates enumerable string keys including
inherited ones, which is especially risky on reactive arrays (tasks, labels,
assignees, etc.) where polyfilled properties may appear.
Loops that mutate via splice during iteration now iterate backwards to avoid
index-shift bugs. Adds a no-restricted-syntax ESLint rule forbidding
ForInStatement to prevent regressions.
Closes#513
Every file input in the codebase is hidden (via class="is-hidden" or
scoped display:none) and triggered programmatically by a custom XButton.
None of Bulma's .file / .file-label / .file-cta / .file-input / .file-name /
.file-icon classes are used anywhere in .vue files, so the partial is dead
code.
Vikunja's Modal.vue uses a native <dialog> element with its own locally-
scoped classes (modal-dialog, modal-container, modal-content, modal-header).
None of Bulma's modal classes (.modal, .modal-background, .modal-card*) are
used anywhere in the app. The two CSS variables this partial provided
(--modal-card-head-padding, --modal-content-spacing-tablet) were inlined in
the two callers in the previous commits, so the whole partial is now dead
code.
Modal.vue already had several 'reset bulma' overrides fighting the default
rules Bulma applied to .modal-content; those can be cleaned up in a
follow-up.