Files
Project-SDE-WP-Suite/html/wp-chrome.css
n.siegfried 61d1cf4bff Wave 2: form cleanups from the site comments, plus localization, project switcher and global search
Site comments (8/3)
- BIM card: LOD removed, IFF # added next to the coordination status, and required
  once that status is "Signed off (IFF)" — an unnumbered sign-off isn't traceable.
  A LOD already stored on a package is preserved and shown as legacy, not blanked.
- The blue "from SOP types" subtext under a field is now a SOP chip on the label
  with the detail in a tooltip. The chip stays visible rather than hover-only:
  field tablets have no hover, and "this came from the SOP" is the part that
  matters. The hint elements stay in the DOM (hidden) so the code writing to them
  keeps working; an observer mirrors their text into the tooltip.
- Specification Section is no longer typed per package. Each WP type carries a
  spec section on the SOP; the field is read-only in the Creator and follows the
  type, with the SOP's spec folder linked underneath. This reads both spec
  comments as one intent — stop typing it, derive it.
- Assignees and Distribution are multi-selects over the SOP project team, showing
  each person's job function, with the CM pre-added to Distribution (removable per
  package) and a free-text option for people with no account. The stored display
  strings are unchanged so print/export/dashboard keep working; account ids ride
  alongside for the notification work in wave 3.

Localization + time
- Per-user locale/timezone (Language & time in the user menu), an app-wide default
  in the admin console, then the browser. Timezones are validated against the
  server's zoneinfo and the picker is fed from it. Calendar dates are formatted
  from their parts so a due date never reads a day early in another zone.
- Every displayed timestamp now goes through the shared helpers.

Top-bar chrome
- Project switcher beside the logo and a centered global search, injected into
  either generation of top bar; skipped in an iframe so the embedded Creator
  doesn't get a second one. Ctrl/Cmd-K focuses search.
- GET /api/search covers work packages, projects and SOPs, scoped to the caller's
  projects, hiding archived packages, with LIKE wildcards escaped.

Fixed along the way: showForm() cleared every card's inline display, which undid
applyKind() — so the Package Type and BIM cards reappeared on an install-only
project. Split out applyKindVisibility() and re-apply it there.

Verified: 100 API checks on a fresh database (44 permissions + 22 password reset +
34 search/localization), 24 driven UI checks against the real Creator page in
headless Chrome (SOP chips, both people pickers, spec auto-fill, critical tags,
BIM suppression), and the chrome harness on both bar styles. Screenshots reviewed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-03 15:17:51 -07:00

212 lines
6.6 KiB
CSS

/* ============================================================================
SHARED APP CHROME — project switcher + global search
----------------------------------------------------------------------------
Injected by wp-chrome.js into whichever top bar a page has: the dark UI-shell
bar (.wp-appbar on index / admin / field) or the older light bars (.header on
the SOP suite and the WP creator). The two live side by side, so every colour
here comes from a variable that wp-chrome.js sets per host bar — the markup and
behaviour are identical on both.
============================================================================ */
.wp-chrome {
display: flex;
align-items: center;
gap: 10px;
min-width: 0; /* lets the search shrink instead of overflowing */
flex: 1 1 auto;
}
/* Light host bar (the two tool pages) */
.wp-chrome {
--wpc-fg: #161616;
--wpc-fg-dim: #525252;
--wpc-bg: #ffffff;
--wpc-bg-soft: #f4f4f4;
--wpc-border: #c6c6c6;
--wpc-hover: #e8e8e8;
--wpc-accent: #0f62fe;
}
/* Dark host bar (the UI-shell appbar) */
.wp-chrome[data-bar="dark"] {
--wpc-fg: #ffffff;
--wpc-fg-dim: #c6c6c6;
--wpc-bg: #262626;
--wpc-bg-soft: #393939;
--wpc-border: #6f6f6f;
--wpc-hover: #353535;
--wpc-accent: #78a9ff;
}
/* ── project switcher ─────────────────────────────────────────────────────── */
.wpc-proj { position: relative; flex: 0 0 auto; }
.wpc-proj-btn {
display: flex;
align-items: center;
gap: 10px;
max-width: 280px;
padding: 5px 10px;
background: transparent;
border: 1px solid transparent;
border-radius: 3px;
color: var(--wpc-fg);
font: inherit;
font-size: 13px;
line-height: 1.25;
text-align: left;
cursor: pointer;
}
.wpc-proj-btn:hover { background: var(--wpc-hover); border-color: var(--wpc-border); }
.wpc-proj-btn[aria-expanded="true"] { background: var(--wpc-hover); border-color: var(--wpc-border); }
.wpc-proj-labels { min-width: 0; }
.wpc-proj-kicker {
display: block;
font-size: 10px;
font-weight: 600;
letter-spacing: .06em;
text-transform: uppercase;
color: var(--wpc-fg-dim);
}
.wpc-proj-name {
display: block;
font-weight: 600;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 240px;
}
.wpc-caret { flex: 0 0 auto; align-self: flex-end; margin-bottom: 3px; font-size: 10px;
line-height: 1; color: var(--wpc-fg-dim); }
/* ── dropdown / results panel (shared shell) ──────────────────────────────── */
.wpc-pop {
position: absolute;
top: calc(100% + 6px);
left: 0;
z-index: 2000;
min-width: 320px;
max-width: min(460px, 92vw);
max-height: min(70vh, 560px);
overflow-y: auto;
background: #fff;
color: #161616;
border: 1px solid #e0e0e0;
box-shadow: 0 8px 28px rgba(20, 30, 50, .22);
border-radius: 4px;
}
.wpc-pop[hidden] { display: none; }
.wpc-pop-head {
padding: 9px 12px 6px;
font-size: 10px;
font-weight: 700;
letter-spacing: .07em;
text-transform: uppercase;
color: #6f6f6f;
border-bottom: 1px solid #f0f0f0;
}
.wpc-item {
display: block;
width: 100%;
padding: 8px 12px;
background: transparent;
border: 0;
border-left: 3px solid transparent;
text-align: left;
font: inherit;
font-size: 13px;
color: #161616;
cursor: pointer;
text-decoration: none;
}
.wpc-item:hover, .wpc-item.is-active { background: #f4f4f4; }
.wpc-item.is-current { border-left-color: #0f62fe; background: #edf5ff; }
.wpc-item-title { display: block; font-weight: 600; }
.wpc-item-sub { display: block; font-size: 11.5px; color: #6f6f6f; }
.wpc-item-mono { font-family: 'IBM Plex Mono', ui-monospace, Consolas, monospace; font-size: 12px; color: #0f62fe; }
.wpc-empty { padding: 14px 12px; font-size: 13px; color: #6f6f6f; }
.wpc-pop-foot {
padding: 8px 12px;
border-top: 1px solid #f0f0f0;
display: flex;
gap: 8px;
flex-wrap: wrap;
}
.wpc-foot-btn {
font: inherit;
font-size: 12px;
font-weight: 600;
padding: 5px 10px;
border: 1px solid #c6c6c6;
background: #fff;
color: #161616;
border-radius: 3px;
cursor: pointer;
text-decoration: none;
}
.wpc-foot-btn:hover { border-color: #0f62fe; color: #0f62fe; }
/* ── global search ────────────────────────────────────────────────────────── */
/* Centered in the bar: the wrapper takes the free space and centres a capped box,
which keeps the field mid-screen without absolute positioning (so it can never
sit on top of the bar's own buttons). */
.wpc-search {
position: relative;
flex: 1 1 auto;
display: flex;
justify-content: center;
min-width: 0;
}
.wpc-search-box {
position: relative;
width: 100%;
max-width: 560px;
display: flex;
align-items: center;
gap: 8px;
padding: 0 10px;
height: 34px;
background: var(--wpc-bg);
border: 1px solid var(--wpc-border);
border-radius: 3px;
}
.wpc-search-box:focus-within { outline: 2px solid var(--wpc-accent); outline-offset: -2px; }
.wpc-search-ico { flex: 0 0 auto; color: var(--wpc-fg-dim); font-size: 13px; }
.wpc-search-input {
flex: 1 1 auto;
min-width: 0;
background: transparent;
border: 0;
outline: none;
color: var(--wpc-fg);
font: inherit;
font-size: 13.5px;
}
.wpc-search-input::placeholder { color: var(--wpc-fg-dim); }
.wpc-kbd {
flex: 0 0 auto;
font-family: 'IBM Plex Mono', ui-monospace, Consolas, monospace;
font-size: 10.5px;
color: var(--wpc-fg-dim);
border: 1px solid var(--wpc-border);
border-radius: 3px;
padding: 1px 5px;
white-space: nowrap;
}
.wpc-search .wpc-pop { left: 50%; transform: translateX(-50%); min-width: min(560px, 92vw); }
.wpc-clear {
flex: 0 0 auto; background: transparent; border: 0; cursor: pointer;
color: var(--wpc-fg-dim); font: inherit; font-size: 14px; line-height: 1; padding: 2px 4px;
}
.wpc-clear:hover { color: var(--wpc-fg); }
/* ── narrow screens ───────────────────────────────────────────────────────── */
@media (max-width: 900px) {
.wpc-search-box { max-width: none; }
.wpc-kbd { display: none; }
.wpc-proj-btn { max-width: 190px; }
.wpc-proj-name { max-width: 150px; }
}
@media (max-width: 620px) {
/* Keep the switcher (you must be able to change project) and let the search
collapse to an icon-width field rather than pushing the bar out of shape. */
.wpc-proj-kicker { display: none; }
.wpc-search { flex: 1 1 120px; }
}