Skip to content

Commit c0a8011

Browse files
committed
feat(content-switcher): add fds-content-switcher component
1 parent 50cf7c8 commit c0a8011

File tree

5 files changed

+194
-0
lines changed

5 files changed

+194
-0
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
@import '../../../styles/settings/prefix';
2+
@import '../../../design-tokens/build/scss/tokens';
3+
@import '../../../styles/tools/button';
4+
@import '../../../styles/tools/text-truncate';
5+
6+
:host {
7+
display: inline-block;
8+
}
9+
10+
:host(:first-of-type),
11+
:host(:first-of-type[selected]) .#{$prefix}-content-switcher-btn {
12+
border-radius: $button-border-radius 0 0 $button-border-radius;
13+
}
14+
15+
:host(:last-of-type),
16+
:host(:last-of-type[selected]) .#{$prefix}-content-switcher-btn {
17+
border-radius: 0 $button-border-radius $button-border-radius 0;
18+
}
19+
20+
.#{$prefix}-content-switcher-btn {
21+
@include button-base;
22+
23+
height: 100%;
24+
color: inherit;
25+
border-radius: 0;
26+
}
27+
28+
.#{$prefix}-content-switcher-btn__label {
29+
@include truncate;
30+
31+
flex-grow: 1;
32+
}
33+
34+
:host([selected]) .#{$prefix}-content-switcher-btn,
35+
:host([selected]) .#{$prefix}-content-switcher-btn:hover {
36+
background-color: $button-color-outline-active-background;
37+
box-shadow: inset 0 0 0 1px $button-color-outline-active-border;
38+
color: $button-color-outline-active-text;
39+
}
40+
41+
:host([selected]) .#{$prefix}-content-switcher-btn {
42+
cursor: default;
43+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { html, LitElement, TemplateResult, unsafeCSS } from 'lit';
2+
import { customElement, property } from 'lit/decorators.js';
3+
4+
import style from './fds-content-switcher-button.scss';
5+
6+
@customElement('fds-content-switcher-button')
7+
export class FdsContentSwitcherButton extends LitElement {
8+
static get styles() {
9+
return [unsafeCSS(style)];
10+
}
11+
12+
@property({ type: Boolean, reflect: true })
13+
selected = false;
14+
15+
render(): TemplateResult {
16+
return html`
17+
<button class="fds-content-switcher-btn" type="button" aria-pressed="${this.selected}">
18+
<span class="fds-content-switcher-btn__label">
19+
<slot></slot>
20+
</span>
21+
</button>
22+
`;
23+
}
24+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
@import '../../styles/settings/prefix';
2+
@import '../../design-tokens/build/scss/tokens';
3+
4+
5+
:host {
6+
display: inline-flex;
7+
}
8+
9+
.#{$prefix}-content-switcher {
10+
display: inline-flex;
11+
height: $content-switcher-size-height;
12+
flex-wrap: nowrap;
13+
gap: 1px;
14+
}
15+
16+
:host([variant="solid"]) ::slotted(fds-content-switcher-button) {
17+
background-color: $button-color-secondary-background;
18+
box-shadow: inset 0 0 0 1px $button-color-secondary-border;
19+
color: $button-color-secondary-text;
20+
}
21+
22+
:host([variant="solid"]) ::slotted(fds-content-switcher-button:hover) {
23+
background-color: $button-color-secondary-hover-background;
24+
box-shadow: inset 0 0 0 1px $button-color-secondary-hover-border;
25+
}
26+
27+
:host([variant="solid"]) ::slotted(fds-content-switcher-button:active) {
28+
background-color: $button-color-secondary-active-background;
29+
box-shadow: inset 0 0 0 1px $button-color-secondary-active-border;
30+
}
31+
32+
:host([variant="solid"]) ::slotted(fds-content-switcher-button:focus-visible) {
33+
box-shadow: inset 0 0 0 2px $button-color-focus-border,
34+
inset 0 0 0 3px $color-white;
35+
}
36+
37+
:host([variant="outline"]) {
38+
.#{$prefix}-content-switcher {
39+
gap: 0;
40+
}
41+
}
42+
43+
:host([variant="outline"]) ::slotted(fds-content-switcher-button) {
44+
background-color: transparent;
45+
box-shadow: inset 0 0 0 1px $button-color-outline-border;
46+
color: $button-color-outline-text;
47+
}
48+
49+
:host([variant="outline"]) ::slotted(fds-content-switcher-button:not(:first-child)) {
50+
margin-left: -1px;
51+
}
52+
53+
:host([variant="outline"]) ::slotted(fds-content-switcher-button:hover) {
54+
color: $button-color-outline-hover-text;
55+
background-color: $button-color-outline-hover-background;
56+
box-shadow: inset 0 0 0 1px $button-color-outline-hover-border;
57+
}
58+
59+
:host([variant="outline"]) ::slotted(fds-content-switcher-button:active) {
60+
color: $button-color-outline-active-text;
61+
background-color: $button-color-outline-active-background;
62+
box-shadow: inset 0 0 0 1px $button-color-outline-active-border;
63+
}
64+
65+
:host([variant="outline"]) ::slotted(fds-content-switcher-button:focus-visible) {
66+
box-shadow: inset 0 0 0 2px $button-color-focus-border,
67+
inset 0 0 0 3px $color-white;
68+
}
69+
70+
:host([size="small"]) .#{$prefix}-content-switcher {
71+
height: $content-switcher-size-small-height;
72+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { html, LitElement, TemplateResult, unsafeCSS } from 'lit';
2+
import { customElement, property } from 'lit/decorators.js';
3+
4+
import style from './fds-content-switcher.scss';
5+
6+
@customElement('fds-content-switcher')
7+
export class FdsContentSwitcher extends LitElement {
8+
static get styles() {
9+
return [unsafeCSS(style)];
10+
}
11+
12+
@property({ type: String, reflect: true })
13+
variant: 'solid' | 'outline' = 'solid';
14+
15+
@property({ type: String, reflect: true })
16+
size: 'small' | 'medium' = 'medium';
17+
18+
private handleButtonClick = (event: MouseEvent) => {
19+
const target = event.target as HTMLElement;
20+
const clickedButton = target.closest('fds-content-switcher-button') as HTMLElement;
21+
22+
if (!clickedButton) return;
23+
24+
const buttons = this.querySelectorAll('fds-content-switcher-button');
25+
buttons.forEach((button: Element) => {
26+
if (button === clickedButton) {
27+
button.setAttribute('selected', '');
28+
} else {
29+
button.removeAttribute('selected');
30+
}
31+
});
32+
33+
this.dispatchEvent(
34+
new CustomEvent('selection-change', {
35+
detail: { selectedButton: clickedButton },
36+
bubbles: true,
37+
composed: true,
38+
})
39+
);
40+
};
41+
42+
firstUpdated() {
43+
this.addEventListener('click', this.handleButtonClick);
44+
}
45+
46+
render(): TemplateResult {
47+
return html`
48+
<div class="fds-content-switcher">
49+
<slot></slot>
50+
</div>
51+
`;
52+
}
53+
}

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ export { FdsButton } from './components/button/fds-button';
44
export { FdsCard } from './components/card/fds-card';
55
export { FdsCheckbox } from './components/checkbox/fds-checkbox';
66
export { FdsCheckboxGroup } from './components/checkbox-group/fds-checkbox-group';
7+
export { FdsContentSwitcher } from './components/content-switcher/fds-content-switcher';
8+
export { FdsContentSwitcherButton } from './components/content-switcher/content-switcher-button/fds-content-switcher-button';
79
export { FdsHelperText } from './components/helper-text/fds-helper-text';
810
export { FdsIcon } from './components/icon/fds-icon';
911
export { FdsLink } from './components/link/fds-link';

0 commit comments

Comments
 (0)