Skip to content

Commit

Permalink
Merge pull request #29 from efflore/v0.8.5-docs
Browse files Browse the repository at this point in the history
docs: todo-app and lazy-load examples
  • Loading branch information
estherbrunner authored Oct 7, 2024
2 parents f7dc300 + e7b04d0 commit f8854e6
Show file tree
Hide file tree
Showing 25 changed files with 554 additions and 362 deletions.
1 change: 1 addition & 0 deletions docs/assets/css/components.css
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ input-button {
padding: 0 var(--space-s);
font-size: var(--font-size-s);
line-height: var(--line-height-s);
white-space: nowrap;
opacity: var(--opacity-dimmed);
transition: all var(--transition-shorter) var(--easing-inout);

Expand Down
2 changes: 2 additions & 0 deletions docs/assets/css/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@
--easing-in: ease-in;
--easing-out: ease-out;
--easing-inout: ease-in-out;

--input-height: 2rem;
}

@media screen and (min-width: 45em) and (max-width: 75em) {
Expand Down
164 changes: 79 additions & 85 deletions docs/assets/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ InputRadiogroup.define('input-radiogroup')
class LazyLoad extends UIElement {
static observedAttributes = ['src']
static attributeMap = {
src: v => v.map(src => {
src: v => v.map(src => {
let url = ''
try {
url = new URL(src, location.href) // ensure 'src' attribute is a valid URL
Expand All @@ -402,20 +402,20 @@ class LazyLoad extends UIElement {
}
return url.toString()
})
}
}

connectedCallback() {

// show / hide loading message
// Show / hide loading message
this.first('.loading')
.forEach(setProperty('ariaHidden', () => !!this.get('error')))

// set and show / hide error message
// Set and show / hide error message
this.first('.error')
.map(setText('error'))
.forEach(setProperty('ariaHidden', () => !this.get('error')))

// load content from provided URL
// Load content from provided URL
effect(enqueue => {
const src = this.get('src')
if (!src) return // silently fail if no valid URL is provided
Expand All @@ -434,7 +434,7 @@ class LazyLoad extends UIElement {
})
})
this.set('error', '')
} else {
} else {
this.set('error', response.status + ':'+ response.statusText)
}
})
Expand Down Expand Up @@ -525,118 +525,112 @@ class MediaContext extends UIElement {
MediaContext.define('media-context')

class TodoApp extends UIElement {
connectedCallback() {
connectedCallback() {
const [todoList, todoFilter] = ['todo-list', 'input-radiogroup']
.map(selector => this.querySelector(selector))

// Event listener on own element
this.self
.map(on('add-todo', e => todoList?.addItem(e.detail)))

// Coordinate todo-count
this.first('todo-count')
.map(pass({ active: () => todoList?.get('count').active }))

// Coordinate todo-list
this.first('todo-list')
.map(pass({ filter: () => todoFilter?.get('value') }))

// Coordinate .clear-completed button
this.first('.clear-completed')
.map(on('click', () => todoList?.clearCompleted()))
.map(pass({ disabled: () => !todoList?.get('count').completed }))
}
this.self.forEach(on('add-todo', e => todoList?.addItem(e.detail)))

// Coordinate todo-count
this.first('todo-count').forEach(pass({
active: () => todoList?.get('count').active
}))

// Coordinate todo-list
this.first('todo-list').forEach(pass({
filter: () => todoFilter?.get('value')
}))

// Coordinate .clear-completed button
this.first('.clear-completed')
.map(on('click', () => todoList?.clearCompleted()))
.forEach(pass({ disabled: () => !todoList?.get('count').completed }))
}
}
TodoApp.define('todo-app')

class TodoCount extends UIElement {
connectedCallback() {
this.set('active', 0, false)
this.first('.count')
.map(setText('active'))
this.first('.singular')
.map(setProperty('ariaHidden', () => this.get('active') > 1))
this.first('.plural')
.map(setProperty('ariaHidden', () => this.get('active') === 1))
this.first('.remaining')
.map(setProperty('ariaHidden', () => !this.get('active')))
this.first('.all-done')
.map(setProperty('ariaHidden', () => !!this.get('active')))
}
this.set('active', 0, false)
this.first('.count').forEach(setText('active'))
this.first('.singular').forEach(setProperty('ariaHidden', () => this.get('active') > 1))
this.first('.plural').forEach(setProperty('ariaHidden', () => this.get('active') === 1))
this.first('.remaining').forEach(setProperty('ariaHidden', () => !this.get('active')))
this.first('.all-done').forEach(setProperty('ariaHidden', () => !!this.get('active')))
}
}
TodoCount.define('todo-count')

class TodoForm extends UIElement {
connectedCallback() {
const inputField = this.querySelector('input-field')

this.first('form')
.forEach(on('submit', e => {
e.preventDefault()
setTimeout(() => {
this.dispatchEvent(new CustomEvent('add-todo', {
bubbles: true,
detail: inputField.get('value')
}))
inputField.clear()
}, 0)
}))

this.first('input-button')
.forEach(pass({
disabled: () => inputField.get('empty')
}))
this.first('form').forEach(on('submit', e => {
e.preventDefault()
setTimeout(() => {
this.dispatchEvent(new CustomEvent('add-todo', {
bubbles: true,
detail: inputField.get('value')
}))
inputField.clear()
}, 0)
}))

this.first('input-button').forEach(pass({
disabled: () => inputField.get('empty')
}))
}
}
TodoForm.define('todo-form')

class TodoList extends UIElement {
connectedCallback() {
this.set('filter', 'all') // set initial filter
connectedCallback() {
this.set('filter', 'all') // set initial filter
this.#updateList()

// Event listener and attribute on own element
this.self
.map(on('click', e => {
if (e.target.localName === 'button') this.removeItem(e.target)
}))
.map(setAttribute('filter'))

// Update count on each change
this.set('count', () => {
const tasks = this.get('tasks').map(el => el.signal('checked'))
const completed = tasks.filter(fn => fn()).length
const total = tasks.length
return {
this.self
.map(on('click', e => {
if (e.target.localName === 'button') this.removeItem(e.target)
}))
.forEach(setAttribute('filter'))

// Update count on each change
this.set('count', () => {
const tasks = this.get('tasks').map(el => el.signal('checked'))
const completed = tasks.filter(fn => fn()).length
const total = tasks.length
return {
active: total - completed,
completed,
total
}
})
}
})
}

addItem = task => {
const template = this.querySelector('template').content.cloneNode(true)
template.querySelector('span').textContent = task
this.querySelector('ol').appendChild(template)
this.#updateList()
}
addItem = task => {
const template = this.querySelector('template').content.cloneNode(true)
template.querySelector('span').textContent = task
this.querySelector('ol').appendChild(template)
this.#updateList()
}

removeItem = element => {
element.closest('li').remove()
this.#updateList()
}
removeItem = element => {
element.closest('li').remove()
this.#updateList()
}

clearCompleted = () => {
this.get('tasks')
.filter(el => el.get('checked'))
.forEach(el => el.parentElement.remove())
this.#updateList()
}
clearCompleted = () => {
this.get('tasks')
.filter(el => el.get('checked'))
.forEach(el => el.parentElement.remove())
this.#updateList()
}

#updateList() {
this.set('tasks', Array.from(this.querySelectorAll('input-checkbox')))
}
this.set('tasks', Array.from(this.querySelectorAll('input-checkbox')))
}

}
TodoList.define('todo-list')
12 changes: 6 additions & 6 deletions docs/best-practices-patterns.html
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ <h3>Scope Styles via Custom Element Name</h3>
<p class="meta">
<span class="language">css</span>
</p>
<pre><code class="language-css">my-component {
<pre class="language-css"><code>my-component {
padding: 1rem;

/* Only divs that are immediate children of my-component will be styled */
Expand All @@ -146,7 +146,7 @@ <h3>Customize via Class or CSS Custom Properties</h3>
<p class="meta">
<span class="language">css</span>
</p>
<pre><code class="language-css">parent-component {
<pre class="language-css"><code>parent-component {
--box-bg-color: red;
--box-text-color: white;
}
Expand Down Expand Up @@ -178,7 +178,7 @@ <h3>Passing State with pass()</h3>
<p class="meta">
<span class="language">js</span>
</p>
<pre><code class="language-js">class ParentComponent extends UIElement {
<pre class="language-js"><code>class ParentComponent extends UIElement {
connectedCallback() {
this.set('parentColor', 'blue');
this.pass('parentColor', 'child-component', 'color');
Expand All @@ -194,7 +194,7 @@ <h3>Passing State with pass()</h3>
<p class="meta">
<span class="language">js</span>
</p>
<pre><code class="language-js">class ChildComponent extends UIElement {
<pre class="language-js"><code>class ChildComponent extends UIElement {
connectedCallback() {
this.first('.box').map(setStyle('background-color', 'color'));
}
Expand All @@ -213,7 +213,7 @@ <h3>Dispatching Custom Events with <code>emit()</code></h3>
<p class="meta">
<span class="language">js</span>
</p>
<pre><code class="language-js">// In child component
<pre class="language-js"><code>// In child component
this.emit('change', { detail: { value: this.get('value') } });</code></pre>
</code-block>

Expand All @@ -223,7 +223,7 @@ <h3>Handling Custom Events in Parent Components</h3>
<p class="meta">
<span class="language">js</span>
</p>
<pre><code class="language-js">// In parent component
<pre class="language-js"><code>// In parent component
this.first('child-component').map(on('change', (event) => {
console.log('Received change event:', event.detail.value);
// Handle state changes
Expand Down
14 changes: 7 additions & 7 deletions docs/contributing-development.html
Original file line number Diff line number Diff line change
Expand Up @@ -135,16 +135,16 @@ <h2>3. Setting Up the Development Environment</h2>
<ol>
<li>
<strong>Clone the Repository</strong>: Clone the UIElement repository from GitHub:
<pre><code class="language-bash">git clone https://github.com/efflore/ui-element.git</code></pre>
<pre class="language-bash"><code>git clone https://github.com/efflore/ui-element.git</code></pre>
</li>
<li>
<strong>Install Dependencies</strong>: Navigate to the project directory and install the necessary dependencies using npm:
<pre><code class="language-bash">cd ui-element
<pre class="language-bash"><code>cd ui-element
npm install</code></pre>
</li>
<li>
<strong>Run the Development Server</strong>: Start the development server to work on the code and see live updates:
<pre><code class="language-bash">npm start</code></pre>
<pre class="language-bash"><code>npm start</code></pre>
This will run the build process and serve the project locally.
</li>
</ol>
Expand All @@ -155,15 +155,15 @@ <h2>4. Testing and Building</h2>
<ul>
<li>
<strong>Linting</strong>: Run linting to maintain code quality and formatting:
<pre><code class="language-bash">npm run lint</code></pre>
<pre class="language-bash"><code>npm run lint</code></pre>
</li>
<li>
<strong>Unit Testing</strong>: Execute the test suite to ensure everything works correctly:
<pre><code class="language-bash">npm test</code></pre>
<pre class="language-bash"><code>npm test</code></pre>
</li>
<li>
<strong>Building for Production</strong>: When you're ready to build the project for production, run:
<pre><code class="language-bash">npm run build</code></pre>
<pre class="language-bash"><code>npm run build</code></pre>
The production build will be created in the `dist` directory.
</li>
</ul>
Expand All @@ -173,7 +173,7 @@ <h2>4. Testing and Building</h2>
<h2>5. Commit Message Guidelines</h2>
<p>
Use conventional commit messages for consistency and clarity. Examples include:
<pre><code class="language-bash">
<pre class="language-bash"><code>
feat: add new feature to the component
fix: resolve issue with context updates
docs: update documentation for new API
Expand Down
Loading

0 comments on commit f8854e6

Please sign in to comment.