Skip to content

Commit bc28883

Browse files
committed
Implement primitives: avatar and buttons
1 parent bbae908 commit bc28883

13 files changed

Lines changed: 306 additions & 0 deletions

File tree

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { html } from 'lit'
2+
import { defineAuthStoryRender } from '../../../storybook'
3+
4+
import './Avatar'
5+
import { USER_OPTIONS } from '../../../storybook/stubs'
6+
7+
const meta = {
8+
title: 'Primitives/Avatar',
9+
args: {
10+
user: 'Alice',
11+
},
12+
argTypes: {
13+
user: USER_OPTIONS.control,
14+
}
15+
} as const
16+
17+
const render = defineAuthStoryRender<typeof meta.argTypes>(() => html`<solid-avatar></solid-avatar>`)
18+
19+
export const Primary = { render }
20+
export const Fallback = { render, args: { user: 'Bob' } }
21+
export const Guest = { render, args: { user: 'Guest' } }
22+
23+
export default meta
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
:host {
2+
--size: 150px;
3+
4+
display: inline-flex;
5+
overflow: hidden;
6+
width: var(--size);
7+
height: var(--size);
8+
9+
img {
10+
width: 100%;
11+
height: 100%;
12+
object-fit: cover;
13+
}
14+
}
15+
16+
:host(:state(fallback)) {
17+
background: var(--solid-color-gray-100);
18+
justify-content: center;
19+
align-items: center;
20+
21+
icon-lucide-circle-user {
22+
color: var(--solid-color-gray-200);
23+
width: 50%;
24+
height: 50%;
25+
}
26+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { html } from 'lit'
2+
import { customElement, state } from 'lit/decorators.js'
3+
import '~icons/lucide/circle-user'
4+
5+
import styles from './Avatar.styles.css'
6+
7+
import WebComponent from '../../lib/WebComponent'
8+
import { consume } from '@lit/context'
9+
import { authContext, DEFAULT_AUTH_CONTEXT, AuthContext } from '../../lib/auth/context'
10+
import commonStyles from '../../styles/common.styles.css'
11+
12+
@customElement('solid-avatar')
13+
export default class Avatar extends WebComponent {
14+
static styles = [commonStyles, styles]
15+
static states = {
16+
fallback: (component: Avatar) => !component.auth.account?.avatarUrl,
17+
}
18+
19+
@state()
20+
@consume({ context: authContext })
21+
private auth: AuthContext = DEFAULT_AUTH_CONTEXT
22+
23+
protected render () {
24+
if (!this.auth.account?.avatarUrl) {
25+
return html`
26+
<icon-lucide-circle-user></icon-lucide-circle-user>
27+
`
28+
}
29+
30+
return html`
31+
<img src="${this.auth.account?.avatarUrl}" alt="" />
32+
`
33+
}
34+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import Avatar from './Avatar'
2+
3+
export { Avatar }
4+
export default Avatar
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { html } from 'lit'
2+
import { defineStoryRender } from '../../../storybook'
3+
4+
import './LoginButton'
5+
import '~icons/lucide/log-in'
6+
7+
const meta = {
8+
title: 'Primitives/LoginButton',
9+
} as const
10+
11+
export const Primary = {
12+
render: defineStoryRender(() => html`<solid-login-button></solid-login-button>`)
13+
}
14+
15+
export const CustomLabel = {
16+
render: defineStoryRender(() => html`
17+
<solid-login-button>
18+
Sign In
19+
<icon-lucide-log-in style="width: 16px; height: 16px;"></icon-lucide-log-in>
20+
</solid-login-button>
21+
`)
22+
}
23+
24+
export const CustomTrigger = {
25+
render: defineStoryRender(() => html`
26+
<solid-login-button>
27+
<button slot="trigger" type="button">
28+
Sign In
29+
</button>
30+
</solid-login-button>
31+
`)
32+
}
33+
34+
export default meta
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { html } from 'lit'
2+
import { customElement, state } from 'lit/decorators.js'
3+
import commonStyles from '../../styles/common.styles.css'
4+
5+
import WebComponent from '../../lib/WebComponent'
6+
7+
import { AuthContext, authContext, DEFAULT_AUTH_CONTEXT } from '../../lib/auth/context'
8+
import { consume } from '@lit/context'
9+
10+
@customElement('solid-login-button')
11+
export default class LoginButton extends WebComponent {
12+
static styles = commonStyles
13+
14+
@state()
15+
@consume({ context: authContext })
16+
private auth: AuthContext = DEFAULT_AUTH_CONTEXT
17+
18+
protected render () {
19+
return html`
20+
<slot name="trigger" @click=${this.onClick}>
21+
<button type="button">
22+
<slot>
23+
Log In
24+
</slot>
25+
</button>
26+
</slot>
27+
`
28+
}
29+
30+
private onClick (e: MouseEvent) {
31+
e.preventDefault()
32+
33+
this.auth.login()
34+
}
35+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import LoginButton from './LoginButton'
2+
3+
export { LoginButton }
4+
export default LoginButton
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { html } from 'lit'
2+
import { defineStoryRender } from '../../../storybook'
3+
4+
import './LogoutButton'
5+
import '~icons/lucide/log-out'
6+
7+
const meta = {
8+
title: 'Primitives/LogoutButton',
9+
} as const
10+
11+
export const Primary = {
12+
render: defineStoryRender(() => html`<solid-logout-button></solid-logout-button>`)
13+
}
14+
15+
export const CustomLabel = {
16+
render: defineStoryRender(() => html`
17+
<solid-logout-button>
18+
Sign Out
19+
<icon-lucide-log-out style="width: 16px; height: 16px;"></icon-lucide-log-out>
20+
</solid-logout-button>
21+
`)
22+
}
23+
24+
export const CustomTrigger = {
25+
render: defineStoryRender(() => html`
26+
<solid-logout-button>
27+
<button slot="trigger" type="button">
28+
Sign Out
29+
</button>
30+
</solid-logout-button>
31+
`)
32+
}
33+
34+
export default meta
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { html } from 'lit'
2+
import { customElement, state } from 'lit/decorators.js'
3+
import commonStyles from '../../styles/common.styles.css'
4+
5+
import WebComponent from '../../lib/WebComponent'
6+
7+
import { AuthContext, authContext, DEFAULT_AUTH_CONTEXT } from '../../lib/auth/context'
8+
import { consume } from '@lit/context'
9+
10+
@customElement('solid-logout-button')
11+
export default class LogoutButton extends WebComponent {
12+
static styles = commonStyles
13+
14+
@state()
15+
@consume({ context: authContext })
16+
private auth: AuthContext = DEFAULT_AUTH_CONTEXT
17+
18+
protected render () {
19+
return html`
20+
<slot name="trigger" @click=${this.onClick}>
21+
<button type="button">
22+
<slot>
23+
Log Out
24+
</slot>
25+
</button>
26+
</slot>
27+
`
28+
}
29+
30+
private onClick (e: MouseEvent) {
31+
e.preventDefault()
32+
33+
this.auth.logout()
34+
}
35+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import LogoutButton from './LogoutButton'
2+
3+
export { LogoutButton }
4+
export default LogoutButton

0 commit comments

Comments
 (0)