app

Local-first trade for farms and co-ops
git clone https://radroots.dev/git/app.git
Log | Files | Refs | README | LICENSE

commit 479b1a84a11891ba34bcbaeb9a3122acc5c186a3
parent d979476a5d2b580bb2a9bc038da862c57bc01f72
Author: triesap <triesap@radroots.dev>
Date:   Thu, 22 Jan 2026 04:39:41 +0000

app: port trellis css foundation

- add trellis sizing variables to ui tokens
- migrate base utility classes and animations
- add trellis sizing and form helper classes
- align list styles with migrated css utilities

Diffstat:
Mapp/assets/styles.css | 332+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcrates/ui-tokens/assets/tokens.css | 7+++++++
2 files changed, 339 insertions(+), 0 deletions(-)

diff --git a/app/assets/styles.css b/app/assets/styles.css @@ -35,6 +35,23 @@ opacity: 0.5; pointer-events: none; } + + button:focus, + select:focus { + outline: none; + } + + select { + appearance: none; + -webkit-appearance: none; + -moz-appearance: none; + background: transparent; + background-image: none; + } + + select::-ms-expand { + display: none; + } } @layer components { @@ -66,6 +83,294 @@ backdrop-filter: blur(18px) saturate(180%); } + .scroll-hide::-webkit-scrollbar { + display: none; + } + + .scroll-hide { + -ms-overflow-style: none; + scrollbar-width: none; + } + + .fade-in { + opacity: 0; + animation: fade-in 250ms ease-in-out forwards; + } + + .fade-in-long { + opacity: 0; + animation: fade-in 350ms ease-in-out forwards; + } + + .pre-wrap-text { + white-space: pre-wrap; + } + + .flex-fluid { + width: 100%; + height: 100%; + flex: 1 0 100%; + } + + .rounded-touch { + border-radius: var(--radius-xl); + } + + .h-line { + height: var(--size-line); + min-height: var(--size-line); + } + + .h-line_button { + height: var(--size-line-button); + min-height: var(--size-line-button); + } + + .w-trellis_display { + width: var(--size-trellis-display); + min-width: var(--size-trellis-display); + } + + .w-trellis_value { + width: var(--size-trellis-value); + min-width: var(--size-trellis-value); + } + + .w-trellisOffset { + width: var(--size-trellis-offset); + min-width: var(--size-trellis-offset); + } + + .text-trellis_ti { + font: var(--type-caption1); + letter-spacing: 0.02em; + } + + .text-line_d { + font: var(--type-body); + } + + .text-line_d_e { + font: var(--type-subheadline); + } + + .text-form_base { + font: var(--type-body); + } + + .border-t-line { + border-top: 1px solid var(--separator); + } + + .border-b-line { + border-bottom: 1px solid var(--separator); + } + + .el-re { + transition: all var(--dur-2) var(--ease-ios); + } + + .opacity-active:active, + .opacity-active:focus { + opacity: 0.8; + } + + .carousel-container { + display: flex; + flex-grow: 1; + overflow-x: hidden; + scroll-snap-type: x mandatory; + list-style: none; + scroll-behavior: smooth; + -webkit-overflow-scrolling: touch; + } + + .carousel-item { + scroll-snap-align: start; + } + + .carousel-container-trellis { + display: flex; + flex-grow: 1; + height: 100%; + width: 100%; + } + + .carousel-item-trellis { + display: flex; + flex-direction: column; + width: fit-content; + padding: 0 var(--space-4); + gap: var(--space-4); + justify-content: flex-start; + align-items: center; + } + + .entry-line-fluid { + width: 100%; + height: 100%; + border-radius: var(--radius-xl); + } + + .entry-textarea-wrap { + display: flex; + flex-direction: row; + width: 100%; + align-items: center; + border-radius: var(--radius-xl); + } + + .entry-line-wrap { + display: flex; + flex-direction: row; + width: 100%; + padding: 0 var(--space-2); + align-items: center; + } + + .el-textarea { + width: 100%; + height: max-content; + outline: none; + border-radius: var(--radius-xl); + text-wrap: wrap; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + padding: 0; + } + + .el-input, + .el-select, + .el-textarea { + display: flex; + flex-direction: row; + width: 100%; + justify-content: center; + align-items: center; + border: 0; + outline: 0; + background: transparent; + font: var(--type-body); + } + + .el-input::placeholder, + .el-select::placeholder, + .el-textarea::placeholder { + font: var(--type-body); + } + + .el-select-centered { + text-align: center; + text-align-last: center; + } + + .button-base { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + font: var(--type-subheadline); + text-transform: lowercase; + transition: all var(--dur-2) var(--ease-ios); + user-select: none; + cursor: pointer; + } + + .button-simple { + height: var(--size-line-button); + background: var(--bg-elevated); + color: var(--text-primary); + } + + .button-submit { + height: var(--size-line-button); + min-width: 82px; + border-radius: var(--radius-xl); + background: var(--accent); + color: var(--accent-contrast); + } + + .spinner8 { + position: relative; + display: inline-block; + width: 1em; + height: 1em; + } + + .spinner8.center { + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + margin: auto; + } + + .spinner8 .spinner8-blade { + position: absolute; + left: 0.4629em; + bottom: 0; + width: 0.1em; + height: 0.2777em; + border-radius: 0.0555em; + background-color: transparent; + transform-origin: center -0.2222em; + animation: spinner-fade-base 1s infinite linear; + } + + .spinner8-white .spinner8-blade-white { + position: absolute; + left: 0.4629em; + bottom: 0; + width: 0.1em; + height: 0.2777em; + border-radius: 0.0555em; + background-color: transparent; + transform-origin: center -0.2222em; + animation: spinner-fade-white 1s infinite linear; + } + + .spinner8 .spinner8-blade:nth-child(1) { + animation-delay: 0s; + transform: rotate(0deg); + } + + .spinner8 .spinner8-blade:nth-child(2) { + animation-delay: 0.125s; + transform: rotate(45deg); + } + + .spinner8 .spinner8-blade:nth-child(3) { + animation-delay: 0.25s; + transform: rotate(90deg); + } + + .spinner8 .spinner8-blade:nth-child(4) { + animation-delay: 0.375s; + transform: rotate(135deg); + } + + .spinner8 .spinner8-blade:nth-child(5) { + animation-delay: 0.5s; + transform: rotate(180deg); + } + + .spinner8 .spinner8-blade:nth-child(6) { + animation-delay: 0.625s; + transform: rotate(225deg); + } + + .spinner8 .spinner8-blade:nth-child(7) { + animation-delay: 0.75s; + transform: rotate(270deg); + } + + .spinner8 .spinner8-blade:nth-child(8) { + animation-delay: 0.875s; + transform: rotate(315deg); + } + [data-ui="dialog-overlay"], [data-ui="sheet-overlay"] { position: fixed; @@ -164,6 +469,33 @@ } } +@keyframes fade-in { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes spinner-fade-white { + 0% { + background-color: #ffffff; + } + 100% { + background-color: transparent; + } +} + +@keyframes spinner-fade-base { + 0% { + background-color: var(--text-secondary); + } + 100% { + background-color: transparent; + } +} + @keyframes sheet-slide-in { 0% { transform: translateY(110%); diff --git a/crates/ui-tokens/assets/tokens.css b/crates/ui-tokens/assets/tokens.css @@ -40,6 +40,13 @@ --space-7: 32px; --space-8: 40px; + --size-line: 46px; + --size-line-button: 52px; + --size-touch-guide: 54px; + --size-trellis-display: 286px; + --size-trellis-value: 180px; + --size-trellis-offset: 32px; + --radius-sm: 8px; --radius-md: 12px; --radius-lg: 16px;