Conversation
change scss variables to new system add shadow to cards based upon material design
# Conflicts: # src/app/(auth)/login/page.tsx # src/app/_components/NavBar/Menu.tsx # src/app/users/[username]/page.module.scss # src/app/users/[username]/page.tsx
There was a problem hiding this comment.
Pull request overview
This PR introduces a new theme/color system driven by CSS custom properties and updates a wide set of UI styles/components to use the new palette (layer/neumorphism, text colors, box shadows). It also adds a user-admin theme selection page and refactors some navigation/profile UI elements to match the new design direction.
Changes:
- Switches core color tokens to CSS variables and updates many SCSS modules to use
layer,boxShadow, and new text colors. - Adds a user-admin “theme” page with a client-side theme picker and a new
ProfileButtonUI component. - Refactors NavBar menu behavior/styling and redesigns event cards/layout styling.
Reviewed changes
Copilot reviewed 77 out of 77 changed files in this pull request and generated 17 comments.
Show a summary per file
| File | Description |
|---|---|
| src/styles/globals.scss | Defines global CSS custom properties (primary/secondary/text/layer) and updates page background colors. |
| src/styles/_variables.scss | Introduces --rounding as a CSS custom property and changes spacing scale ($gap). |
| src/styles/_mixins.scss | Adds/changes mixins (boxShadow, layer, neumorphism, layouts) and updates table/button styling helpers. |
| src/styles/_colors.scss | Repoints theme color tokens to CSS variables (var(--primary), etc.). |
| src/app/users/[username]/page.tsx | Swaps profile action buttons to ProfileButton + icons and tweaks membership link markup. |
| src/app/users/[username]/page.module.scss | Updates profile page styling for new layering/shadows and adds committee membership link styles. |
| src/app/users/[username]/(user-admin)/theme/ThemeForm.tsx | New client-side theme picker applying CSS variables at runtime. |
| src/app/users/[username]/(user-admin)/theme/page.tsx | New user-admin theme page wrapper (server component). |
| src/app/users/[username]/(user-admin)/theme/page.module.scss | Styling for theme picker grid/cards and swatches. |
| src/app/omegaquotes/OmegaquotesQuote.module.scss | Adds a background color to quote text block. |
| src/app/not-found.module.scss | Updates colors and comments out image invert filter. |
| src/app/news/[nameAndId]/page.module.scss | Makes .moreNews vertically scrollable. |
| src/app/layout.tsx | Adds a class to the <html> element to support CSS-variable rounding. |
| src/app/layout.module.scss | Sets global text/nav background colors and adjusts content min-height. |
| src/app/events/EventsLandingLayout.module.scss | Switches to the new event card list layout mixin and updates text colors. |
| src/app/events/CreateOrUpdateEventForm.module.scss | Adds padding based on the new gap variable. |
| src/app/events/[nameAndId]/page.module.scss | Uses layer styling for overlays/aside and updates text color. |
| src/app/error.module.scss | Updates colors and comments out image invert filter. |
| src/app/committees/page.module.scss | Updates text color and grid alignment. |
| src/app/career/page.module.scss | Restyles links section with neumorphism + responsive layout updates. |
| src/app/career/jobads/[nameAndId]/page.module.scss | Replaces background with layer styling. |
| src/app/cabin/book/CabinCalendar.module.scss | Replaces color.adjust with color-mix for range background. |
| src/app/articles/[category]/SideBar.module.scss | Reworks sidebar layering/padding/z-index for new theme. |
| src/app/applications/[periodName]/page.module.scss | Replaces darken(...) with color-mix(...) for hover styling. |
| src/app/admin/SlideSidebar.module.scss | Restyles admin sidebar with layering, mobile fixed behavior, and scroll handling. |
| src/app/admin/page.module.scss | Updates icon color to match new text token. |
| src/app/admin/layout.tsx | Wraps SlideSidebar in a dedicated container for layout styling. |
| src/app/admin/layout.module.scss | Adds sticky sidebar behavior and mobile layout constraints. |
| src/app/admin/groups/page.module.scss | Uses layer styling for group rows and updates text color. |
| src/app/admin/dots/page.module.scss | Uses layer styling for “create new” container. |
| src/app/admin/dots/DotList.module.scss | Uses layer styling and tweaks selection layout. |
| src/app/admin/dots/CreateDotForm.module.scss | Updates SVG icon color to match new text token. |
| src/app/admin/api-keys/page.module.scss | Replaces lighten(...) with color-mix(...) for status badges. |
| src/app/(frontpage)/Section.module.scss | Adjusts section colors to the new theme tokens. |
| src/app/(frontpage)/LoggedInSection.module.scss | Updates link colors and hover states. |
| src/app/(frontpage)/InfoBubbles.module.scss | Applies layer styling and adjusts icon/text colors. |
| src/app/(auth)/login/page.tsx | Refactors login markup (form structure, divider, copy, links). |
| src/app/(auth)/login/page.module.scss | Adds styling for new login layout elements. |
| src/app/(auth)/layout.module.scss | Refactors auth layout to flex-based neumorphism card layout. |
| src/app/_components/YouTube/YouTube.tsx | Adds title to iframe for accessibility. |
| src/app/_components/User/UserList/UserList.module.scss | Applies layer + boxShadow styling and padding tweaks. |
| src/app/_components/User/UserCard.module.scss | Applies layer + new hover shadow behavior and spacing updates. |
| src/app/_components/UI/TextInput.module.scss | Updates “black” variant colors to new text token. |
| src/app/_components/UI/Textarea.module.scss | Applies layer styling, padding, and text color. |
| src/app/_components/UI/Slider.tsx | Changes default slider color from secondary to primary. |
| src/app/_components/UI/ProfileButton.tsx | Adds a new Link-based “profile button” component. |
| src/app/_components/UI/ProfileButton.module.scss | Styles the new ProfileButton with layer/shadow and hover states. |
| src/app/_components/UI/Dropzone.module.scss | Replaces lighten(...) with color-mix(...) for backgrounds. |
| src/app/_components/School/School.module.scss | Updates shadow behavior to new boxShadow(state) mixin. |
| src/app/_components/PopUp/PopUp.module.scss | Applies layer + new shadows/padding and mobile border radius tweaks. |
| src/app/_components/Permission/Permission.module.scss | Applies layer styling. |
| src/app/_components/NavBar/UserNavigation.tsx | Fixes spelling (“Innstillinger”). |
| src/app/_components/NavBar/UserNavigation.module.scss | Applies new shadow/layer behaviors and hover transitions. |
| src/app/_components/NavBar/ReportButton.module.scss | Adjusts margins and hover transition placement. |
| src/app/_components/NavBar/NavBar.tsx | Updates Menu usage to new prop (openBtnContext). |
| src/app/_components/NavBar/NavBar.module.scss | Updates NavBar colors/background and layout sizing. |
| src/app/_components/NavBar/MobileNavBar.tsx | Updates Menu usage to new prop (openBtnContext). |
| src/app/_components/NavBar/MobileNavBar.module.scss | Removes left border styling between items. |
| src/app/_components/NavBar/Menu.tsx | Refactors menu open button to context-based rendering (desktop/mobile). |
| src/app/_components/NavBar/Menu.module.scss | Reworks menu layout/animation and card-like item styling. |
| src/app/_components/NavBar/Item.module.scss | Updates link color to new text token. |
| src/app/_components/MazeMap/MazeMap.tsx | Adds title to iframe for accessibility. |
| src/app/_components/ImageCard/ImageCard.module.scss | Adjusts sizing/padding, layering, and uses card() styling. |
| src/app/_components/Footer/Footer.tsx | Comments out PWA special image/link section. |
| src/app/_components/Footer/Footer.module.scss | Updates footer styling and icon link mixin name. |
| src/app/_components/Event/SmallEventTag.module.scss | Adjusts hover label positioning. |
| src/app/_components/Event/EventCard.tsx | Redesigns EventCard markup/layout and introduces attendance bar/footer. |
| src/app/_components/Event/EventCard.module.scss | Adds full styling for the redesigned EventCard layout. |
| src/app/_components/EditModeSwitch/EditModeSwitch.module.scss | Updates icon color to new text token. |
| src/app/_components/EditableTextField/EditableTextField.module.scss | Updates icon/border colors to primary. |
| src/app/_components/CommitteeImage/CommitteeImage.module.scss | Replaces color.adjust with color-mix. |
| src/app/_components/CommitteeCard/CommitteeCard.module.scss | Updates card styling (shape, layering, hover behavior, text colors). |
| src/app/_components/Cms/CmsParagraph/CmsParagraph.module.scss | Updates CMS text/link colors to new tokens. |
| src/app/_components/Cms/CmsImage/CmsImageEditor.module.scss | Updates backgrounds to new theme colors/mixes. |
| src/app/_components/Cms/Article/Article.module.scss | Adjusts article gradient overlay color. |
| src/app/_components/BackdropImage/BackdropImage.tsx | Removes inline width style on the image container. |
| src/app/_components/BackdropImage/BackdropImage.module.scss | Adjusts backdrop image sizing/overflow and internal element sizing. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| th, td { | ||
| border: 1px solid colors.$gray-300; | ||
| padding: 8px; | ||
| padding: variables.$gap | ||
| } |
There was a problem hiding this comment.
@mixin table: missing semicolon after padding: variables.$gap will cause SCSS compilation to fail. Add the semicolon (and ensure the declaration block still parses correctly).
There was a problem hiding this comment.
This should be a lint rule...
| right: calc($padding / 2); | ||
| top: calc($padding / 2); | ||
| color: ohma.$colors-yellow; | ||
| color: ohma.$colors-primary | ||
| } | ||
| .text { | ||
| position: relative; | ||
| padding: $padding; | ||
| border: $border solid ohma.$colors-yellow;; // Add this line | ||
| border: $border solid ohma.$colors-primary;; // Add this line | ||
| border-radius: ohma.$rounding; |
There was a problem hiding this comment.
Missing semicolon after color: ohma.$colors-primary will break SCSS parsing for this rule. Add the trailing semicolon (and consider removing the double ;; on the border line while touching this block).
src/app/_components/NavBar/Menu.tsx
Outdated
| <div ref={menuRef} className={styles.Menu}> | ||
| <FontAwesomeIcon className={styles.close} icon={faTimes} onClick={() => closeMenu(menuRef)}/> | ||
| <ul> | ||
| <FontAwesomeIcon className={styles.close} icon={faTimes} onClick={() => closeMenu}/> |
There was a problem hiding this comment.
The close button handler is never invoked: onClick={() => closeMenu} returns the function instead of calling it, so the menu can't be closed via the X button. Call closeMenu(menuRef) (or otherwise invoke the close logic) in the click handler.
| <FontAwesomeIcon className={styles.close} icon={faTimes} onClick={() => closeMenu}/> | |
| <FontAwesomeIcon className={styles.close} icon={faTimes} onClick={() => closeMenu(menuRef)}/> |
| ) : null | ||
| } | ||
| <button className={styles.openBtn} onClick={() => setIsOpen(true)}> | ||
| {openBtnContent} | ||
| {openBtnContext === 'mobile' && !isOpen && |
There was a problem hiding this comment.
openBtn always calls setIsOpen(true), so when the menu is open the button (showing “Mindre”/X) still cannot close it. Make this a toggle (or call the same close routine) so the UI state matches the control’s behavior.
| import SmallEventTag from './SmallEventTag' | ||
| import styles from './EventCard.module.scss' | ||
| import ImageCard from '@/components/ImageCard/ImageCard' | ||
| import { formatVevenUri } from '@/lib/urlEncoding' | ||
| import CmsImage from '@/components/Cms/CmsImage/CmsImage' | ||
| import {updateEventCmsCoverImageAction} from "@/services/events/actions"; | ||
| import React from 'react' | ||
| import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' | ||
| import { faCalendar, faLocationDot, faUsers } from '@fortawesome/free-solid-svg-icons' | ||
| import type { EventExpanded } from '@/services/events/types' | ||
| import {configureAction} from "@/services/configureAction"; | ||
|
|
There was a problem hiding this comment.
This file now has several unused imports (CmsImage, updateEventCmsCoverImageAction, configureAction, and React) because the related code is commented out. With @typescript-eslint/no-unused-vars enabled, this will fail lint/CI—either remove the imports or re-enable the implementation.
| { | ||
| name: 'Dragonlore', | ||
| colors: { | ||
| primary: 'linear-gradient(to right, #BF953F, #FCF6BA, #B38728, #FBF5B7, #AA771C)', | ||
| secondary: 'hsl(210, 5%, 12%)', | ||
| layer: 'linear-gradient(to right, #BF953F, #FCF6BA, #B38728, #FBF5B7, #AA771C)', | ||
| text: 'hsl(0,0%,10%)', | ||
| textMuted: 'hsl(0,0%,20%)', | ||
| }, | ||
| }, |
There was a problem hiding this comment.
Some themes set CSS vars like primary/layer to linear-gradient(...) values. Those vars are also used in places that expect a plain color (e.g. color, border-color, box-shadow), so applying such a theme can yield invalid CSS and unreadable UI. Consider restricting theme values to actual colors or splitting gradient vars from color vars.
| {Object.entries(theme.colors).map(([key, value]) => ( | ||
| <div | ||
| key={key} | ||
| className={styles.ColorSwatch} | ||
| style={{ backgroundColor: value }} | ||
| title={`${key}: ${value}`} | ||
| /> |
There was a problem hiding this comment.
The swatches use style={{ backgroundColor: value }}, but for non-color values (e.g. gradients) backgroundColor will be ignored. Use background (or filter out unsupported values) so the preview matches the applied theme.
| import type { ButtonHTMLAttributes } from 'react' | ||
|
|
||
|
|
||
| export type PropTypes = ButtonHTMLAttributes<HTMLButtonElement> & { | ||
| children: React.ReactNode, | ||
| href: string, | ||
| } | ||
|
|
||
| export default function ProfileButton({ children, href }: PropTypes) { | ||
| return <Link className={styles.button} href={href}>{ children }</Link> | ||
| } |
There was a problem hiding this comment.
ProfileButton is typed as ButtonHTMLAttributes<HTMLButtonElement> but renders a next/link and doesn’t forward any of those props (e.g. onClick, disabled, type). This is misleading and will cause callers’ props to be silently ignored. Prefer LinkProps/AnchorHTMLAttributes<HTMLAnchorElement> and forward remaining props to the rendered element.
src/styles/_variables.scss
Outdated
| .html { | ||
| --rounding: 12px; | ||
| } | ||
|
|
||
| $gap: 8px; |
There was a problem hiding this comment.
_variables.scss now emits a real CSS rule (.html { --rounding: 12px; }). Since this file is @forwarded through styles/ohma.scss and @used by many SCSS modules, that global rule is likely duplicated across many compiled CSS module outputs. Move this global custom property to globals.scss (or another single global stylesheet) and keep _variables.scss for Sass variables only.
| import styles from './page.module.scss' | ||
| import { readUserProfileAction } from '@/services/users/actions' | ||
| import { notFound } from 'next/navigation' | ||
| import type { PropTypes } from '@/app/users/[username]/page' | ||
| import ThemeForm from "@/app/users/[username]/(user-admin)/theme/ThemeForm"; | ||
|
|
There was a problem hiding this comment.
styles is imported but never used in this file. With @typescript-eslint/no-unused-vars enabled, this will fail lint/CI—remove the import or use the styles.
Minor visual overhaul
This PR aims to refactor the visual styling of projectNext.
General changes
Added dark mode to everything and more consistent theming overall.
Additions
ohma.layer(): A mixin that creates a transparent blurred background that replaces having multiple colors for backgrounds.ohma.neumorphism(): A mixing for creating neumorphism shadows, currently in use on the login form.Linked issues
Closes #440
Related to #333
Related to #401
Follow ups