Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

103 webcomponents #2

Merged
merged 21 commits into from
Dec 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 5 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# kbsb Profile Filter

A profile webpage with filter functionality using Typescript, Vite and PNPM.
A profile webpage with filter functionality. Built with Typescript, Vite, PNPM and vanilla Web Components.

- Install PNPM with `npm install -g pnpm`
- URL coming soon.
Expand Down Expand Up @@ -29,14 +29,9 @@ pnpm run build
```


## Typescript version

The Vite scaffold project uses Typescript 4.4.4. This project uses: `"typescript": "^4.5.3"`.


## Vite tsconfig.json settings

Add `"moduleResolution": "node",` otherwise the TS compiler complains about a `module resolution strategy`.
Add `"moduleResolution": "node",` otherwise the TS compiler complains about a `module resolution strategy`. Note: The Vite scaffold project uses Typescript 4.4.4. This project uses: `"typescript": "^4.5.3"`.

```json
{
Expand Down Expand Up @@ -70,7 +65,8 @@ Add `"moduleResolution": "node",` otherwise the TS compiler complains about a `m
- [X] Create class for the dev skills
- [X] Add Typescript as dev-dep
- [X] Optional: add Vite
- [ ] Add project to Vercel: https://vitejs.dev/guide/static-deploy.html#vercel
- [ ] Add methods and logic for the filter states
- [ ] Scaffold some WebComponents
- [ ] Create the filter and developer DOM elements
- [ ] Add methods and logic for the filter states
- [ ] Add styling and basic animations
- [ ] Add project to Vercel: https://vitejs.dev/guide/static-deploy.html#vercel
37 changes: 13 additions & 24 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,28 @@
<link href='https://tools-static.wmflabs.org/fontcdn/css?family=IBM+Plex+Sans:300,400,600' rel='stylesheet' type='text/css'>
</head>
<body>
<!-- Vite settings -->
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>

<!-- default kbsb navigation -->
<nav class="container nav">
<a href="https://www.kaboomshebang.com/" target='_blank' rel="noopener noreferrer">
<img class="logo-kaboom" src="https://www.kaboomshebang.com/logos/kaboom_shebang_logo.svg" alt="Kaboom Shebang">
</a>
</nav>
<!-- default kbsb navigation component -->
<kbsb-navbar>
<img slot="logo" src="https://www.kaboomshebang.com/logos/kaboom_shebang_logo.svg" alt="Kaboom Shebang"/>
</kbsb-navbar>


<!-- profile app -->
<section class="section">
<div class="container">
<h1 class="heading">
Typescript Portfolio Filter
<h1 class="heading center">
Kaboom Profile Filter
</h1>
<p>Person by Knut M. Synstad from NounProject.com</p>
<p>https://thenounproject.com/icon/person-856455/</p>
</div>
<div class="container">
<div id="app"></div>
</div>
</section>


<!-- default kbsb footer -->
<footer class="footer footer-text">
<span>
Webfonts by: <a href="https://fontcdn.toolforge.org/" target='_blank' rel="noopener noreferrer">FontCDN</a>
</span>
<span> | </span>
<span>
Created by <a href="https://www.fredsnyder.net" target='_blank' rel="noopener noreferrer">Fred Snyder</a>
</span>
<img class="logo-shebang" src="https://www.kaboomshebang.com/logos/shebang_3d_for_web.svg" alt="The Kaboom Shebang">
</footer>
<kbsb-footer></kbsb-footer>
<kbsb-footer-shebang></kbsb-footer-shebang>

</body>
</html>
81 changes: 81 additions & 0 deletions src/app/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
const appLogic = (data: any) => {
// a map of all the unique skills
// value represents the filter state // default false (inactive)
const skills = new Map<string, boolean>();

type skill = {
id: number;
name: string;
active: boolean;
};

class Filter {
skills: skill[];
active: boolean;

constructor(skills: skill[], state: boolean) {
this.skills = skills;
this.active = state;
}
}

// define a Dev type according to the expected json structure
type Dev = {
userId: number;
name: string;
skills: string[];
color: string;
roles: string;
};

class Developer {
person: Dev;
visible: boolean;

constructor(d: Dev) {
this.person = d;
this.visible = true;
}
}

console.log(data.developers);

const fltr: Filter = { skills: [], active: false };
const devs: Developer[] = [];

createDevs(data.developers);
createFilter(data.developers);

function createDevs(d: Dev[]) {
d.forEach((e) => {
devs.push(new Developer(e));
});
}

// create the map with all the filters
function createFilter(d: Dev[]) {
d.forEach((e: Dev) => {
e.skills.forEach((sk: string) => {
skills.set(sk, false);
});
});
}

// add all the filters to the Filter object
function addFilters(skills: Map<string, boolean>) {
let id: number = 0;
// convert map of unique skills to skill[]
for (let [skl, act] of skills.entries()) {
fltr.skills.push({ id: id, name: skl, active: act });
id++;
}
}

addFilters(skills);

console.log('Filter obeject', fltr);
console.log('Devs: ', devs);
console.log('Skills', skills);
};

export default appLogic;
35 changes: 35 additions & 0 deletions src/components/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Readme

Contains all the applications components.

Instead of including the styling in the component itself you can also use an style import in the component.
- Upside: you get syntax highlighting
- Downside: hot-update or hot-reload doesn't work for these styles.

```css
/* optional: put this in footer.css */
.footer {
position: relative;
width: 100%;
}

.footer-container {
max-width: 1200px;
margin: 0 auto;
}
```

```ts
// and import in the footer.ts component
import footerCss from './footer.css';
// console.log(footerCss);
```

## Read data from the DOM tag

```ts
// take attribute content and put it inside the info span
const text = this.getAttribute('data-text');
const div = document.createElement('div');
div.textContent = text;
```
45 changes: 45 additions & 0 deletions src/components/filterBtn.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const filterBtnTemplate = document.createElement('template');

filterBtnTemplate.innerHTML = `
<style>
.filter {
all: unset;
padding: 10px;
margin: 10px 5px;
min-width: 70px;
background-color: lightgrey;
cursor: pointer;
transition: background 200ms;

}
.filter:active {
background-color: black !important;
color: white;
}
:host([active]) .filter {
background-color: lightslategrey;
color: white;
}
</style>
<button class="filter">Empty</button>
`;

// Create a class for the element
class FilterBtn extends HTMLElement {
constructor() {
// Always call super first in constructor
super();

// Create a shadow root
const shadow = this.attachShadow({ mode: 'open' });
shadow.appendChild(filterBtnTemplate.content.cloneNode(true));

// Take attribute content and put it inside the info span
if (typeof this.getAttribute('filter') === 'string') {
shadow.querySelector('.filter')!.textContent = this.getAttribute('filter');
}
}
}

// Define the new element
customElements.define('kbsb-filter-button', FilterBtn);
39 changes: 39 additions & 0 deletions src/components/filters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// use a template instead of multiple createElement
const filterTemplate = document.createElement('template');

filterTemplate.innerHTML = `
<style>
.filterWrapper {
max-width: -var(--max-width, 800px);
margin: 20px auto 40px auto;
text-align: center;
}
</style>

<div class="filterWrapper">
<kbsb-filter-button filter="Javascript" active></kbsb-filter-button>
<kbsb-filter-button filter="Golang"></kbsb-filter-button>
<kbsb-filter-button filter="Rust"></kbsb-filter-button>
<kbsb-filter-button filter="Java"></kbsb-filter-button>
<kbsb-filter-button filter="Typescript" active></kbsb-filter-button>
<kbsb-filter-button></kbsb-filter-button>
<kbsb-filter-button></kbsb-filter-button>
<kbsb-filter-button></kbsb-filter-button>
<kbsb-filter-button></kbsb-filter-button>
</div>
`;

// create a class for the element
class Filters extends HTMLElement {
constructor() {
// always call super first in constructor
super();

// create a shadow root
const shadow = this.attachShadow({ mode: 'open' });
shadow.appendChild(filterTemplate.content.cloneNode(true));
}
}

// Define the new element
customElements.define('kbsb-filters', Filters);
Loading