Skip to content

Feat/islands - #554

Draft
kake21 wants to merge 142 commits into
mainfrom
feat/islands
Draft

Feat/islands#554
kake21 wants to merge 142 commits into
mainfrom
feat/islands

Conversation

@kake21

@kake21 kake21 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Major style overhaul of projectNext.

Extends #526 and #514.
Continues work on #357 and #401.
Implements hamburger menu from #7 issue.

Waiting on SVG support from CMS to color logos in mobile navbar.

  • Standardizes core UI components (Button, TextInput, DateInput, Checkbox, Textarea, NumberInput, SubmitButton) onto a consistent card/gap/rounding system, and adds new Dropdown/SearchableDropdown components used to rebuild the admin user list (sortable, standardized).
  • Various admin page redesigns (sidebar as nested cards, /admin/dots, flairs with animated drag-to-reorder, a new component test page) and smaller fixes (CommitteeCard, HeaderItemPopUp, PopUp, jobads/events zoning, omegaquote bubble tail, edit-mode icon visibility, frontpage preview link).
  • PageTitle context: PageTitleProvider (mounted once in layout.tsx) holds the current title; each page
    renders <PageTitleSetter title="..." />, which pushes the title up via a plain useEffect (set on mount/ch
    ange, clear on unmount) and NavBarTitle reads it back out to render in the nav bar. Adopted across ~15 pages
    (auth, admin, users, events, committees, images, error/not-found, etc.) to avoid prop-drilling a title throug
    h every layout.
  • Changed the colors to a base16 inspired layout.

Images showing the proposed stylechange:

Logged in main page desktop:
image

Profile page desktop:
image

Logged in main page mobile:
Screen Shot 2026-08-05 at 17 46 52

Pofile page mobile:
Screen Shot 2026-08-05 at 17 47 53

kake21 and others added 30 commits April 15, 2026 10:01
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
kake21 and others added 26 commits July 28, 2026 22:23
Replace the full-bleed photo-hero tile (hover-zoom, text overlaid on
the image) with an actual card: solid surface background, a 128x128
contained logo tile instead of a cropped background image, and the
title laid out beside it. Reuses the boxShadow/rounding/surface-*
tokens already established elsewhere (SlideSidebar, NavBar). Widens
the committees grid columns to fit the new row layout.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Buttons now use rounding - gap instead of the full card radius, and
the shared table mixin gets rounded corners, a raised header, and
zebra/hover states pulled from the surface color tokens instead of
the old color-mix + blur hacks.
Swap the Opp/Ned buttons on the flairs admin table for a drag handle,
using framer-motion's Reorder for the spring-animated reordering. The
table markup moves from <table> to a flex "fake table" since Framer's
layout animations don't play well with table-row layout. Drop commits
the new position by replaying increase/decreaseFlairRankAction the
right number of times, then refreshes.
…tandard

Fields now use the filled surface-raised background, rounding - gap
corners, and primary-blue focus border established for buttons and
tables. DateInput also gets color-scheme: dark so the native picker
icon/popup stop rendering as a stark white box, and Checkbox swaps
the unstyled native control for a custom appearance:none box with a
CSS-drawn checkmark.
The root layout's mobile grid reserved a full nav-height row for a
"subPageNavBar" area that nothing ever renders into — each page's
SubPageNavBar lives inside its own content flow, not that named grid
area. Dropping the empty row gives .content back ~72px of height it
was silently losing on every mobile page.
…v layout

Adds the user's top-ranked flair color as a border/frame accent on
UserCard and the profile page, keeps the profile page's sub-nav pinned
above the mobile nav bar at all times, and makes the profile card's
content scroll within its fixed-height frame instead of the whole page.

Also tweaks surface color tokens and swaps the secondary font to Roboto.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Migrates the flat legacy palette (primary/secondary/red/green/gray-*/
white/black) and duplicate aliases (tertiary, border, ink-base,
ink-faint, text-sec, shadowColor) across the app to the surface/ink/
text/accent-* tokens so every surface actually responds to theme
switching. Extends ThemeColors and all four theme presets (Standard,
Light, Solarized, StjerneInnbygger) to drive the newly consolidated
tokens, and fixes a couple of real bugs uncovered along the way:
MobileNavBar and a few other components hardcoded white/black text on
top of an already-themed background, which would have gone invisible
under the Light theme.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ry button contrast

Adds an /admin/component-test page rendering the UI kit (buttons,
inputs, checkbox, slider, file input, progress bar) for visual/theme
QA, linked from the admin sidebar under "Annet".

SubmitButton's confirmation now teleports into the app's standard
PopUp overlay instead of an inline swap, with explicit Ja/Nei actions.
Fixes two bugs surfaced by that change: the trigger button defaulted
to type="submit" and fired the real action immediately, and the real
submit button ended up outside the <form>'s DOM once teleported so
"Ja" did nothing — a hidden submit button now stays inside the form
and is triggered via ref from the popup.

Also fixes secondary buttons/links (Button, BorderButton, CmsLink,
FileInput) using surface-base as their fill/border color, which is
the same color as the page/card background they usually sit on and
made them nearly invisible; they now use surface-hover instead.

stateOfOmega's order number gets a centered, dramatic plaque treatment.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… input variant

Simplifies ohma.card to just the rounding radius (dropping the
box-shadow/hover elevation), and reduces it from cardRounding to the
base rounding token.

Redesigns /admin/dots: migrates NumberInput to the same floating-label
standard as TextInput (it had never been updated, which was throwing
off alignment next to TextInput), restructures CreateDotForm into
clear header/user-select/form sections, and gives both panels
consistent card styling.

Migrating NumberInput onto the new surface-raised fill exposed that
inputs placed on an already-raised card become invisible (same fill as
their container), so TextInput, NumberInput, DateInput and Textarea
all get a new `background: 'base' | 'raised'` prop that bumps the
field fill up to surface-hover when needed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ndardized user list

Adds two new fully-custom dropdown components matching the standard
input styling (floating label, surface-raised fill, accent-blue
focus): Dropdown for plain selection, and SearchableDropdown which
filters options as you type. Both support roving keyboard navigation
(ArrowUp/ArrowDown to move a highlighted option, Enter to select,
Escape/outside-click to close), matching the pattern native <select>
uses of keeping focus on the trigger rather than the option list.
Both demoed on /admin/component-test.

Converts UserList's fake grid-of-spans layout to a real <table> using
the same ohma.table() mixin as the rest of the app, adds sortable
Navn/Brukernavn columns backed by real orderBy on the readPage
operation (Studie/Klasse are derived post-query from memberships and
aren't sortable at the DB level without a bigger restructuring), and
replaces the raw name-search <input> and native <select> group filters
with TextInput/Dropdown/SearchableDropdown — Komité is searchable per
request. UserRow now returns a <td> fragment since UserList owns the
<tr> for real table semantics.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Article gains articleClassName/addSectionClassName props (alongside
the existing coverImageClass/sideBarClassName) so per-consumer zone
styling doesn't require touching the shared component's defaults, and
a height: 100% on its root grid so it can fill a definite-height
parent when one opts in - both no-ops for the other consumer
(committees/about). jobads/[nameAndId] uses these to split into
rounded surface-base zones matching events' aside/main/registrationList
treatment, and stretches to fill the page vertically.

OmegaquotesQuote's speech-bubble tail was a Unicode "▼" glyph nudged
into place with a hardcoded negative margin, colored to match the
bubble's old ohma.layer() blur background - so it was both mispositioned
(the parent was missing position: relative, so the absolutely
positioned glyph anchored to some unrelated ancestor) and the wrong
color once the bubble moved to a solid surface-raised fill. Replaced
it with a CSS-drawn diamond (::after) that overlaps the bubble exactly,
so there's no gap between the two.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…obile menu containment/animation

EditModeSwitch's clickable label only sized itself to the icon glyph,
so on desktop - where it sits inside a much bigger hoverable nav-icon
square - only that small icon actually responded to clicks. Made it
fill its container instead. That in turn requires the container to
have a definite size to resolve the percentage against; mobile's
badge had none, so it silently collapsed to zero height and vanished.
Gave it an explicit size instead.

DesktopSideBar (a server component) always rendered the edit-mode nav
slot regardless of permission, leaving an empty hoverable square for
users with nothing to edit. Extracted EditModeNavIcon, a small client
component that checks EditModeContext itself and renders nothing at
all when there's nothing to edit, instead of relying on the child
returning null while the parent's wrapper markup stays behind.
MobileNavBar's own edit-mode bubble was also missing position:
relative on its container, so it anchored to some unrelated ancestor.

The frontpage's editor-only "preview as logged out/in" link had the
same missing-position-context bug, landing it up near the navbar, and
was using ohma.btn() with no color argument (defaults to white),
rendering a plain white box against the dark theme.

The mobile expanded nav menu used a raw fixed full-viewport overlay
that only accounted for one nav bar's height, so it bled behind the
header and under the bottom mobile nav bar. Insets it to sit between
both bars instead, and fixes the nav-item width calc to match.

Replaces the mobile hamburger's instant icon-swap (bars <-> X) with an
animated three-bar CSS morph, and fixes the open/close button to
actually toggle - it previously only ever opened the menu.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…o post-mount

Tooltip.Trigger's asChild clones Radix-managed props (aria-describedby,
data-state, pointer/focus handlers, ref) onto its child during render.
Something in that computation wasn't landing identically between the
server render and the client's first render pass, causing a recurring
hydration mismatch on every nav link wrapped in NavTooltip. Renders
just the bare children until after mount - guaranteed to match the
server output exactly, since asChild adds no wrapping DOM element - and
adds the Tooltip.Provider/Root/Trigger/Portal in a normal post-hydration
re-render instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… show

The admin nav background panel always rendered even with nothing
inside it (no admin link, no edit-mode icon), leaving an empty rounded
box in the sidebar for non-admin users with nothing to edit.

Extracted AdminNav, a client component that checks both isAdmin
(known server-side, passed down) and EditModeContext.somethingToEdit
(client-only) together and renders nothing at all - not just the
icons, the wrapping nav/panel too - unless at least one is true.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The profile page (/users/[username]) was missing the Omega-ID and Konto
action buttons that UserNavigation already exposes for the logged-in
user's own profile. Added both, folding the existing own-profile check
into the shared isOwnProfile flag alongside the pre-existing Logg ut
button.

Replaced the bespoke, single-use ProfileButton component with the
standard Button wrapped in Link, matching the pattern UserNavigation
already uses for its own nav buttons. Added an .actionButton class to
page.module.scss to preserve the icon+text flex layout that
ProfileButton previously provided inline, since the base Button/
ohma.btn() mixin has no such layout of its own.

ProfileButton had no other callers, so it and its stylesheet are
deleted as dead code.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ard styling

The sticky sub-nav on /users/[username]'s admin subpages (settings, dots,
notifications, etc.) rendered flush against the viewport edge instead of
floating like it does on the profile page, and the settings page content
was collapsing to zero height. Root causes: a stray <br/> among the layout's
grid children threw off implicit row placement, and PageWrapper's title bar
competed with the grid for height with no way to size against the remainder.

- Add opt-in `fillHeight`/`hideTitle` props to PageWrapper so a page can size
  a scrollable body against the actual remaining height instead of the whole
  wrapper (avoids overflowing past the title bar) and skip the redundant
  title text.
- Rebuild (user-admin)/layout to mirror the profile page's own grid/scroll
  pattern, and extract the duplicated sub-nav JSX into UserAdminNavBar,
  shared by both the profile page and the admin layout.
- Move card background/padding out of the shared layout and into each
  subpage, so dots/flairs/notifications/permissions/settings can each own
  their own card styling instead of inheriting one forced surface color.
- Give Permission's list-item card a solid surface-raised background instead
  of the glass/blur `layer` mixin, which did nothing over a solid backdrop.
- Drop UserProfileSettingsForm.module.scss, orphaned since the form moved
  from Select to Dropdown.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Each theme option now takes a full-width row instead of a small tile, and
next to its color swatches shows a miniature static mockup of the actual
app layout (nav bar with logo/title/icons, icon sidebar, content card)
rendered in that theme's own colors, so you can see roughly what a theme
looks like before applying it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Swap the mount/localStorage useEffect+setState pattern in NavTooltip and
ThemeForm for useSyncExternalStore, which avoids react-hooks/set-state-in-effect
without changing behavior. Also wraps several lines that exceeded max-len.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@kake21 kake21 self-assigned this Aug 5, 2026
kake21 and others added 3 commits August 5, 2026 17:40
…olumns

Switches the footer from a fixed CSS grid to flex-wrap so sections
keep their natural content width and drop to a new row as whole
blocks instead of shrinking narrow enough to break emails/phone
numbers mid-word. Kontakt and Adresse are grouped in a shared
.infoGroup flex item so they always move together rather than
splitting across rows independently.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Uses standard scrollbar-color/scrollbar-width plus WebKit pseudo-elements
for Chrome, styled with the existing theme colors.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants