Skip to content

Commit

Permalink
feat: allow disable color vars, radius, global styles (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
NamesMT authored May 11, 2024
1 parent c59e42a commit e68464b
Show file tree
Hide file tree
Showing 15 changed files with 422 additions and 45 deletions.
6 changes: 5 additions & 1 deletion eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import hyoban from 'eslint-config-hyoban'

export default hyoban()
export default hyoban(
{ ignores: [
'test/snapshot/**/*',
] },
)
61 changes: 43 additions & 18 deletions src/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,42 @@ function generateColorCSSVars(color: ThemeCSSVars) {
.join('\n')
}

function colorCSSVarsStyles(lightVars: string, darkVars: string, { radius, themeName }: { radius?: number | false, themeName?: string | false }) {
return `
${themeName ? `.theme-${themeName}` : ':root'} {
${lightVars}
${radius ? generateRadiusCSSVars(radius) : ''}
}
${themeName ? `.dark .theme-${themeName}` : '.dark'} {
${darkVars}
}`
}

function generateRadiusCSSVars(radius: number) {
return ` --radius: ${radius}rem;`
}

function radiusCSSVarsStyles(radius: number) {
return `
:root {
${generateRadiusCSSVars(radius)}
}
`
}

export function generateGlobalStyles() {
return `
* {
border-color: hsl(var(--border));
}
body {
color: hsl(var(--foreground));
background: hsl(var(--background));
}
`
}

function getBuiltInTheme(name: string) {
const theme = themes.find(t => t.name === name)
if (!theme)
Expand Down Expand Up @@ -58,27 +90,20 @@ export function generateCSSVars(
return theme.map(t => generateCSSVars(t, false)).join('\n')

const { color = 'zinc', radius = 0.5 } = theme
const { light, dark, name } = getColorTheme(color)
const lightVars = generateColorCSSVars(light)
const darkVars = generateColorCSSVars(dark)

if (!onlyOne) {
return `.theme-${name} {
${lightVars}
${generateRadiusCSSVars(radius)}
}
let cssStyle = ''

.dark .theme-${name} {
${darkVars}
}`
if (!color) {
if (radius)
cssStyle += radiusCSSVarsStyles(radius)
}
else {
const { light, dark, name } = getColorTheme(color)
const lightVars = generateColorCSSVars(light)
const darkVars = generateColorCSSVars(dark)

return `:root {
${lightVars}
${generateRadiusCSSVars(radius)}
}
cssStyle += colorCSSVarsStyles(lightVars, darkVars, { radius, themeName: !onlyOne && name })
}

.dark {
${darkVars}
}`
return cssStyle
}
17 changes: 7 additions & 10 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import type { Preset } from 'unocss'
import type { Theme } from 'unocss/preset-mini'

import { generateCSSVars } from './generate'
import { generateCSSVars, generateGlobalStyles } from './generate'
import { themes } from './themes'
import type { PresetShadcnOptions } from './types'

export const builtinColors = themes.map(theme => theme.name)
export const builtinRadiuses = [0, 0.3, 0.5, 0.75, 1] as const

export function presetShadcn(options: PresetShadcnOptions = {}): Preset<Theme> {
/**
* @param globals Generates global variables, like *.border-color, body.color, body.background.
* @default true
*/
export function presetShadcn(options: PresetShadcnOptions = {}, globals = true): Preset<Theme> {
return {
name: 'unocss-preset-shadcn',
preflights: [
Expand All @@ -21,14 +25,7 @@ export function presetShadcn(options: PresetShadcnOptions = {}): Preset<Theme> {
${generateCSSVars(options)}
* {
border-color: hsl(var(--border));
}
body {
color: hsl(var(--foreground));
background: hsl(var(--background));
}
${globals ? generateGlobalStyles() : ''}
`,
},
],
Expand Down
4 changes: 2 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ export type ThemeOptions = {
/**
* @default 'zinc'
*/
color?: ColorOptions
color?: ColorOptions | false
/**
* @default 0.5
*/
radius?: number
radius?: number | false
}

export type PresetShadcnOptions = ArrayOrSingle<ThemeOptions>
65 changes: 60 additions & 5 deletions test/generate.test.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,76 @@
import { createGenerator } from 'unocss'
import { describe, expect, it } from 'vitest'

import presetShadcn from '../src'
import { generateCSSVars } from '../src/generate'

const unoGenerator = createGenerator()

describe('presetShadcn()-execute-getCSS', () => {
it('default options', async () => {
const presetReturn = presetShadcn()
await expect(presetReturn).toMatchFileSnapshot('snapshot/presetShadcn()-default.json')

await expect(
presetReturn.preflights![0]?.getCSS({ generator: unoGenerator, theme: {} }),
).toMatchFileSnapshot('snapshot/presetShadcn()-default-getCSS.css')
})

it('disable color', async () => {
const presetReturn = presetShadcn({ color: false })
// Don't think this is needed for now
// await expect(presetReturn).toMatchFileSnapshot('snapshot/presetShadcn()-disable_color.json')

await expect(
presetReturn.preflights![0]?.getCSS({ generator: unoGenerator, theme: {} }),
).toMatchFileSnapshot('snapshot/presetShadcn()-disable_color-getCSS.css')
})

it('disable radius', async () => {
const presetReturn = presetShadcn({ radius: false })
// Don't think this is needed for now
// await expect(presetReturn).toMatchFileSnapshot('snapshot/presetShadcn()-disable_radius.json')

await expect(
presetReturn.preflights![0]?.getCSS({ generator: unoGenerator, theme: {} }),
).toMatchFileSnapshot('snapshot/presetShadcn()-disable_radius-getCSS.css')
})

it('disable color and radius', async () => {
const presetReturn = presetShadcn({ color: false, radius: false })
// Don't think this is needed for now
// await expect(presetReturn).toMatchFileSnapshot('snapshot/presetShadcn()-disable_color_and_radius.json')

await expect(
presetReturn.preflights![0]?.getCSS({ generator: unoGenerator, theme: {} }),
).toMatchFileSnapshot('snapshot/presetShadcn()-disable_color_and_radius-getCSS.css')
})

it('disable global styles', async () => {
const presetReturn = presetShadcn(undefined, false)
// Don't think this is needed for now
// await expect(presetReturn).toMatchFileSnapshot('snapshot/presetShadcn()-disable_global_styles.json')

await expect(
presetReturn.preflights![0]?.getCSS({ generator: unoGenerator, theme: {} }),
).toMatchFileSnapshot('snapshot/presetShadcn()-disable_global_styles-getCSS.css')
})
})

describe('generate-theme-css-var', () => {
it('built in themes', async () => {
await expect(
generateCSSVars({
color: 'zinc',
radius: 0.5,
}),
).toMatchFileSnapshot('zinc-0.5.css')
).toMatchFileSnapshot('snapshot/zinc-0.5.css')
await expect(
generateCSSVars({
color: 'neutral',
radius: 0.75,
}),
).toMatchFileSnapshot('neutral-0.75.css')
).toMatchFileSnapshot('snapshot/neutral-0.75.css')
})

it('custom theme', async () => {
Expand Down Expand Up @@ -68,7 +123,7 @@ describe('generate-theme-css-var', () => {
},
radius: 1,
}),
).toMatchFileSnapshot('custom.css')
).toMatchFileSnapshot('snapshot/custom.css')
})

it('custom theme based on built in theme', async () => {
Expand All @@ -84,7 +139,7 @@ describe('generate-theme-css-var', () => {
},
radius: 1,
}),
).toMatchFileSnapshot('custom.css')
).toMatchFileSnapshot('snapshot/custom.css')
})

it('generate multiple themes', async () => {
Expand All @@ -99,6 +154,6 @@ describe('generate-theme-css-var', () => {
radius: 0.75,
},
]),
).toMatchFileSnapshot('multiple.css')
).toMatchFileSnapshot('snapshot/multiple.css')
})
})
4 changes: 2 additions & 2 deletions test/custom.css → test/snapshot/custom.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

:root {
--background: 0 1% 100%;
--foreground: 240 10% 3.9%;
Expand All @@ -20,7 +21,6 @@
--ring: 240 5.9% 10%;
--radius: 1rem;
}

.dark {
--background: 240 10% 3.9%;
--foreground: 0 0% 98%;
Expand All @@ -41,4 +41,4 @@
--border: 240 3.7% 15.9%;
--input: 240 3.7% 15.9%;
--ring: 240 4.9% 83.9%;
}
}
6 changes: 3 additions & 3 deletions test/multiple.css → test/snapshot/multiple.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

.theme-zinc {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
Expand All @@ -20,7 +21,6 @@
--ring: 240 5.9% 10%;
--radius: 0.5rem;
}

.dark .theme-zinc {
--background: 240 10% 3.9%;
--foreground: 0 0% 98%;
Expand All @@ -42,6 +42,7 @@
--input: 240 3.7% 15.9%;
--ring: 240 4.9% 83.9%;
}

.theme-neutral {
--background: 0 0% 100%;
--foreground: 0 0% 3.9%;
Expand All @@ -64,7 +65,6 @@
--ring: 0 0% 3.9%;
--radius: 0.75rem;
}

.dark .theme-neutral {
--background: 0 0% 3.9%;
--foreground: 0 0% 98%;
Expand All @@ -85,4 +85,4 @@
--border: 0 0% 14.9%;
--input: 0 0% 14.9%;
--ring: 0 0% 83.1%;
}
}
4 changes: 2 additions & 2 deletions test/neutral-0.75.css → test/snapshot/neutral-0.75.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

:root {
--background: 0 0% 100%;
--foreground: 0 0% 3.9%;
Expand All @@ -20,7 +21,6 @@
--ring: 0 0% 3.9%;
--radius: 0.75rem;
}

.dark {
--background: 0 0% 3.9%;
--foreground: 0 0% 98%;
Expand All @@ -41,4 +41,4 @@
--border: 0 0% 14.9%;
--input: 0 0% 14.9%;
--ring: 0 0% 83.1%;
}
}
62 changes: 62 additions & 0 deletions test/snapshot/presetShadcn()-default-getCSS.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@

@keyframes shadcn-down { from{ height: 0 } to { height: var(--radix-accordion-content-height)} }
@keyframes shadcn-up { from{ height: var(--radix-accordion-content-height)} to { height: 0 } }
@keyframes shadcn-collapsible-down { from{ height: 0 } to { height: var(--radix-collapsible-content-height)} }
@keyframes shadcn-collapsible-up { from{ height: var(--radix-collapsible-content-height)} to { height: 0 } }


:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--card: 0 0% 100%;
--card-foreground: 240 10% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 240 10% 3.9%;
--primary: 240 5.9% 10%;
--primary-foreground: 0 0% 98%;
--secondary: 240 4.8% 95.9%;
--secondary-foreground: 240 5.9% 10%;
--muted: 240 4.8% 95.9%;
--muted-foreground: 240 3.8% 46.1%;
--accent: 240 4.8% 95.9%;
--accent-foreground: 240 5.9% 10%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 240 5.9% 90%;
--input: 240 5.9% 90%;
--ring: 240 5.9% 10%;
--radius: 0.5rem;
}
.dark {
--background: 240 10% 3.9%;
--foreground: 0 0% 98%;
--card: 240 10% 3.9%;
--card-foreground: 0 0% 98%;
--popover: 240 10% 3.9%;
--popover-foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 240 5.9% 10%;
--secondary: 240 3.7% 15.9%;
--secondary-foreground: 0 0% 98%;
--muted: 240 3.7% 15.9%;
--muted-foreground: 240 5% 64.9%;
--accent: 240 3.7% 15.9%;
--accent-foreground: 0 0% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 0 0% 98%;
--border: 240 3.7% 15.9%;
--input: 240 3.7% 15.9%;
--ring: 240 4.9% 83.9%;
}


* {
border-color: hsl(var(--border));
}

body {
color: hsl(var(--foreground));
background: hsl(var(--background));
}


Loading

0 comments on commit e68464b

Please sign in to comment.