-
Notifications
You must be signed in to change notification settings - Fork 2
SDK UI Conventions
The patterns a new screen is expected to follow. They exist so that a user who has learned one Cairn screen has learned them all, and so that a reviewer can tell "different" from "wrong".
The visual system itself, the palette, typography, spacing, motion and accessibility commitments, is the brand guidelines. That document is the source of truth; this page is how it lands in a template.
Server-rendered Django templates, Bootstrap 5.3, HTMX for partial updates, Apache ECharts for graphs. There is no bundler and no npm. A change that needs one is a change that needs a conversation first.
/styleguide/ renders the whole component set in a running instance. Look there
before inventing a component.
Every front-end library is served from the instance itself. Referencing
cdn.jsdelivr.net, unpkg.com or Google Fonts from a template fails the build
(core/tests/test_dependencies.py), because an isolated deployment would then
render an unstyled page and every visitor would be announced to a third party.
To add one :
- Declare it in
core/dependencies.pyas aDependencyin theFRONTENDgroup, with itspinned_versionand oneVendorAssetper file it needs. Keep the sub-directory layout the library expects of itself : a stylesheet that asks forfonts/…orimages/…needs those files at that relative path. - Get the digests with
python manage.py vendor_assets --print-hashesand paste them into the declaration. The download is refused if they do not match. - Mirror the files locally with
python manage.py vendor_assets. - Load it in the template with
{% static "vendor/<library>/<file>" %}- no version in the path, nointegrityattribute (the file is same-origin and was verified when it was fetched).
Upgrading is the same list : change the version, re-run --print-hashes, paste,
then vendor_assets --force. The tests check that the pinned version is the one
the declared URLs actually fetch, and that every vendor/… path a template asks
for is a file something mirrors.
Use a two-column card layout : the main content on the left, a sticky metadata sidebar on the right carrying status, people and dates. Group the rest into stacked cards and collapsible sections.
Tabs hide content and cost the reader a click to discover what they do not know
is there. Use them only where the views are genuinely distinct modes, as the
compliance assessment does with Planning, Findings and History.
compliance/templates/compliance/action_plan_detail.html is the reference
implementation.
Add LifecycleStepperMixin to the DetailView, include the shared template:
{% include "includes/lifecycle_stepper.html" %}It renders done, current, next and future steps, the permission-aware next step,
refusal and rework through clickable earlier pills, the archived off-ramp, and
the comment modal for transitions that require one. State badges use
{% workflow_badge obj %}.
Never a plain button, never a status dropdown, never per-page stepper markup. Each of those reintroduces on one page the divergence the engine exists to prevent, and each is invisible until an auditor finds the page where the gate was missing.
SortableListMixin gives server-side sorting with the user's choice persisted
in User.table_preferences, so a sort survives navigation and devices. Combine
it with ScopeFilterMixin for tenancy.
Table conventions, column order, alignment, density, are in brand/table-standard.md.
Every component must render correctly in light and dark. Use Bootstrap semantic classes and the brand's CSS custom properties; never hardcode a colour value.
Check both before calling a change done. A component that only works in the theme you happen to use is half a component.
Test narrow viewports, and pay attention to the three things that break first : multi-select widgets, sticky bars and form layouts.
Bootstrap Icons, exclusively. No second icon set, no inline SVG for something the set already has.
Wrapped with {% trans %} or {% blocktrans %}, with the French entry added in
the same change. A literal string in a template is a bug even when it is an
English word that reads fine. See
internationalisation.
Partial updates return a fragment, not a full page. django-htmx puts
request.htmx on the request so a view can serve both. Keep the fragment's
template separate rather than branching inside one template with a conditional
wrapper.
Boosted navigation means a page can be swapped into an existing document rather than loaded fresh. Anything that initialises on page load has to survive that, which is the usual cause of "it only works after a hard refresh".
The commitment is WCAG 2.2 AA. In practice, on a new screen: every control has
an accessible name, focus is visible, colour is never the only carrier of
meaning, and motion honours prefers-reduced-motion.
- Detail page is a two-column card layout, tabs only if genuinely distinct modes
- Lifecycle transitions go through the shared stepper
- Lists use
SortableListMixinandScopeFilterMixin - Renders correctly in light and dark
- Checked on a narrow viewport
- Bootstrap Icons only
- Every string wrapped and translated
- Works after a boosted navigation, not only a hard refresh
- Controls named, focus visible, colour not the only signal
Built from docs/ at v0.36.0. Edits made here are overwritten by the next release : open a pull request against the source instead.
- Administration
- Ask Cairn
- Assets and suppliers
- Compliance
- The dashboard
- Finding your way
- Getting started
- Incidents
- How records move
- Organisational context
- Reports and management review
- Risks
- Trust Center
- Architecture
- Configuration
- Contributing
- The documentation system
- Installation
- Internationalisation
- Operations
- Release process
- Security
- Testing
- Adding an assistant provider
- Adding a dashboard widget
- Adding a domain entity
- Declaring a lifecycle
- Adding an MCP tool
- Adding a REST endpoint
- Adding a report
- Interface conventions
- Dashboard widgets
- Lifecycles
- MCP tools
- MCP tool parameters : Assets
- MCP tool parameters : Compliance
- MCP tool parameters : Governance and context
- MCP tool parameters : General
- MCP tool parameters : Incidents
- MCP tool parameters : Reports and management review
- MCP tool parameters : Risks
- MCP tool parameters : System and administration
- MCP tool parameters : Trust Center
- Management commands
- Models
- Permissions
- REST endpoints
- Environment variables
- MCP server
- REST API
- Assistant module (Ask Cairn)
- Module 0: User Management and Access Control
- Module 1: Context and Organization
- Module 2: Asset Management
- Module 3: Compliance
- Module 4: Risk Management
- Module 4 bis - EBIOS Risk Manager
- Module 5 : Trust Center
- Module 6 : Security Incident Management
- Management review : ISO 27001:2022 compliance (clause 9.3)