a homebrewed DnD campaign based in the Honkai: Star Rail universe
hsr honkaistarrail dnd
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ui updates to breadcrumb, link, and textarea components

+72 -45
+8 -10
app/src/lib/ui/components/link/Link.svelte
··· 4 4 import { tv } from 'tailwind-variants' 5 5 import { cn } from '$lib/utils' 6 6 7 - type LinkRootElement = Exclude<SvelteHTMLElements['a'], 'href'> 7 + type LinkRootElement = SvelteHTMLElements['a'] 8 8 type LinkProps = WithElementRef<WithChildren<LinkRootElement>> & { 9 9 href: string, 10 - isUnderlined?: boolean, 11 10 } 12 11 13 12 let { 14 13 href, 15 - isUnderlined = false, 16 14 children, 17 15 class: className, 18 16 'data-slot': dataSlot = 'page-link', 19 17 ref = $bindable(null), 20 18 ...restProps 21 19 }: LinkProps = $props() 20 + 22 21 const link = tv({ 23 - base: 'text-link-foreground', 24 - variants: { 25 - isUnderlined: { 26 - true: 'underline', 27 - } 28 - } 22 + base: [ 23 + ':not-[aria-current="page"]:hover:underline', 24 + ':not-[aria-current="page"]:hover:underline-offset-2', 25 + '[&:not-([aria-current=page]):hover:text-hsr-gold]', 26 + ], 29 27 }) 30 28 </script> 31 29 ··· 33 31 {href} 34 32 bind:this={ref} 35 33 data-slot={dataSlot} 36 - class={cn(link({ isUnderlined }), className)} 34 + class={cn(link(), className)} 37 35 {...restProps} 38 36 > 39 37 {@render children?.()}
+2 -2
app/src/lib/ui/form/text-input/textarea-input.svelte
··· 4 4 import { cn, tv } from 'tailwind-variants' 5 5 6 6 type TextAreaInputRootElement = SvelteHTMLElements['textarea'] 7 - type TextAreaInputProps = WithElementRef<Exclude<TextAreaInputRootElement, 'resize'>> & { 7 + type TextAreaInputProps = WithElementRef<TextAreaInputRootElement> & { 8 8 name: string, 9 9 resizable?: boolean, 10 - value?: string, 10 + value?: string | number, 11 11 } 12 12 13 13 let {
+9 -12
app/src/lib/ui/layout/breadcrumb/Breadcrumb.svelte
··· 2 2 import { cn, tv } from 'tailwind-variants' 3 3 import type { BreadcrumbProps } from './types' 4 4 import BreadcrumbItem from './breadcrumb-item.svelte' 5 + import BreadcrumbSeparator from './breadcrumb-separator.svelte' 5 6 6 7 let { 7 8 ref = $bindable(null), ··· 18 19 19 20 const breadcrumbTv = tv({ 20 21 slots: { 21 - root: 'mx-32', 22 - list: 'flex flex-row gap-2', 23 - listItem: [ 24 - "not-last:after:content-['/']", 25 - 'not-last:after:ml-2', 26 - 'not-last:after:text-zinc-300', 27 - 'not-last:after:font-light', 28 - 'last:font-medium', 29 - ] 22 + root: 'px-32 py-2 border-t border-b border-gray-200', 23 + list: 'flex flex-row items-center gap-2', 30 24 } 31 25 }) 32 - const { root, list, listItem } = breadcrumbTv() 26 + const { root, list } = breadcrumbTv() 33 27 </script> 34 28 35 29 <nav ··· 41 35 > 42 36 <ol class={list()}> 43 37 {#each allLinks as link, idx (`id-${link.path}-${link.text}`)} 44 - {@const isLastLink = allLinks.length - 1 === idx} 38 + {@const isLastLink = idx === allLinks.length - 1} 45 39 {@const ariaCurrent = isLastLink ? 'page' : false} 46 - <BreadcrumbItem {...link } anchorProps={{ 40 + <BreadcrumbItem {...link} anchorProps={{ 47 41 'aria-current': ariaCurrent 48 42 }} /> 43 + {#if !isLastLink} 44 + <BreadcrumbSeparator /> 45 + {/if} 49 46 {/each} 50 47 </ol> 51 48 </nav>
+19 -9
app/src/lib/ui/layout/breadcrumb/breadcrumb-item.svelte
··· 1 1 <script lang="ts"> 2 2 import { cn, tv } from 'tailwind-variants' 3 + import { Link } from '$ui/components/link' 3 4 import type { BreadcrumbItemProps } from './types' 5 + 4 6 let { 5 7 ref = $bindable(null), 6 8 'data-slot': dataSlot = 'breadcrumb-item', ··· 12 14 }: BreadcrumbItemProps = $props() 13 15 14 16 const listItemTv = tv({ 15 - base: [ 16 - "not-last:after:content-['/']", 17 - 'not-last:after:ml-2', 18 - 'not-last:after:text-zinc-300', 19 - 'not-last:after:font-light', 20 - 'last:font-medium', 21 - ] 17 + slots: { 18 + item: [ 19 + 'last:font-medium', 20 + 'focus-within:outline-0', 21 + 'focus-within:ring-2', 22 + 'focus-within:ring-offset-2', 23 + 'focus-within:ring-hsr-gold', 24 + ], 25 + anchor: [ 26 + 'focus-within:outline-0', 27 + 'hover:underline', 28 + 'hover:underline-offset-2', 29 + ] 30 + } 22 31 }) 32 + const { item, anchor } = listItemTv() 23 33 </script> 24 34 25 35 <li 26 36 bind:this={ref} 27 37 data-slot={dataSlot} 28 - class={cn(listItemTv(), className)} 38 + class={cn(item(), className)} 29 39 {...restProps} 30 40 > 31 - <a href={path} {...anchorProps}>{text}</a> 41 + <Link class={anchor()} href={path} {...anchorProps}>{text}</Link> 32 42 </li>
+27
app/src/lib/ui/layout/breadcrumb/breadcrumb-separator.svelte
··· 1 + <script lang="ts"> 2 + import ChevronRightIcon from '@lucide/svelte/icons/chevron-right' 3 + import { cn, tv } from 'tailwind-variants' 4 + import type { BreadcrumbSeparatorProps } from './types' 5 + 6 + let { 7 + ref = $bindable(null), 8 + class: className, 9 + ...restProps 10 + }: BreadcrumbSeparatorProps = $props() 11 + 12 + const stylesTv = tv({ 13 + base: '[&>svg]:size-5 text-zinc-500 font-light select-none', 14 + }) 15 + const styles = $derived(cn(stylesTv(), className)) 16 + </script> 17 + 18 + <li 19 + bind:this={ref} 20 + data-slot="breadcrumb-separator" 21 + role="presentation" 22 + aria-hidden="true" 23 + class={styles} 24 + {...restProps} 25 + > 26 + <ChevronRightIcon /> 27 + </li>
+7 -6
app/src/lib/ui/layout/breadcrumb/types.ts
··· 1 1 import type { WithElementRef, WithoutChildren } from 'bits-ui' 2 - import type { SvelteHTMLElements } from 'svelte/elements' 2 + import type { HTMLLiAttributes, SvelteHTMLElements } from 'svelte/elements' 3 3 4 + export type BreadcrumbProps = WithElementRef< 5 + SvelteHTMLElements['nav'] & { 6 + links?: BreadcrumbItemProps[] 7 + } 8 + > 4 9 export type BreadcrumbItemProps = WithElementRef< 5 10 WithoutChildren< 6 11 SvelteHTMLElements['li'] & { ··· 11 16 > 12 17 > 13 18 14 - export type BreadcrumbProps = WithElementRef< 15 - SvelteHTMLElements['nav'] & { 16 - links?: BreadcrumbItemProps[] 17 - } 18 - > 19 + export type BreadcrumbSeparatorProps = WithoutChildren<WithElementRef<HTMLLiAttributes>>
-6
app/src/styles/color.css
··· 78 78 --heading-foreground: var(--palette-accent); 79 79 --subheading-foreground: light-dark(var(--palette-gray-500), var(--palette-gray-700)); 80 80 81 - /* ui(text): link */ 82 - --link-foreground: var(--palette-accent); 83 - 84 81 /* ui(form): checkbox */ 85 82 --checkbox-unchecked: light-dark(var(--color-white), var(--color-hsr-dark)); 86 83 --checkbox-unchecked-border: light-dark(var(--palette-gray-200), var(--palette-gray-800)); ··· 154 151 --color-menu-content: var(--menu-content); 155 152 --color-menu-content-border: var(--menu-content-border); 156 153 --color-menu-item-hover: var(--menu-item-hover); 157 - 158 - /* ui(text): link */ 159 - --color-link-foreground: var(--link-foreground); 160 154 161 155 /* ui(text): heading */ 162 156 --color-heading-foreground: var(--heading-foreground);