Enforce shared metric and description layouts
This commit is contained in:
@@ -115,18 +115,29 @@ The current structural vocabulary is:
|
|||||||
- `FormSection` owns form-section heading, description, actions, content flow,
|
- `FormSection` owns form-section heading, description, actions, content flow,
|
||||||
separation, and panel presentation. It does not own field values,
|
separation, and panel presentation. It does not own field values,
|
||||||
validation, permissions, or domain wording.
|
validation, permissions, or domain wording.
|
||||||
|
- `MetricGrid` owns the responsive grouping around `MetricCard`: fixed one-to-five
|
||||||
|
columns or auto-fit, minimum card width, density, surrounding rhythm, and a
|
||||||
|
named collapse point. Modules provide the metric, tone, and consequence;
|
||||||
|
they do not recreate the group grid or reach across module CSS to size it.
|
||||||
|
- `DescriptionList` and `DescriptionItem` own semantic property presentation.
|
||||||
|
The stacked variant supports compact multi-column facts; the inline variant
|
||||||
|
supports one-column term/value rows with a standard term width. Both own
|
||||||
|
density, wrapping, and responsive collapse while modules retain the terms,
|
||||||
|
values, provenance, and actions.
|
||||||
- `Dialog` owns size and administration variants, body padding, description,
|
- `Dialog` owns size and administration variants, body padding, description,
|
||||||
notices, and fixed footer placement. `DialogActions`, `DialogForm`, and
|
notices, and fixed footer placement. `DialogActions`, `DialogForm`, and
|
||||||
`DialogSection` own the footer action flow, native form flow, and body
|
`DialogSection` own the footer action flow, native form flow, and body
|
||||||
grouping used inside it. Modules compose fields and consequences rather than
|
grouping used inside it. Modules compose fields and consequences rather than
|
||||||
recreating dialog anatomy.
|
recreating dialog anatomy.
|
||||||
|
|
||||||
Raw toolbar tags, the former generic grid classes, raw dialog-form wrappers,
|
Raw toolbar tags, the former generic grid and property-list classes, raw
|
||||||
and module-local definitions of these contracts are rejected by the focused
|
dialog-form wrappers, and module-local definitions of these contracts are
|
||||||
workspace checks. The next promotion candidates are metric groups,
|
rejected by the focused workspace checks. Dialog widths matching the Core size
|
||||||
description/property lists, filter/search composition, responsive data
|
scale must use `Dialog size`; other local widths require a reviewed exception
|
||||||
summaries, and unified empty/error state composition. Their APIs must remain
|
and may only decrease. The next promotion candidates are assignment/picker
|
||||||
composable; a central component is not a single oversized page template.
|
composition, filter/search composition, and unified empty/error state
|
||||||
|
composition. Their APIs must remain composable; a central component is not a
|
||||||
|
single oversized page template.
|
||||||
|
|
||||||
## Surface Archetypes
|
## Surface Archetypes
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
# Shared WebUI Primitive Inventory
|
# Shared WebUI Primitive Inventory
|
||||||
|
|
||||||
This 2026-08-18 inventory records the implementation state after the first
|
This 2026-08-18 inventory records the implementation state after the
|
||||||
product-wide toolbar, grid, form-section, and dialog-anatomy migration. It is
|
product-wide toolbar, grid, form-section, dialog-anatomy, metric-group, and
|
||||||
|
description-list migrations. It is
|
||||||
evidence for prioritization, not a substitute for the normative
|
evidence for prioritization, not a substitute for the normative
|
||||||
[interface pattern language](../architecture/INTERFACE_PATTERN_LANGUAGE.md).
|
[interface pattern language](../architecture/INTERFACE_PATTERN_LANGUAGE.md).
|
||||||
|
|
||||||
@@ -16,25 +17,38 @@ evidence for prioritization, not a substitute for the normative
|
|||||||
| `DialogActions` | Every Core `Dialog` footer | Footer wrapping and alignment are no longer repeated by consumers. |
|
| `DialogActions` | Every Core `Dialog` footer | Footer wrapping and alignment are no longer repeated by consumers. |
|
||||||
| `DialogForm` | 6 source files | Raw `*-dialog-form` form wrappers are rejected. |
|
| `DialogForm` | 6 source files | Raw `*-dialog-form` form wrappers are rejected. |
|
||||||
| `DialogSection` | 6 source files | Repeated dialog field/content grouping is available as a shared primitive. |
|
| `DialogSection` | 6 source files | Repeated dialog field/content grouping is available as a shared primitive. |
|
||||||
|
| `MetricGrid` | 29 uses in 25 source files | The former `metric-grid` class and module-specific column overrides were removed. Core now owns 1–5/auto-fit columns, minimum width, density, block/inset/zero spacing, and collapse. |
|
||||||
|
| `DescriptionList` and `DescriptionItem` | 51 lists in 28 source files; item composition in 11 files | The former `admin-details-grid` and `detail-list` classes were removed. Core now owns stacked and inline property layouts, density, term width, wrapping, and collapse while preserving native `dl`/`dt`/`dd` semantics. |
|
||||||
|
| Standard dialog sizing | 9 consumers and 6 duplicated width rules removed | Confirmations and compatible Calendar, credential, Campaign, Files, and Voting dialogs use the Core small/large/wide scale. The 61 remaining specialized selectors across 22 CSS files are registered and decrease-only. |
|
||||||
|
|
||||||
`tools/checks/check-shared-webui-primitives.py` verifies Core exports and
|
`tools/checks/check-shared-webui-primitives.py` verifies Core exports and
|
||||||
ownership, representative consumers, the absence of the retired raw anatomy,
|
ownership, representative consumers, the absence of the retired raw anatomy,
|
||||||
and composition of every `Dialog` footer through `DialogActions`.
|
and composition of every `Dialog` footer through `DialogActions`.
|
||||||
|
|
||||||
|
## Dialog Width Classification
|
||||||
|
|
||||||
|
The remaining 61 width selectors do not duplicate the Core 460/560/680/1040/
|
||||||
|
1440px scale. They cover bounded editor widths between scale steps, high-density
|
||||||
|
definition and governance editors, preview/chooser canvases, message and file
|
||||||
|
overlays with coupled height behavior, and responsive full-canvas workflows.
|
||||||
|
Their exact selector set lives in
|
||||||
|
`tools/checks/shared-webui-dialog-width-exceptions.txt`. The focused check fails
|
||||||
|
for a new selector, a stale baseline entry, or any local width that duplicates
|
||||||
|
the Core scale.
|
||||||
|
|
||||||
## Remaining Promotion Candidates
|
## Remaining Promotion Candidates
|
||||||
|
|
||||||
The post-migration scan found 101 uses of 30 non-Core grid class names across
|
The post-migration scan still finds domain-specific grids, but the repeated
|
||||||
54 files. Most are intentionally domain-specific; repeated groups identify the
|
generic metric and property-list geometry is gone. Remaining grids are mostly
|
||||||
next useful primitives:
|
unequal-track editors, visualizations, workflow facts, import mappings, and
|
||||||
|
collection layouts. The next useful candidates depend on interaction semantics:
|
||||||
|
|
||||||
| Priority | Remaining pattern | Evidence | Proposed contract |
|
| Priority | Remaining pattern | Evidence | Proposed contract |
|
||||||
| --- | --- | ---: | --- |
|
| --- | --- | ---: | --- |
|
||||||
| 1 | Metric-card groups | `metric-grid`: 29 uses in 25 files | `MetricGrid` or `MetricGroup` owning 1–4/auto-fit columns, compact spacing, inset mode, and narrow stacking around the existing `MetricCard`. |
|
| 1 | Empty and collection state anatomy | More than 70 module-prefixed empty/state class uses remain; only loading, alerts, blockers, and DataGrid empty actions are centralized | A composable `StatePanel`/`CollectionState` covering empty, recoverable error, permission block, partial result, and next action without hiding domain consequences. First distinguish a whole-surface state from a compact empty row or optional-value placeholder. |
|
||||||
| 2 | Property/description lists | `admin-details-grid`: 13 uses in 11 files | Semantic `DescriptionList` with compact/default density, 1–2 columns, wrapping, and narrow collapse. |
|
| 2 | Filter and search rows | More than 50 filter/search class tokens cover simple text search, facets, popovers, result counts, active filters, bulk selection, and overlay search | Define `FilterBar` only after the input/submit, live filtering, facet, result-summary, and bulk-action accessibility variants have been compared. Plain action placement already uses `ActionToolbar`. |
|
||||||
| 3 | Assignment/picker groups | `admin-assignment-grid`: 5 uses in 4 files | A selection/assignment layout only after its list, search, empty, and permission variants are compared; plain geometry can already use `ContentGrid`. |
|
| 3 | Assignment/picker groups | `admin-assignment-grid`: 5 uses in 4 files | Promote a selection/assignment composition only after its list, search, empty, policy, and permission variants are compared; plain geometry can already use `ContentGrid`. |
|
||||||
| 4 | Filter and search rows | Toolbars are centralized, but filter fields, result counts, bulk selection, and action grouping still vary | `FilterBar` composed from `ActionToolbar`, with an explicit search region, filters, result summary, and bulk actions. |
|
| 4 | Repeated domain fact and statistic grids | `campaign-header-grid` (8), `review-flow-fact-grid` (6), `postbox-form-grid` (5), plus smaller families | Compare semantics before promotion. Some can use `ContentGrid` or `DescriptionList`; others intentionally own unequal tracks or workflow visualization. |
|
||||||
| 5 | Dialog sizing exceptions | Dialog consumers still use 62 module class tokens across 53 files; 26 module/Core CSS files contain dialog/modal width declarations needing review | Migrate standard widths to `Dialog size`; retain only documented full-canvas, preview, chooser, and domain-editor exceptions. |
|
|
||||||
| 6 | State and collection anatomy | Loading components exist, but empty/error/retry/action placement is not yet one composition | A composable `StatePanel`/`CollectionState` covering empty, recoverable error, permission block, partial result, and next action without hiding domain consequences. |
|
|
||||||
|
|
||||||
The other custom grids are mostly bounded domain visualizations or unequal-track
|
The other custom grids are mostly bounded domain visualizations or unequal-track
|
||||||
editors: conflict mappings, import mapping, campaign review facts, charts,
|
editors: conflict mappings, import mapping, campaign review facts, charts,
|
||||||
@@ -45,8 +59,8 @@ created merely because two implementations both use CSS Grid.
|
|||||||
|
|
||||||
## Next Audit
|
## Next Audit
|
||||||
|
|
||||||
The next bounded slice should implement the metric and description-list
|
The next bounded slice should compare whole-surface empty states across list,
|
||||||
contracts, migrate their consumers, and then classify dialog width declarations
|
detail, permission, capability, and recoverable-error contexts and promote only
|
||||||
as standard-size migrations or registered exceptions. After that, compare
|
their shared anatomy. Filter/search composition follows after its live versus
|
||||||
filter/search rows before defining their composition; their accessibility and
|
submitted filtering and bulk-selection behavior is explicit. Assignment grids
|
||||||
bulk-selection behavior matter more than visual similarity.
|
remain deferred until their permission and policy variants are understood.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""Enforce Core ownership of repeated WebUI toolbar, grid and dialog anatomy."""
|
"""Enforce Core ownership of repeated WebUI layout and dialog anatomy."""
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
@@ -11,6 +11,7 @@ import sys
|
|||||||
META_ROOT = pathlib.Path(__file__).resolve().parents[2]
|
META_ROOT = pathlib.Path(__file__).resolve().parents[2]
|
||||||
REPOS_ROOT = META_ROOT.parent
|
REPOS_ROOT = META_ROOT.parent
|
||||||
CORE_INDEX = pathlib.Path("govoplan-core/webui/src/index.ts")
|
CORE_INDEX = pathlib.Path("govoplan-core/webui/src/index.ts")
|
||||||
|
DIALOG_WIDTH_EXCEPTIONS = META_ROOT / "tools/checks/shared-webui-dialog-width-exceptions.txt"
|
||||||
|
|
||||||
RAW_ELEMENT = re.compile(
|
RAW_ELEMENT = re.compile(
|
||||||
r'<(?P<tag>div|span|header|section|form)\b(?P<attrs>[^>]*?)'
|
r'<(?P<tag>div|span|header|section|form)\b(?P<attrs>[^>]*?)'
|
||||||
@@ -24,6 +25,9 @@ LEGACY_LAYOUT_TOKENS = {
|
|||||||
"settings-grid",
|
"settings-grid",
|
||||||
"admin-dialog",
|
"admin-dialog",
|
||||||
"admin-dialog-wide",
|
"admin-dialog-wide",
|
||||||
|
"admin-details-grid",
|
||||||
|
"detail-list",
|
||||||
|
"metric-grid",
|
||||||
}
|
}
|
||||||
CENTRAL_COMPONENTS = {
|
CENTRAL_COMPONENTS = {
|
||||||
"ActionToolbar": pathlib.Path(
|
"ActionToolbar": pathlib.Path(
|
||||||
@@ -55,6 +59,15 @@ CENTRAL_COMPONENTS = {
|
|||||||
"DialogSection": pathlib.Path(
|
"DialogSection": pathlib.Path(
|
||||||
"govoplan-core/webui/src/components/DialogAnatomy.tsx"
|
"govoplan-core/webui/src/components/DialogAnatomy.tsx"
|
||||||
),
|
),
|
||||||
|
"DescriptionList": pathlib.Path(
|
||||||
|
"govoplan-core/webui/src/components/DescriptionList.tsx"
|
||||||
|
),
|
||||||
|
"DescriptionItem": pathlib.Path(
|
||||||
|
"govoplan-core/webui/src/components/DescriptionList.tsx"
|
||||||
|
),
|
||||||
|
"MetricGrid": pathlib.Path(
|
||||||
|
"govoplan-core/webui/src/components/MetricGrid.tsx"
|
||||||
|
),
|
||||||
}
|
}
|
||||||
REQUIRED_CONSUMERS = {
|
REQUIRED_CONSUMERS = {
|
||||||
"ActionToolbar": (
|
"ActionToolbar": (
|
||||||
@@ -89,7 +102,42 @@ REQUIRED_CONSUMERS = {
|
|||||||
pathlib.Path("govoplan-files/webui/src/features/files/components/FileShareDialog.tsx"),
|
pathlib.Path("govoplan-files/webui/src/features/files/components/FileShareDialog.tsx"),
|
||||||
pathlib.Path("govoplan-templates/webui/src/features/templates/TemplatesPage.tsx"),
|
pathlib.Path("govoplan-templates/webui/src/features/templates/TemplatesPage.tsx"),
|
||||||
),
|
),
|
||||||
|
"DescriptionList": (
|
||||||
|
pathlib.Path("govoplan-access/webui/src/features/admin/UsersPanel.tsx"),
|
||||||
|
pathlib.Path("govoplan-campaign/webui/src/features/campaigns/CampaignReportPage.tsx"),
|
||||||
|
pathlib.Path("govoplan-docs/webui/src/features/docs/DocsPage.tsx"),
|
||||||
|
pathlib.Path("govoplan-policy/webui/src/features/policy/ViewPoliciesPanel.tsx"),
|
||||||
|
),
|
||||||
|
"MetricGrid": (
|
||||||
|
pathlib.Path("govoplan-core/webui/src/features/dashboard/DashboardPage.tsx"),
|
||||||
|
pathlib.Path("govoplan-admin/webui/src/features/admin/ModuleManagementPanel.tsx"),
|
||||||
|
pathlib.Path("govoplan-campaign/webui/src/features/operator/OperatorQueuePage.tsx"),
|
||||||
|
pathlib.Path("govoplan-notifications/webui/src/features/notifications/NotificationSummaryWidget.tsx"),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
LEGACY_CSS_SELECTOR = re.compile(
|
||||||
|
r"(?<![-\w])\.(?:admin-details-grid|detail-list|metric-grid)(?![-\w])"
|
||||||
|
)
|
||||||
|
CSS_BLOCK = re.compile(r"([^{}]+)\{([^{}]*)\}")
|
||||||
|
CSS_COMMENT = re.compile(r"/\*.*?\*/", re.DOTALL)
|
||||||
|
DIALOG_CLASS = re.compile(r"\.([A-Za-z0-9_-]*(?:dialog|modal)[A-Za-z0-9_-]*)", re.IGNORECASE)
|
||||||
|
DIALOG_WIDTH = re.compile(r"(?:^|;)\s*(?:width|max-width)\s*:", re.MULTILINE)
|
||||||
|
DIALOG_WIDTH_VALUE = re.compile(
|
||||||
|
r"(?:^|;)\s*(?:width|max-width)\s*:\s*([^;]+)", re.MULTILINE
|
||||||
|
)
|
||||||
|
STANDARD_DIALOG_WIDTH = re.compile(r"\b(?:460|560|680|1040|1440)px\b")
|
||||||
|
DIALOG_INTERNAL_SUFFIXES = (
|
||||||
|
"-actions",
|
||||||
|
"-body",
|
||||||
|
"-close",
|
||||||
|
"-content",
|
||||||
|
"-field",
|
||||||
|
"-fields",
|
||||||
|
"-footer",
|
||||||
|
"-form",
|
||||||
|
"-header",
|
||||||
|
"-title",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def source_paths() -> list[pathlib.Path]:
|
def source_paths() -> list[pathlib.Path]:
|
||||||
@@ -101,6 +149,15 @@ def source_paths() -> list[pathlib.Path]:
|
|||||||
return paths
|
return paths
|
||||||
|
|
||||||
|
|
||||||
|
def css_paths() -> list[pathlib.Path]:
|
||||||
|
paths: list[pathlib.Path] = []
|
||||||
|
for repository in sorted(REPOS_ROOT.glob("govoplan*")):
|
||||||
|
source_root = repository / "webui" / "src"
|
||||||
|
if source_root.is_dir():
|
||||||
|
paths.extend(sorted(source_root.rglob("*.css")))
|
||||||
|
return paths
|
||||||
|
|
||||||
|
|
||||||
def relative(path: pathlib.Path) -> pathlib.Path:
|
def relative(path: pathlib.Path) -> pathlib.Path:
|
||||||
return path.relative_to(REPOS_ROOT)
|
return path.relative_to(REPOS_ROOT)
|
||||||
|
|
||||||
@@ -123,9 +180,47 @@ def raw_reason(classes: str) -> str | None:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def normalized_css_selector(selector: str) -> str:
|
||||||
|
return " ".join(selector.split())
|
||||||
|
|
||||||
|
|
||||||
|
def dialog_width_exceptions(styles: dict[pathlib.Path, str]) -> dict[str, str]:
|
||||||
|
exceptions: dict[str, str] = {}
|
||||||
|
central_dialog_styles = pathlib.Path("govoplan-core/webui/src/styles/dialogs.css")
|
||||||
|
for path, content in styles.items():
|
||||||
|
if path == central_dialog_styles:
|
||||||
|
continue
|
||||||
|
without_comments = CSS_COMMENT.sub("", content)
|
||||||
|
for match in CSS_BLOCK.finditer(without_comments):
|
||||||
|
selector = normalized_css_selector(match.group(1))
|
||||||
|
declarations = match.group(2)
|
||||||
|
if not DIALOG_WIDTH.search(declarations):
|
||||||
|
continue
|
||||||
|
dialog_classes = DIALOG_CLASS.findall(selector)
|
||||||
|
if not dialog_classes:
|
||||||
|
continue
|
||||||
|
if all(name.lower().endswith(DIALOG_INTERNAL_SUFFIXES) for name in dialog_classes):
|
||||||
|
continue
|
||||||
|
signature = f"{path}|{selector}"
|
||||||
|
exceptions[signature] = declarations
|
||||||
|
return exceptions
|
||||||
|
|
||||||
|
|
||||||
|
def exception_baseline() -> set[str]:
|
||||||
|
if not DIALOG_WIDTH_EXCEPTIONS.exists():
|
||||||
|
return set()
|
||||||
|
return {
|
||||||
|
line.strip()
|
||||||
|
for line in DIALOG_WIDTH_EXCEPTIONS.read_text(encoding="utf-8").splitlines()
|
||||||
|
if line.strip() and not line.lstrip().startswith("#")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def main() -> int:
|
def main() -> int:
|
||||||
sources = source_paths()
|
sources = source_paths()
|
||||||
source_text = {relative(path): path.read_text(encoding="utf-8") for path in sources}
|
source_text = {relative(path): path.read_text(encoding="utf-8") for path in sources}
|
||||||
|
styles = css_paths()
|
||||||
|
style_text = {relative(path): path.read_text(encoding="utf-8") for path in styles}
|
||||||
errors: list[str] = []
|
errors: list[str] = []
|
||||||
|
|
||||||
for path, content in source_text.items():
|
for path, content in source_text.items():
|
||||||
@@ -138,6 +233,24 @@ def main() -> int:
|
|||||||
f"Raw {match.group('tag')} repeats shared anatomy ({reason}): {path}:{line}"
|
f"Raw {match.group('tag')} repeats shared anatomy ({reason}): {path}:{line}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
for path, content in style_text.items():
|
||||||
|
legacy_match = LEGACY_CSS_SELECTOR.search(CSS_COMMENT.sub("", content))
|
||||||
|
if legacy_match:
|
||||||
|
line = content.count("\n", 0, legacy_match.start()) + 1
|
||||||
|
errors.append(f"Legacy shared layout selector is not allowed: {path}:{line}")
|
||||||
|
|
||||||
|
dialog_exceptions = dialog_width_exceptions(style_text)
|
||||||
|
baseline = exception_baseline()
|
||||||
|
for signature in sorted(set(dialog_exceptions) - baseline):
|
||||||
|
errors.append(f"Unreviewed local dialog width; use Dialog size or register a justified exception: {signature}")
|
||||||
|
for signature in sorted(baseline - set(dialog_exceptions)):
|
||||||
|
errors.append(f"Stale dialog width exception can be removed: {signature}")
|
||||||
|
for signature, declarations in sorted(dialog_exceptions.items()):
|
||||||
|
width_values = " ".join(DIALOG_WIDTH_VALUE.findall(declarations))
|
||||||
|
standard = STANDARD_DIALOG_WIDTH.search(width_values)
|
||||||
|
if standard:
|
||||||
|
errors.append(f"Local dialog width duplicates Core size {standard.group(0)}: {signature}")
|
||||||
|
|
||||||
for name, owner in CENTRAL_COMPONENTS.items():
|
for name, owner in CENTRAL_COMPONENTS.items():
|
||||||
definition = re.compile(
|
definition = re.compile(
|
||||||
rf"\b(?:function|class)\s+{name}\b|\bconst\s+{name}\s*="
|
rf"\b(?:function|class)\s+{name}\b|\bconst\s+{name}\s*="
|
||||||
@@ -178,9 +291,9 @@ def main() -> int:
|
|||||||
|
|
||||||
migrated = ", ".join(
|
migrated = ", ".join(
|
||||||
f"{name}={usage_counts[name]} files"
|
f"{name}={usage_counts[name]} files"
|
||||||
for name in ("ActionToolbar", "ContentGrid", "FormGrid", "FormSection", "DialogForm", "DialogSection")
|
for name in ("ActionToolbar", "ContentGrid", "FormGrid", "FormSection", "DialogForm", "DialogSection", "MetricGrid", "DescriptionList")
|
||||||
)
|
)
|
||||||
print(f"Shared WebUI primitive contract passed: {migrated}; no raw legacy anatomy.")
|
print(f"Shared WebUI primitive contract passed: {migrated}; {len(dialog_exceptions)} reviewed dialog width exceptions; no raw legacy anatomy.")
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
# Reviewed module-specific Dialog and modal width selectors.
|
||||||
|
#
|
||||||
|
# Standard Core widths (460/560/680/1040/1440px) are never valid here.
|
||||||
|
# Remove an entry when its consumer moves to Dialog size; additions require
|
||||||
|
# an explicit design review and an inventory explanation.
|
||||||
|
govoplan-addresses/webui/src/styles/addresses.css|.address-governance-dialog .dialog-panel
|
||||||
|
govoplan-addresses/webui/src/styles/addresses.css|.address-import-dialog
|
||||||
|
govoplan-addresses/webui/src/styles/addresses.css|.address-sync-dialog
|
||||||
|
govoplan-addresses/webui/src/styles/addresses.css|.dialog-panel.address-contact-dialog
|
||||||
|
govoplan-addresses/webui/src/styles/addresses.css|.dialog-panel.address-member-dialog
|
||||||
|
govoplan-addresses/webui/src/styles/addresses.css|.dialog-panel.address-quality-dialog, .address-quality-dialog .dialog-panel
|
||||||
|
govoplan-approvals/webui/src/styles/approvals.css|.approval-request-dialog, .approval-template-dialog
|
||||||
|
govoplan-approvals/webui/src/styles/approvals.css|.approval-template-history-dialog
|
||||||
|
govoplan-calendar/webui/src/styles/calendar.css|.calendar-delete-dialog
|
||||||
|
govoplan-calendar/webui/src/styles/calendar.css|.calendar-migration-dialog
|
||||||
|
govoplan-calendar/webui/src/styles/calendar.css|.calendar-outbox-dialog
|
||||||
|
govoplan-calendar/webui/src/styles/calendar.css|.calendar-vevent-dialog
|
||||||
|
govoplan-campaign/webui/src/styles/campaign-workspace.css|.attachment-linking-detail-modal
|
||||||
|
govoplan-campaign/webui/src/styles/campaign-workspace.css|.attachment-rules-modal
|
||||||
|
govoplan-campaign/webui/src/styles/campaign-workspace.css|.campaign-content-library-dialog
|
||||||
|
govoplan-campaign/webui/src/styles/campaign-workspace.css|.campaign-copy-dialog
|
||||||
|
govoplan-campaign/webui/src/styles/campaign-workspace.css|.campaign-schedule-dialog
|
||||||
|
govoplan-campaign/webui/src/styles/campaign-workspace.css|.dialog-panel-wide
|
||||||
|
govoplan-campaign/webui/src/styles/campaign-workspace.css|.message-preview-modal
|
||||||
|
govoplan-campaign/webui/src/styles/campaign-workspace.css|.recipient-address-editor-modal
|
||||||
|
govoplan-campaign/webui/src/styles/campaign-workspace.css|.recipient-import-modal
|
||||||
|
govoplan-campaign/webui/src/styles/campaign-workspace.css|.template-action-dialog
|
||||||
|
govoplan-campaign/webui/src/styles/campaign-workspace.css|.template-expression-dialog
|
||||||
|
govoplan-campaign/webui/src/styles/campaign-workspace.css|.template-preview-modal
|
||||||
|
govoplan-cases/webui/src/styles/cases.css|.case-decision-dialog
|
||||||
|
govoplan-cases/webui/src/styles/cases.css|.case-share-dialog
|
||||||
|
govoplan-committee/webui/src/styles/committee.css|.committee-ballot-dialog
|
||||||
|
govoplan-committee/webui/src/styles/committee.css|.committee-record-dialog
|
||||||
|
govoplan-core/webui/src/styles/components.css|.dialog-panel.wysiwyg-editor-dialog
|
||||||
|
govoplan-core/webui/src/styles/components.css|.guided-config-dialog
|
||||||
|
govoplan-core/webui/src/styles/components.css|.password-generator-dialog
|
||||||
|
govoplan-core/webui/src/styles/components.css|.unsaved-changes-dialog
|
||||||
|
govoplan-core/webui/src/styles/layout.css|.concurrency-conflict-dialog
|
||||||
|
govoplan-dashboard/webui/src/styles/dashboard.css|.dashboard-widget-config-dialog
|
||||||
|
govoplan-dataflow/webui/src/styles/dataflow.css|.dataflow-decision-dialog
|
||||||
|
govoplan-dataflow/webui/src/styles/dataflow.css|.dataflow-definition-dialog
|
||||||
|
govoplan-dataflow/webui/src/styles/dataflow.css|.dataflow-run-dialog
|
||||||
|
govoplan-dataflow/webui/src/styles/dataflow.css|.dataflow-source-dialog
|
||||||
|
govoplan-dataflow/webui/src/styles/dataflow.css|.dataflow-triggers-dialog
|
||||||
|
govoplan-datasources/webui/src/styles/datasources.css|.datasources-add-dialog
|
||||||
|
govoplan-datasources/webui/src/styles/datasources.css|.datasources-governance-dialog
|
||||||
|
govoplan-dist-lists/webui/src/styles/dist-lists.css|.dist-lists-entry-dialog
|
||||||
|
govoplan-dist-lists/webui/src/styles/dist-lists.css|.dist-lists-explanation-dialog
|
||||||
|
govoplan-files/webui/src/styles/file-manager.css|.file-dialog
|
||||||
|
govoplan-files/webui/src/styles/file-manager.css|.file-dialog:has(.archive-preview)
|
||||||
|
govoplan-files/webui/src/styles/file-manager.css|.file-dialog:has(.connector-sync-grid)
|
||||||
|
govoplan-files/webui/src/styles/file-manager.css|.file-dialog:has(.file-share-dialog-content)
|
||||||
|
govoplan-files/webui/src/styles/file-manager.css|.managed-file-chooser-dialog
|
||||||
|
govoplan-forms-runtime/webui/src/styles/forms-runtime.css|.form-intake-dialog
|
||||||
|
govoplan-forms/webui/src/styles/forms.css|.form-definition-dialog
|
||||||
|
govoplan-organizations/webui/src/styles/organizations.css|.organization-upgrade-dialog
|
||||||
|
govoplan-postbox/webui/src/styles/postbox.css|.postbox-dialog
|
||||||
|
govoplan-postbox/webui/src/styles/postbox.css|.postbox-message-dialog
|
||||||
|
govoplan-postbox/webui/src/styles/postbox.css|.postbox-template-dialog
|
||||||
|
govoplan-projects/webui/src/styles/projects.css|.project-editor-dialog
|
||||||
|
govoplan-records/webui/src/styles/records.css|.records-dialog
|
||||||
|
govoplan-reporting/webui/src/styles/reporting.css|.reporting-drill-dialog
|
||||||
|
govoplan-views/webui/src/styles/views.css|.views-assignment-dialog
|
||||||
|
govoplan-workflow/webui/src/styles/workflow.css|.workflow-definition-dialog
|
||||||
|
govoplan-workflow/webui/src/styles/workflow.css|.workflow-runs-dialog
|
||||||
|
govoplan-workflow/webui/src/styles/workflow.css|.workflow-standard-comparison-dialog
|
||||||
|
|
||||||
Reference in New Issue
Block a user