diff --git a/app/assets/images/activity.svg b/app/assets/images/activity.svg index 8c58e62ec..c7c24e67f 100644 --- a/app/assets/images/activity.svg +++ b/app/assets/images/activity.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/images/alert.svg b/app/assets/images/alert.svg deleted file mode 100644 index 90c7c0b2d..000000000 --- a/app/assets/images/alert.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/assets/images/blob.svg b/app/assets/images/blob.svg deleted file mode 100644 index 7dfcb310b..000000000 --- a/app/assets/images/blob.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/assets/images/calendar-add.svg b/app/assets/images/calendar-add.svg deleted file mode 100644 index faceba80b..000000000 --- a/app/assets/images/calendar-add.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/assets/images/calendar.svg b/app/assets/images/calendar.svg deleted file mode 100644 index 9e25f1564..000000000 --- a/app/assets/images/calendar.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/assets/images/card-add.svg b/app/assets/images/card-add.svg deleted file mode 100644 index 8767b6117..000000000 --- a/app/assets/images/card-add.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/assets/images/cards.svg b/app/assets/images/cards.svg deleted file mode 100644 index 2892ca629..000000000 --- a/app/assets/images/cards.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/assets/images/chart.svg b/app/assets/images/chart.svg deleted file mode 100644 index 8a42e538e..000000000 --- a/app/assets/images/chart.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/assets/images/closure.svg b/app/assets/images/closure.svg deleted file mode 100644 index 9a72ca8da..000000000 --- a/app/assets/images/closure.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/assets/images/comment.svg b/app/assets/images/comment.svg index 26eb50ca9..2cc709702 100644 --- a/app/assets/images/comment.svg +++ b/app/assets/images/comment.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/images/drag.svg b/app/assets/images/drag.svg deleted file mode 100644 index 26b655f04..000000000 --- a/app/assets/images/drag.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/assets/images/grid.svg b/app/assets/images/grid.svg deleted file mode 100644 index fa6bca113..000000000 --- a/app/assets/images/grid.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/assets/images/history.svg b/app/assets/images/history.svg deleted file mode 100644 index f36d73631..000000000 --- a/app/assets/images/history.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/assets/images/hourglass.svg b/app/assets/images/hourglass.svg deleted file mode 100644 index 50d90d9c9..000000000 --- a/app/assets/images/hourglass.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/assets/images/inbox.svg b/app/assets/images/inbox.svg deleted file mode 100644 index 50252472c..000000000 --- a/app/assets/images/inbox.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/assets/images/menu.svg b/app/assets/images/menu.svg deleted file mode 100644 index 44e889047..000000000 --- a/app/assets/images/menu.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/assets/images/picture-add.svg b/app/assets/images/picture-add.svg index a64cf38d6..63fca5189 100644 --- a/app/assets/images/picture-add.svg +++ b/app/assets/images/picture-add.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/assets/images/picture-double.svg b/app/assets/images/picture-double.svg deleted file mode 100644 index f3a34a736..000000000 --- a/app/assets/images/picture-double.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/assets/images/sort-ascending.svg b/app/assets/images/sort-ascending.svg deleted file mode 100644 index 0c4767d23..000000000 --- a/app/assets/images/sort-ascending.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/assets/images/sort-descending.svg b/app/assets/images/sort-descending.svg deleted file mode 100644 index cadc3129c..000000000 --- a/app/assets/images/sort-descending.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/assets/images/temperature.svg b/app/assets/images/temperature.svg deleted file mode 100644 index 7f02650ac..000000000 --- a/app/assets/images/temperature.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/app/assets/stylesheets/animation.css b/app/assets/stylesheets/animation.css index c2a510c18..c99081856 100644 --- a/app/assets/stylesheets/animation.css +++ b/app/assets/stylesheets/animation.css @@ -9,16 +9,6 @@ } /* Keyframes */ - @keyframes float-up-left { - 0% { transform: translate(10px, 20px); } - 100% { transform: translate(0, 0); } - } - - @keyframes float-down-right { - 0% { transform: translate(-10px, -20px); } - 100% { transform: translate(0, 0); } - } - @keyframes react { 0% { transform: scale(0.3); opacity: 0; } 50% { transform: scale(1.15); opacity: 1; } @@ -36,30 +26,4 @@ 50% { transform: translateX(-1rem); } 75% { transform: translateX(1rem); } } - - @keyframes wobble { - 0% { transform: rotate(calc(var(--card-rotate) + 90deg)); } - 15% { border-radius: 66% 34% 72% 28% / 39% 63% 37% 61%; } - 25% { border-radius: 55% 47% 62% 40% / 58% 50% 52% 44%; } - 33% { border-radius: 46% 54% 61% 39% / 50% 51% 49% 50%; } - 50% { border-radius: 54% 46% 61% 39% / 57% 49% 51% 43%; } - 75% { border-radius: 53% 45% 60% 38% / 56% 48% 50% 42%; } - } - - @keyframes wobble-alt { - 0% { transform: rotate(calc(var(--card-rotate) + -90deg)); } - 12% { border-radius: 66% 34% 72% 28% / 39% 63% 37% 61%; } - 25% { border-radius: 53% 45% 60% 38% / 56% 48% 50% 42%; } - 33% { border-radius: 55% 47% 62% 40% / 58% 50% 52% 44%; } - 50% { border-radius: 46% 54% 61% 39% / 50% 51% 49% 50%; } - 75% { border-radius: 54% 46% 61% 39% / 57% 49% 51% 43%; } - } - - @keyframes wobble-img { - 15% { border-radius: 66% 34% 72% 28% / 39% 63% 37% 61%; } - 25% { border-radius: 55% 47% 62% 40% / 58% 50% 52% 44%; } - 33% { border-radius: 46% 54% 61% 39% / 50% 51% 49% 50%; } - 50% { border-radius: 54% 46% 61% 39% / 57% 49% 51% 43%; } - 75% { border-radius: 53% 45% 60% 38% / 56% 48% 50% 42%; } - } } diff --git a/app/assets/stylesheets/avatars.css b/app/assets/stylesheets/avatars.css index 6d0094f75..c5ee440d7 100644 --- a/app/assets/stylesheets/avatars.css +++ b/app/assets/stylesheets/avatars.css @@ -24,42 +24,6 @@ } } - .avatar__group { - --avatar-size: 2.5ch; - - block-size: 5ch; - display: grid; - gap: 1px; - grid-template-columns: 1fr 1fr; - grid-template-rows: min-content; - inline-size: 5ch; - place-content: center; - - .avatar { - margin: auto; - } - - &:where(:has(> :last-child:nth-child(2))) { - --avatar-size: 3.5ch; - - > :first-child { - margin-block-end: 1.5ch; - margin-inline-end: -0.75ch; - } - - > :last-child { - margin-block-start: 1.5ch; - margin-inline-start: -0.75ch; - } - } - - &:where(:has(> :last-child:nth-child(3))) { - > :last-child { - margin-inline: 1.25ch -1.25ch; - } - } - } - .avatar__form { display: grid; grid-template-columns: 1fr auto 1fr; diff --git a/app/assets/stylesheets/bubbles.css b/app/assets/stylesheets/bubbles.css deleted file mode 100644 index 509cb62d0..000000000 --- a/app/assets/stylesheets/bubbles.css +++ /dev/null @@ -1,493 +0,0 @@ -:root { - --bubble-shape: 54% 46% 61% 39% / 57% 49% 51% 43%; - --bubble-shift: 10deg; - --bubble-size-one: 14cqi; - --bubble-size-two: 16cqi; - --bubble-size-three: 18cqi; - --bubble-size-four: 20cqi; - --bubble-size-five: 22cqi; -} - -@layer components { - .bubbles { - --column-gap: 2cqi; - --row-gap: 1cqi; - - margin-block: clamp(var(--block-space), 3%, calc(var(--block-space) * 2)); - - > * { - flex-shrink: 1; - } - } - - .something-to-rename { - --bubble-background: radial-gradient(circle at center, color(from var(--bubble-color) srgb r g b / 0.25), color(from var(--bubble-color) srgb r g b / 0.05)); - --bubble-border-width: 0.2rem; - --hover-size: 0; - - aspect-ratio: 1; - block-size: var(--bubble-size); - color: var(--bubble-color, currentColor); - container-type: inline-size; - display: grid; - place-items: center; - position: relative; - transition: 0.2s ease; - - .bubbles & { - &:nth-child(1) { order: 5; } - &:nth-child(2) { order: 3; } - &:nth-child(3) { order: 3; } - &:nth-child(4) { order: 7; } - &:nth-child(5) { order: 9; } - &:nth-child(6) { order: 5; } - &:nth-child(7) { order: 4; } - &:nth-child(8) { order: 9; } - &:nth-child(9) { order: 3; } - &:nth-child(10) { order: 7; } - &:nth-of-type(n+6) { - align-self: start; - } - } - - [data-turbo-preview] & { animation: none; } - - > * { - grid-area: 1/1; - } - - .bubble__perma & { - --bubble-border-width: 0.3rem; - --bubble-size: 40dvh !important; - - z-index: 1; - } - } - .bubble__detail { - --bubble-border-color: color-mix(in srgb, var(--bubble-color) 30%, var(--color-bg)); - --bubble-border-width: 0.15em; - - aspect-ratio: 1; - background: var(--color-bg); - block-size: auto; - border: var(--bubble-border-width) solid var(--bubble-border-color); - border-radius: var(--bubble-shape); - display: flex; - font-size: 5cqi; - font-weight: 800; - line-height: 1; - max-inline-size: 18ch; - padding: 1em; - place-content: center; - place-items: center; - position: absolute; - scale: 1; - text-overflow: ellipsis; - transform: none; - transition: transform 200ms ease-out; - white-space: nowrap; - z-index: 1; - - a { - color: var(--bubble-color); - } - - &.bubble__assignee { - font-size: 4.5cqi; - inset: 8em auto auto -1.7em; - padding: 0.2em; - - + & { - inset: 4em auto auto -1em; - - + & { - inset: 1em auto auto 2em; - } - } - - .avatar { - border-radius: var(--bubble-shape); - } - - @media (hover: hover) { - .bubbles .something-to-rename:not(.popped):hover & { - transform: translate(0, -1rem); - } - - .bubbles .something-to-rename:not(.popped):hover & + & { - transform: translate(1rem, -1rem); - } - - .bubbles .something-to-rename:not(.popped):hover & + & + & { - transform: translate(1.5rem, -0.5rem);; - } - } - - .assignee__name { - display: none; - - .bubble__perma & { - color: var(--bubble-color); - display: inline-block; - font-size: 0.9em; - font-weight: normal; - inline-size: 15ch; - inset: 0.3em 3.6em auto auto; - position: absolute; - text-align: end; - white-space: normal; - } - } - } - - &.bubble__comments { - --arrow-size: 1.5em; - --border-size: var(--bubble-border-width); - - aspect-ratio: 9/6; - inset: auto auto 2em -1em; - - &::before { - aspect-ratio: 2; - background: var(--bubble-border-color); - clip-path: polygon(50% 100%, 100% 0, 0 0); - inline-size: var(--arrow-size); - content: ""; - display: block; - inset-block-end: auto; - inset-block-start: 94%; - inset-inline-start: 66%; - position: absolute; - transform: translateX(-50%) rotate(-20deg); - } - - &::after { - aspect-ratio: 2; - background: var(--color-bg); - clip-path: polygon(50% 100%, 100% 0, 0 0); - inline-size: var(--arrow-size); - content: ""; - display: block; - inset-block-end: auto; - inset-block-start: calc(94% - var(--border-size) * 1.5); - inset-inline-start: 64%; - position: absolute; - transform: translateX(-50%) rotate(-20deg); - } - - @media (hover: hover) { - .bubbles .something-to-rename:not(.popped):hover & { - transform: translate(-0.5rem, -2rem); - } - } - } - - &.bubble__date { - --rotation: -45deg; - - aspect-ratio: 5/7; - cursor: pointer; - inset: 1cqb 1cqi auto auto; - transform: rotate(var(--rotation)); - - .bubble__date-text { - transform: rotate(calc(var(--rotation) * -1)); - } - - @media (hover: hover) { - .bubbles .something-to-rename:not(.popped):hover & { - transform: rotate(calc(var(--rotation) + var(--bubble-shift) * 1)) translate(0rem, 0.5rem); - } - } - } - - @media (hover: hover) { - .bubbles .something-to-rename:not(.popped):hover & { - transform: translate(1rem, 1rem); - } - - .bubbles .something-to-rename:not(.popped):hover & + & { - transform: translate(0, -1rem); - } - - .bubbles .something-to-rename:not(.popped):hover & + & + & { - transform: translate(-1rem, -1rem); - } - } - } - - .bubble__image { - border: none; - border-radius: var(--bubble-shape); - block-size: 100cqi; - inline-size: 100cqi; - overflow: hidden; - pointer-events: none; - transform: rotate(var(--bubble-rotate)) scale(0.92); - transition: 0.2s ease; - - @media (hover: hover) { - .bubbles .something-to-rename:not(.popped):hover & { - transform: rotate(calc(var(--bubble-rotate) + var(--bubble-shift))) scale(0.9); - } - } - - img { - block-size: 100cqi; - inline-size: 100cqi; - max-inline-size: none; - object-fit: cover; - transform: rotate(calc(var(--bubble-rotate) * -1)) scale(1.1); - - &:is([src=""]) { - display: none; - } - } - - :is(.bubbles, .bubbles-list) .bubble--wobble & { - animation: wobble-img 1200ms normal forwards ease-out; - } - } - - .bubble__link { - content: ""; - inset: 0; - position: absolute; - z-index: -1; - - .bubbles & { - z-index: 1; - } - } - - .bubbles-list { - --bubble-border-width: 0.15rem; - --bubble-shift: 15deg; - --bubble-size: 1.8em; - --divider-offset: 1.2em; - --hover-size: 0; - - margin-inline: auto; - - @media (min-width: 150ch) { - margin-inline: var(--tray-size); - } - - .something-to-rename { - order: 0; - } - - .bubble__title-link { - color: var(--color-txt); - text-decoration: none; - } - - ul { - li { - border-radius: 0; - list-style: none; - padding: 0.5em var(--inline-space); - position: relative; - transition: background-color 200ms ease-out; - } - - &:not(.dragging) { - li { - @media (hover: hover) { - &:hover { - background-color: color(from var(--bubble-color) srgb r g b / 0.15); - border: 0; - } - } - } - } - } - - .avatar { - --avatar-size: 1.1em; - - > * { - font-size: 0.5em; - } - } - } - - .bubble__title-text { - font-weight: 700; - flex-grow: 1; - letter-spacing: -0.015em; - white-space: nowrap; - - .drafted & { - color: color(from var(--color-ink) srgb r g b / 0.5); - } - - &::after { - border-block-end: 1px dotted var(--color-subtle-dark); - content: ""; - flex-grow: 1; - margin-block-end: 0.25em; - } - } - - .bubble__tags { - --row-gap: 0; - - font-size: var(--text-small); - margin-block-start: 0.3cqb; - max-block-size: 4lh; - max-inline-size: 75cqi; - overflow: hidden; - text-overflow: ellipsis; - - .bubble__perma & { - font-size: var(--text-medium); - } - } - - .bubble__tag { - font-weight: 700; - max-inline-size: 75cqi; - } - - .bubble__title { - align-items: center; - display: flex; - flex-direction: column; - justify-content: center; - margin: auto; - max-block-size: 90cqi; - max-inline-size: 70cqi; - - .bubbles & { - pointer-events: none; - } - - a { - color: var(--splat-color); - - &.bubble__title-rendered { - -webkit-line-clamp: var(--lines, 4); - -webkit-box-orient: vertical; - display: -webkit-box; - font-size: 9cqi; - font-weight: 800; - line-height: 1.2; - overflow: hidden; - text-overflow: clip; - white-space: normal; - } - } - - /*textarea {*/ - /* --input-color: var(--bubble-color);*/ - /* --input-border-radius: 0;*/ - - /* font-size: 9cqi;*/ - /* font-weight: 800;*/ - /* line-height: 1.2;*/ - - /* &::selection {*/ - /* background-color: var(--bubble-color);*/ - /* color: var(--color-ink-reversed);*/ - /* }*/ - /*}*/ - - @media (hover: hover) { - .something-to-rename:has(.bubble__image img:not([src=""])):hover & { - color: var(--color-ink-reversed); - text-shadow: 0 0 0.2em var(--bubble-color), 0 0 0.2em var(--bubble-color), 0 0 0.2em var(--bubble-color); - position: relative; - z-index: 1; - } - } - } - - .bubble__shape { - background: var(--bubble-background); - block-size: var(--bubble-size, 1.2em); - border-color: var(--bubble-border-color, color-mix(in srgb, var(--bubble-color) 15%, var(--color-bg))); - border-radius: var(--bubble-shape); - border-style: var(--bubble-border-style, solid); - border-width: 1px; - inline-size: var(--bubble-size, 1.2em); - pointer-events: none; - position: relative; - transform: rotate(var(--bubble-rotate)); - transition: 200ms ease-out; - z-index: 0; - - @media (prefers-color-scheme: dark) { - --bubble-background: radial-gradient(circle at center, color(from var(--bubble-color) srgb r g b / 0.45), color(from var(--bubble-color) srgb r g b / 0.15)); - --bubble-border-color: color-mix(in srgb, var(--bubble-color) 30%, var(--color-bg)); - } - - .something-to-rename & { - --bubble-size: 100%; - } - - .drafted & { - --bubble-border-style: dashed; - } - - :is(.bubbles, .bubbles-list) .bubble--wobble & { - animation: wobble 1200ms normal forwards ease-out; - } - - .bubble--wobble:nth-child(even) & { - animation-name: wobble-alt; - animation-duration: 900ms; - } - - .popped & { - display: none; - } - - .event &, - .bucket &, - .bubbles-list & { - --bubble-background: color-mix(in srgb, var(--bubble-color) 30%, var(--color-bg)); - --bubble-border-color: color-mix(in srgb, var(--bubble-color) 40%, var(--color-bg)) - } - } - - .bubble__actions-container { - background-color: color-mix(in srgb, var(--bubble-color) 20%, var(--color-bg)); - margin-block-start: -0.7em; - position: relative; - z-index: 1; - - .btn--plain { - --btn-color: var(--bubble-color); - - text-decoration: underline; - } - - .bubble__pop-message { - color: var(--bubble-color); - } - } - - .bubble__splat { - display: none; - pointer-events: none; - transform: rotate(var(--bubble-rotate)); - - .popped & { - display: block; - fill: color-mix(in srgb, var(--bubble-color) 20%, var(--color-bg)); - position: absolute; - scale: 130%; - z-index: -1; - } - - .bubbles-list & { - block-size: var(--bubble-size); - fill: color-mix(in srgb, var(--bubble-color) 35%, var(--color-bg)); - inline-size: var(--bubble-size); - position: relative; - scale: 1; - z-index: 0; - } - } -} diff --git a/app/assets/stylesheets/buttons.css b/app/assets/stylesheets/buttons.css index 0ca763506..75c8baf10 100644 --- a/app/assets/stylesheets/buttons.css +++ b/app/assets/stylesheets/buttons.css @@ -181,10 +181,6 @@ --btn-border-color: var(--color-bg); } - .btn--small { - font-size: 0.8em; - } - .btn--success { animation: success 1s ease-out; diff --git a/app/assets/stylesheets/collections.css b/app/assets/stylesheets/collections.css deleted file mode 100644 index 4d0ad7245..000000000 --- a/app/assets/stylesheets/collections.css +++ /dev/null @@ -1,40 +0,0 @@ -@layer components { - .collection { - inline-size: min(35ch, 40%); - line-height: 1.2; - - mark { - background-color: transparent; - color: var(--color-link); - text-decoration: underline; - } - } - - .collections { - --gap: 2cqi; - --hover-size: 0; - --column-gap: var(--gap); - --row-gap: var(--gap); - - list-style: none; - padding: var(--gap); - } - - .collection__button { - position: absolute; - inset: calc((var(--btn-size) * -1) - 2cqi) 1cqi auto auto; - } - - .collection__cards { - --border-radius: 1.5em; - - margin-block: 0; - max-inline-size: 100%; - padding: 1cqi; - } - - .cards__container { - aspect-ratio: 18 / 9; - container-type: inline-size; - } -} diff --git a/app/assets/stylesheets/icons.css b/app/assets/stylesheets/icons.css index 2f0989518..1f3d193dc 100644 --- a/app/assets/stylesheets/icons.css +++ b/app/assets/stylesheets/icons.css @@ -17,41 +17,28 @@ background: none; } - .icon--activity { --svg: url("activity.svg "); } .icon--add { --svg: url("add.svg "); } - .icon--alert { --svg: url("alert.svg "); } .icon--arrow-left { --svg: url("arrow-left.svg "); } .icon--arrow-right { --svg: url("arrow-right.svg "); } .icon--art { --svg: url("art.svg "); } .icon--assigned { --svg: url("assigned.svg "); } .icon--bell-off { --svg: url("bell-off.svg "); } .icon--bell { --svg: url("bell.svg "); } - .icon--blob { --svg: url("blob.svg "); } .icon--bolt { --svg: url("bolt.svg "); } .icon--bookmark-outline { --svg: url("bookmark-outline.svg "); } .icon--bookmark { --svg: url("bookmark.svg "); } - .icon--card-add { --svg: url("card-add.svg "); } - .icon--cards { --svg: url("cards.svg "); } - .icon--calendar-add { --svg: url("calendar-add.svg "); } - .icon--calendar { --svg: url("calendar.svg "); } .icon--camera { --svg: url("camera.svg "); } .icon--caret-down { --svg: url("caret-down.svg "); } - .icon--chart { --svg: url("chart.svg "); } .icon--check { --svg: url("check.svg "); } .icon--close { --svg: url("close.svg "); } .icon--comment { --svg: url("comment.svg "); } .icon--copy-paste { --svg: url("copy-paste.svg "); } .icon--crown { --svg: url("crown.svg "); } - .icon--drag { --svg: url("drag.svg "); } .icon--email { --svg: url("email.svg "); } .icon--everyone { --svg: url("everyone.svg "); } .icon--filter { --svg: url("filter.svg "); } .icon--globe { --svg: url("globe.svg "); } - .icon--grid { --svg: url("grid.svg "); } - .icon--history { --svg: url("history.svg "); } .icon--home { --svg: url("home.svg "); } - .icon--hourglass { --svg: url("hourglass.svg "); } - .icon--inbox { --svg: url("inbox.svg "); } .icon--logout { --svg: url("logout.svg "); } .icon--menu { --svg: url("menu.svg "); } .icon--menu-dots-horizontal { --svg: url("menu-dots-horizontal.svg "); } @@ -66,7 +53,6 @@ .icon--picture-double { --svg: url("picture-double.svg "); } .icon--picture-remove { --svg: url("picture-remove.svg "); } .icon--pinned { --svg: url("pinned.svg "); } - .icon--closure { --svg: url("closure.svg "); } .icon--qr-code { --svg: url("qr-code.svg "); } .icon--reaction { --svg: url("reaction.svg "); } .icon--refresh { --svg: url("refresh.svg "); } @@ -75,11 +61,8 @@ .icon--rename { --svg: url("rename.svg "); } .icon--settings { --svg: url("settings.svg "); } .icon--share { --svg: url("share.svg "); } - .icon--sort-ascending { --svg: url("sort-ascending.svg "); } - .icon--sort-descending { --svg: url("sort-descending.svg "); } .icon--star { --svg: url("star.svg "); } .icon--tag { --svg: url("tag.svg "); } - .icon--temperature { --svg: url("temperature.svg "); } .icon--thumb-up { --svg: url("thumb-up.svg "); } .icon--trash { --svg: url("trash.svg "); } .icon--unpinned { --svg: url("unpinned.svg"); } diff --git a/app/assets/stylesheets/notifications.css b/app/assets/stylesheets/notifications.css index 45eb46929..d8779c2e6 100644 --- a/app/assets/stylesheets/notifications.css +++ b/app/assets/stylesheets/notifications.css @@ -1,4 +1,8 @@ @layer components { + .notification { + position: relative; + } + .notification-tray { inset: auto var(--inline-space) var(--block-space-half) auto; @@ -48,7 +52,7 @@ .notificiations-list--read & { --border-color: var(--color-subtle); - box-shadow: none; + box-shadow: none !important; } } diff --git a/app/assets/stylesheets/panels.css b/app/assets/stylesheets/panels.css index 86126c15e..108d7c42a 100644 --- a/app/assets/stylesheets/panels.css +++ b/app/assets/stylesheets/panels.css @@ -2,8 +2,8 @@ .panel { background-color: var(--color-bg); border: var(--panel-border-size, 1px) solid var(--panel-border-color, var(--color-subtle)); - color: var(--color-ink); border-radius: var(--panel-border-radius, 1em); + color: var(--color-ink); inline-size: var(--panel-size, 60ch); max-inline-size: 100%; padding: var(--panel-padding, calc(var(--block-space) * 2)); diff --git a/app/assets/stylesheets/pins.css b/app/assets/stylesheets/pins.css index 292f7c691..c55e0cb87 100644 --- a/app/assets/stylesheets/pins.css +++ b/app/assets/stylesheets/pins.css @@ -1,19 +1,4 @@ @layer components { - .pin-tray { - inset: auto auto var(--block-space-half) var(--inline-space); - - .pin { - --z: calc(10 - var(--position)); - - &:nth-child(7) { --position: 7; } - &:nth-child(8) { --position: 8; } - &:nth-child(9) { --position: 9; } - &:nth-child(10) { --position: 10; } - - &:nth-child(1n + 11) { display: none; } - } - } - .pin__collection { background-color: var(--card-color); font-weight: 800; @@ -51,4 +36,19 @@ .pin__title { margin-block-start: 0.3rem; } + + .pin-tray { + inset: auto auto var(--block-space-half) var(--inline-space); + + .pin { + --z: calc(10 - var(--position)); + + &:nth-child(7) { --position: 7; } + &:nth-child(8) { --position: 8; } + &:nth-child(9) { --position: 9; } + &:nth-child(10) { --position: 10; } + + &:nth-child(1n + 11) { display: none; } + } + } } diff --git a/app/assets/stylesheets/closureup.css b/app/assets/stylesheets/popup.css similarity index 100% rename from app/assets/stylesheets/closureup.css rename to app/assets/stylesheets/popup.css diff --git a/app/assets/stylesheets/translations.css b/app/assets/stylesheets/translations.css deleted file mode 100644 index 93c34e258..000000000 --- a/app/assets/stylesheets/translations.css +++ /dev/null @@ -1,35 +0,0 @@ -@layer components { - /* Language translations */ - .lanuage-list-menu { - --max-width: 40ch; - - background-color: var(--color-subtle); - border: 1px solid var(--color-subtle-dark); - border-radius: 0.5em; - inset: auto; - inline-size: max-content; - margin-inline: var(--inline-space); - max-inline-size: 40ch; - overflow: clip; - position: absolute; - z-index: 1; - - @media (max-width: 70ch) { - max-inline-size: calc(var(--max-width) - var(--inline-space)); - } - - .popover-orientation-top & { - inset-block-end: 100%; - } - } - - .language-list { - display: grid; - gap: var(--block-space-half) var(--inline-space); - grid-template-rows: min-content; - grid-template-columns: min-content 1fr; - justify-content: start; - margin: 0; - text-align: start; - } -} diff --git a/app/assets/stylesheets/trays.css b/app/assets/stylesheets/trays.css index cad63dcec..e60631c08 100644 --- a/app/assets/stylesheets/trays.css +++ b/app/assets/stylesheets/trays.css @@ -22,6 +22,7 @@ --scale: calc(1 - var(--position) / 30); --z: calc(6 - var(--position)); + display: flex; inset: auto 0 0; inline-size: var(--tray-size); outline: 0; diff --git a/app/assets/stylesheets/workflows.css b/app/assets/stylesheets/workflows.css index 4f93ce4b8..43ead2256 100644 --- a/app/assets/stylesheets/workflows.css +++ b/app/assets/stylesheets/workflows.css @@ -14,10 +14,6 @@ background-color: color(from var(--card-color) srgb r g b / 0.15); } } - - .cards-list & { - display: none; - } } .workflow-stage--current { @@ -38,30 +34,5 @@ border-radius: 0.2em; color: var(--color-ink-reversed); } - - .cards-list & { - display: flex; - background: transparent; - border-radius: 0.2em; - color: var(--color-ink); - padding: 0; - border: 0; - } - } - - .workflow__popup { - --panel-border-radius: 0.5em; - --panel-padding: 0.5em; - --panel-size: 100%; - - inline-size: auto !important; - inset: 0 auto auto 0; - margin-block-start: 1lh; - margin-inline-start: calc((var(--panel-padding) + 0.7em) * -1); - min-inline-size: 12ch; - max-inline-size: var(--panel-size) !important; - position: absolute; - transform-origin: top left; - z-index: 1; } } diff --git a/app/controllers/cards/previews_controller.rb b/app/controllers/cards/previews_controller.rb new file mode 100644 index 000000000..f8893266f --- /dev/null +++ b/app/controllers/cards/previews_controller.rb @@ -0,0 +1,8 @@ +class Cards::PreviewsController < ApplicationController + include FilterScoped + before_action :set_filter, only: :index + + def index + set_page_and_extract_portion_from @filter.cards, per_page: CardsController::PAGE_SIZE + end +end diff --git a/app/controllers/cards_controller.rb b/app/controllers/cards_controller.rb index 1485ad33f..103c05e99 100644 --- a/app/controllers/cards_controller.rb +++ b/app/controllers/cards_controller.rb @@ -1,20 +1,17 @@ +require "ostruct" + class CardsController < ApplicationController - include CollectionScoped + include CollectionScoped, FilterScoped skip_before_action :set_collection, only: :index - - before_action :set_filter, only: :index before_action :set_card, only: %i[ show edit update destroy ] - before_action :handle_display_count, only: :index - DISPLAY_COUNT_OPTIONS = [ 6, 12, 18, 24 ].freeze - DEFAULT_DISPLAY_COUNT = 6 - RECENTLY_CLOSED_LIMIT = 100 + PAGE_SIZE = 50 def index - @considering_cards = @filter.cards.considering.load_async - @doing_cards = @filter.cards.doing.load_async - @closed_cards = @filter.with(indexed_by: "closed").cards.recently_closed_first.limit(RECENTLY_CLOSED_LIMIT).load_async + @considering = page_and_filter_for @filter.with(engagement_status: "considering", indexed_by: "latest"), per_page: PAGE_SIZE + @doing = page_and_filter_for @filter.with(engagement_status: "doing", indexed_by: "latest"), per_page: PAGE_SIZE + @closed = page_and_filter_for @filter.with(indexed_by: "closed"), per_page: PAGE_SIZE end def create @@ -38,16 +35,16 @@ class CardsController < ApplicationController end private - DEFAULT_PARAMS = { indexed_by: "newest" } - - def set_filter - @filter = Current.user.filters.from_params params.reverse_merge(**DEFAULT_PARAMS).permit(*Filter::PERMITTED_PARAMS) - end - def set_card @card = @collection.cards.find params[:id] end + def page_and_filter_for(filter, per_page: nil) + OpenStruct.new \ + page: GearedPagination::Recordset.new(filter.cards, per_page:).page(1), + filter: filter + end + def card_params params.expect(card: [ :status, :title, :color, :due_on, :image, :draft_comment, tag_ids: [] ]) end @@ -55,17 +52,4 @@ class CardsController < ApplicationController def deleted_notice "Card deleted" unless @card.creating? end - - def handle_display_count - if params[:set_display_count].present? - cookies[:display_count] = params[:set_display_count] - redirect_to cards_path( - params.permit(*Filter::PERMITTED_PARAMS, :collection_ids).except(:set_display_count) - ) - end - end - - def display_count - (cookies[:display_count] || DEFAULT_DISPLAY_COUNT).to_i - end end diff --git a/app/controllers/concerns/filter_scoped.rb b/app/controllers/concerns/filter_scoped.rb new file mode 100644 index 000000000..f3d5df02c --- /dev/null +++ b/app/controllers/concerns/filter_scoped.rb @@ -0,0 +1,14 @@ +module FilterScoped + extend ActiveSupport::Concern + + included do + before_action :set_filter, only: :index + end + + private + DEFAULT_PARAMS = { indexed_by: "newest" } + + def set_filter + @filter = Current.user.filters.from_params params.reverse_merge(**DEFAULT_PARAMS).permit(*Filter::PERMITTED_PARAMS) + end +end diff --git a/app/controllers/workflows/stages_controller.rb b/app/controllers/workflows/stages_controller.rb index c85016dcc..f6422f9d6 100644 --- a/app/controllers/workflows/stages_controller.rb +++ b/app/controllers/workflows/stages_controller.rb @@ -31,6 +31,6 @@ class Workflows::StagesController < ApplicationController end def stage_params - params.expect workflow_stage: [ :name ] + params.require(:workflow_stage).permit(:name, :color) end end diff --git a/app/helpers/avatars_helper.rb b/app/helpers/avatars_helper.rb index 2a6d927f4..732825572 100644 --- a/app/helpers/avatars_helper.rb +++ b/app/helpers/avatars_helper.rb @@ -11,7 +11,7 @@ module AvatarsHelper end def avatar_tag(user, hidden_for_screen_reader: false, **options) - link_to user_path(user), title: user.name, class: "btn avatar", data: { turbo_frame: "_top" }, + link_to user_path(user), class: "btn avatar", data: { turbo_frame: "_top" }, aria: { hidden: hidden_for_screen_reader, label: user.name }, tabindex: hidden_for_screen_reader ? -1 : nil do avatar_image_tag(user, **options) @@ -19,6 +19,6 @@ module AvatarsHelper end def avatar_image_tag(user, **options) - image_tag user_avatar_path(user), aria: { hidden: "true" }, size: 48, class: ("avatar__photo" if user.avatar.attached?), **options + image_tag user_avatar_path(user), aria: { hidden: "true" }, size: 48, title: user.name, class: ("avatar__photo" if user.avatar.attached?), **options end end diff --git a/app/helpers/cards_helper.rb b/app/helpers/cards_helper.rb index c340f2827..ba75a6d4a 100644 --- a/app/helpers/cards_helper.rb +++ b/app/helpers/cards_helper.rb @@ -11,14 +11,19 @@ module CardsHelper "--card-rotate: #{value}deg;" end - def display_count_options - CardsController::DISPLAY_COUNT_OPTIONS.map do |count| - { - value: count, - label: count, - selected: @display_count == count, - id: "display-count-#{count}" - } + def cards_next_page_link(target, page:, filter:, fetch_on_visible: false, data: {}, **options) + url = cards_previews_path(target: target, page: page.next_param, **filter.as_params) + + if fetch_on_visible + data[:controller] = "#{data[:controller]} fetch-on-visible" + data[:fetch_on_visible_url_value] = url end + + link_to "Load more", + url, + id: "#{target}-load-page-#{page.next_param}", + data: { turbo_stream: true, **data }, + class: "btn txt-small", + **options end end diff --git a/app/helpers/notifications_helper.rb b/app/helpers/notifications_helper.rb index 3c5e0d680..12bc5f745 100644 --- a/app/helpers/notifications_helper.rb +++ b/app/helpers/notifications_helper.rb @@ -22,7 +22,7 @@ module NotificationsHelper end def notification_tag(notification, &) - tag.div id: dom_id(notification), class: "notification tray__item border-radius flex txt-normal" do + tag.div id: dom_id(notification), class: "notification tray__item border-radius txt-normal" do concat( link_to(notification.resource, class: "notification__content border-radius shadow fill-white flex align-start txt-align-start gap flex-item-grow max-width border txt-ink", diff --git a/app/helpers/translations_helper.rb b/app/helpers/translations_helper.rb deleted file mode 100644 index f50a397e2..000000000 --- a/app/helpers/translations_helper.rb +++ /dev/null @@ -1,29 +0,0 @@ -module TranslationsHelper - TRANSLATIONS = { - user_name: { "🇺🇸": "Enter your name", "🇪🇸": "Introduce tu nombre", "🇫🇷": "Entrez votre nom", "🇮🇳": "अपना नाम दर्ज करें", "🇩🇪": "Geben Sie Ihren Namen ein", "🇧🇷": "Insira seu nome" }, - email_address: { "🇺🇸": "Enter your email address", "🇪🇸": "Introduce tu correo electrónico", "🇫🇷": "Entrez votre adresse courriel", "🇮🇳": "अपना ईमेल पता दर्ज करें", "🇩🇪": "Geben Sie Ihre E-Mail-Adresse ein", "🇧🇷": "Insira seu endereço de email" }, - password: { "🇺🇸": "Enter your password", "🇪🇸": "Introduce tu contraseña", "🇫🇷": "Saisissez votre mot de passe", "🇮🇳": "अपना पासवर्ड दर्ज करें", "🇩🇪": "Geben Sie Ihr Passwort ein", "🇧🇷": "Insira sua senha" }, - collection_name: { "🇺🇸": "Give it a name", "🇪🇸": "Dale un nombre", "🇫🇷": "Donnez lui un nom", "🇮🇳": "इसे एक नाम दें", "🇩🇪": "Gib ihm einen Namen", "🇧🇷": "Dê-lhe um nome" } - } - - def translations_for(translation_key) - tag.dl(class: "language-list") do - TRANSLATIONS[translation_key].map do |language, translation| - concat tag.dt(language) - concat tag.dd(translation, class: "margin-none") - end - end - end - - def translation_button(translation_key) - tag.div(class: "position-relative", data: { controller: "popover", action: "keydown.esc->popover#close click@document->popover#closeOnClickOutside", popover_orientation_top_class: "popover-orientation-top" }) do - tag.button(type: "button", class: "btn", tabindex: -1, data: { action: "popover#toggle" }) do - concat image_tag("globe.svg", class: "icon", role: "presentation") - concat tag.span("Translate", class: "for-screen-reader") - end + - tag.dialog(class: "lanuage-list-menu popover shadow", data: { popover_target: "menu" }) do - translations_for(translation_key) - end - end - end -end diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb index 58b3e12d6..e0a2c4422 100644 --- a/app/helpers/users_helper.rb +++ b/app/helpers/users_helper.rb @@ -2,4 +2,10 @@ module UsersHelper def prepend_current_user_to(users_scope) users_scope.to_a.prepend(Current.user).uniq end + + def familiar_name_for(user) + names = user.name.split + return user.name if names.length == 1 + "#{names.first} #{names[1..].map { |n| "#{n[0]}." }.join}" + end end diff --git a/app/helpers/workflows_helper.rb b/app/helpers/workflows_helper.rb index 32fd5e68a..ad56ea1fe 100644 --- a/app/helpers/workflows_helper.rb +++ b/app/helpers/workflows_helper.rb @@ -9,4 +9,8 @@ module WorkflowsHelper end end end + + def stage_color(stage) + stage.color.presence || Colorable::DEFAULT_COLOR + end end diff --git a/app/javascript/initializers/custom_stream_actions.js b/app/javascript/initializers/custom_stream_actions.js new file mode 100644 index 000000000..fecb25ff5 --- /dev/null +++ b/app/javascript/initializers/custom_stream_actions.js @@ -0,0 +1,8 @@ +import { Turbo } from "@hotwired/turbo-rails" + +Turbo.StreamActions.set_css_variable = function() { + const name = this.getAttribute("name") + const value = this.getAttribute("value") + + this.targetElements.forEach(element => element.style.setProperty(name, value)) +} diff --git a/app/javascript/initializers/index.js b/app/javascript/initializers/index.js index 10fb36975..01fdd9220 100644 --- a/app/javascript/initializers/index.js +++ b/app/javascript/initializers/index.js @@ -1 +1,2 @@ import "initializers/current" +import "initializers/custom_stream_actions" diff --git a/app/models/card.rb b/app/models/card.rb index 50f2f541b..4c50d6029 100644 --- a/app/models/card.rb +++ b/app/models/card.rb @@ -15,6 +15,7 @@ class Card < ApplicationRecord scope :reverse_chronologically, -> { order created_at: :desc, id: :desc } scope :chronologically, -> { order created_at: :asc, id: :asc } + scope :latest, -> { order updated_at: :desc, id: :desc } scope :in_collection, ->(collection) { where collection: collection } scope :indexed_by, ->(index) do @@ -24,11 +25,19 @@ class Card < ApplicationRecord when "most_boosted" then ordered_by_boosts when "newest" then reverse_chronologically when "oldest" then chronologically + when "latest" then latest when "stalled" then ordered_by_staleness when "closed" then closed end end + scope :by_engagement_status, ->(status) do + case status.to_s + when "considering" then considering + when "doing" then doing + end + end + def cache_key [ super, collection&.name ].compact.join("/") end diff --git a/app/models/card/closeable.rb b/app/models/card/closeable.rb index bcc41308a..3f98cb719 100644 --- a/app/models/card/closeable.rb +++ b/app/models/card/closeable.rb @@ -1,7 +1,7 @@ module Card::Closeable extend ActiveSupport::Concern - AUTO_CLOSURE_AFTER = 30.days + AUTO_CLOSE_AFTER = 30.days included do has_one :closure, dependent: :destroy @@ -10,7 +10,7 @@ module Card::Closeable scope :active, -> { where.missing(:closure) } scope :recently_closed_first, -> { closed.order("closures.created_at": :desc) } - scope :due_to_be_closed, -> { considering.where(last_active_at: ..AUTO_CLOSURE_AFTER.ago) } + scope :due_to_be_closed, -> { considering.where(last_active_at: ..AUTO_CLOSE_AFTER.ago) } end class_methods do @@ -22,7 +22,7 @@ module Card::Closeable end def auto_close_at - last_active_at + AUTO_CLOSURE_AFTER if last_active_at + last_active_at + AUTO_CLOSE_AFTER if last_active_at end def closed? diff --git a/app/models/card/colored.rb b/app/models/card/colored.rb index 7d4ae9c54..99e934a94 100644 --- a/app/models/card/colored.rb +++ b/app/models/card/colored.rb @@ -1,9 +1,12 @@ module Card::Colored extend ActiveSupport::Concern - COLORS = %w[ #b7462b #ff63a8 #eb7a32 #6ac967 #2c6da8 #663251 ] - - included do - attribute :color, default: "#2c6da8" + def color + color_from_stage || Colorable::DEFAULT_COLOR end + + private + def color_from_stage + stage&.color&.presence if doing? + end end diff --git a/app/models/colorable.rb b/app/models/colorable.rb new file mode 100644 index 000000000..4fba4556d --- /dev/null +++ b/app/models/colorable.rb @@ -0,0 +1,10 @@ +module Colorable + extend ActiveSupport::Concern + + COLORS = %w[ #3b3633 #67695e #eb7a32 #bf7c2b #c09c6f #746b1e #2c6da8 #5d618f #663251 #ff63a8 ] + DEFAULT_COLOR = "#2c6da8" + + included do + attribute :color, default: DEFAULT_COLOR + end +end diff --git a/app/models/concerns/filter/params.rb b/app/models/concerns/filter/params.rb deleted file mode 100644 index 7c500942a..000000000 --- a/app/models/concerns/filter/params.rb +++ /dev/null @@ -1,22 +0,0 @@ -module Filter::Params - extend ActiveSupport::Concern - - PERMITTED_PARAMS = %i[ - indexed_by assignment_status collection_ids creator_ids - assignee_ids stage_ids tag_ids terms display_count - ].freeze - - def as_params - self.class.normalize_params( - indexed_by: indexed_by, - assignment_status: assignment_status, - collection_ids: collections.ids, - creator_ids: creators.ids, - assignee_ids: assignees.ids, - stage_ids: stages.ids, - tag_ids: tags.ids, - terms: terms, - display_count: display_count - ) - end -end diff --git a/app/models/filter.rb b/app/models/filter.rb index 62f89015c..1ec1a5e6c 100644 --- a/app/models/filter.rb +++ b/app/models/filter.rb @@ -20,6 +20,7 @@ class Filter < ApplicationRecord @cards ||= begin result = creator.accessible_cards.indexed_by(indexed_by) result = result.active unless indexed_by.closed? + result = result.by_engagement_status(engagement_status) if engagement_status.present? result = result.unassigned if assignment_status.unassigned? result = result.assigned_to(assignees.ids) if assignees.present? result = result.where(creator_id: creators.ids) if creators.present? diff --git a/app/models/filter/fields.rb b/app/models/filter/fields.rb index 56fca6ac7..e6028e551 100644 --- a/app/models/filter/fields.rb +++ b/app/models/filter/fields.rb @@ -1,13 +1,13 @@ module Filter::Fields extend ActiveSupport::Concern - INDEXES = %w[ most_discussed most_boosted newest oldest stalled ] + INDEXES = %w[ most_discussed most_boosted newest oldest latest stalled ] delegate :default_value?, to: :class class_methods do def default_values - { indexed_by: "most_active" } + { indexed_by: "latest" } end def default_value?(key, value) @@ -16,7 +16,7 @@ module Filter::Fields end included do - store_accessor :fields, :assignment_status, :indexed_by, :terms + store_accessor :fields, :assignment_status, :indexed_by, :terms, :engagement_status def assignment_status super.to_s.inquiry @@ -26,6 +26,10 @@ module Filter::Fields (super || default_indexed_by).inquiry end + def engagement_status + super&.inquiry + end + def terms Array(super) end diff --git a/app/models/filter/params.rb b/app/models/filter/params.rb index dd519ec84..7a4b85d60 100644 --- a/app/models/filter/params.rb +++ b/app/models/filter/params.rb @@ -4,6 +4,7 @@ module Filter::Params PERMITTED_PARAMS = [ :assignment_status, :indexed_by, + :engagement_status, assignee_ids: [], creator_ids: [], collection_ids: [], @@ -35,6 +36,7 @@ module Filter::Params def as_params {}.tap do |params| params[:indexed_by] = indexed_by + params[:engagement_status] = engagement_status params[:assignment_status] = assignment_status params[:terms] = terms params[:tag_ids] = tags.ids diff --git a/app/views/accounts/users/_user.html.erb b/app/views/accounts/users/_user.html.erb index e8e57b096..ae9326c48 100644 --- a/app/views/accounts/users/_user.html.erb +++ b/app/views/accounts/users/_user.html.erb @@ -15,7 +15,7 @@ <% end %> <%# FIXME: Move this Current.user check to a stimulus controller that just checks for admin? or the like we so we can cache user list %> - <%= button_to account_user_path(user), method: :delete, class: "btn btn--small btn--negative flex-item-no-shrink", + <%= button_to account_user_path(user), method: :delete, class: "btn txt-small btn--negative flex-item-no-shrink", disabled: !Current.user.can_administer?(user), data: { turbo_confirm: "Are you sure you want to permanently remove this person from the account?" } do %> <%= icon_tag "minus" %> diff --git a/app/views/cards/_display_count_selector.html.erb b/app/views/cards/_display_count_selector.html.erb deleted file mode 100644 index 75c3ad3ae..000000000 --- a/app/views/cards/_display_count_selector.html.erb +++ /dev/null @@ -1,37 +0,0 @@ -