Skip to content

Commit 7fd2908

Browse files
authored
feat: #37
1 parent 73843a9 commit 7fd2908

File tree

2 files changed

+44
-53
lines changed

2 files changed

+44
-53
lines changed

components/src/Switcher/Switcher.stories.svelte

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,7 @@
1212

1313
<Story name="Two Options">
1414
<DesignTokens>
15-
<Switcher
16-
options={['Option A', 'Option B']}
17-
groupName="two-options"
18-
value="Option A"
19-
size="default"
20-
label="Label"
21-
/>
15+
<Switcher options={['Option A', 'Option B']} value="Option A" size="default" label="Label" />
2216
</DesignTokens>
2317
</Story>
2418

@@ -41,7 +35,6 @@
4135
<DesignTokens>
4236
<Switcher
4337
options={['Apples', 'Oranges', 'Bananas', 'Peaches']}
44-
groupName="four-options"
4538
value="Oranges"
4639
label="Label"
4740
size="small"

components/src/Switcher/Switcher.svelte

Lines changed: 43 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
<script lang="ts">
22
interface SwitcherProps {
33
/**
4-
* Human-readable label for the input.
4+
* Human-readable label
55
*/
66
label: string;
7-
options: string[];
87
/**
9-
* Machine-readable name for the input. Should be unique across the document.
8+
* Available options
109
*/
11-
groupName: string;
10+
options: string[];
1211
/**
13-
* Type size
12+
* Display size
1413
*/
1514
size?: 'default' | 'small';
1615
/**
@@ -19,18 +18,12 @@
1918
value: string | null;
2019
}
2120
22-
let {
23-
label,
24-
options,
25-
groupName,
26-
size = 'default',
27-
value = $bindable(null)
28-
}: SwitcherProps = $props();
21+
let { label, options, size = 'default', value = $bindable(null) }: SwitcherProps = $props();
22+
23+
const groupId = $props.id();
24+
const groupName = 'select-' + groupId;
2925
3026
function optionToID(o: string) {
31-
// TODO: This should use $id() when it comes out, so
32-
// input IDs are guaranteed unique across the app
33-
// See: https://github.com/sveltejs/svelte/issues/13108
3427
return `${groupName}-option-${o.replace(/ /g, '-').toLowerCase()}`;
3528
}
3629
</script>
@@ -42,12 +35,6 @@
4235
<li class:is-selected={o === value}>
4336
<label for={optionToID(o)}>
4437
{o}
45-
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
46-
<path
47-
d="M19.7054 6.29119C20.0969 6.68077 20.0984 7.31393 19.7088 7.7054L9.75697 17.7054C9.56928 17.894 9.31416 18 9.04809 18C8.78201 18 8.52691 17.8939 8.33925 17.7053L4.2911 13.6365C3.90157 13.245 3.90318 12.6118 4.2947 12.2223C4.68621 11.8327 5.31938 11.8344 5.7089 12.2259L9.04825 15.5823L18.2912 6.2946C18.6808 5.90314 19.3139 5.90161 19.7054 6.29119Z"
48-
fill="currentColor"
49-
/>
50-
</svg>
5138
</label>
5239
<input id={optionToID(o)} name={groupName} value={o} type="radio" bind:group={value} />
5340
</li>
@@ -56,36 +43,43 @@
5643
</fieldset>
5744

5845
<style lang="scss">
46+
@use '../styles/base.scss';
47+
5948
fieldset {
6049
border: 0;
6150
font-family: var(--swr-sans);
6251
}
6352
6453
legend {
6554
font-size: var(--fs-small-2);
66-
margin-bottom: 0.25em;
55+
font-weight: 500;
56+
margin-bottom: 0.35em;
6757
}
6858
6959
ul {
7060
width: 100%;
7161
display: flex;
72-
flex-direction: row;
73-
border-radius: var(--br-small);
62+
flex-direction: column;
7463
overflow: hidden;
7564
padding: 0;
7665
margin: 0;
77-
overflow: hidden;
7866
border: 1px solid currentColor;
67+
border-radius: var(--br-small);
68+
69+
@media (min-width: base.$break-phone) {
70+
flex-flow: row;
71+
}
7972
8073
&:focus-within,
8174
&:active {
82-
outline: 3px solid rgba(white, 0.5);
75+
outline: 2px solid var(--blue-light-2);
8376
}
8477
}
8578
li {
8679
display: contents;
8780
&:last-child label {
8881
border-right: 0;
82+
border-bottom: 0;
8983
}
9084
}
9185
input {
@@ -94,41 +88,45 @@
9488
}
9589
.small label {
9690
font-size: var(--fs-small-1);
91+
height: 2.25em;
92+
padding: 0 0.65em;
9793
}
9894
label {
9995
font-size: var(--fs-base);
100-
height: 2.5em;
10196
line-height: 1;
97+
white-space: nowrap;
98+
padding: 0 1em;
10299
cursor: pointer;
103100
margin: 0;
104-
flex-basis: 0;
105-
flex-grow: 1;
106101
align-items: center;
107102
display: flex;
108-
justify-content: center;
109103
color: currentColor;
110104
position: relative;
111105
transition: var(--fast);
112-
text-underline-offset: 0.1em;
113-
border-right: 1px solid currentColor;
106+
text-underline-offset: 0.2em;
107+
border-bottom: 1px solid currentColor;
108+
height: 2.25em;
109+
@media (min-width: base.$break-phone) {
110+
justify-content: center;
111+
padding: 0 1em;
112+
flex-basis: 0;
113+
flex-grow: 1;
114+
border-right: 1px solid currentColor;
115+
border-bottom: 0;
116+
}
117+
@media (min-width: base.$break-tablet) {
118+
height: 2.5em;
119+
}
114120
&:hover,
115121
&:focus-visible {
116122
text-decoration: underline;
117123
}
118-
svg {
119-
position: absolute;
120-
left: 0.65em;
121-
width: 1em;
122-
height: auto;
123-
opacity: 0;
124-
transition: var(--fast);
125-
display: block;
126-
}
127124
.is-selected & {
128-
background: white;
129-
color: black;
130-
svg {
131-
opacity: 1;
125+
background: rgb(247, 247, 247);
126+
font-weight: 700;
127+
box-shadow: inset 5px 0px 0 0 var(--violet-dark-5);
128+
@media (min-width: base.$break-phone) {
129+
box-shadow: inset 0 -3px 0 0 var(--violet-dark-5);
132130
}
133131
}
134132
}

0 commit comments

Comments
 (0)