Standardize NodeDC UI components
This commit is contained in:
@@ -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."
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
]
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
|
||||
@@ -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 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -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 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user