Skip to content

Commit b6a848c

Browse files
Refactor breast features (#149)
1 parent b5296aa commit b6a848c

File tree

11 files changed

+1941
-1491
lines changed

11 files changed

+1941
-1491
lines changed

app/assets/javascript/breast-features.js

Lines changed: 1223 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
// app/assets/sass/components/_breast-features.scss
2+
3+
@use "nhsuk-frontend/dist/nhsuk/core/settings" as *;
4+
@use "nhsuk-frontend/dist/nhsuk/core/tools" as *;
5+
@use "nhsuk-frontend/dist/nhsuk/core/helpers" as *;
6+
@use "nhsuk-frontend/dist/nhsuk/core/objects" as *;
7+
@use "nhsuk-frontend/dist/nhsuk/core/styles/typography" as *;
8+
9+
10+
// Custom variables for breast features
11+
$breast-features-marker-size: 40px;
12+
$breast-features-border-width: 2px;
13+
$breast-features-spacing-small: 8px;
14+
$breast-features-spacing-medium: 16px;
15+
$breast-features-spacing-large: 32px;
16+
$breast-features-border-radius: 2px;
17+
$breast-features-marker-font-size: 18px;
18+
$breast-features-popover-min-width: 280px;
19+
$breast-features-popover-max-width: 400px;
20+
$breast-features-z-index-marker: 50; // Below sticky nav (999)
21+
$breast-features-z-index-popover: 1000; // Above sticky nav
22+
$breast-features-z-index-dragging: 60; // Still below sticky nav but above normal markers
23+
24+
// ELEMENT: Side labels above the diagram
25+
.breast-features__side-labels {
26+
display: flex;
27+
justify-content: space-between;
28+
margin-bottom: $breast-features-spacing-small;
29+
font-weight: 600;
30+
font-size: 19px;
31+
color: $nhsuk-text-colour;
32+
}
33+
34+
// ELEMENT: SVG diagram container
35+
.breast-features__diagram {
36+
position: relative;
37+
border: 3px solid $nhsuk-text-colour;
38+
background: nhsuk-colour("white");
39+
margin: 0;
40+
cursor: crosshair;
41+
overflow: hidden;
42+
}
43+
44+
// MODIFIER: Read-only diagram
45+
.breast-features__diagram--read-only {
46+
cursor: default;
47+
}
48+
49+
// ELEMENT: SVG element itself
50+
.breast-features__svg {
51+
width: 100%;
52+
height: auto;
53+
aspect-ratio: 2 / 1;
54+
cursor: inherit;
55+
pointer-events: all;
56+
display: block;
57+
}
58+
59+
// ELEMENT: Interactive markers on the diagram
60+
.breast-features__marker {
61+
position: absolute;
62+
width: $breast-features-marker-size;
63+
height: $breast-features-marker-size;
64+
background-color: $nhsuk-link-colour;
65+
border: $breast-features-border-width solid nhsuk-colour("white");
66+
border-radius: $breast-features-border-radius;
67+
z-index: $breast-features-z-index-marker;
68+
pointer-events: all;
69+
display: flex;
70+
align-items: center;
71+
justify-content: center;
72+
color: nhsuk-colour("white");
73+
font-size: $breast-features-marker-font-size;
74+
font-weight: bold;
75+
cursor: pointer;
76+
user-select: none;
77+
-webkit-user-select: none;
78+
-moz-user-select: none;
79+
-webkit-touch-callout: none;
80+
-webkit-tap-highlight-color: transparent;
81+
}
82+
83+
// MODIFIER: Dragging marker state
84+
.breast-features__marker--dragging {
85+
cursor: grabbing;
86+
opacity: 0.8;
87+
transform: scale(1.05);
88+
box-shadow: 0 4px 12px rgba(33, 43, 50, 0.3);
89+
}
90+
91+
// MODIFIER: Read-only marker
92+
.breast-features__marker--read-only {
93+
cursor: default;
94+
}
95+
96+
// ELEMENT: Text labels next to markers
97+
.breast-features__marker-label {
98+
background: nhsuk-colour("white");
99+
border: $breast-features-border-width solid $nhsuk-text-colour;
100+
padding: 4px $breast-features-spacing-small;
101+
font-size: 14px;
102+
font-weight: 600;
103+
color: $nhsuk-text-colour;
104+
position: absolute;
105+
white-space: nowrap;
106+
z-index: 100;
107+
line-height: 1.2;
108+
cursor: grab;
109+
user-select: none;
110+
border-radius: $breast-features-border-radius;
111+
left: 45px;
112+
top: -10px;
113+
}
114+
115+
.breast-features__marker-label:hover {
116+
background: nhsuk-colour("grey-5");
117+
}
118+
119+
// MODIFIER: Dragging label state
120+
.breast-features__marker-label--dragging {
121+
cursor: grabbing;
122+
opacity: 0.8;
123+
z-index: $breast-features-z-index-dragging;
124+
transform: scale(1.05);
125+
box-shadow: 0 4px 12px rgba(33, 43, 50, 0.3);
126+
}
127+
128+
// ELEMENT: Popover for adding/editing features
129+
.breast-features__popover {
130+
position: fixed;
131+
background: nhsuk-colour("white");
132+
border: 4px solid $nhsuk-link-colour;
133+
padding: $breast-features-spacing-large;
134+
padding-bottom: calc($breast-features-spacing-large - 20px); // reduce padding by margin size on buttons. Ideally this would be dynamically generated.
135+
box-shadow: 0 4px 16px rgba(33, 43, 50, 0.16);
136+
z-index: $breast-features-z-index-popover;
137+
min-width: $breast-features-popover-min-width;
138+
max-width: $breast-features-popover-max-width;
139+
display: none;
140+
border-radius: 4px;
141+
max-height: 80vh;
142+
overflow-y: auto;
143+
}
144+
145+
// ELEMENT: Features list component
146+
.breast-features__list {
147+
margin-top: 20px;
148+
}
149+
150+
// ELEMENT: List header
151+
.breast-features__list-header {
152+
display: flex;
153+
justify-content: space-between;
154+
align-items: center;
155+
margin-bottom: $breast-features-spacing-medium;
156+
}
157+
158+
// ELEMENT: List title
159+
.breast-features__list-title {
160+
margin: 0;
161+
}
162+
163+
// ELEMENT: Clear all link
164+
.breast-features__list-clear-link {
165+
font-size: 14px;
166+
}
167+
168+
// ELEMENT: List items container
169+
.breast-features__list-items {
170+
list-style: none;
171+
padding: 0;
172+
margin: 0;
173+
}
174+
175+
// ELEMENT: Individual feature item in the list
176+
.breast-features__item {
177+
display: flex;
178+
align-items: center;
179+
justify-content: space-between;
180+
padding: 12px 0;
181+
border-bottom: 1px solid $nhsuk-secondary-text-colour;
182+
gap: 12px;
183+
}
184+
185+
.breast-features__item:last-child {
186+
border-bottom: none;
187+
}
188+
189+
// MODIFIER: Interactive item
190+
.breast-features__item--interactive {
191+
cursor: pointer;
192+
}
193+
194+
// ELEMENT: Left side of feature item (number + label)
195+
.breast-features__item-left {
196+
display: flex;
197+
align-items: center;
198+
gap: 12px;
199+
}
200+
201+
// ELEMENT: Feature number badge
202+
.breast-features__item-number {
203+
position: relative;
204+
width: $breast-features-marker-size;
205+
height: $breast-features-marker-size;
206+
flex-shrink: 0;
207+
background-color: $nhsuk-link-colour;
208+
border: $breast-features-border-width solid nhsuk-colour("white");
209+
border-radius: $breast-features-border-radius;
210+
display: flex;
211+
align-items: center;
212+
justify-content: center;
213+
color: nhsuk-colour("white");
214+
font-size: $breast-features-marker-font-size;
215+
font-weight: bold;
216+
}
217+
218+
// ELEMENT: Feature text label
219+
.breast-features__item-label {
220+
font-weight: 600;
221+
color: $nhsuk-text-colour;
222+
font-size: 16px;
223+
}
224+
225+
// ELEMENT: Feature position/location
226+
.breast-features__item-position {
227+
color: $nhsuk-text-colour;
228+
font-size: 14px;
229+
font-weight: normal;
230+
}
231+
232+
// ELEMENT: Anatomical region borders (hidden by default)
233+
.breast-features__regions {
234+
opacity: 0;
235+
pointer-events: all;
236+
}
237+
238+
// MODIFIER: Visible regions
239+
.breast-features__regions--visible {
240+
opacity: 1;
241+
}
242+
243+
// ELEMENT: Individual anatomical region
244+
.breast-features__region {
245+
stroke: $nhsuk-secondary-text-colour;
246+
stroke-width: 1px;
247+
stroke-dasharray: 5, 5;
248+
fill: none;
249+
opacity: 0;
250+
pointer-events: all;
251+
}
252+
253+
// When regions are visible, show them
254+
.breast-features__regions--visible .breast-features__region {
255+
opacity: 1;
256+
}
257+
258+
// Only show axilla borders when toggled
259+
.breast-features__regions--visible .breast-features__region[data-region="axilla"] {
260+
opacity: 1 !important;
261+
}
262+
263+
// Responsive design
264+
@media (max-width: 768px) {
265+
.breast-features {
266+
padding: $breast-features-spacing-medium;
267+
}
268+
269+
.breast-features__popover {
270+
min-width: $breast-features-popover-min-width;
271+
max-width: 90vw;
272+
padding: 20px;
273+
}
274+
}

0 commit comments

Comments
 (0)