Skip to content

Member Portal — design system & conventions

Shared visual conventions for the member portal (the {permalink}.raklet.com app — Application/ Razor views + Raklet.Backend/Content/styles/core/social/*.scss). Follow these when building or restyling portal pages so headers, cards, buttons, inputs, and brand colour stay consistent. This codifies the conventions established during the portal modernization (PR #14021); see also Member portal modernization — design.

Scope: the member-facing portal only. The AngularJS admin SPA (admin.raklet.com) has its own styling and is out of scope here.

Build & deploy

  • SCSS lives in Raklet.Backend/Content/styles/core/social/ (compiles to Content/dist/styles/social.css → minified social.min.css, served from backend.raklet.com/content/dist/styles/). After editing SCSS: cd Raklet.Backend && npx grunt dart-sass cssmin. Content/dist/ is gitignored — commit only the .scss source; CI/deploy rebuilds it.
  • Razor views (Application/.../*.cshtml) deploy directly. Escape any literal @ in inline <style>/<script> as @@ or the page 500s.
  • Controller/.cs changes need an MSBuild (scripts/dev/build-fast.ps1 -Site portal).

Brand colour

  • The brand accent is per-org, themed by a generated branding.css (Azure blob customcode), exposed to CSS as --portal-accent (and --portal-brand for the header bar). Use these variables — never hardcode a brand colour.
  • .btn-primary, links, focus rings, and active states are all driven by the org's branding. Do not override them with a fixed colour.

Cards

The canonical card (reference: the /c/introductions post cards):

background: #fff;
border: 1px solid rgba(0, 0, 0, 0.125);
border-radius: 0.5rem;
margin-bottom: 1rem;                 // spacing between cards
transition: box-shadow 0.15s ease, border-color 0.15s ease;

&:hover {                            // only when the card is clickable
    box-shadow: 0 4px 14px rgba(16, 24, 40, 0.08);
    border-color: rgba(0, 0, 0, 0.2);
}
  • List pages render each item as its own card, not divider-separated rows in one big card. When the markup wraps items in a container card, neutralize the wrapper (border: none; background: transparent; padding: 0;) so each item is the card. Applied to: Jobs (.JobPostingList), Directory (.directoryItem), Connections — cities/countries/tags/sectors/institutions (#listView .list-group-item), Subscription plans (.subscription-card).
  • Reserve the hover lift for clickable cards. Static info cards keep the border without the hover.

Inputs & selects

  • border-radius: 8px.
  • Focus: border-color: var(--portal-accent) with a soft neutral ring (box-shadow: 0 0 0 3px rgba(0,0,0,0.06)). Never the Bootstrap default blue (#3b82f6).
  • Native <select> option lists are OS-rendered and cannot be styled cross-browser — style the closed control only.

Buttons

  • Primary action: .btn-primary (inherits the org brand). Use for the main CTA per view (Search, Send Message, Select Plan, Post a Job).
  • Avoid .btn-outline-secondary on coloured backgroundsbranding.css gives it a hard black border that clashes on the brand-coloured header. The header search was unified into one translucent control instead (.SocialHeader-search: rgba(255,255,255,.16) fill, rgba(255,255,255,.28) border, white icon).

Contrast traps (two recurring non-obvious failures)

  1. <a class="btn btn-primary" onclick=…> with no href loses its label colour. Bootstrap 4 reboot's a:not([href]):not([tabindex]){color:inherit} has higher specificity than branding.css's .btn-primary{color:#fff} — the button keeps its branded background but the text inherits body colour (dark-on-dark). Fix: markup only — add role="button" tabindex="0" (or href="#"). A CSS rule alone cannot fix this because the button colour is per-org (set in branding.css).
  2. color: var(--portal-accent) as a foreground on a white surface (~1.1:1 contrast on light-accent orgs such as demo.raklet.net with yellow rgb(255,220,0)). Use color-mix(in srgb, var(--portal-accent) 35%, var(--portal-ink,#1a2233)) or compute on-accent foregrounds at branding.css generation time. These bugs reproduce only on light-accent orgs — always verify on demo.raklet.net, not just on gercek (dark orange accent).

Page headers

Headers are the least consistent area today and the main target of the ongoing consistency work:

  • Preferred pattern: the shared .card.PageHeader with a b.h2 title (Directory and Jobs follow this).
  • Several pages still use <h4> or bespoke per-page headers (e.g. Announcements, Members). These should converge on one pattern.

Touch targets

  • Interactive controls ≥ 44×44px hit area (pad the control; the visible icon can stay smaller). Bottom-bar tabs are 60px; header icon controls (hamburger, back, drawer close) are padded to 44px.

SCSS file map

Area File
Header / nav / search layout/social-header.scss
Shared content/layout layout/social-content.scss
Mobile nav drawer / account sheet pages/social-mobile-navigation.scss
Directory pages/social-directory.scss
Jobs pages/social-job-board.scss
Connections (cities/countries/tags/sectors) pages/social-connections.scss
Events pages/social-events.scss
Profile (self) pages/social-profile.scss
Member-details modal pages/social-member-details.scss
Membership / subscription pages/social-membership.scss
Announcements / boards pages/social-announcement.scss

Ongoing work

A full design-consistency pass is planned: codify the above into a project DESIGN.md via gstack /design-consultation, then enforce it page-by-page with /design-review --deep against the live portal. Page-header unification is the top item.