shadcn.io is not affiliated with official shadcn/ui
Seasonal Sale Pricing Block for Solid
A seasonal sale for a stock-photo library: an oversized '−41%' stamp in the header row under an 'Autumn sale' ribbon, over three plans in shared-hairline cells with struck prices and the sale price at display size.
Installation
Overview
Run a sale that looks like one with this seasonal sale pricing section. The hero is a stamp: "−41%" at display size in a double frame, tilted a few degrees, with a dark ribbon across its foot that names the sale ("Autumn sale"). It sits in the header row, opposite a headline ("Save up to 41% this autumn") and the deadline ("Ends Sunday at midnight"). Below it, three plans for a stock-photo library (10 images, 50 images and Unlimited) share their hairlines in one band with + marks at its corners. Each cell leads with its struck regular price, an outline Badge with the saving and the sale price at 60 px; the featured plan is tinted and holds the block's one primary Shine Button. On a phone a Segment Group shows one plan at a time, the featured one first. Built with Segment Group, Badge, Shine Button, Guides and Lucide icons, with CSS transitions only. For seasonal and holiday sales, anniversaries and any discount with a name.
FAQ
How do I change the plans, the prices and the sale?
Edit the data at the top of the file. Each entry in PLANS has its name, description, features, regular original price and sale price per month, and featured for the tint, the badge and the primary button. The percentages are all worked out from the two prices: each plan's badge and button, and the stamp, which shows the best discount (BEST_PERCENT), so 41% appears because 29 to 17 is the biggest cut. SALE holds the ribbon's name and the deadline's words.
How do I show a real deadline?
"Ends Sunday at midnight" is plain text, written relative on purpose so the page never shows a past date. Replace it with your sale's real dates, or pair the idea with the Countdown Offer block for a live clock. Whatever the page says, end the sale on your server at that moment: stop applying the sale prices at checkout and render the plans at their regular price.
How do I connect the buttons to checkout?
Each call to action is a real link to its plan's href. It's a ShineButton whose asChild renders the link. The label says what the buyer gets ("Claim 40% off"), and a screen reader hears the plan too ("Claim 40% off, 50 images plan"). Point each link at a checkout that applies the sale price, with no coupon code needed.
Is the sale accessible?
The stamp and its ribbon are decorative and hidden from assistive technology: the headline says "Save up to 41% this autumn", and each price is written for a screen reader as "Was $99, 40% off, now $59 per month", with the struck price in a real s element. On a phone the plan selector is a radio group named "Plan": the arrow keys change the plan, and the plans that aren't shown are invisible to Tab and screen readers.
How does it look on a phone?
The stamp shrinks beside the headline, so the header stays within the first screen, then the Segment Group, then one plan with its price and button. The three plans share one grid cell and the hidden ones are invisible, so the block keeps the height of the tallest plan and nothing jumps when you switch plans. From md the three plans sit side by side and share their rows through CSS subgrid so names, prices, buttons and feature lists line up.
How is this different from a plain discount?
A struck price on a plan tells people it's cheaper; a stamp and a named sale tell them why now. Use it when the discount is real and temporary (a seasonal sale, an anniversary, a launch) and say when it ends. If the lower price is permanent, or tied to who the buyer is, use a plan card with a struck price instead.