-
Notifications
You must be signed in to change notification settings - Fork 1
Lyric UI Setup #217
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
JamesTLopez
wants to merge
26
commits into
main
Choose a base branch
from
feat/lyric-ui-setup
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Lyric UI Setup #217
Changes from all commits
Commits
Show all changes
26 commits
Select commit
Hold shift + click to select a range
cde3637
feat: shadcn and storybook init
JamesTLopez 1f96358
feat: rename button
JamesTLopez 4567392
feat: change to tailwind 4
JamesTLopez 07dac1c
feat: update bundled css naming
JamesTLopez 9816b56
feat: compatible theming with external apps
JamesTLopez a38ecec
feat: remove dark
JamesTLopez 52ab73e
feat: add readme
JamesTLopez 1b01b85
Merge branch 'main' into feat/lyric-ui-setup
JamesTLopez a33c78d
fix: build issues
JamesTLopez 2b4fb47
fix: remove animate tailwind
JamesTLopez 6a4c91d
fix: change button location to support shadcn components
JamesTLopez 4372a27
feat: instructions to add components from shad
JamesTLopez bc67869
fix: update README
JamesTLopez 8c7c422
fix: upgrade all packages to latest and remove outdated
JamesTLopez 2bcc41f
fix: re-add buttons remove default from components.json
JamesTLopez 00f8d85
missing lock
JamesTLopez 4ed8e1c
fix: resolve exporting commonjs
JamesTLopez 575f31f
fix: update components style
JamesTLopez 53bc1e4
feat: add lucide add icon support on button
JamesTLopez 1645a25
Update pnpm-lock.yaml
JamesTLopez dca3a23
fix: resolve asChild slot issue
JamesTLopez e72b988
feat: disabled story
JamesTLopez 6e8290a
fix: resolve remove hsl
JamesTLopez 5800ba3
Merge branch 'main' into feat/lyric-ui-setup
JamesTLopez ba8c8da
refactor: rename lyric-ui package to ui
JamesTLopez 1713b78
fix: remove alias import
JamesTLopez File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| import type { StorybookConfig } from '@storybook/react-vite'; | ||
|
|
||
| const config: StorybookConfig = { | ||
| stories: ['../src/**/*.stories.@(ts|tsx)'], | ||
| framework: { | ||
| name: '@storybook/react-vite', | ||
| options: {}, | ||
| }, | ||
| }; | ||
|
|
||
| export default config; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| import '@/style.css'; | ||
|
|
||
| import type { Preview } from '@storybook/react'; | ||
|
|
||
| const preview: Preview = { | ||
| parameters: { | ||
| controls: { | ||
| matchers: { | ||
| color: /(background|color)$/i, | ||
| date: /Date$/i, | ||
| }, | ||
| }, | ||
| }, | ||
| }; | ||
|
|
||
| export default preview; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| # lyric-ui | ||
|
|
||
| Shared React component library for Lyric-based UIs. | ||
|
|
||
| `lyric-ui` provides a set of accessible, themeable UI primitives for building front-end applications that interact with the [Lyric](https://github.com/overture-stack/lyric) data submission system. | ||
|
|
||
| --- | ||
|
|
||
| ## Features | ||
|
|
||
| - **Themeable** — Theming can be customized using css variables in the main .css file in your application. Please see section [Theming]. | ||
| - **Variant-driven components** — built with [`class-variance-authority`](https://cva.style/) so each component exposes a clean, type-safe variant API. | ||
| - **Dual-format build** — ships both ES module (`lyric-ui.js`) and CommonJS (`lyric-ui.cjs`) outputs so it works in both modern bundlers and legacy setups. | ||
| - **Storybook** — every component has stories for interactive development and visual documentation. | ||
|
|
||
| --- | ||
|
|
||
| ### Utilities | ||
|
|
||
| | Export | Description | | ||
| | ---------------- | ------------------------------------------------------------------------------------------------------------- | | ||
| | `cn(...inputs)` | Merges Tailwind class strings, resolving conflicts via `tailwind-merge` and conditional logic via `clsx`. | | ||
| | `buttonVariants` | The underlying CVA variant factory for `Button`, useful when you need the class string without the component. | | ||
|
|
||
| --- | ||
|
|
||
| ## Technologies | ||
|
|
||
| | Technology | Role | | ||
| | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------- | | ||
| | [React 18](https://react.dev/) | Component runtime | | ||
| | [TypeScript](https://www.typescriptlang.org/) | Authoring language; types shipped in `dist/` | | ||
| | [Tailwind CSS v4](https://tailwindcss.com/) | Utility-first styling | | ||
| | [class-variance-authority](https://cva.style/) | Variant and slot management for components | | ||
| | [clsx](https://github.com/lukeed/clsx) + [tailwind-merge](https://github.com/dcastil/tailwind-merge) | Conditional class composition without conflicts | | ||
| | [Vite](https://vitejs.dev/) | Library build (ESM + CJS, bundled CSS) | | ||
| | [Storybook 8](https://storybook.js.org/) | Component development environment and visual docs | | ||
|
|
||
| The theming system follows a similar [shadcn/ui](https://ui.shadcn.com/) convention: design tokens are declared as CSS custom properties in a `@layer base` block, then referenced by Tailwind via `@theme`. shadcn uses HSL to apply their themes by default, this implementation will also be able to support other formats. Ultimately, callers can override the full palette simply by redefining the CSS variables in their own stylesheet which will be explained further in the next section. | ||
|
|
||
| ### Theming | ||
|
|
||
| Tailoring lyric-ui components to a target application is done by overriding CSS variables in your application's main `.css` file. The following tokens control the full palette: | ||
|
|
||
| | Variable | Default value | Description | | ||
| | -------------------------- | ------------------------ | ------------------------------------------------------------------- | | ||
| | `--background` | `hsl(0 0% 100%)` | Page/surface background | | ||
| | `--foreground` | `hsl(222.2 84% 4.9%)` | Default text and icon color | | ||
| | `--primary` | `hsl(222.2 47.4% 11.2%)` | Primary action color (buttons, links) | | ||
| | `--primary-foreground` | `hsl(210 40% 98%)` | Text/icons rendered on a primary-colored surface | | ||
| | `--secondary` | `hsl(210 40% 96.1%)` | Secondary action or surface color | | ||
| | `--secondary-foreground` | `hsl(222.2 47.4% 11.2%)` | Text/icons rendered on a secondary-colored surface | | ||
| | `--muted` | `hsl(210 40% 96.1%)` | Subdued background for non-interactive areas (badges, placeholders) | | ||
| | `--muted-foreground` | `hsl(215.4 16.3% 46.9%)` | Text/icons rendered on a muted surface | | ||
| | `--accent` | `hsl(210 40% 96.1%)` | Highlight or hover state background | | ||
| | `--accent-foreground` | `hsl(222.2 47.4% 11.2%)` | Text/icons rendered on an accent-colored surface | | ||
| | `--destructive` | `hsl(0 84.2% 60.2%)` | Destructive/error action color (delete, error states) | | ||
| | `--destructive-foreground` | `hsl(210 40% 98%)` | Text/icons rendered on a destructive-colored surface | | ||
| | `--border` | `hsl(214.3 31.8% 91.4%)` | Default border color for cards, inputs, and dividers | | ||
| | `--input` | `hsl(214.3 31.8% 91.4%)` | Input field border color | | ||
| | `--ring` | `hsl(222.2 84% 4.9%)` | Focus ring color for interactive elements | | ||
| | `--radius` | `0.5rem` | Base border-radius used across components | | ||
|
|
||
| Your main css file should look something like this: | ||
|
|
||
| ```css | ||
| :root { | ||
| --background: hsl(0 0% 100%); | ||
| --foreground: hsl(222.2 84% 4.9%); | ||
| --primary: hsl(222.2 47.4% 11.2%); | ||
| --primary-foreground: hsl(210 40% 98%); | ||
| --secondary: hsl(210 40% 96.1%); | ||
| --secondary-foreground: hsl(222.2 47.4% 11.2%); | ||
| --muted: hsl(210 40% 96.1%); | ||
| --muted-foreground: hsl(215.4 16.3% 46.9%); | ||
| --accent: hsl(210 40% 96.1%); | ||
| --accent-foreground: hsl(222.2 47.4% 11.2%); | ||
| --destructive: hsl(0 84.2% 60.2%); | ||
| --destructive-foreground: hsl(210 40% 98%); | ||
| --border: hsl(214.3 31.8% 91.4%); | ||
| --input: hsl(214.3 31.8% 91.4%); | ||
| --ring: hsl(222.2 84% 4.9%); | ||
| --radius: 0.5rem; | ||
| } | ||
| ``` | ||
|
|
||
| If you are using tailwind along side with lyric-ui, you can use tailwind css variable to populate lyric-ui as a source of truth: | ||
|
|
||
| ```css | ||
| @theme { | ||
| --color-primary-900: #054a74; | ||
| } | ||
|
|
||
| :root { | ||
| --primary: var(--color-primary-900); | ||
| } | ||
| ``` | ||
|
|
||
| Because tailwind is being bundled with these exported components, it's worth noting that a project also using tailwind may possibly overlap on styles. This won't functionally affect the project, but may cause unintended visual issues. | ||
|
|
||
| --- | ||
|
|
||
| ## Adding new components from Shadcn | ||
|
|
||
| From the component library from [shadcn](https://ui.shadcn.com/docs/components), select targeted component and run the command they give you for that component. | ||
| For example, `pnpm dlx shadcn@latest add card` will add a card component. All components added through this method will be added to the path `components/ui/*`. | ||
|
|
||
| NOTE: Some components may also install third-party libraries. | ||
| For example `pnpm dlx shadcn@latest add popover` will add `@radix-ui/react-popover`. | ||
|
|
||
| ## Installation | ||
|
|
||
| <!-- | ||
| ```bash | ||
| pnpm add @overture-stack/lyric-ui | ||
| ```--> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| { | ||
| "$schema": "https://ui.shadcn.com/schema.json", | ||
| "style": "new-york", | ||
| "rsc": false, | ||
| "tsx": true, | ||
| "tailwind": { | ||
| "config": "", | ||
| "css": "src/style.css", | ||
| "baseColor": "slate", | ||
| "cssVariables": true | ||
| }, | ||
| "aliases": { | ||
| "components": "@/components", | ||
| "utils": "@/lib/utils" | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| { | ||
| "name": "@overture-stack/lyric-ui", | ||
| "version": "0.0.0-dev", | ||
| "description": "Shared React component library for Lyric-based UIs.", | ||
| "type": "module", | ||
| "main": "./dist/lyric-ui.cjs", | ||
| "module": "./dist/lyric-ui.js", | ||
| "types": "./dist/index.d.ts", | ||
| "exports": { | ||
| ".": { | ||
| "types": "./dist/index.d.ts", | ||
| "import": "./dist/lyric-ui.js", | ||
| "require": "./dist/lyric-ui.cjs" | ||
| }, | ||
| "./dist/lyric-ui.css": "./dist/lyric-ui.css" | ||
| }, | ||
| "files": [ | ||
| "dist/" | ||
| ], | ||
| "engines": { | ||
| "node": ">=20.0.0" | ||
| }, | ||
| "scripts": { | ||
| "nuke:build": "npx rimraf dist", | ||
| "build:all": "pnpm nuke:build && vite build && tsc -p tsconfig.build.json", | ||
| "storybook": "storybook dev -p 6006", | ||
| "build:storybook": "storybook build" | ||
| }, | ||
| "author": "Ontario Institute for Cancer Research", | ||
| "license": "AGPL-3.0-or-later", | ||
| "repository": { | ||
| "type": "git", | ||
| "url": "https://github.com/overture-stack/lyric.git" | ||
| }, | ||
| "peerDependencies": { | ||
| "react": "^18.3.0", | ||
| "react-dom": "^18.3.0" | ||
| }, | ||
| "dependencies": { | ||
| "@radix-ui/react-slot": "^1.3.3", | ||
| "class-variance-authority": "^0.7.1", | ||
| "clsx": "^2.1.1", | ||
| "lucide-react": "^1.33.0", | ||
| "tailwind-merge": "^3.6.0" | ||
| }, | ||
| "devDependencies": { | ||
| "@storybook/react": "^10.5.9", | ||
| "@storybook/react-vite": "^10.5.9", | ||
| "@tailwindcss/vite": "^4.3.3", | ||
| "@types/react": "^19.2.18", | ||
| "@types/react-dom": "^19.2.4", | ||
| "@vitejs/plugin-react": "^6.0.5", | ||
| "autoprefixer": "^10.5.4", | ||
| "postcss": "^8.5.26", | ||
| "react": "^19.2.8", | ||
| "react-dom": "^19.2.8", | ||
| "rimraf": "^6.1.3", | ||
| "storybook": "^10.5.9", | ||
| "tailwindcss": "^4.3.3", | ||
| "vite": "^8.2.1" | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| import type { Meta, StoryObj } from '@storybook/react'; | ||
| import { Download } from 'lucide-react'; | ||
|
|
||
| import { Button } from './button'; | ||
|
|
||
| const meta: Meta<typeof Button> = { | ||
| title: 'Components/Button', | ||
| component: Button, | ||
| tags: ['autodocs'], | ||
| argTypes: { | ||
| variant: { | ||
| control: 'select', | ||
| options: ['default', 'destructive', 'outline', 'secondary', 'ghost', 'link'], | ||
| }, | ||
| size: { | ||
| control: 'select', | ||
| options: ['default', 'sm', 'lg', 'icon'], | ||
| }, | ||
| }, | ||
| args: { | ||
| children: 'Button', | ||
| }, | ||
| }; | ||
|
|
||
| export default meta; | ||
|
|
||
| type Story = StoryObj<typeof Button>; | ||
|
|
||
| export const Default: Story = { | ||
| args: { | ||
| variant: 'default', | ||
| }, | ||
| }; | ||
|
|
||
| export const DefaultWithIcon: Story = { | ||
| args: { | ||
| variant: 'default', | ||
| icon: <Download />, | ||
| }, | ||
| }; | ||
|
|
||
| export const Disabled: Story = { | ||
| args: { | ||
| variant: 'default', | ||
| disabled: true, | ||
| }, | ||
| }; | ||
|
|
||
| export const Secondary: Story = { | ||
| args: { | ||
| variant: 'secondary', | ||
| }, | ||
| }; | ||
|
|
||
| export const Destructive: Story = { | ||
| args: { | ||
| variant: 'destructive', | ||
| }, | ||
| }; | ||
|
|
||
| export const Outline: Story = { | ||
| args: { | ||
| variant: 'outline', | ||
| }, | ||
| }; | ||
|
|
||
| export const Ghost: Story = { | ||
| args: { | ||
| variant: 'ghost', | ||
| }, | ||
| }; | ||
|
|
||
| export const Link: Story = { | ||
| args: { | ||
| variant: 'link', | ||
| }, | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| import { Slot } from '@radix-ui/react-slot'; | ||
| import { cva, type VariantProps } from 'class-variance-authority'; | ||
| import * as React from 'react'; | ||
|
|
||
| import { cn } from '@/lib/utils'; | ||
|
|
||
| const buttonVariants = cva( | ||
| 'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0', | ||
| { | ||
| variants: { | ||
| variant: { | ||
| default: 'bg-primary text-primary-foreground hover:bg-primary/90', | ||
| destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90', | ||
| outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground', | ||
| secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80', | ||
| ghost: 'hover:bg-accent hover:text-accent-foreground', | ||
| link: 'text-primary underline-offset-4 hover:underline', | ||
| }, | ||
| size: { | ||
| default: 'h-10 px-4 py-2', | ||
| sm: 'h-9 rounded-md px-3', | ||
| lg: 'h-11 rounded-md px-8', | ||
| icon: 'h-10 w-10', | ||
| }, | ||
| }, | ||
| defaultVariants: { | ||
| variant: 'default', | ||
| size: 'default', | ||
| }, | ||
| }, | ||
| ); | ||
|
|
||
| export interface ButtonProps | ||
| extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> { | ||
| asChild?: boolean; | ||
| icon?: React.ReactNode; | ||
| iconPosition?: 'left' | 'right'; | ||
| } | ||
|
|
||
| const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( | ||
| ({ className, variant, size, asChild = false, icon, iconPosition = 'left', children, ...props }, ref) => { | ||
| const Comp = asChild ? Slot : 'button'; | ||
|
|
||
| return ( | ||
| <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props}> | ||
| <> | ||
| {!asChild && icon && iconPosition === 'left' && icon} | ||
| {size !== 'icon' ? children : null} | ||
| {!asChild && icon && iconPosition === 'right' && icon} | ||
| </> | ||
| </Comp> | ||
| ); | ||
| }, | ||
| ); | ||
| Button.displayName = 'Button'; | ||
|
|
||
| export { Button, buttonVariants }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| import './style.css'; | ||
|
|
||
| export { Button, type ButtonProps, buttonVariants } from './components/ui/button'; | ||
| export { cn } from './lib/utils'; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| import { type ClassValue, clsx } from 'clsx'; | ||
| import { twMerge } from 'tailwind-merge'; | ||
|
|
||
| export function cn(...inputs: ClassValue[]) { | ||
| return twMerge(clsx(inputs)); | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.