pinakes-ui: add plugin component stylesheet

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I05de526f0cea5df269b0fee226ef1edf6a6a6964
This commit is contained in:
raf 2026-03-11 21:26:41 +03:00
commit 071ea19c8f
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF
2 changed files with 701 additions and 7 deletions

File diff suppressed because one or more lines are too long

View file

@ -7,6 +7,20 @@
// The layout rules here consume those properties via var() so the renderer // The layout rules here consume those properties via var() so the renderer
// never injects full CSS rule strings. // never injects full CSS rule strings.
// Page wrapper
.plugin-page {
padding: $space-8 $space-12;
max-width: 100%;
overflow-x: hidden;
}
.plugin-page-title {
font-size: $font-size-xl;
font-weight: $font-weight-semibold;
color: $text-0;
margin: 0 0 $space-8;
}
// Container: vertical flex column with configurable gap and padding. // Container: vertical flex column with configurable gap and padding.
.plugin-container { .plugin-container {
display: flex; display: flex;
@ -65,20 +79,568 @@
min-width: 0; min-width: 0;
} }
// Media grid reuses the same column/gap variables as .plugin-grid. // Card
.plugin-card {
background: $bg-2;
border: 1px solid $border;
border-radius: $radius-md;
overflow: hidden;
}
.plugin-card-header {
padding: $space-6 $space-8;
font-size: $font-size-md;
font-weight: $font-weight-semibold;
color: $text-0;
border-bottom: 1px solid $border;
background: $bg-3;
}
.plugin-card-content {
padding: $space-8;
}
.plugin-card-footer {
padding: $space-6 $space-8;
border-top: 1px solid $border;
background: $bg-1;
}
// Typography
.plugin-heading {
color: $text-0;
margin: 0;
line-height: $line-height-tight;
&.level-1 { font-size: $font-size-6xl; font-weight: $font-weight-bold; }
&.level-2 { font-size: $font-size-4xl; font-weight: $font-weight-semibold; }
&.level-3 { font-size: $font-size-3xl; font-weight: $font-weight-semibold; }
&.level-4 { font-size: $font-size-xl; font-weight: $font-weight-medium; }
&.level-5 { font-size: $font-size-lg; font-weight: $font-weight-medium; }
&.level-6 { font-size: $font-size-md; font-weight: $font-weight-medium; }
}
.plugin-text {
margin: 0;
font-size: $font-size-md;
color: $text-0;
line-height: $line-height-normal;
&.text-secondary { color: $text-1; }
&.text-error { color: $error-text; }
&.text-success { color: $success; }
&.text-warning { color: $warning; }
&.text-bold { font-weight: $font-weight-semibold; }
&.text-italic { font-style: italic; }
&.text-small { font-size: $font-size-sm; }
&.text-large { font-size: $font-size-2xl; }
}
.plugin-code {
background: $bg-1;
border: 1px solid $border;
border-radius: $radius;
padding: $space-8 $space-12;
font-family: $font-family-mono;
font-size: $font-size-md;
color: $text-0;
overflow-x: auto;
white-space: pre;
code {
font-family: inherit;
font-size: inherit;
color: inherit;
}
}
// Tabs
.plugin-tabs {
display: flex;
flex-direction: column;
}
.plugin-tab-list {
display: flex;
gap: 2px;
border-bottom: 1px solid $border;
margin-bottom: $space-8;
}
.plugin-tab {
padding: $space-4 $space-10;
font-size: $font-size-md;
font-weight: $font-weight-medium;
color: $text-1;
background: transparent;
border: none;
border-bottom: 2px solid transparent;
cursor: pointer;
transition: color $transition-base, border-color $transition-base;
&:hover {
color: $text-0;
}
&.active {
color: $accent-text;
border-bottom-color: $accent;
}
.tab-icon {
margin-right: $space-2;
}
}
.plugin-tab-panels {}
.plugin-tab-panel {
&:not(.active) { display: none; }
}
// Description list
.plugin-description-list-wrapper {
width: 100%;
}
.plugin-description-list {
display: grid;
grid-template-columns: max-content 1fr;
gap: $space-2 $space-8;
margin: 0;
padding: 0;
dt {
font-size: $font-size-sm;
font-weight: $font-weight-medium;
color: $text-1;
text-transform: uppercase;
letter-spacing: $letter-spacing-uppercase;
padding: $space-3 0;
white-space: nowrap;
}
dd {
font-size: $font-size-md;
color: $text-0;
padding: $space-3 0;
margin: 0;
word-break: break-word;
}
&.horizontal {
display: flex;
flex-wrap: wrap;
gap: $space-8 $space-12;
dt {
width: auto;
padding: 0;
}
dd {
width: auto;
padding: 0;
}
// Pair dt+dd side by side
dt, dd {
display: inline;
}
// Each dt/dd pair sits in its own flex group via a wrapper approach.
// Since we can't group them, use a two-column repeat trick instead.
display: grid;
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
dt {
font-size: $font-size-xs;
text-transform: uppercase;
letter-spacing: $letter-spacing-uppercase;
color: $text-2;
margin-bottom: $space-1;
}
dd {
font-size: $font-size-lg;
font-weight: $font-weight-semibold;
color: $text-0;
}
}
}
// Data table
.plugin-data-table-wrapper {
overflow-x: auto;
}
.plugin-data-table {
width: 100%;
border-collapse: collapse;
font-size: $font-size-md;
thead {
tr {
border-bottom: 1px solid $border-strong;
}
th {
padding: $space-4 $space-6;
text-align: left;
font-size: $font-size-sm;
font-weight: $font-weight-semibold;
color: $text-1;
text-transform: uppercase;
letter-spacing: $letter-spacing-uppercase;
white-space: nowrap;
}
}
tbody {
tr {
border-bottom: 1px solid $border-subtle;
transition: background $transition-fast;
&:hover {
background: $overlay-light;
}
&:last-child {
border-bottom: none;
}
}
td {
padding: $space-4 $space-6;
color: $text-0;
vertical-align: middle;
}
}
}
// Table column with a plugin-specified fixed width.
.plugin-col-constrained {
width: var(--plugin-col-width);
}
.table-filter {
margin-bottom: $space-6;
input {
width: 240px;
padding: $space-3 $space-6;
background: $bg-1;
border: 1px solid $border;
border-radius: $radius;
color: $text-0;
font-size: $font-size-md;
&::placeholder { color: $text-2; }
&:focus {
outline: none;
border-color: $accent;
}
}
}
.table-pagination {
display: flex;
align-items: center;
gap: $space-6;
padding: $space-4 0;
font-size: $font-size-md;
color: $text-1;
}
.row-actions {
white-space: nowrap;
width: 1%;
.plugin-button {
padding: $space-2 $space-4;
font-size: $font-size-sm;
margin-right: $space-2;
}
}
// Media grid: reuses column/gap variables from plugin-grid.
.plugin-media-grid { .plugin-media-grid {
display: grid; display: grid;
grid-template-columns: repeat(var(--plugin-columns, 2), 1fr); grid-template-columns: repeat(var(--plugin-columns, 2), 1fr);
gap: var(--plugin-gap, 8px); gap: var(--plugin-gap, 8px);
} }
// Table column with a plugin-specified fixed width. .media-grid-item {
// The width is passed as --plugin-col-width on the th element. background: $bg-2;
.plugin-col-constrained { border: 1px solid $border;
width: var(--plugin-col-width); border-radius: $radius-md;
overflow: hidden;
display: flex;
flex-direction: column;
}
.media-grid-img {
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
display: block;
}
.media-grid-no-img {
width: 100%;
aspect-ratio: 16 / 9;
background: $bg-3;
display: flex;
align-items: center;
justify-content: center;
font-size: $font-size-sm;
color: $text-2;
}
.media-grid-caption {
padding: $space-4 $space-6;
font-size: $font-size-sm;
color: $text-0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
// List
.plugin-list-wrapper {}
.plugin-list {
list-style: none;
margin: 0;
padding: 0;
}
.plugin-list-item {
padding: $space-4 0;
}
.plugin-list-divider {
border: none;
border-top: 1px solid $border-subtle;
margin: 0;
}
.plugin-list-empty {
padding: $space-8;
text-align: center;
color: $text-2;
font-size: $font-size-md;
}
// Interactive: buttons
.plugin-button {
display: inline-flex;
align-items: center;
gap: $space-3;
padding: $space-4 $space-8;
border: 1px solid $border;
border-radius: $radius;
font-size: $font-size-md;
font-weight: $font-weight-medium;
cursor: pointer;
transition: background $transition-fast, border-color $transition-fast,
color $transition-fast;
background: $bg-2;
color: $text-0;
&:disabled {
opacity: 0.45;
cursor: not-allowed;
}
&.btn-primary {
background: $accent;
border-color: $accent;
color: #fff;
&:hover:not(:disabled) { background: $accent-hover; }
}
&.btn-secondary {
background: $bg-3;
border-color: $border-strong;
color: $text-0;
&:hover:not(:disabled) { background: $overlay-medium; }
}
&.btn-tertiary {
background: transparent;
border-color: transparent;
color: $accent-text;
&:hover:not(:disabled) { background: $accent-dim; }
}
&.btn-danger {
background: transparent;
border-color: $error-border;
color: $error-text;
&:hover:not(:disabled) { background: $error-bg; }
}
&.btn-success {
background: transparent;
border-color: $success-border;
color: $success;
&:hover:not(:disabled) { background: $success-bg; }
}
&.btn-ghost {
background: transparent;
border-color: transparent;
color: $text-1;
&:hover:not(:disabled) { background: $btn-ghost-hover; }
}
}
// Badges
.plugin-badge {
display: inline-flex;
align-items: center;
padding: $space-1 $space-4;
border-radius: $radius-full;
font-size: $font-size-xs;
font-weight: $font-weight-semibold;
letter-spacing: $letter-spacing-uppercase;
text-transform: uppercase;
&.badge-default, &.badge-neutral {
background: $overlay-medium;
color: $text-1;
}
&.badge-primary {
background: $accent-dim;
color: $accent-text;
}
&.badge-secondary {
background: $overlay-light;
color: $text-0;
}
&.badge-success {
background: $success-bg;
color: $success;
}
&.badge-warning {
background: $warning-bg;
color: $warning;
}
&.badge-error {
background: $error-bg;
color: $error-text;
}
&.badge-info {
background: $info-bg;
color: $accent-text;
}
}
// Form
.plugin-form {
display: flex;
flex-direction: column;
gap: $space-8;
}
.form-field {
display: flex;
flex-direction: column;
gap: $space-3;
label {
font-size: $font-size-md;
font-weight: $font-weight-medium;
color: $text-0;
}
input, textarea, select {
padding: $space-4 $space-6;
background: $bg-1;
border: 1px solid $border;
border-radius: $radius;
color: $text-0;
font-size: $font-size-md;
font-family: inherit;
&::placeholder { color: $text-2; }
&:focus {
outline: none;
border-color: $accent;
box-shadow: 0 0 0 2px $accent-dim;
}
}
textarea {
min-height: 80px;
resize: vertical;
}
select {
appearance: none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%23a0a0b8' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right $space-6 center;
padding-right: $space-16;
}
}
.form-help {
margin: 0;
font-size: $font-size-sm;
color: $text-2;
}
.form-actions {
display: flex;
gap: $space-6;
padding-top: $space-4;
}
.required {
color: $error;
}
// Link
.plugin-link {
color: $accent-text;
text-decoration: none;
&:hover { text-decoration: underline; }
}
.plugin-link-blocked {
color: $text-2;
text-decoration: line-through;
cursor: not-allowed;
}
// Progress
.plugin-progress {
background: $bg-1;
border: 1px solid $border;
border-radius: $radius;
height: 8px;
overflow: hidden;
display: flex;
align-items: center;
gap: $space-4;
} }
// Progress bar: the fill element carries --plugin-progress.
.plugin-progress-bar { .plugin-progress-bar {
height: 100%; height: 100%;
background: $accent; background: $accent;
@ -87,8 +649,140 @@
width: var(--plugin-progress, 0%); width: var(--plugin-progress, 0%);
} }
.plugin-progress-label {
font-size: $font-size-sm;
color: $text-1;
white-space: nowrap;
flex-shrink: 0;
}
// Chart wrapper: height is driven by --plugin-chart-height. // Chart wrapper: height is driven by --plugin-chart-height.
.plugin-chart { .plugin-chart {
overflow: auto; overflow: auto;
height: var(--plugin-chart-height, 200px); height: var(--plugin-chart-height, 200px);
.chart-title {
font-size: $font-size-lg;
font-weight: $font-weight-semibold;
color: $text-0;
margin-bottom: $space-4;
}
.chart-x-label, .chart-y-label {
font-size: $font-size-sm;
color: $text-2;
margin-bottom: $space-2;
}
.chart-data-table {
overflow-x: auto;
}
.chart-no-data {
padding: $space-12;
text-align: center;
color: $text-2;
font-size: $font-size-md;
}
}
// Loading / error states
.plugin-loading {
padding: $space-8;
color: $text-1;
font-size: $font-size-md;
font-style: italic;
}
.plugin-error {
padding: $space-6 $space-8;
background: $error-bg;
border: 1px solid $error-border;
border-radius: $radius;
color: $error-text;
font-size: $font-size-md;
}
// Feedback toast
.plugin-feedback {
position: sticky;
bottom: $space-8;
display: flex;
align-items: center;
justify-content: space-between;
gap: $space-8;
padding: $space-6 $space-8;
border-radius: $radius-md;
font-size: $font-size-md;
z-index: $z-toast;
box-shadow: $shadow-lg;
&.success {
background: $success-bg;
border: 1px solid $success-border;
color: $success;
}
&.error {
background: $error-bg;
border: 1px solid $error-border;
color: $error-text;
}
}
.plugin-feedback-dismiss {
background: transparent;
border: none;
color: inherit;
font-size: $font-size-xl;
cursor: pointer;
line-height: 1;
padding: 0;
opacity: 0.7;
&:hover { opacity: 1; }
}
// Modal
.plugin-modal-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.65);
display: flex;
align-items: center;
justify-content: center;
z-index: $z-modal-backdrop;
}
.plugin-modal {
position: relative;
background: $bg-2;
border: 1px solid $border-strong;
border-radius: $radius-xl;
padding: $space-16;
min-width: 380px;
max-width: 640px;
max-height: 80vh;
overflow-y: auto;
box-shadow: $shadow-lg;
z-index: $z-modal;
}
.plugin-modal-close {
position: absolute;
top: $space-8;
right: $space-8;
background: transparent;
border: none;
color: $text-1;
font-size: $font-size-xl;
cursor: pointer;
line-height: 1;
padding: $space-2;
border-radius: $radius;
&:hover {
background: $overlay-medium;
color: $text-0;
}
} }