Standardize NodeDC UI components

This commit is contained in:
DCCONSTRUCTIONS
2026-05-02 10:56:43 +03:00
parent c99c91c826
commit 69eb5260b0
22 changed files with 1955 additions and 550 deletions
+2 -3
View File
@@ -23,7 +23,7 @@
"tbody rows",
"inline editable cells",
"StatusControl cells",
"DateField cells",
"NodeDcDateField cells",
"CircleActionButton action cells"
],
"visualContract": {
@@ -36,8 +36,7 @@
"Create action is a solid circular plus, not a wide text CTA.",
"Inline editable cells use transparent input surfaces that brighten on hover/focus.",
"Status cells use StatusControl.",
"Date cells use CalendarPopover/DateField.",
"Date cells use CalendarPopover through NodeDcDateField.",
"Drag handles move full rows, not detached ghosts."
]
}
+12 -2
View File
@@ -7,7 +7,18 @@
"sourceRefs": [
{
"project": "nodedc_launcher",
"file": "src/widgets/top-bar/TopBar.tsx"
"file": "src/widgets/top-bar/TopBar.tsx",
"functions": ["TopBar"]
},
{
"project": "nodedc_launcher",
"file": "src/shared/nodedc-ui/Select.tsx",
"exports": ["NodeDcSelect"]
},
{
"project": "nodedc_launcher",
"file": "src/shared/nodedc-ui/ProfileMenu.tsx",
"exports": ["NodeDcProfileMenu"]
},
{
"project": "nodedc_launcher",
@@ -37,4 +48,3 @@
"Launcher and Task Manager headers must remain visually identical where routes overlap."
]
}
@@ -4,6 +4,12 @@
"kind": "component",
"status": "stable-reference",
"summary": "Date picker popover based on Task Manager DateDropdown and nodedc-calendar-shell styling.",
"implementation": {
"baseLibrary": "react-day-picker@9.5.0",
"localePackage": "date-fns@4.1.0",
"launcherComponent": "NodeDcDateField renders NodeDcDropdown + NodeDcCalendar; NodeDcCalendar delegates the month grid/range math to DayPicker instead of a hand-written grid.",
"isolation": "Calendar logic and styling live in src/shared/nodedc-ui/Calendar.tsx and src/shared/nodedc-ui/calendar.css. Feature screens must consume NodeDcDateField or NodeDcCalendar directly instead of creating local date wrappers."
},
"sourceRefs": [
{
"project": "nodedc_taskmanager",
@@ -15,10 +21,28 @@
"file": "plane-src/apps/web/styles/globals.css",
"classes": ["nodedc-calendar-shell"]
},
{
"project": "nodedc_launcher",
"file": "src/shared/nodedc-ui/Calendar.tsx",
"exports": [
"NodeDcDateField",
"NodeDcCalendar",
"NodeDcDateFieldProps",
"NodeDcCalendarProps",
"NodeDcCalendarRangePreview",
"NodeDcDateInput",
"NodeDcWeekStartsOn"
]
},
{
"project": "nodedc_launcher",
"file": "src/shared/nodedc-ui/calendar.css",
"classes": ["nodedc-ui-calendar", "nodedc-ui-calendar-frame", "nodedc-ui-date-trigger"]
},
{
"project": "nodedc_launcher",
"file": "src/widgets/admin-overlay/AdminOverlay.tsx",
"functions": ["DateField"]
"consumers": ["ClientsSection", "ClientEditorModal", "InvitesSection"]
}
],
"anatomy": [
@@ -33,15 +57,22 @@
"surface": "DropdownSurface",
"calendarRadius": "1.1rem",
"dayButtonRadius": "999px",
"selectedRangeFill": "accentRgb with high contrast dark text",
"selectedRangeFill": "continuous accent row fill under the day numbers; row breaks create rounded start/end caps",
"todayMarker": "today is always a circular ring marker; inside an accent range the ring uses the dark on-accent color and the day cell remains range-filled, not solid-filled",
"outsideDays": "muted"
},
"behaviorContract": [
"Default placement bottom-start.",
"Render through portal.",
"Support minDate, maxDate, clearable value, start-of-week preference.",
"Close on select when closeOnSelect is true."
"Support minDate, maxDate, clearable value, closeOnSelect, empty labels, popover width, and start-of-week preference.",
"Close on select when closeOnSelect is true.",
"When rangePreview or rangeStart/rangeEnd are present, render a continuous accent range preview while still selecting one field value.",
"When only one date is present, render a single circular selected date.",
"Today must not be solid-filled. It uses an inset circular ring both outside and inside a range; inside a range the row fill remains visible behind the ring."
],
"nextImplementationStep": "Replace launcher native input date fallback with this shared calendar component."
"currentConsumers": [
"Client demo/contract/paid dates",
"Invite expiration dates",
"Any future date field in admin modals and tables"
]
}
@@ -16,12 +16,13 @@
},
{
"project": "nodedc_launcher",
"file": "src/shared/ui/PortalDropdown.tsx"
"file": "src/shared/nodedc-ui/Dropdown.tsx",
"exports": ["NodeDcDropdown"]
},
{
"project": "nodedc_launcher",
"file": "src/styles/globals.css",
"classes": ["portal-dropdown", "nodedc-dropdown-surface"]
"classes": ["nodedc-ui-dropdown-surface", "nodedc-dropdown-surface", "nodedc-ui-option", "nodedc-ui-dropdown-search"]
}
],
"visualContract": {
@@ -35,7 +36,7 @@
"behaviorContract": [
"Render on fixed/portal layer when inside cards, sidebars, tables, sticky headers, or scroll containers.",
"Close on outside pointer and Escape.",
"Use Popper or equivalent fixed-position placement.",
"Use Popper or equivalent fixed-position placement based on trigger bounds.",
"Default selection placement is bottom-start.",
"Default action placement for card quick actions is bottom-start or bottom-end depending on anchor edge."
],
@@ -45,4 +46,3 @@
"outline": "none"
}
}
+12 -2
View File
@@ -14,6 +14,16 @@
"project": "nodedc_taskmanager",
"file": "plane-src/packages/ui/src/dropdowns/action-dropdown.tsx",
"exports": ["ActionDropdown"]
},
{
"project": "nodedc_launcher",
"file": "src/shared/nodedc-ui/ProfileMenu.tsx",
"exports": ["NodeDcProfileMenu"]
},
{
"project": "nodedc_launcher",
"file": "src/widgets/top-bar/TopBar.tsx",
"functions": ["TopBar profile trigger"]
}
],
"anatomy": [
@@ -35,7 +45,7 @@
"rules": [
"Profile popover is an ActionDropdown menuContent variant, not a separate dropdown engine.",
"Avatar trigger stays circular and borderless.",
"Menu uses DropdownSurface/ActionDropdown stacking rules."
"Menu uses DropdownSurface/ActionDropdown stacking rules.",
"Launcher implementation must keep the profile trigger pill visually identical to Task Manager header."
]
}
@@ -0,0 +1,51 @@
{
"id": "select-dropdown",
"name": "NodeDcSelect",
"kind": "component",
"status": "draft-stable",
"summary": "Shared select/dropdown control for statuses, roles, clients, profile switches, filters, and compact table cells.",
"sourceRefs": [
{
"project": "nodedc_launcher",
"file": "src/shared/nodedc-ui/Select.tsx",
"exports": ["NodeDcSelect", "NodeDcSelectOption"]
},
{
"project": "nodedc_launcher",
"file": "src/shared/nodedc-ui/Dropdown.tsx",
"exports": ["NodeDcDropdown"]
},
{
"project": "nodedc_taskmanager",
"file": "plane-src/packages/ui/src/dropdowns/action-dropdown.tsx",
"exports": ["ActionDropdown"]
}
],
"anatomy": [
"trigger button or custom trigger render",
"portal DropdownSurface",
"optional search row",
"option rows with optional icon, description, tone, and selected check"
],
"visualContract": {
"triggerRadius": "999px for table/header/status controls, 1rem inside entity forms",
"menuSurface": "DropdownSurface",
"optionRadius": "0.92rem",
"selectedFill": "white/10 or tone-specific transparent fill",
"outline": "none"
},
"behaviorContract": [
"Never use native select for NODE.DC runtime UI.",
"Render options through portal/fixed dropdown layer.",
"Close on option select, outside pointer, and Escape.",
"Support custom trigger render for header pills and side-nav client switcher."
],
"currentConsumers": [
"TopBar client switcher",
"TopBar profile-role switcher",
"AdminOverlay client switcher",
"AdminOverlay client type selects",
"AdminOverlay membership role selects",
"AdminOverlay invite role selects"
]
}
+16 -7
View File
@@ -47,8 +47,16 @@
{
"id": "dropdown-surface",
"spec": "components/dropdown-surface.json",
"status": "stable-reference",
"primarySource": "nodedc_taskmanager"
"status": "draft-stable",
"primarySource": "nodedc_launcher",
"taskManagerReference": true
},
{
"id": "select-dropdown",
"spec": "components/select-dropdown.json",
"status": "draft-stable",
"primarySource": "nodedc_launcher",
"taskManagerReference": true
},
{
"id": "action-dropdown",
@@ -65,14 +73,16 @@
{
"id": "calendar-popover",
"spec": "components/calendar-popover.json",
"status": "stable-reference",
"primarySource": "nodedc_taskmanager"
"status": "draft-stable",
"primarySource": "nodedc_launcher",
"taskManagerReference": true
},
{
"id": "profile-menu",
"spec": "components/profile-menu.json",
"status": "stable-reference",
"primarySource": "nodedc_taskmanager"
"status": "draft-stable",
"primarySource": "nodedc_launcher",
"taskManagerReference": true
},
{
"id": "admin-side-nav",
@@ -125,4 +135,3 @@
"globalRules": "rules/ui-rules.json",
"sourceMap": "sources/source-map.json"
}
+1 -2
View File
@@ -9,7 +9,7 @@
{
"id": "no-outlines",
"severity": "error",
"text": "Visible browser outlines and hard colored outlines are forbidden. Use surface hover/focus states."
"text": "Visible outlines, stroke borders, focus rings, and hard colored contours are forbidden on runtime UI. Use only fill, opacity, blur, and surface hover/focus states."
},
{
"id": "circle-actions",
@@ -48,4 +48,3 @@
}
]
}
+14 -5
View File
@@ -22,7 +22,12 @@
"primitiveUi": [
"src/shared/ui/Button.tsx",
"src/shared/ui/Glass.tsx",
"src/shared/ui/PortalDropdown.tsx"
"src/shared/ui/PortalDropdown.tsx",
"src/shared/nodedc-ui/Dropdown.tsx",
"src/shared/nodedc-ui/Select.tsx",
"src/shared/nodedc-ui/Calendar.tsx",
"src/shared/nodedc-ui/ProfileMenu.tsx",
"src/shared/nodedc-ui/index.ts"
],
"storage": [
"src/shared/api/storageApi.ts"
@@ -63,17 +68,22 @@
"crossProjectMapping": [
{
"component": "dropdown-surface",
"launcher": ["portal-dropdown", "nodedc-dropdown-surface"],
"launcher": ["NodeDcDropdown", "nodedc-ui-dropdown-surface", "nodedc-dropdown-surface"],
"taskManager": ["nodedc-dropdown-surface", "nodedc-dropdown-option"]
},
{
"component": "select-dropdown",
"launcher": ["NodeDcSelect", "TopBar selectors", "AdminOverlay role/type/client selectors"],
"taskManager": ["ActionDropdown option menu pattern"]
},
{
"component": "calendar-popover",
"launcher": ["DateField", "nodedc-calendar-shell placeholder"],
"launcher": ["NodeDcDateField", "NodeDcCalendar", "src/shared/nodedc-ui/calendar.css"],
"taskManager": ["DateDropdown", "nodedc-calendar-shell"]
},
{
"component": "profile-menu",
"launcher": ["topbar profile cluster needs implementation"],
"launcher": ["NodeDcProfileMenu", "TopBar profile cluster"],
"taskManager": ["UserMenuRoot"]
},
{
@@ -83,4 +93,3 @@
}
]
}