Skip to content

Commit 6c78931

Browse files
Radio icon buttons (#5121)
* buttony radios * buttons go
1 parent ea22cf2 commit 6c78931

2 files changed

Lines changed: 159 additions & 37 deletions

File tree

modules/@apostrophecms/schema/ui/apos/components/AposInputRadio.vue

Lines changed: 138 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -7,45 +7,70 @@
77
:modifiers="modifiers"
88
>
99
<template #body>
10-
<label
11-
v-for="{label, value, tooltip} in choices"
12-
:key="value"
13-
class="apos-choice-label"
14-
:for="getChoiceId(uid, value)"
15-
:class="{'apos-choice-label--disabled': field.readOnly}"
10+
<div
11+
class="apos-radio-wrapper"
12+
:class="{'apos-radio-wrapper--buttons': field.buttons }"
1613
>
17-
<input
18-
:id="getChoiceId(uid, value)"
19-
type="radio"
20-
class="apos-sr-only apos-input--choice apos-input--radio"
21-
:value="JSON.stringify(value)"
22-
:name="field.name"
23-
:checked="next === value"
24-
tabindex="1"
25-
:disabled="field.readOnly"
26-
@change="change($event.target.value)"
14+
<label
15+
v-for="{label, value, tooltip, icon} in choices"
16+
:key="value"
17+
v-apos-tooltip="(field.buttons && !!tooltip) ? $t(tooltip) : null"
18+
:aria-label="label"
19+
class="apos-choice-label"
20+
:for="getChoiceId(uid, value)"
21+
:class="[
22+
{ 'apos-choice-label--disabled': field.readOnly },
23+
{ 'apos-choice-label--checked': next === value }
24+
]"
25+
tabindex="0"
26+
@keydown.space="next = value"
2727
>
28-
<span
29-
class="apos-input-indicator"
30-
aria-hidden="true"
31-
>
32-
<component
33-
:is="`${next === value ? 'check-bold-icon' : 'span'}`"
34-
v-if="next === value"
35-
:size="8"
36-
/>
37-
</span>
38-
<span class="apos-choice-label-text">
39-
{{ $t(label) }}
40-
<AposIndicator
41-
v-if="tooltip"
42-
class="apos-choice-label-info"
43-
:tooltip="tooltip"
44-
:icon-size="14"
45-
icon="information-icon"
46-
/>
47-
</span>
48-
</label>
28+
<input
29+
:id="getChoiceId(uid, value)"
30+
type="radio"
31+
class="apos-sr-only apos-input--choice apos-input--radio"
32+
:value="JSON.stringify(value)"
33+
:name="field.name"
34+
:checked="next === value"
35+
tabindex="0"
36+
:disabled="field.readOnly"
37+
@change="change($event.target.value)"
38+
>
39+
<span
40+
v-if="!field.buttons"
41+
class="apos-input-indicator"
42+
aria-hidden="true"
43+
>
44+
<component
45+
:is="`${next === value ? 'check-bold-icon' : 'span'}`"
46+
v-if="next === value"
47+
:size="8"
48+
/>
49+
</span>
50+
<span
51+
v-if="icon"
52+
class="apos-choice-label-icon"
53+
>
54+
<AposIndicator
55+
:icon-size="14"
56+
:icon="icon"
57+
/>
58+
</span>
59+
<span
60+
v-if="label"
61+
class="apos-choice-label-text"
62+
>
63+
{{ $t(label) }}
64+
<AposIndicator
65+
v-if="tooltip && !field.buttons"
66+
class="apos-choice-label-info"
67+
:tooltip="$t(tooltip)"
68+
:icon-size="14"
69+
icon="information-icon"
70+
/>
71+
</span>
72+
</label>
73+
</div>
4974
</template>
5075
</AposInputWrapper>
5176
</template>
@@ -69,4 +94,80 @@ export default {
6994
position: relative;
7095
top: 3px;
7196
}
97+
98+
.apos-choice-label + .apos-choice-label {
99+
margin: unset;
100+
}
101+
102+
.apos-radio-wrapper {
103+
display: inline-flex;
104+
flex-direction: column;
105+
gap: $spacing-base;
106+
}
107+
108+
.apos-choice-label {
109+
&:focus,
110+
&:active {
111+
outline: 1px solid var(--a-primary);
112+
}
113+
}
114+
115+
.apos-radio-wrapper--buttons {
116+
flex-direction: row;
117+
gap: 0;
118+
119+
.apos-choice-label-icon {
120+
margin-left: 0;
121+
}
122+
123+
.apos-choice-label:first-of-type {
124+
border-radius: var(--a-border-radius) 0 0 var(--a-border-radius);
125+
border-left: 1px solid var(--a-base-8);
126+
}
127+
128+
.apos-choice-label:last-of-type {
129+
border-radius: 0 var(--a-border-radius) var(--a-border-radius) 0;
130+
border-right: 1px solid var(--a-base-8);
131+
}
132+
133+
.apos-choice-label + .apos-choice-label {
134+
&::before {
135+
content: '';
136+
position: absolute;
137+
left: -0.5px;
138+
width: 1px;
139+
height: 50%;
140+
background-color: var(--a-base-7);
141+
}
142+
}
143+
144+
.apos-choice-label--checked + .apos-choice-label::before,
145+
.apos-choice-label--checked::before {
146+
display: none;
147+
}
148+
149+
.apos-choice-label {
150+
position: relative;
151+
height: 34px;
152+
padding: 0 $spacing-base;
153+
border-top: 1px solid var(--a-base-8);
154+
border-bottom: 1px solid var(--a-base-8);
155+
background-color: var(--a-base-9);
156+
157+
&:focus,
158+
&:active {
159+
outline-offset: -1px;
160+
}
161+
162+
&:hover,
163+
&--checked {
164+
background-color: var(--a-base-8);
165+
166+
// stylelint-disable max-nesting-depth
167+
.apos-choice-label-icon {
168+
color: var(--a-black);
169+
}
170+
}
171+
}
172+
}
72173
</style>

modules/@apostrophecms/ui/ui/apos/scss/global/_inputs.scss

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,18 @@
147147
font-size: var(--a-type-smaller);
148148
}
149149

150+
&.apos-field--radio {
151+
.apos-radio-wrapper--buttons {
152+
width: 100%;
153+
}
154+
155+
.apos-radio-wrapper--buttons .apos-choice-label {
156+
flex: 1;
157+
height: 27px;
158+
place-content: center;
159+
}
160+
}
161+
150162
&.apos-field--relationship {
151163
.apos-input-relationship__button {
152164
top: 1px;
@@ -336,6 +348,11 @@
336348
display: flex;
337349
}
338350

351+
.apos-choice-label-icon {
352+
margin-left: $spacing-half;
353+
line-height: 0;
354+
}
355+
339356
.apos-choice-label-text {
340357
@include type-base;
341358

@@ -344,6 +361,10 @@
344361
}
345362
}
346363

364+
.apos-choice-label-icon + .apos-choice-label-text {
365+
margin-left: $spacing-half;
366+
}
367+
347368
.apos-input-indicator {
348369
@include apos-transition($what: all, $duration: 0.1s, $ease: ease-in-out);
349370

0 commit comments

Comments
 (0)