Skip to content

Commit

Permalink
tabコンポーネントをつくってみた
Browse files Browse the repository at this point in the history
  • Loading branch information
hazuki-okuda-UB committed Oct 30, 2024
1 parent 99cde7a commit 441b1b3
Show file tree
Hide file tree
Showing 4 changed files with 467 additions and 0 deletions.
142 changes: 142 additions & 0 deletions src/components/tab/sp-tab.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
// @ts-ignore
import foundationStyle from "../foundation.css?inline" assert { type: "css" };
// @ts-ignore
import tabStyle from "./tab.css?inline" assert { type: "css" };
import { SpeedaIconTypes } from "../icon/icons";
import { SpIcon } from "../icon/sp-icon";

type TabType = "tabWhite" | "tabGray";

const styles = new CSSStyleSheet();
styles.replaceSync(`${foundationStyle} ${tabStyle}`);

export class SpTab extends HTMLElement {
#selected: boolean;
#disabled: boolean;
#type: TabType;
#createNewIcon: boolean;
#createNewIconElement = new SpIcon();
tabElement = document.createElement("button");
textElement = document.createElement("span");

set text(value: string) {
this.textElement.innerText = value;
}

get selected() {
return this.#selected;
}
set selected(value: boolean) {
this.#selected = value;
value ? this.#onSelectedAdd() : this.#onSelectedRemove();
}

get disabled() {
return this.#disabled;
}
set disabled(value: boolean) {
const tab = this.tabElement;
this.#disabled = value;
value ? tab.classList.add("isDisable") : tab.classList.remove("isDisable");
this.#tabDisabledUpdate();
}

get type() {
return this.#type;
}
set type(value: TabType) {
const tab = this.tabElement;
const typeClassList = {
tabWhite: "-white",
tabGray: "-gray",
};
tab.classList.remove(typeClassList[this.#type]);
tab.classList.add(typeClassList[value]);
this.#type = value;
}
get createNewIcon() {
return this.#createNewIcon;
}
set createNewIcon(value: boolean) {
this.#createNewIcon = value;
if (value === true) {
this.tabElement.insertBefore(
this.#createNewIconElement,
this.textElement,
);
} else {
this.#createNewIconElement.remove();
}
}

static get observedAttributes() {
return ["text", "selected", "create-new-icon", "disabled", "type"];
}

constructor() {
super();
this.attachShadow({ mode: "open" });
this.shadowRoot.adoptedStyleSheets = [
...this.shadowRoot.adoptedStyleSheets,
styles,
];
this.tabElement.classList.add("spds__tab");
this.tabElement.setAttribute("role", "tab");
this.tabElement.setAttribute("aria-tabindex", "0");
this.textElement.classList.add("spds__tabText");
this.tabElement.appendChild(this.textElement);
}
connectedCallback() {
this.#createNewIconElement.classList.add("base__icon");
this.#createNewIconElement.size = "small";
this.#createNewIconElement.type = "plus";
if (typeof this.selected === "undefined") {
// this.selected = false;
this.tabElement.setAttribute("aria-selected", "false");
}
if (typeof this.type === "undefined") this.type = "tabWhite";
this.setAttribute("role", "tablist");
this.shadowRoot.appendChild(this.tabElement);
}
attributeChangedCallback(name: string, oldValue: string, newValue: string) {
if (oldValue === newValue) return;
switch (name) {
case "text":
this.text = newValue;
break;
case "selected":
this.selected = newValue === "true" || newValue === "";
break;
case "disabled":
this.disabled = newValue === "true" || newValue === "";
break;
case "type":
this.type = newValue as TabType;
break;
case "create-new-icon":
this.createNewIcon = newValue === "true" || newValue === "";
break;
}
}

#onSelectedAdd() {
this.tabElement.classList.add("-selected");
this.tabElement.setAttribute("aria-selected", "true");
}
#onSelectedRemove() {
this.tabElement.classList.remove("-selected");
this.tabElement.setAttribute("aria-selected", "false");
}

#tabDisabledUpdate() {
this.tabElement.disabled = this.disabled;
}
}

customElements.get("sp-tab") || customElements.define("sp-tab", SpTab);

declare global {
interface HTMLElementTagNameMap {
"sp-tab": SpTab;
}
}
160 changes: 160 additions & 0 deletions src/components/tab/tab.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
:host {
--icon-color: var(--color-semantic-text-button-outline-default);
--padding-inline: 16px;

display: inline-block;
min-width: 0;
max-width: 100%;
}

.tabList{
display: flex;
gap: 8px
}

.spds__tab {
outline: none;
font: inherit;
background: none;
display: inline-flex;
min-width: 80px;
padding: 2px 16px;
justify-content: center;
align-items: center;
color: var(--color-semantic-text-body-regular);
font-size:14px;
border-radius: 14px;
min-height: 28px;

&:hover{
cursor:pointer;
}

&:disabled{
border: 1px solid var(--color-semantic-border-regular);
background-color: var(--color-semantic-surface-regular-2);
color: var(--color-semantic-text-disabled);
cursor: not-allowed;
--icon-color: var(--color-semantic-text-disabled);
}

&.-selected{
border: 1px solid var(--color-semantic-border-selected);
background-color: var(--color-semantic-surface-selected);
color: var(--color-semantic-text-inverse);

--icon-color: var(--color-semantic-text-button-selected);

font-weight: bold;

&:hover{
border: 1px solid var(--color-semantic-surface-selected-hover);
background-color: var(--color-semantic-surface-selected-hover);
}

&:disabled{
border: 1px solid var(--color-semantic-border-regular);
background-color: var(--color-semantic-surface-regular-2);

--icon-color: var(--color-semantic-text-disabled);

color: var(--color-semantic-text-disabled);
cursor: not-allowed;
font-weight: normal;
}
}

&.-gray{
border: 1px solid var(--color-semantic-border-regular);
background-color: var(--color-semantic-surface-regular-2);

&:hover{
background-color: var(--color-semantic-surface-regular-4);
}

&.-selected {
border: 1px solid var(--color-semantic-border-selected);
background-color: var(--color-semantic-surface-selected);
color: var(--color-semantic-text-inverse);

&:hover {
border: 1px solid var(--color-semantic-surface-selected-hover);
background-color: var(--color-semantic-surface-selected-hover);
}

&:disabled{
border: 1px solid var(--color-semantic-border-regular);
background-color: var(--color-semantic-surface-regular-2);
color: var(--color-semantic-text-disabled);
cursor: not-allowed;
--icon-color: var(--color-semantic-text-disabled);
}
&:disabled{
border: 1px solid var(--color-semantic-border-regular);
background-color: var(--color-semantic-surface-regular-2);
color: var(--color-semantic-text-disabled);
cursor: not-allowed;
--icon-color: var(--color-semantic-text-disabled);
}
}
&:disabled{
border: 1px solid var(--color-semantic-border-regular);
background-color: var(--color-semantic-surface-regular-2);
color: var(--color-semantic-text-disabled);
cursor: not-allowed;
--icon-color: var(--color-semantic-text-disabled);
}
}

&.-white{
border: 1px solid var(--color-semantic-border-regular);
background-color: var(--color-semantic-surface-regular-1);

&:hover{
background-color: var(--color-semantic-surface-regular-3);
}
&.-selected {
border: 1px solid var(--color-semantic-border-selected);
background-color: var(--color-semantic-surface-selected);
color: var(--color-semantic-text-inverse);
&:hover {
border: 1px solid var(--color-semantic-surface-selected-hover);
background-color: var(--color-semantic-surface-selected-hover);
}
&:disabled{
border: 1px solid var(--color-semantic-border-regular);
background-color: var(--color-semantic-surface-regular-2);
color: var(--color-semantic-text-disabled);
cursor: not-allowed;
--icon-color: var(--color-semantic-text-disabled);
}
}
&:disabled{
border: 1px solid var(--color-semantic-border-regular);
background-color: var(--color-semantic-surface-regular-2);
color: var(--color-semantic-text-disabled);
cursor: not-allowed;
--icon-color: var(--color-semantic-text-disabled);
}
}

&:focus-visible{
outline: canvastext solid 3px;
box-shadow: canvas 0 0 0 5px;
outline-offset: 1px;
background-color: var(--color-semantic-surface-regular-4);
}
}













1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export { SpCheckboxText } from "./components/checkbox/sp-checkbox-text";
export { SpCheckboxList } from "./components/checkbox/sp-checkbox-list";
export { SpIcon } from "./components/icon/sp-icon";
export { SpRadioButtonTextGroup } from "./components/radio/sp-radio-button-text-group";
export { SpTab } from "./components/tab/sp-tab";
Loading

0 comments on commit 441b1b3

Please sign in to comment.