From ace3865fdfeafc29a1330f17597d1bb740855ca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A1n=20UB?= <22903142+adrian-ub@users.noreply.github.com> Date: Thu, 7 Nov 2024 17:46:54 -0500 Subject: [PATCH] docs: add colors page --- docs/src/components/Color.astro | 74 +++++++ docs/src/components/ColorFormatSelector.astro | 186 ++++++++++++++++++ docs/src/components/ColorPalette.astro | 29 +++ docs/src/config/docs.ts | 4 + docs/src/lib/colors.ts | 87 ++++++++ docs/src/pages/colors/_colors.astro | 10 + docs/src/pages/colors/index.astro | 47 +++++ 7 files changed, 437 insertions(+) create mode 100644 docs/src/components/Color.astro create mode 100644 docs/src/components/ColorFormatSelector.astro create mode 100644 docs/src/components/ColorPalette.astro create mode 100644 docs/src/lib/colors.ts create mode 100644 docs/src/pages/colors/_colors.astro create mode 100644 docs/src/pages/colors/index.astro diff --git a/docs/src/components/Color.astro b/docs/src/components/Color.astro new file mode 100644 index 0000000..3a99361 --- /dev/null +++ b/docs/src/components/Color.astro @@ -0,0 +1,74 @@ +--- +import { type Color } from '@/lib/colors' + +export interface Props { + color: Color +} +const { color } = Astro.props +--- + + diff --git a/docs/src/components/ColorFormatSelector.astro b/docs/src/components/ColorFormatSelector.astro new file mode 100644 index 0000000..ec23abb --- /dev/null +++ b/docs/src/components/ColorFormatSelector.astro @@ -0,0 +1,186 @@ +--- +import { getColorFormat, type Color } from '@/lib/colors' +import { cn } from '@/lib/utils' + +export interface Props { + class?: string + color: Color +} + +const { color, class: className } = Astro.props + +const formats = getColorFormat(color) + +const options = Object.entries(formats).map(([format, title]) => ({ value: format, title, format })) +--- + +
a.value).indexOf(this.selectableItemActive); + if(index < this.selectableItems.length-1){ + this.selectableItemActive = this.selectableItems[index+1].value; + this.selectScrollToActiveItem(); + } + }, + selectableItemActivePrevious(){ + let index = this.selectableItems.map(a=>a.value).indexOf(this.selectableItemActive); + if(index > 0){ + this.selectableItemActive = this.selectableItems[index-1].value; + this.selectScrollToActiveItem(); + } + }, + selectScrollToActiveItem(){ + if(this.selectableItemActive){ + activeElement = document.getElementById(this.selectableItemActive + '-' + this.selectId) + newScrollPos = (activeElement.offsetTop + activeElement.offsetHeight) - this.$refs.selectableItemsList.offsetHeight; + if(newScrollPos > 0){ + this.$refs.selectableItemsList.scrollTop=newScrollPos; + } else { + this.$refs.selectableItemsList.scrollTop=0; + } + } + }, + selectKeydown(event){ + if (event.keyCode >= 65 && event.keyCode <= 90) { + + this.selectKeydownValue += event.key; + selectedItemBestMatch = this.selectItemsFindBestMatch(); + if(selectedItemBestMatch){ + if(this.selectOpen){ + this.selectableItemActive = selectedItemBestMatch; + this.selectScrollToActiveItem(); + } else { + this.selectedItem = this.selectableItemActive = selectedItemBestMatch; + } + } + + if(this.selectKeydownValue != ''){ + clearTimeout(this.selectKeydownClearTimeout); + this.selectKeydownClearTimeout = setTimeout(() => { + this.selectKeydownValue = ''; + }, this.selectKeydownTimeout); + } + } + }, + selectItemsFindBestMatch(){ + typedValue = this.selectKeydownValue.toLowerCase(); + var bestMatch = null; + var bestMatchIndex = -1; + for (var i = 0; i < this.selectableItems.length; i++) { + var title = this.selectableItems[i].title.toLowerCase(); + var index = title.indexOf(typedValue); + if (index > -1 && (bestMatchIndex == -1 || index < bestMatchIndex) && !this.selectableItems[i].disabled) { + bestMatch = this.selectableItems[i].value; + bestMatchIndex = index; + } + } + return bestMatch; + }, + selectPositionUpdate(){ + selectDropdownBottomPos = this.$refs.selectButton.getBoundingClientRect().top + this.$refs.selectButton.offsetHeight + parseInt(window.getComputedStyle(this.$refs.selectableItemsList).maxHeight); + if(window.innerHeight < selectDropdownBottomPos){ + this.selectDropdownPosition = 'top'; + } else { + this.selectDropdownPosition = 'bottom'; + } + } +}` + x-init=" + $watch('selectOpen', function(){ + if(!selectedItem){ + selectableItemActive=selectableItems[0].value; + } else { + selectableItemActive=selectedItem; + } + setTimeout(function(){ + selectScrollToActiveItem(); + }, 10); + selectPositionUpdate(); + window.addEventListener('resize', (event) => { selectPositionUpdate(); }); + }); +" + x-effect="selectedItem = $store.format;" + @keydown.escape="if(selectOpen){ selectOpen=false; }" + @keydown.down="if(selectOpen){ selectableItemActiveNext(); } else { selectOpen=true; } event.preventDefault();" + @keydown.up="if(selectOpen){ selectableItemActivePrevious(); } else { selectOpen=true; } event.preventDefault();" + @keydown.enter="$store.format=selectableItemActive; selectOpen=false;" + @keydown="selectKeydown($event);" +> + + + +
diff --git a/docs/src/components/ColorPalette.astro b/docs/src/components/ColorPalette.astro new file mode 100644 index 0000000..b5aa2b2 --- /dev/null +++ b/docs/src/components/ColorPalette.astro @@ -0,0 +1,29 @@ +--- +import type { ColorPalette } from '@/lib/colors' +import Color from './Color.astro' +import ColorFormatSelector from './ColorFormatSelector.astro' + +export interface Props { + colorPalette: ColorPalette +} + +const { colorPalette } = Astro.props +--- + +
+
+
+

{colorPalette.name}

+
+ +
+
+ {colorPalette.colors.map((color) => )} +
+
+ + diff --git a/docs/src/config/docs.ts b/docs/src/config/docs.ts index a72be01..22d8b2d 100644 --- a/docs/src/config/docs.ts +++ b/docs/src/config/docs.ts @@ -32,6 +32,10 @@ export const docsConfig: TDocsConfig = { title: 'Examples', href: '/examples/authentication', }, + { + title: 'Colors', + href: '/colors', + }, ], sidebarNav: [ { diff --git a/docs/src/lib/colors.ts b/docs/src/lib/colors.ts new file mode 100644 index 0000000..40a3040 --- /dev/null +++ b/docs/src/lib/colors.ts @@ -0,0 +1,87 @@ +import { colors } from '@/registry/registry-colors' + +import { z } from 'zod' + +const colorSchema = z.object({ + name: z.string(), + id: z.string(), + scale: z.number(), + class: z.string(), + hex: z.string(), + rgb: z.string(), + hsl: z.string(), + foreground: z.string(), +}) + +const colorPaletteSchema = z.object({ + name: z.string(), + colors: z.array(colorSchema), +}) + +export type ColorPalette = z.infer + +export function getColorFormat(color: Color): { class: string, hex: string, rgb: string, hsl: string } { + return { + class: `bg-${color.name}-100`, + hex: color.hex, + rgb: color.rgb, + hsl: color.hsl, + } +} + +export type ColorFormat = keyof ReturnType + +export function getColors(): ColorPalette[] { + const tailwindColors = colorPaletteSchema.array().parse( + Object.entries(colors) + .map(([name, color]) => { + if (!Array.isArray(color)) { + return null + } + + return { + name, + colors: color.map((color) => { + const rgb = color.rgb.replace( + /^rgb\((\d+),(\d+),(\d+)\)$/, + '$1 $2 $3', + ) + + return { + ...color, + name, + id: `${name}-${color.scale}`, + class: `${name}-${color.scale}`, + rgb, + hsl: color.hsl.replace( + /^hsl\(([\d.]+),([\d.]+%),([\d.]+%)\)$/, + '$1 $2 $3', + ), + foreground: getForegroundFromBackground(rgb), + } + }), + } + }) + .filter(Boolean), + ) + + return tailwindColors +} + +export type Color = ReturnType[number]['colors'][number] + +function toLinear(number: number): number { + const base = number / 255 + return base <= 0.04045 + ? base / 12.92 + : ((base + 0.055) / 1.055) ** 2.4 +} + +function getForegroundFromBackground(rgb: string): string { + const [r, g, b] = rgb.split(' ').map(Number) + + const luminance + = 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b) + + return luminance > 0.179 ? '#000' : '#fff' +} diff --git a/docs/src/pages/colors/_colors.astro b/docs/src/pages/colors/_colors.astro new file mode 100644 index 0000000..aca9460 --- /dev/null +++ b/docs/src/pages/colors/_colors.astro @@ -0,0 +1,10 @@ +--- +import { getColors } from '@/lib/colors' +import ColorPalette from '@/components/ColorPalette.astro' + +const colors = getColors() +--- + +
+ {colors.map((colorPalette) => )} +
diff --git a/docs/src/pages/colors/index.astro b/docs/src/pages/colors/index.astro new file mode 100644 index 0000000..1e670cc --- /dev/null +++ b/docs/src/pages/colors/index.astro @@ -0,0 +1,47 @@ +--- +import Announcement from '@/components/Announcement.astro' +import { PageActions, PageHeader, PageHeaderDescription, PageHeaderHeading } from '@/components/page-header' +import RootLayout from '@/layouts/RootLayout.astro' +import { buttonVariants } from '@/registry/new-york/ui/button' + +import Colors from './_colors.astro' +import { siteConfig } from '@/config/site' +--- + + +
+ + + Tailwind Colors + Tailwind CSS colors in HSL, RGB, and HEX formats. + + + + Browse Colors + + + Documentation + + + + +
+
+ +
+
+
+