Files
fizzy/app/assets/stylesheets/cards.css
T
Andy Smith cab6992555 Merge branch 'main' into collapsible-nav-sections
* main: (32 commits)
  Fix VCR fixtures
  Format
  Touch user on modification to invalidate cache
  Fix add card not working in the cards screen
  Submit and refresh results as you type terms
  Fix: When expanding filters, submitting filters should keep the filters expanded
  Invalidate cache when filter changes
  Switch to gpt-5-chat
  Reorded method and remove unnecessary param
  Add migration to convert accesses
  Handle filter toggles with JS
  Prevent glitch where you see the filter bar expanded when you clear it
  Remove unused templates
  Fix: all collections link not working after moving to turbo frame
  Restore cache I deleted by mistake
  Speed up filter expansion with turbo stream
  Fix: filtering collections not working after moving menu to turbo frame
  Respect params when loading the menu or they won't be reflected!
  Add HTTP cache for the menu
  Load main menu lazily with a turbo frame
  ...
2025-09-12 12:53:44 -05:00

483 lines
11 KiB
CSS

@layer components {
/* Base
/* ------------------------------------------------------------------------ */
.card {
--avatar-size: 2.75em;
--card-bg-color: color-mix(in srgb, var(--card-color) 4%, var(--color-canvas));
--card-padding-inline: var(--inline-space-double);
--card-padding-block: var(--block-space);
--border-color: transparent;
--border-radius: 0.2em;
--border-size: 0;
aspect-ratio: var(--card-aspect-ratio, auto);
background-color: var(--card-bg-color);
border-radius: var(--border-radius);
box-shadow: var(--shadow);
color: color-mix(in srgb, var(--card-color) 40%, var(--color-ink));
display: flex;
flex-direction: column;
inline-size: 100%;
padding: var(--card-padding-block) var(--card-padding-inline);
position: relative;
text-align: start;
z-index: 1;
@media (prefers-color-scheme: dark) {
box-shadow: 0 0 0 1px var(--color-ink-lighter);
}
.popup {
inline-size: 260px;
}
}
/* Header
/* ------------------------------------------------------------------------ */
.card__header {
align-items: center;
border-radius: var(--border-radius) 0 0 0;
display: flex;
flex-wrap: nowrap;
gap: var(--inline-space);
margin-block-start: calc(-1 * var(--card-padding-block));
margin-inline: calc(-1 * var(--card-padding-inline)) calc(-0.5 * var(--card-padding-inline));
max-inline-size: unset;
min-inline-size: 0;
.workflow-stage {
display: none;
}
}
.card__id {
flex-shrink: 0;
margin-inline-start: calc(var(--inline-space) * -1);
.card-perma &:before {
content: "No.";
opacity: 0.5;
}
}
.card__collection {
background-color: var(--card-color);
border-radius: var(--border-radius) 0 var(--border-radius) 0;
color: var(--color-ink-inverted);
display: inline-flex;
font-weight: 800;
max-inline-size: 100%;
min-inline-size: 0;
padding: var(--block-space-half) var(--inline-space) var(--block-space-half) var(--card-padding-inline);
&:has(.collection-picker__button) {
cursor: pointer;
transition: background-color 100ms ease-out;
@media (any-hover: hover) {
&:hover {
background-color: color-mix(in srgb, var(--card-color) 90%, var(--color-ink));
}
}
&:has(.btn:focus-visible) {
outline: var(--focus-ring-size) solid var(--focus-ring-color);
outline-offset: var(--focus-ring-offset);
}
}
}
.card__collection-name {
border-inline-start: 1px solid color-mix(in srgb, var(--color-ink-inverted) 33%, var(--card-color));
color: currentcolor;
display: flex;
margin-inline-start: var(--inline-space-half);
max-inline-size: 100%;
min-inline-size: 0;
padding-inline-start: calc(var(--inline-space) * 0.75);
text-transform: uppercase;
.cards--considering & {
border-inline-start: 1px solid color-mix(in srgb, var(--color-ink) 33%, var(--color-canvas));
color: color-mix(in srgb, var(--card-color) 40%, var(--color-ink));
}
}
.card__tag {
color: var(--card-color);
font-weight: 700;
}
.card__tags {
align-items: center;
color: var(--card-color);
display: flex;
min-inline-size: 0;
}
/* Body
/* ------------------------------------------------------------------------ */
.card__body {
display: flex;
flex-grow: 1;
gap: 1ch;
inline-size: 100%;
padding-block: calc(var(--card-padding-block) / 2);
@media (min-width: 640px) {
gap: var(--card-padding-inline);
}
}
.card__content {
contain: inline-size;
flex: 2 1 auto;
max-inline-size: 100%;
}
.card__title {
--input-border-radius: 0;
--input-color: color-mix(in srgb, var(--card-color) 40%, var(--color-ink));
--lines: 3;
color: inherit;
font-size: var(--text-xx-large);
font-weight: 900;
line-height: 1.3;
text-wrap: balance;
@supports not (field-sizing: content) {
&:has(textarea) {
text-wrap: unset; /* Safari is annoying if you have text-wrap: balance in textareas */
}
}
.card-field__title {
&:is(textarea)::placeholder {
color: inherit;
opacity: 0.66;
}
}
.card__title-link {
color: inherit;
}
}
.card__description {
/* Hide the empty element that Lexical saves when nothing is added to the description <p><br /></p> */
action-text-content p:only-child:has(br:only-child) {
display: none;
}
& ~ .btn {
--btn-background: var(--card-color);
--btn-color: var(--color-ink-inverted);
}
}
.card-field__description {
lexxy-toolbar {
border-block-start: 1px solid var(--color-ink-light);
margin-block-start: var(--block-margin) !important;
}
}
.card__stages {
display: flex;
flex: 0 1 auto;
flex-direction: column;
justify-self: end;
max-inline-size: 20ch;
padding-block: var(--block-space-half);
}
/* Meta
/* ------------------------------------------------------------------------ */
.card__meta {
--meta-border: 1px solid color-mix(in srgb, var(--card-color) 50%, transparent);
--meta-spacer-block: 0.5ch;
--meta-spacer-inline: 0.75ch;
align-items: center;
display: grid;
font-size: var(--text-x-small);
font-weight: 500;
grid-template-areas:
"avatars-author text-added text-updated avatars-assignees"
"avatars-author text-author text-assignees avatars-assignees";
grid-template-columns: auto auto 1fr auto;
inline-size: fit-content;
text-transform: uppercase;
strong,
.local-time-value {
font-weight: 900;
}
}
/* Assign grid areas */
.card__meta-avatars--author { grid-area: avatars-author; }
.card__meta-avatars--assignees { grid-area: avatars-assignees; }
.card__meta-text--added { grid-area: text-added; }
.card__meta-text--author { grid-area: text-author; }
.card__meta-text--updated { grid-area: text-updated; }
.card__meta-text--assignees { grid-area: text-assignees; }
.card__meta-avatars {
align-self: center;
}
.card__meta-avatars--author {
margin-inline-end: var(--meta-spacer-inline);
}
.card__meta-avatars--assignees {
display: flex;
margin-inline-start: var(--meta-spacer-inline);
.avatar {
margin-inline-end: calc(-1 * var(--meta-spacer-inline));
}
}
.card__meta-text {
line-height: 1;
white-space: nowrap;
.icon {
--icon-size: 0.9em;
margin-inline-end: 0.5ch;
vertical-align: top;
}
}
/* Top */
.card__meta-text:nth-of-type(odd) {
border-block-end: var(--meta-border);
padding-block-end: var(--meta-spacer-block);
}
/* Bottom */
.card__meta-text:nth-of-type(even) {
padding-block-start: var(--meta-spacer-block);
}
/* Left */
.card__meta-text:nth-of-type(-n+2) {
border-inline-end: var(--meta-border);
padding-inline-end: var(--meta-spacer-inline);
}
/* Right */
.card__meta-text:nth-of-type(n+3) {
padding-inline-start: var(--meta-spacer-inline);
}
@media (max-width: 639px) {
.card__meta {
inline-size: 100%;
}
.card__meta-avatars--author,
.card__meta-avatars--assignees .avatar {
display: none;
}
}
/* Closed stamp
/* ------------------------------------------------------------------------ */
.card__closed {
--stamp-color: oklch(var(--lch-green-medium) / 0.65);
align-items: center;
background-color: color-mix(in srgb, var(--card-bg-color) 90%, transparent);
border-radius: 0.2em;
border: 0.5ch solid var(--stamp-color);
color: var(--color-ink-dark);
display: flex;
flex-direction: column;
font-weight: bold;
inset: auto 1ch 1ch auto;
justify-content: center;
max-inline-size: 25ch;
min-inline-size: 16ch;
padding: 1ch;
position: absolute;
rotate: 5deg;
transform-origin: top right;
}
.card:has(.card__closed),
.card-perma:has(.card__closed) {
--card-color: var(--color-card-complete) !important;
}
.card__closed-title {
color: var(--stamp-color);
font-size: 1.3em;
font-weight: 900;
line-height: 1.2;
position: relative;
text-align: center;
text-transform: uppercase;
}
.card__closed-date {
font-family: var(--font-mono);
text-transform: uppercase;
}
.card__closed-by {
border-block-end: 1px dashed currentcolor;
}
/* Misc bits
/* ------------------------------------------------------------------------ */
.card__background {
inset: 0;
position: absolute;
z-index: -1;
img {
block-size: 100%;
border-radius: var(--border-radius);
inline-size: 100%;
object-fit: cover;
object-position: center;
opacity: 1;
transition: filter 0.2s ease-in-out, opacity 0.2s ease-in-out;
}
}
.card__link {
content: "";
inset: 0;
position: absolute;
z-index: -1;
}
.card:nth-child(2n+1) .bubble { --bubble-rotate: -90deg; }
.card:nth-child(3n+1) .bubble { --bubble-rotate: 45deg; }
/* Variants
/* ------------------------------------------------------------------------ */
.card--notification {
--card-color: var(--color-card-default);
--card-padding-inline: 1ch;
--card-padding-block: 1ch;
background-color: var(--color-canvas);
&.card--closed {
--card-color: var(--color-card-complete) !important;
}
.card__body {
padding-block-end: 0;
}
.card__collection {
font-size: var(--text-xx-small);
padding-block: 0.5ch;
padding-inline-start: var(--inline-space-double);
}
.card__header {
margin-block-start: calc(-1.1 * var(--card-padding-block));
margin-inline: calc(-1 * var(--card-padding-inline));
max-inline-size: unset;
}
.card__timestamp {
opacity: 0.66;
}
.card__notification-body {
font-size: var(--text-x-small);
}
.card__notification-meta {
font-size: var(--text-xx-small);
font-weight: 600;
text-transform: uppercase;
}
.card__notification-mentioner {
background-color: var(--color-highlight);
border-radius: 0.7em 0.2em 0.7em 0.2em;
color: inherit;
display: inline-flex;
padding: 0.1em 0.3em;
}
.card__title {
font-size: var(--text-small);
font-weight: bold;
min-block-size: 0;
}
}
.card__notification-unread-indicator {
--btn-background: var(--color-canvas);
--btn-border-color: var(--color-canvas);
--btn-icon-size: 0.75em;
--btn-padding: 0;
--btn-size: 1.25em;
position: relative;
z-index: 1;
&:before,
.icon {
transition: opacity 150ms ease;
}
/* The red dot */
&:before {
aspect-ratio: 1;
background-color: var(--color-marker);
border-radius: 50%;
content: "";
inline-size: 50%;
inset: 50% auto auto 50%;
position: absolute;
translate: -50% -50%;
}
/* The X */
.icon {
opacity: 0;
}
@media (hover: hover) {
.card:hover & {
--btn-background: transparent;
&:before { opacity: 0; }
.icon { opacity: 1; }
}
}
}
.card__collection-public-description {
max-inline-size: 66ch;
p:first-child {
margin-block-start: 0;
}
p:last-child {
margin-block-end: 0;
}
}
}