summaryrefslogtreecommitdiff
path: root/examples/hackernews/src/components
diff options
context:
space:
mode:
authorGravatar Tony Sullivan <tony.f.sullivan@outlook.com> 2022-11-01 16:20:04 +0000
committerGravatar GitHub <noreply@github.com> 2022-11-01 16:20:04 +0000
commit4e2bd173932c231697a17a3098dc22ef3e481525 (patch)
tree0cf7877436a1463d78dad231ef28ebd8116225fc /examples/hackernews/src/components
parentbb6e8800094dc59841eb3b345fcb8baca9e17ce9 (diff)
downloadastro-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.astro59
-rw-r--r--examples/hackernews/src/components/For.astro21
-rw-r--r--examples/hackernews/src/components/Nav.astro97
-rw-r--r--examples/hackernews/src/components/Show.astro9
-rw-r--r--examples/hackernews/src/components/Story.astro77
-rw-r--r--examples/hackernews/src/components/Toggle.astro78
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'}>
+ &nbsp;
+ <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>