diff options
author | 2022-11-01 16:20:04 +0000 | |
---|---|---|
committer | 2022-11-01 16:20:04 +0000 | |
commit | 4e2bd173932c231697a17a3098dc22ef3e481525 (patch) | |
tree | 0cf7877436a1463d78dad231ef28ebd8116225fc /examples/hackernews/src/components | |
parent | bb6e8800094dc59841eb3b345fcb8baca9e17ce9 (diff) | |
download | astro-4e2bd173932c231697a17a3098dc22ef3e481525.tar.gz astro-4e2bd173932c231697a17a3098dc22ef3e481525.tar.zst astro-4e2bd173932c231697a17a3098dc22ef3e481525.zip |
Adds a Hackernews example site (#5213)
* adds the hackernews example - TODO add readme content
* refactor: moving styles from root.css into components
* chore: add README content
* chore: lint fixes + prettier-plugin-astro@0.4.0
* Update examples/hackernews/README.md
Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
* lint: remove unused variable
* nit: adding check command to example
Co-authored-by: Sarah Rainsberger <sarah@rainsberger.ca>
Diffstat (limited to 'examples/hackernews/src/components')
-rw-r--r-- | examples/hackernews/src/components/Comment.astro | 59 | ||||
-rw-r--r-- | examples/hackernews/src/components/For.astro | 21 | ||||
-rw-r--r-- | examples/hackernews/src/components/Nav.astro | 97 | ||||
-rw-r--r-- | examples/hackernews/src/components/Show.astro | 9 | ||||
-rw-r--r-- | examples/hackernews/src/components/Story.astro | 77 | ||||
-rw-r--r-- | examples/hackernews/src/components/Toggle.astro | 78 |
6 files changed, 341 insertions, 0 deletions
diff --git a/examples/hackernews/src/components/Comment.astro b/examples/hackernews/src/components/Comment.astro new file mode 100644 index 000000000..50fa3e9e4 --- /dev/null +++ b/examples/hackernews/src/components/Comment.astro @@ -0,0 +1,59 @@ +--- +import For from './For.astro'; +import Show from './Show.astro'; +import Toggle from './Toggle.astro'; +import type { IComment } from '../types.js'; + +export interface Props { + comment: IComment; +} + +const { comment } = Astro.props; +--- + +<li> + <div class="by"> + <a href={`/users/${comment.user}`}>{comment.user}</a>{' '} + {comment.time_ago} ago + </div> + <div class="text" set:html={comment.content}></div> + <Show when={comment.comments.length}> + <Toggle open> + <For each={comment.comments}>{(comment: IComment) => <Astro.self comment={comment} />}</For> + </Toggle> + </Show> +</li> + +<style> + li { + border-top: 1px solid #eee; + position: relative; + } + + .by, + .text { + font-size: 0.9em; + margin: 1em 0; + } + + .by { + color: rgb(51 65 85); + } + + .by a { + color: rgb(51 65 85); + text-decoration: underline; + } + + .text { + overflow-wrap: break-word; + } + + .text :global(a:hover) { + color: #335d92; + } + + .text :global(pre) { + white-space: pre-wrap; + } +</style> diff --git a/examples/hackernews/src/components/For.astro b/examples/hackernews/src/components/For.astro new file mode 100644 index 000000000..b784f8f8a --- /dev/null +++ b/examples/hackernews/src/components/For.astro @@ -0,0 +1,21 @@ +--- +import Show from './Show.astro'; + +export interface Props<T> { + each: Iterable<T>; +} + +const { each } = Astro.props; +--- + +{(async function* () { + for await (const value of each) { + let html = await Astro.slots.render('default', [value]); + yield <Fragment set:html={html} />; + yield '\n'; + } +})()} + +<Show when={!each.length}> + <slot name="fallback" /> +</Show> diff --git a/examples/hackernews/src/components/Nav.astro b/examples/hackernews/src/components/Nav.astro new file mode 100644 index 000000000..10bf0f899 --- /dev/null +++ b/examples/hackernews/src/components/Nav.astro @@ -0,0 +1,97 @@ +--- +interface Link { + href: string; + text: string; +} + +const links: Link[] = [ + { href: '/', text: 'HN' }, + { href: '/new', text: 'New' }, + { href: '/show', text: 'Show' }, + { href: '/ask', text: 'Ask' }, + { href: '/job', text: 'Jobs' }, +]; +--- + +<header> + <nav aria-label="Main menu"> + {links.map(({ href, text }) => ( + <a href={href} aria-current={href === Astro.url.pathname ? 'page' : undefined}> + <strong>{text}</strong> + </a> + ))} + <a class="github" href="http://github.com/withastro/astro" target="_blank" rel="noreferrer"> + Built with Astro + </a> + </nav> +</header> + +<style> + header { + background-color: rgb(107 33 168); + position: fixed; + z-index: 999; + height: 55px; + top: 0; + left: 0; + right: 0; + } + + nav { + max-width: 800px; + box-sizing: border-box; + margin: 0 auto; + padding: 15px 5px; + } + + nav a { + color: rgba(248, 250, 252, 0.8); + line-height: 24px; + transition: color 0.15s ease; + display: inline-block; + vertical-align: middle; + font-weight: 300; + letter-spacing: 0.075em; + margin-right: 1.8em; + } + + nav a:hover { + color: rgb(248 250 252); + } + + nav [aria-current='page'] { + color: rgb(248 250 252); + font-weight: 400; + } + + nav a:last-of-type { + margin-right: 0; + } + + .github { + color: rgb(248 250 252); + font-size: 0.9em; + margin: 0; + float: right; + } + + @media (max-width: 860px) { + nav { + padding: 15px 30px; + } + } + + @media (max-width: 600px) { + nav { + padding: 15px; + } + + a { + margin-right: 1em; + } + + .github { + display: none; + } + } +</style> diff --git a/examples/hackernews/src/components/Show.astro b/examples/hackernews/src/components/Show.astro new file mode 100644 index 000000000..7e0887784 --- /dev/null +++ b/examples/hackernews/src/components/Show.astro @@ -0,0 +1,9 @@ +--- +export interface Props<T> { + when: T | number | boolean | undefined | null; +} + +const { when } = Astro.props; +--- + +{!!when ? <slot /> : <slot name="fallback" />} diff --git a/examples/hackernews/src/components/Story.astro b/examples/hackernews/src/components/Story.astro new file mode 100644 index 000000000..ee43bab17 --- /dev/null +++ b/examples/hackernews/src/components/Story.astro @@ -0,0 +1,77 @@ +--- +import Show from './Show.astro'; +import type { IStory } from '../types.js'; + +export interface Props { + story: IStory; +} + +const { story } = Astro.props; +--- + +<li> + <span class="score">{story.points}</span> + <span class="title"> + <Show when={story.url}> + <a href={story.url} target="_blank" rel="noreferrer"> + {story.title} + </a> + <span class="host"> ({story.domain})</span> + <a slot="fallback" href={`/item/${story.id}`}>{story.title}</a> + </Show> + </span> + <br /> + <span class="meta"> + <Show when={story.type !== 'job'}> + by <a href={`/users/${story.user}`}>{story.user}</a>{' '} + {story.time_ago}{' '}|{' '} + <a href={`/stories/${story.id}`}> + {story.comments_count ? `${story.comments_count} comments` : 'discuss'} + </a> + <a slot="fallback" href={`/stories/${story.id}`}>{story.time_ago}</a> + </Show> + </span> + <Show when={story.type !== 'link'}> + + <span class="label">{story.type}</span> + </Show> +</li> + +<style> + li { + background-color: rgb(248 250 252); + padding: 20px 30px 20px 80px; + border-bottom: 1px solid #eee; + position: relative; + line-height: 20px; + } + + .score { + color: rgb(88 28 135); + font-size: 1.1em; + font-weight: 700; + position: absolute; + top: 50%; + left: 0; + width: 80px; + text-align: center; + margin-top: -10px; + } + + .host, + .meta { + font-size: 0.85em; + color: rgb(51 65 85); + } + + .host a, + .meta a { + color: rgb(51 65 85); + text-decoration: underline; + } + + .host a:hover, + .meta a:hover { + color: #335d92; + } +</style> diff --git a/examples/hackernews/src/components/Toggle.astro b/examples/hackernews/src/components/Toggle.astro new file mode 100644 index 000000000..87b686981 --- /dev/null +++ b/examples/hackernews/src/components/Toggle.astro @@ -0,0 +1,78 @@ +--- +export interface Props { + open?: boolean; +} + +const { open = false } = Astro.props; +--- + +<hn-toggle open={open ? '' : undefined}> + <div class="toggle"> + <a>{open ? '[-]' : '[+] comments collapsed'}</a> + </div> + <ul class="comment-children"> + <slot /> + </ul> +</hn-toggle> + +<style> + hn-toggle[open] > .toggle { + padding: 0; + background-color: transparent; + margin-bottom: -0.5em; + } + + hn-toggle:not([open]) > .toggle { + background-color: rgb(255 247 237); + } + hn-toggle:not([open]) ul { + display: none; + } + + .toggle { + font-size: 0.9em; + margin: 1em 0; + padding: 0.3em 0.5em; + border-radius: 4px; + } + + a { + color: rgb(51 65 85); + cursor: pointer; + } +</style> + +<script> + class HnToggle extends HTMLElement { + #btn = this.querySelector<HTMLAnchorElement>('a')!; + #toggleOpen = this.toggleOpen.bind(this); + + connectedCallback() { + this.#btn.addEventListener('click', this.#toggleOpen, false); + } + + disconnectedCallback() { + this.#btn.addEventListener('click', this.#toggleOpen); + } + + get open() { + return this.hasAttribute('open'); + } + + set open(value: boolean) { + if (value) { + this.setAttribute('open', ''); + this.#btn.textContent = '[-]'; + } else { + this.removeAttribute('open'); + this.#btn.textContent = '[+] comments collapsed'; + } + } + + toggleOpen() { + this.open = !this.open; + } + } + + customElements.define('hn-toggle', HnToggle); +</script> |