Files
iistwin/client/src/index.css
Ильяс Султанов 7d975b0b00 fix(ui): пакет фиксов по ревью better-interface (HIGH+MEDIUM)
HIGH:
- mobile: поля задачи доступны для форм без вкладок (fallback-аккордеон)
- удаление вложений доступно на тач-устройствах (кнопка всегда видна)
- бейдж статуса: контрастный текст по яркости (statusColor.ts), также в реестре и канбане
- кнопки согласования: контрастные дефолты #15803d/#b91c1c + текст по яркости
- клавиатура: focus-visible у карандаша, focus-ring у поиска, InlineField с клавиатуры

MEDIUM:
- iOS: инпуты text-base на мобильном (убран зум при фокусе)
- системные поля унифицированы с кастомными (inline label+value)
- тач-таргеты ≥32px, кнопка удаления задачи отделена ms-auto
- токены --warning/--success/--info во всех скинах, хардкод-цвета → семантика
- заголовок задачи крупнее + title с полным текстом; мелкий текст ≥11px
- UX-тексты: «Не удалось …» вместо «Ошибка», имена вместо ID
- button.tsx: без transition-all, глобальный active:scale-[0.96]
- ARIA: aria-label инпутам, role=alert ошибкам, Escape в dropdown
2026-08-04 09:36:13 +03:00

532 lines
13 KiB
CSS

@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
@import url('https://fonts.googleapis.com/css2?family=DM+Mono:wght@400;500&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;500;600;700&display=swap');
@import './themes/styles/generated-skins.css';
@tailwind base;
@tailwind components;
@tailwind utilities;
/*
* Fallback переменные для случая, когда data-skin/data-theme ещё не применены
* (например, во время гидратации). Основные значения берутся из generated-skins.css.
*/
:root {
--background: hsl(0 0% 100%);
--foreground: hsl(220 10% 15%);
--card: hsl(0 0% 100%);
--card-foreground: hsl(220 10% 15%);
--popover: hsl(0 0% 100%);
--popover-foreground: hsl(220 10% 15%);
--primary: hsl(220 10% 15%);
--primary-foreground: hsl(0 0% 100%);
--secondary: hsl(220 5% 96%);
--secondary-foreground: hsl(220 10% 15%);
--muted: hsl(220 5% 96%);
--muted-foreground: hsl(220 5% 45%);
--accent: hsl(220 5% 93%);
--accent-foreground: hsl(220 10% 15%);
--destructive: hsl(0 72% 51%);
--destructive-foreground: hsl(0 0% 100%);
--border: hsl(220 5% 90%);
--input: hsl(0 0% 100%);
--ring: hsl(220 10% 15%);
--status-done: hsl(142 50% 45%);
--status-progress: hsl(45 90% 50%);
--status-overdue: hsl(0 70% 55%);
--status-paused: hsl(220 5% 60%);
--warning: hsl(48 96% 89%);
--warning-foreground: hsl(25 83% 31%);
--success: hsl(141 84% 93%);
--success-foreground: hsl(142 72% 24%);
--info: hsl(214 95% 93%);
--info-foreground: hsl(224 71% 40%);
--chart-1: hsl(220 10% 25%);
--chart-2: hsl(142 50% 45%);
--chart-3: hsl(45 90% 50%);
--chart-4: hsl(200 70% 50%);
--chart-5: hsl(0 70% 55%);
--sidebar: hsl(0 0% 100%);
--sidebar-foreground: hsl(220 10% 15%);
--sidebar-primary: hsl(220 10% 15%);
--sidebar-primary-foreground: hsl(0 0% 100%);
--sidebar-accent: hsl(220 5% 96%);
--sidebar-accent-foreground: hsl(220 10% 15%);
--sidebar-border: hsl(220 5% 92%);
--sidebar-ring: hsl(220 10% 15%);
--font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
--font-mono: "DM Mono", "SF Mono", "Monaco", "Inconsolata", monospace;
--radius: 0.25rem;
--shadow-2xs: none;
--shadow-xs: none;
--shadow-sm: none;
--shadow: none;
--shadow-md: 0 1px 2px 0 rgba(0, 0, 0, 0.03);
--shadow-lg: 0 1px 3px 0 rgba(0, 0, 0, 0.05);
--shadow-xl: 0 2px 4px 0 rgba(0, 0, 0, 0.05);
--shadow-2xl: 0 4px 6px -1px rgba(0, 0, 0, 0.05);
--tracking-normal: -0.01em;
--spacing: 0.25rem;
--elevate-1: rgba(0, 0, 0, 0.03);
--elevate-2: rgba(0, 0, 0, 0.08);
}
.dark {
--elevate-1: rgba(255, 255, 255, 0.03);
--elevate-2: rgba(255, 255, 255, 0.08);
--background: hsl(220 10% 8%);
--foreground: hsl(220 5% 92%);
--card: hsl(220 10% 10%);
--card-foreground: hsl(220 5% 92%);
--popover: hsl(220 10% 10%);
--popover-foreground: hsl(220 5% 92%);
--primary: hsl(0 0% 100%);
--primary-foreground: hsl(220 10% 8%);
--secondary: hsl(220 10% 14%);
--secondary-foreground: hsl(220 5% 92%);
--muted: hsl(220 10% 14%);
--muted-foreground: hsl(220 5% 55%);
--accent: hsl(220 10% 16%);
--accent-foreground: hsl(220 5% 92%);
--destructive: hsl(0 70% 55%);
--destructive-foreground: hsl(0 0% 100%);
--border: hsl(220 10% 18%);
--input: hsl(220 10% 12%);
--ring: hsl(0 0% 100%);
--status-done: hsl(142 50% 55%);
--status-progress: hsl(45 90% 55%);
--status-overdue: hsl(0 70% 60%);
--status-paused: hsl(220 5% 55%);
--warning: hsl(32 92% 14%);
--warning-foreground: hsl(43 96% 56%);
--success: hsl(144 80% 10%);
--success-foreground: hsl(142 71% 58%);
--info: hsl(224 64% 21%);
--info-foreground: hsl(213 97% 81%);
--chart-1: hsl(220 5% 70%);
--chart-2: hsl(142 50% 55%);
--chart-3: hsl(45 90% 55%);
--chart-4: hsl(200 70% 55%);
--chart-5: hsl(0 70% 60%);
--sidebar: hsl(220 10% 8%);
--sidebar-foreground: hsl(220 5% 92%);
--sidebar-primary: hsl(0 0% 100%);
--sidebar-primary-foreground: hsl(220 10% 8%);
--sidebar-accent: hsl(220 10% 14%);
--sidebar-accent-foreground: hsl(220 5% 92%);
--sidebar-border: hsl(220 10% 16%);
--sidebar-ring: hsl(0 0% 100%);
--radius: 0.25rem;
--shadow-md: 0 1px 2px 0 rgba(0, 0, 0, 0.15);
--shadow-lg: 0 2px 4px 0 rgba(0, 0, 0, 0.2);
--shadow-xl: 0 4px 6px -1px rgba(0, 0, 0, 0.2);
--shadow-2xl: 0 8px 10px -2px rgba(0, 0, 0, 0.25);
}
@layer base {
* {
@apply border-border;
}
body {
@apply font-sans antialiased bg-background text-foreground;
font-size: 13px;
line-height: 1.5;
letter-spacing: -0.01em;
font-feature-settings: "cv11", "ss01";
}
/* Clean typography */
h1 {
@apply text-xl font-semibold tracking-tight;
}
h2 {
@apply text-lg font-medium tracking-tight;
}
h3 {
@apply text-base font-medium;
}
h4 {
@apply text-sm font-medium;
}
/* Fast transitions */
button, a, input, select, textarea {
@apply transition-colors duration-100 ease-out;
}
}
@layer components {
/* Page container */
.page-container {
@apply max-w-6xl mx-auto;
}
/* Page header */
.page-header {
@apply flex items-center justify-between mb-4 pb-3 border-b border-border;
}
.page-title {
@apply text-lg font-medium text-foreground;
}
/* Compact buttons */
.btn-compact {
@apply h-7 px-2.5 text-xs font-medium;
}
.btn-small {
@apply h-6 px-2 text-xs;
}
.btn-icon {
@apply h-7 w-7 p-0;
}
/* Compact inputs */
.input-compact {
@apply h-7 px-2 text-xs;
}
/* Clean table */
.table-minimal {
@apply w-full text-xs;
}
.table-minimal thead {
@apply border-b border-border;
}
.table-minimal th {
@apply py-2 px-3 text-left font-medium text-muted-foreground uppercase tracking-wider text-[10px];
}
.table-minimal td {
@apply py-2 px-3 border-b border-border/50;
}
.table-minimal tbody tr:hover {
@apply bg-muted/30;
}
/* Card minimal */
.card-minimal {
@apply border border-border rounded bg-card p-3;
}
/* Badge minimal */
.badge-minimal {
@apply inline-flex items-center px-1.5 py-0.5 text-[10px] font-medium rounded;
}
/* Status colors */
.status-badge {
@apply inline-flex items-center gap-1.5 px-2 py-0.5 text-xs rounded-full;
}
.status-badge-done {
background-color: color-mix(in srgb, var(--status-done) 12%, transparent);
color: var(--status-done);
}
.status-badge-progress {
background-color: color-mix(in srgb, var(--status-progress) 12%, transparent);
color: var(--status-progress);
}
.status-badge-overdue {
background-color: color-mix(in srgb, var(--status-overdue) 12%, transparent);
color: var(--status-overdue);
}
/* Nav item */
.nav-item {
@apply flex items-center gap-2 px-2 py-1.5 text-xs font-medium text-muted-foreground rounded hover:bg-muted hover:text-foreground transition-colors;
}
.nav-item-active {
@apply bg-muted text-foreground;
}
/* Section header */
.section-header {
@apply text-[10px] font-medium text-muted-foreground uppercase tracking-wider px-2 py-1.5;
}
/* Toolbar */
.toolbar {
@apply flex items-center gap-1.5 p-1.5 border-b border-border bg-background;
}
/* Empty state */
.empty-state {
@apply flex flex-col items-center justify-center py-12 text-center text-muted-foreground;
}
/* Form grid */
.form-grid {
@apply grid gap-3;
}
.form-row {
@apply flex items-center gap-2;
}
.form-label {
@apply text-xs font-medium text-muted-foreground;
}
/* List item */
.list-item {
@apply flex items-center gap-3 px-3 py-2 border-b border-border/50 hover:bg-muted/30 cursor-pointer;
}
.list-item:last-child {
@apply border-b-0;
}
}
@layer utilities {
/* Status badge utilities */
.status-done {
background-color: hsl(var(--status-done));
}
.status-progress {
background-color: hsl(var(--status-progress));
}
.status-overdue {
background-color: hsl(var(--status-overdue));
}
.status-paused {
background-color: hsl(var(--status-paused));
}
/* Text utilities */
.text-caption {
@apply text-[10px] text-muted-foreground;
}
.text-label {
@apply text-xs font-medium;
}
/* Truncate utilities */
.line-clamp-1 {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
}
/* Finance elevation */
.hover-elevate {
position: relative;
}
.hover-elevate::after {
content: "";
position: absolute;
inset: 0;
border-radius: inherit;
pointer-events: none;
opacity: 0;
background: var(--elevate-1);
transition: opacity 0.15s ease;
}
.hover-elevate:hover::after {
opacity: 1;
}
.hover-elevate-2 {
position: relative;
}
.hover-elevate-2::after {
content: "";
position: absolute;
inset: 0;
border-radius: inherit;
pointer-events: none;
opacity: 0;
background: var(--elevate-2);
transition: opacity 0.15s ease;
}
.hover-elevate-2:hover::after {
opacity: 1;
}
.active-elevate:active::after {
opacity: 1;
}
.active-elevate-2:active::after {
opacity: 1;
}
.toggle-elevate[data-state="on"]::after,
.toggle-elevate-2[data-state="on"]::after {
opacity: 1;
}
}
/* jspreadsheet formula cell highlight */
td.formula-highlight {
background-color: var(--tw-background-transparent-secondary) !important;
border: 1px solid var(--tw-border-strong) !important;
}
/* Mobile bottom navigation safe area */
.safe-area-bottom {
padding-bottom: env(safe-area-inset-bottom, 0);
}
/* Fix: Tailwind utility .flex overrides preflight [hidden] rule.
Radix primitives (Tabs, Dialog, Accordion, etc.) use hidden attr for inactive/unmounted content.
Ensure [hidden] always hides even when combined with flex/grid/display utilities. */
[hidden] {
display: none !important;
}
/* Fix Radix ScrollArea display:table horizontal overflow in chats */
.chat-scroll-area [data-radix-scroll-area-viewport] > div {
display: block !important;
min-width: 0 !important;
}
/* Scrollbar minimal */
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
background: transparent;
}
::-webkit-scrollbar-thumb {
background: var(--tw-border-strong);
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--tw-font-extra-light);
}
/* Focus visible — removed per user request */
@layer base {
*:focus-visible {
outline: none;
--tw-ring-offset-shadow: none;
--tw-ring-shadow: none;
box-shadow: none;
}
}
/* Selection */
::selection {
background-color: var(--tw-background-transparent-secondary);
}
/* ============================================================
Notion-Style Task Detail — Inline Edit System
Added: 2026-07-16
============================================================ */
@layer components {
/* --- Unified field grid: label + value --- */
.notion-field-row {
@apply grid gap-x-3 gap-y-1 py-1.5 px-2 -mx-2 rounded transition-colors;
grid-template-columns: 1fr; /* mobile: stacked */
}
@media (min-width: 768px) {
.notion-field-row {
grid-template-columns: minmax(120px, 140px) 1fr;
align-items: start;
}
}
/* Editable hover state */
.notion-field-row[data-editable="true"]:not([data-editing="true"]):hover {
@apply bg-muted/40;
}
/* --- Label column --- */
.notion-field-label {
@apply flex items-center gap-1;
}
@media (min-width: 768px) {
.notion-field-label {
@apply justify-end text-right;
padding-top: 2px;
}
}
/* --- Value column --- */
.notion-field-value {
@apply min-w-0;
}
/* --- Sticky bottom action bar --- */
.sticky-action-bar {
@apply sticky bottom-0 z-40 bg-background/95 backdrop-blur-sm border-t;
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
}
/* --- Inline editor inputs (unified height) --- */
.inline-input {
@apply border border-input rounded-md bg-background px-2 text-[13px];
@apply focus:outline-none focus:ring-1 focus:ring-primary focus:border-primary;
height: 32px;
line-height: 30px;
padding-top: 0;
padding-bottom: 0;
}
.inline-textarea {
@apply border border-input rounded-md bg-background px-2 py-1.5 text-[13px];
@apply focus:outline-none focus:ring-1 focus:ring-primary focus:border-primary;
min-height: 32px;
line-height: 1.5;
}
.inline-select {
@apply inline-input w-full appearance-none;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%236B7280' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: right 8px center;
padding-right: 28px;
}
}
/* --- PWA Safe Area --- */
.safe-area-bottom {
padding-bottom: env(safe-area-inset-bottom, 0);
}
@supports (padding-bottom: env(safe-area-inset-bottom)) {
.safe-area-bottom {
padding-bottom: max(12px, env(safe-area-inset-bottom));
}
}