mirror of
https://github.com/itflow-org/itflow
synced 2026-11-11 15:07:24 +00:00
332 lines
8.0 KiB
CSS
332 lines
8.0 KiB
CSS
/* Ticket detail page */
|
|
|
|
/*
|
|
* Page layout.
|
|
*
|
|
* Desktop: two columns that both start at the top - the header and the
|
|
* conversation on the left, the sidebar (Details, Contact, Tasks, Linked,
|
|
* History) on the right, so the ticket's properties sit beside its title
|
|
* instead of in a strip that wrapped onto a second row.
|
|
*
|
|
* Phone: one column. Left alone, the whole sidebar would land under the
|
|
* conversation and put status and priority at the bottom of a long page. The
|
|
* sidebar wrapper steps aside (display: contents) so its cards become items of
|
|
* the column, and `order` lifts Details up between the header and the
|
|
* conversation while the other sidebar cards stay below it.
|
|
*/
|
|
.ticket-layout {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.ticket-layout-header {
|
|
order: 0;
|
|
}
|
|
|
|
.ticket-layout-main {
|
|
order: 2;
|
|
min-width: 0;
|
|
}
|
|
|
|
.ticket-layout-side {
|
|
display: contents;
|
|
}
|
|
|
|
.ticket-layout-side > * {
|
|
order: 3;
|
|
}
|
|
|
|
.ticket-layout-side > .ticket-details {
|
|
order: 1;
|
|
}
|
|
|
|
@media (min-width: 992px) {
|
|
.ticket-layout {
|
|
display: grid;
|
|
grid-template-columns: minmax(0, 1fr) 300px;
|
|
/* The second row soaks up the height, so the header row is only as tall as the header */
|
|
grid-template-rows: auto 1fr;
|
|
grid-template-areas:
|
|
"header side"
|
|
"main side";
|
|
column-gap: 1rem;
|
|
align-items: start;
|
|
}
|
|
|
|
.ticket-layout-header {
|
|
grid-area: header;
|
|
}
|
|
|
|
.ticket-layout-main {
|
|
grid-area: main;
|
|
}
|
|
|
|
.ticket-layout-side {
|
|
display: block;
|
|
grid-area: side;
|
|
min-width: 0;
|
|
}
|
|
}
|
|
|
|
@media (min-width: 1400px) {
|
|
.ticket-layout {
|
|
grid-template-columns: minmax(0, 1fr) 340px;
|
|
}
|
|
}
|
|
|
|
/* Header */
|
|
|
|
/* The subject is the page's real heading, so let it breathe */
|
|
.ticket-subject {
|
|
font-weight: 600;
|
|
word-break: break-word;
|
|
}
|
|
|
|
/* The pencil next to the subject shouldn't drag the heading's line height around */
|
|
.ticket-subject .btn-tool {
|
|
font-size: 0.9rem;
|
|
vertical-align: middle;
|
|
}
|
|
|
|
.ticket-meta {
|
|
font-size: 0.85rem;
|
|
color: var(--bs-secondary-color);
|
|
word-break: break-word;
|
|
}
|
|
|
|
/*
|
|
* Details panel - one property per row, label on the left, value on the right.
|
|
*
|
|
* A value that can be changed is a full-width button: it highlights on hover and
|
|
* shows a small pencil, which is how the page says "click to change" without a
|
|
* column of blue links. Values that can't be changed get the same box with no
|
|
* hover, so every row lines up whether it is editable or not.
|
|
*/
|
|
.ticket-prop {
|
|
display: grid;
|
|
grid-template-columns: 6.25rem minmax(0, 1fr);
|
|
align-items: center;
|
|
min-height: 2.4rem;
|
|
}
|
|
|
|
.ticket-prop + .ticket-prop {
|
|
border-top: 1px solid var(--bs-border-color-translucent);
|
|
}
|
|
|
|
.ticket-prop dt {
|
|
margin: 0;
|
|
padding-left: 0.5rem;
|
|
font-size: 0.8rem;
|
|
font-weight: 500;
|
|
color: var(--bs-secondary-color);
|
|
}
|
|
|
|
.ticket-prop dd {
|
|
margin: 0;
|
|
min-width: 0;
|
|
}
|
|
|
|
.ticket-prop-edit,
|
|
.ticket-prop-static {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 0.5rem;
|
|
width: 100%;
|
|
min-width: 0;
|
|
padding: 0.3rem 0.5rem;
|
|
border: 0;
|
|
border-radius: var(--bs-border-radius);
|
|
background: transparent;
|
|
color: var(--bs-body-color);
|
|
font: inherit;
|
|
text-align: left;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.ticket-prop-edit:hover,
|
|
.ticket-prop-edit:focus-visible,
|
|
.ticket-prop-edit[aria-expanded="true"] {
|
|
background-color: var(--bs-tertiary-bg);
|
|
color: var(--bs-body-color);
|
|
}
|
|
|
|
.ticket-prop-edit-icon {
|
|
flex: 0 0 auto;
|
|
font-size: 0.7rem;
|
|
color: var(--bs-secondary-color);
|
|
opacity: 0;
|
|
transition: opacity 0.15s;
|
|
}
|
|
|
|
.ticket-prop-edit:hover .ticket-prop-edit-icon,
|
|
.ticket-prop-edit:focus-visible .ticket-prop-edit-icon,
|
|
.ticket-prop-edit[aria-expanded="true"] .ticket-prop-edit-icon {
|
|
opacity: 1;
|
|
}
|
|
|
|
/* Touch screens have no hover, so the pencil stays faintly visible there */
|
|
@media (hover: none) {
|
|
.ticket-prop-edit-icon {
|
|
opacity: 0.6;
|
|
}
|
|
}
|
|
|
|
/* A second line under a value - the SLA plan name, Onsite/Remote */
|
|
.ticket-prop-sub {
|
|
display: block;
|
|
font-size: 0.8rem;
|
|
color: var(--bs-secondary-color);
|
|
}
|
|
|
|
.ticket-prop .badge {
|
|
font-size: 0.78rem;
|
|
font-weight: 600;
|
|
/* Badges never wrap by default, and an SLA countdown can be wider than a narrow column */
|
|
white-space: normal;
|
|
text-align: left;
|
|
}
|
|
|
|
/* Small uppercase headings inside the Linked and History cards */
|
|
.ticket-link-heading {
|
|
font-size: 0.72rem;
|
|
font-weight: 600;
|
|
letter-spacing: 0.04em;
|
|
text-transform: uppercase;
|
|
color: var(--bs-secondary-color);
|
|
}
|
|
|
|
/* Tasks - the progress count lives in the card heading, the one place it is shown */
|
|
.ticket-task-count {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.4rem;
|
|
font-size: 0.8rem;
|
|
font-weight: 400;
|
|
color: var(--bs-secondary-color);
|
|
vertical-align: middle;
|
|
}
|
|
|
|
.ticket-task-progress {
|
|
width: 48px;
|
|
height: 5px;
|
|
}
|
|
|
|
.ticket-task-table td {
|
|
vertical-align: top;
|
|
padding-top: 0.45rem;
|
|
padding-bottom: 0.45rem;
|
|
}
|
|
|
|
.ticket-task-check {
|
|
width: 1.75rem;
|
|
}
|
|
|
|
.ticket-task-table .drag-handle {
|
|
cursor: grab;
|
|
opacity: 0.4;
|
|
}
|
|
|
|
.ticket-task-table tr:hover .drag-handle {
|
|
opacity: 1;
|
|
}
|
|
|
|
/* History - label/value pairs in two columns */
|
|
.ticket-history-facts {
|
|
display: grid;
|
|
grid-template-columns: auto minmax(0, 1fr);
|
|
column-gap: 0.75rem;
|
|
row-gap: 0.4rem;
|
|
font-size: 0.875rem;
|
|
}
|
|
|
|
.ticket-history-facts dt {
|
|
font-weight: 500;
|
|
color: var(--bs-secondary-color);
|
|
}
|
|
|
|
.ticket-history-facts dd {
|
|
margin: 0;
|
|
}
|
|
|
|
/* Conversation - the coloured edge says who wrote it and who can see it */
|
|
.ticket-reply.border-start {
|
|
border-left-width: 4px !important;
|
|
}
|
|
|
|
/*
|
|
* Dark mode: Bootstrap's "dark" is the page colour there, so the ticket reference,
|
|
* the Internal badge and an internal note's edge would all vanish into the card.
|
|
* Lift them to a mid grey that still reads as the dark/neutral one.
|
|
*/
|
|
[data-bs-theme="dark"] .ticket-ref,
|
|
[data-bs-theme="dark"] .ticket-badge-internal {
|
|
background-color: #495057 !important;
|
|
color: #fff !important;
|
|
}
|
|
|
|
/* A public note - seen in the portal, not emailed - is the quieter of the two public badges */
|
|
.ticket-badge-note {
|
|
background-color: var(--bs-info-bg-subtle);
|
|
color: var(--bs-info-text-emphasis);
|
|
border: 1px solid var(--bs-info-border-subtle);
|
|
}
|
|
|
|
/* "Emailed to ..." on a reply, and who each one went to */
|
|
.ticket-reply-emailed {
|
|
text-decoration: none;
|
|
}
|
|
|
|
.ticket-reply-emailed:hover,
|
|
.ticket-reply-emailed:focus-visible {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
.ticket-reply-recipients {
|
|
padding: 0.5rem 0.75rem;
|
|
border-radius: var(--bs-border-radius);
|
|
background-color: var(--bs-tertiary-bg);
|
|
}
|
|
|
|
[data-bs-theme="dark"] .ticket-reply.border-dark {
|
|
border-left-color: #6c757d !important;
|
|
}
|
|
|
|
/* The "who will see this" line under the reply type buttons */
|
|
.ticket-reply-audience {
|
|
padding: 0.5rem 0.75rem;
|
|
border-radius: var(--bs-border-radius);
|
|
background-color: var(--bs-tertiary-bg);
|
|
color: var(--bs-secondary-color);
|
|
}
|
|
|
|
.ticket-reply-audience strong {
|
|
color: var(--bs-body-color);
|
|
}
|
|
|
|
/*
|
|
* Bootstrap cancels hover on any .btn following a .btn-check (twbs #31149 / PR #37026):
|
|
* a checked outline toggle and an unchecked one looked identical while hovered, so you
|
|
* could not read the control's state without moving the pointer away. Correct, but the
|
|
* selector also catches the UNCHECKED buttons, and with nothing preselected here that
|
|
* leaves the whole strip with no feedback at all.
|
|
*
|
|
* Give the unchecked ones a NEUTRAL tint - not the variant fill, which is what checked
|
|
* looks like and would reintroduce exactly the ambiguity #31149 was about. Upstream's
|
|
* color and border-color still apply, so only the background moves.
|
|
*/
|
|
#replyTypePicker .btn-check:not(:checked) + .btn:hover {
|
|
background-color: var(--bs-secondary-bg);
|
|
}
|
|
|
|
/* Paper gets one column, conversation first */
|
|
@media print {
|
|
.ticket-layout {
|
|
display: block;
|
|
}
|
|
|
|
.ticket-layout-side {
|
|
display: block;
|
|
}
|
|
}
|